metaplex-foundation / solita

Genrates an SDK API from solana contract IDL.
Apache License 2.0
142 stars 33 forks source link

feat: override accound keys and program id #62

Closed thlorenz closed 2 years ago

thlorenz commented 2 years ago

Summary

This PR adds the ability for users to do the following:

Example

Auction Houes buy instruction serves as a shortened example of what is generated now:

Accounts Type

/**
 * Accounts required by the _buy_ instruction
 *
 * @property [**signer**] wallet
 * @property [_writable_] paymentAccount
 * @property [] transferAuthority
 * @property [] treasuryMint
 * @property [] tokenAccount
 * @property [] metadata
 * @property [_writable_] escrowPaymentAccount
 * @property [] authority
 * @property [] auctionHouse
 * @property [_writable_] auctionHouseFeeAccount
 * @property [_writable_] buyerTradeState
 * @category Instructions
 * @category Buy
 * @category generated
 */
export type BuyInstructionAccounts = {
  wallet: web3.PublicKey
  paymentAccount: web3.PublicKey
  transferAuthority: web3.PublicKey
  treasuryMint: web3.PublicKey
  tokenAccount: web3.PublicKey
  metadata: web3.PublicKey
  escrowPaymentAccount: web3.PublicKey
  authority: web3.PublicKey
  auctionHouse: web3.PublicKey
  auctionHouseFeeAccount: web3.PublicKey
  buyerTradeState: web3.PublicKey
  tokenProgram?: web3.PublicKey
  systemProgram?: web3.PublicKey
  rent?: web3.PublicKey
}

NOTE: that the optional accounts are not included in the comments as overriding them is a hidden feature.

Known Account Resolution

  const keys: web3.AccountMeta[] = [
    {
      pubkey: accounts.wallet,
      isWritable: false,
      isSigner: true,
    },
    [ .. many more .. ]
    {
      pubkey: accounts.tokenProgram ?? splToken.TOKEN_PROGRAM_ID,
      isWritable: false,
      isSigner: false,
    },
    {
      pubkey: accounts.systemProgram ?? web3.SystemProgram.programId,
      isWritable: false,
      isSigner: false,
    },
    {
      pubkey: accounts.rent ?? web3.SYSVAR_RENT_PUBKEY,
      isWritable: false,
      isSigner: false,
    },
  ]

Program ID

/**
 * Creates a _Buy_ instruction.
 *
 * @param accounts that will be accessed while the instruction is processed
 * @param args to provide as instruction data to the program
 *
 * @category Instructions
 * @category Buy
 * @category generated
 */
export function createBuyInstruction(
  accounts: BuyInstructionAccounts,
  args: BuyInstructionArgs,
  programId = new web3.PublicKey('hausS13jsjafwWwGqZTUQRmWyvyxn9EQpqMwV1PBBmk')
) {

  // [ .. ]

  const ix = new web3.TransactionInstruction({
    programId,
    keys,
    data,
  })

  return ix
}

NOTE: programId is not listed in the docs as overriding it is a hidden feature as well.

FIXES: #44

lorisleiva commented 2 years ago

That's great thank you!

I've got a small question, but I'm happy for you to merge this as-is if you think it's best.

export function createBuyInstruction(
  accounts: BuyInstructionAccounts,
  args: BuyInstructionArgs,
  programId = new web3.PublicKey('hausS13jsjafwWwGqZTUQRmWyvyxn9EQpqMwV1PBBmk')
)

On the 4th line of the above example, wouldn't it make more sense to use the PROGRAM_ID constant defined in generated/index.ts?

thlorenz commented 2 years ago

On the 4th line of the above example, wouldn't it make more sense to use the PROGRAM_ID constant defined in generated/index.ts?

I think it's fine to hard code this in generated code instead of depending on the index.ts much higher up and potentially causing circular imports. The PROGRAM_ID exported there is just for user convenience.