I am aiming to Cross Program Invoke the transfer method of token_metadata_program.
The method takes optional parameters:
...
#[account(6, optional, name="edition", desc="Edition of token asset")]
#[account(7, optional, writable, name="owner_token_record", desc="Owner token record account")]
#[account(8, optional, writable, name="destination_token_record", desc="Destination token record account")]
#[account(9, signer, name="authority", desc="Transfer authority (token owner or delegate)")]
...
How can I properly forge the CPI call to skip the optional accounts?
What I have so far:
pub fn initialize_auction_2(ctx: Context<InitializeAuction2> ... ) {
...
let transfer_accounts = MetadataTransfer {
token: ctx.accounts.signer_withdraw_wallet.to_account_info(),
token_owner: ctx.accounts.signer.to_account_info(),
destination: ctx.accounts.treasury_token.to_account_info(),
destination_owner: ctx.accounts.treasury.to_account_info(),
mint: ctx.accounts.treasury_mint.to_account_info(),
metadata: ctx.accounts.metadata.to_account_info(),
edition: ctx.accounts.edition.to_account_info(),
owner_token_record: ctx.accounts.owner_token_record.to_account_info(),
destination_token_record: ctx.accounts.destination_token_record.to_account_info(),
authority: ctx.accounts.signer.to_account_info(),
payer: ctx.accounts.signer.to_account_info(),
system_program: ctx.accounts.system_program.to_account_info(),
sysvar_instructions: ctx.accounts.sysvar_instructions.to_account_info(),
spl_token_program: ctx.accounts.token_program.to_account_info(),
spl_ata_program: ctx.accounts.associated_token_program.to_account_info(),
authorization_rules: ctx.accounts.auth_rules.to_account_info(),
authorization_rules_program:ctx.accounts.auth_rules_token_program.to_account_info(),
};
let cpi_ctx = CpiContext::new_with_signer(
ctx.accounts.token_metadata_program.to_account_info(),
transfer_accounts,
signer_seeds
);
token_metadata_transfer(cpi_ctx, 1)?;
Where token_metadata_transfer is defined as:
pub fn token_metadata_transfer<'info>(
ctx: CpiContext<'_, '_, '_, 'info, MetadataTransfer<'info>>,
amount: u64,
) -> Result<()> {
let ix = build_mpl_token_metadata_instruction_with_builder(
ctx.accounts.authority.key,
ctx.accounts.authority.key,
ctx.accounts.token.key,
ctx.accounts.destination_owner.key,
Some(*ctx.accounts.destination.key),
ctx.accounts.metadata.key,
ctx.accounts.payer.key,
None,
ctx.accounts.mint.key,
None,
Some(*ctx.accounts.edition.key),
amount,
);
solana_program::program::invoke_signed(
&ix,
&[
ctx.accounts.token.clone(), // Token account
ctx.accounts.token_owner.clone(), // Token account Owner
ctx.accounts.destination.clone(), // Destination token account
ctx.accounts.destination_owner.clone(), // Destination token account owner
ctx.accounts.mint.clone(), // Mint
ctx.accounts.metadata.clone(), // Token Metadata
ctx.accounts.edition.clone(), // Edition
ctx.accounts.owner_token_record.clone(), // Owner token record
ctx.accounts.destination_token_record.clone(), // Destination token record
ctx.accounts.authority.clone(), // Authority
ctx.accounts.payer.clone(), // Payer
ctx.accounts.system_program.clone(), // System Program
ctx.accounts.sysvar_instructions.clone(), // Sysvar Instructions
ctx.accounts.spl_token_program.clone(), // SPL Token Program
ctx.accounts.spl_ata_program.clone(), // System Program
ctx.accounts.authorization_rules.clone(), // Authorization rules
ctx.accounts.authorization_rules_program.clone(), // Authorization rules program
], ctx.signer_seeds).map_err(Into::into)
If I try to comment one of the Optional accounts from the accounts list passed to invoke_signed
the mpl_token_metadata complains that:
Instruction references an unknown account <pubkey>
What other options do I have?