I'm trying to call a specific endpoint on a Solana smart contract using @solana-web3 and I can't quite figure out how todo that. Iv'e seen it done like this:
const buffer = Buffer.from("hello");
const instruction = new web3.TransactionInstruction({
keys: [{ pubkey: fromWallet.publicKey, isSigner: false, isWritable: true }],
programId: new web3.PublicKey(metaDataProgramID),
data: buffer,
});
const confirmation = await web3.sendAndConfirmTransaction(
connection,
new web3.Transaction().add(instruction),
[fromWallet],
{
commitment: "singleGossip",
preflightCommitment: "singleGossip",
}
);`
But I'm not sure how todo it will a smart contract like this with multiple end points. Because how would one tell the smart contract what endpoint to use and what data to pass to that endpoint?:
pub fn process_instruction<'a>(
program_id: &'a Pubkey,
accounts: &'a [AccountInfo<'a>],
input: &[u8],
) -> ProgramResult {
let instruction = MetadataInstruction::try_from_slice(input)?;
match instruction {
MetadataInstruction::CreateMetadataAccount(args) => {
msg!("Instruction: Create Metadata Accounts");
process_create_metadata_accounts(
program_id,
accounts,
args.data,
false,
args.is_mutable,
)
}
MetadataInstruction::UpdateMetadataAccount(args) => {
msg!("Instruction: Update Metadata Accounts");
process_update_metadata_accounts(
program_id,
accounts,
args.data,
args.update_authority,
args.primary_sale_happened,
)
}
MetadataInstruction::DeprecatedCreateMasterEdition(args) => {
msg!("Instruction: Deprecated Create Master Edition");
process_deprecated_create_master_edition(program_id, accounts, args.max_supply)
}
MetadataInstruction::DeprecatedMintNewEditionFromMasterEditionViaPrintingToken => {
msg!("Instruction: Deprecated Mint New Edition from Master Edition Via Token");
process_deprecated_mint_new_edition_from_master_edition_via_printing_token(
program_id, accounts,
)
}
MetadataInstruction::UpdatePrimarySaleHappenedViaToken => {
msg!("Instruction: Update primary sale via token");
process_update_primary_sale_happened_via_token(program_id, accounts)
}
MetadataInstruction::MintNewEditionFromMasterEditionViaVaultProxy(args) => {
msg!("Instruction: Mint New Edition from Master Edition Via Vault Proxy");
process_mint_new_edition_from_master_edition_via_vault_proxy(
program_id,
accounts,
args.edition,
)
}
MetadataInstruction::PuffMetadata => {
msg!("Instruction: Puff Metadata");
process_puff_metadata_account(program_id, accounts)
}
}
}
Here is the full code for the smart contract: https://github.com/metaplex-foundation/metaplex/tree/master/rust/token-metadata/program
The choice of "endpoint" to call on a smart contract in Solana is decided by that buffer
that you passed in as the data
of the instruction. Given that data, the program decides which instruction processor to call.
In your example, the choice of instruction is likely based on the first byte of the instruction, so 0
may correspond to MetadataInstruction::CreateMetadataAccount
.
Your best bet is to use a package provided by the program developer. In the case of the metadata program, the instruction and type definitions live at: https://github.com/solana-labs/oyster/blob/e79c5a66ed5290d3fb752f4cd6b4e90f7974ec94/packages/common/src/actions/metadata.ts