diff --git a/CHANGELOG.md b/CHANGELOG.md index dcab69a022..e6b15c769b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ The minor version will be incremented upon a breaking change and the patch versi ### Features +- spl: Implemented `withdrawWithheldTokensFromAccounts` instruction ([#3128]([https://github.com/coral-xyz/anchor/pull/3128)). - ts: Add optional `commitment` parameter to `Program.addEventListener` ([#3052](https://github.com/coral-xyz/anchor/pull/3052)). - cli, idl: Pass `cargo` args to IDL generation when building program or IDL ([#3059](https://github.com/coral-xyz/anchor/pull/3059)). - cli: Add checks for incorrect usage of `idl-build` feature ([#3061](https://github.com/coral-xyz/anchor/pull/3061)). diff --git a/spl/src/token_2022_extensions/transfer_fee.rs b/spl/src/token_2022_extensions/transfer_fee.rs index e68926c2e8..708d905d30 100644 --- a/spl/src/token_2022_extensions/transfer_fee.rs +++ b/spl/src/token_2022_extensions/transfer_fee.rs @@ -158,3 +158,36 @@ pub struct WithdrawWithheldTokensFromMint<'info> { pub destination: AccountInfo<'info>, pub authority: AccountInfo<'info>, } + +pub fn withdraw_withheld_tokens_from_accounts<'info>( + ctx: CpiContext<'_, '_, '_, 'info, WithdrawWithheldTokensFromAccounts<'info>>, + sources: Vec>, +) -> Result<()> { + let ix = spl_token_2022::extension::transfer_fee::instruction::withdraw_withheld_tokens_from_accounts( + ctx.accounts.token_program_id.key, + ctx.accounts.mint.key, + ctx.accounts.destination.key, + ctx.accounts.authority.key, + &[], + sources.iter().map(|a| a.key).collect::>().as_slice(), + )?; + + let mut account_infos = vec![ + ctx.accounts.token_program_id, + ctx.accounts.mint, + ctx.accounts.destination, + ctx.accounts.authority, + ]; + account_infos.extend_from_slice(&sources); + + anchor_lang::solana_program::program::invoke_signed(&ix, &account_infos, ctx.signer_seeds) + .map_err(Into::into) +} + +#[derive(Accounts)] +pub struct WithdrawWithheldTokensFromAccounts<'info> { + pub token_program_id: AccountInfo<'info>, + pub mint: AccountInfo<'info>, + pub destination: AccountInfo<'info>, + pub authority: AccountInfo<'info>, +}