Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

Commit 662545f

Browse files
committed
add offchain helper invoke_transfer_checked_with_fee
1 parent 594b725 commit 662545f

File tree

1 file changed

+68
-1
lines changed

1 file changed

+68
-1
lines changed

token/program-2022/src/onchain.rs

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
44
use {
55
crate::{
6-
extension::{transfer_hook, StateWithExtensions},
6+
extension::{transfer_fee, transfer_hook, StateWithExtensions},
77
instruction,
88
state::Mint,
99
},
@@ -78,3 +78,70 @@ pub fn invoke_transfer_checked<'a>(
7878

7979
invoke_signed(&cpi_instruction, &cpi_account_infos, seeds)
8080
}
81+
82+
/// Helper to CPI into token-2022 on-chain, looking through the additional
83+
/// account infos to create the proper instruction with the proper account infos
84+
#[allow(clippy::too_many_arguments)]
85+
pub fn invoke_transfer_checked_with_fee<'a>(
86+
token_program_id: &Pubkey,
87+
source_info: AccountInfo<'a>,
88+
mint_info: AccountInfo<'a>,
89+
destination_info: AccountInfo<'a>,
90+
authority_info: AccountInfo<'a>,
91+
additional_accounts: &[AccountInfo<'a>],
92+
amount: u64,
93+
decimals: u8,
94+
fee: u64,
95+
seeds: &[&[&[u8]]],
96+
) -> ProgramResult {
97+
let mut cpi_instruction = transfer_fee::instruction::transfer_checked_with_fee(
98+
token_program_id,
99+
source_info.key,
100+
mint_info.key,
101+
destination_info.key,
102+
authority_info.key,
103+
&[], // add them later, to avoid unnecessary clones
104+
amount,
105+
decimals,
106+
fee,
107+
)?;
108+
109+
let mut cpi_account_infos = vec![
110+
source_info.clone(),
111+
mint_info.clone(),
112+
destination_info.clone(),
113+
authority_info.clone(),
114+
];
115+
116+
// if it's a signer, it might be a multisig signer, throw it in!
117+
additional_accounts
118+
.iter()
119+
.filter(|ai| ai.is_signer)
120+
.for_each(|ai| {
121+
cpi_account_infos.push(ai.clone());
122+
cpi_instruction
123+
.accounts
124+
.push(AccountMeta::new_readonly(*ai.key, ai.is_signer));
125+
});
126+
127+
// scope the borrowing to avoid a double-borrow during CPI
128+
{
129+
let mint_data = mint_info.try_borrow_data()?;
130+
let mint = StateWithExtensions::<Mint>::unpack(&mint_data)?;
131+
if let Some(program_id) = transfer_hook::get_program_id(&mint) {
132+
add_extra_accounts_for_execute_cpi(
133+
&mut cpi_instruction,
134+
&mut cpi_account_infos,
135+
&program_id,
136+
source_info,
137+
mint_info.clone(),
138+
destination_info,
139+
authority_info,
140+
amount,
141+
additional_accounts,
142+
)?;
143+
}
144+
}
145+
146+
invoke_signed(&cpi_instruction, &cpi_account_infos, seeds)
147+
}

0 commit comments

Comments
 (0)