token-2022: plumb program_id through instruction builders (#2792)
* Plumb program_id into ix builders * Don't unwrap extension instructions
This commit is contained in:
parent
3e1dd7cac8
commit
cc8826ac70
|
@ -3,7 +3,7 @@ use solana_zk_token_sdk::encryption::{auth_encryption::AeCiphertext, elgamal::El
|
||||||
pub use solana_zk_token_sdk::zk_token_proof_instruction::*;
|
pub use solana_zk_token_sdk::zk_token_proof_instruction::*;
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
extension::confidential_transfer::ConfidentialTransferMint, id,
|
check_program_account, extension::confidential_transfer::ConfidentialTransferMint,
|
||||||
instruction::TokenInstruction, pod::*,
|
instruction::TokenInstruction, pod::*,
|
||||||
},
|
},
|
||||||
bytemuck::{Pod, Zeroable},
|
bytemuck::{Pod, Zeroable},
|
||||||
|
@ -312,6 +312,7 @@ pub(crate) fn decode_instruction_data<T: Pod>(input: &[u8]) -> Result<&T, Progra
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_instruction<T: Pod>(
|
fn encode_instruction<T: Pod>(
|
||||||
|
token_program_id: &Pubkey,
|
||||||
accounts: Vec<AccountMeta>,
|
accounts: Vec<AccountMeta>,
|
||||||
instruction_type: ConfidentialTransferInstruction,
|
instruction_type: ConfidentialTransferInstruction,
|
||||||
instruction_data: &T,
|
instruction_data: &T,
|
||||||
|
@ -320,27 +321,35 @@ fn encode_instruction<T: Pod>(
|
||||||
data.push(ToPrimitive::to_u8(&instruction_type).unwrap());
|
data.push(ToPrimitive::to_u8(&instruction_type).unwrap());
|
||||||
data.extend_from_slice(bytemuck::bytes_of(instruction_data));
|
data.extend_from_slice(bytemuck::bytes_of(instruction_data));
|
||||||
Instruction {
|
Instruction {
|
||||||
program_id: id(),
|
program_id: *token_program_id,
|
||||||
accounts,
|
accounts,
|
||||||
data,
|
data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a `InitializeMint` instruction
|
/// Create a `InitializeMint` instruction
|
||||||
pub fn initialize_mint(mint: &Pubkey, auditor: &ConfidentialTransferMint) -> Instruction {
|
pub fn initialize_mint(
|
||||||
|
token_program_id: &Pubkey,
|
||||||
|
mint: &Pubkey,
|
||||||
|
auditor: &ConfidentialTransferMint,
|
||||||
|
) -> Result<Instruction, ProgramError> {
|
||||||
|
check_program_account(token_program_id)?;
|
||||||
let accounts = vec![AccountMeta::new(*mint, false)];
|
let accounts = vec![AccountMeta::new(*mint, false)];
|
||||||
encode_instruction(
|
Ok(encode_instruction(
|
||||||
|
token_program_id,
|
||||||
accounts,
|
accounts,
|
||||||
ConfidentialTransferInstruction::InitializeMint,
|
ConfidentialTransferInstruction::InitializeMint,
|
||||||
auditor,
|
auditor,
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
/// Create a `UpdateMint` instruction
|
/// Create a `UpdateMint` instruction
|
||||||
pub fn update_mint(
|
pub fn update_mint(
|
||||||
|
token_program_id: &Pubkey,
|
||||||
mint: &Pubkey,
|
mint: &Pubkey,
|
||||||
new_auditor: &ConfidentialTransferMint,
|
new_auditor: &ConfidentialTransferMint,
|
||||||
authority: &Pubkey,
|
authority: &Pubkey,
|
||||||
) -> Instruction {
|
) -> Result<Instruction, ProgramError> {
|
||||||
|
check_program_account(token_program_id)?;
|
||||||
let accounts = vec![
|
let accounts = vec![
|
||||||
AccountMeta::new(*mint, false),
|
AccountMeta::new(*mint, false),
|
||||||
AccountMeta::new_readonly(*authority, true),
|
AccountMeta::new_readonly(*authority, true),
|
||||||
|
@ -349,23 +358,26 @@ pub fn update_mint(
|
||||||
new_auditor.authority != Pubkey::default(),
|
new_auditor.authority != Pubkey::default(),
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
encode_instruction(
|
Ok(encode_instruction(
|
||||||
|
token_program_id,
|
||||||
accounts,
|
accounts,
|
||||||
ConfidentialTransferInstruction::UpdateMint,
|
ConfidentialTransferInstruction::UpdateMint,
|
||||||
new_auditor,
|
new_auditor,
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a `ConfigureAccount` instruction
|
/// Create a `ConfigureAccount` instruction
|
||||||
#[cfg(not(target_arch = "bpf"))]
|
#[cfg(not(target_arch = "bpf"))]
|
||||||
pub fn configure_account(
|
pub fn configure_account(
|
||||||
|
token_program_id: &Pubkey,
|
||||||
token_account: &Pubkey,
|
token_account: &Pubkey,
|
||||||
mint: &Pubkey,
|
mint: &Pubkey,
|
||||||
elgamal_pk: ElGamalPubkey,
|
elgamal_pk: ElGamalPubkey,
|
||||||
decryptable_zero_balance: AeCiphertext,
|
decryptable_zero_balance: AeCiphertext,
|
||||||
authority: &Pubkey,
|
authority: &Pubkey,
|
||||||
multisig_signers: &[&Pubkey],
|
multisig_signers: &[&Pubkey],
|
||||||
) -> Vec<Instruction> {
|
) -> Result<Vec<Instruction>, ProgramError> {
|
||||||
|
check_program_account(token_program_id)?;
|
||||||
let mut accounts = vec![
|
let mut accounts = vec![
|
||||||
AccountMeta::new(*token_account, false),
|
AccountMeta::new(*token_account, false),
|
||||||
AccountMeta::new_readonly(*mint, false),
|
AccountMeta::new_readonly(*mint, false),
|
||||||
|
@ -376,43 +388,49 @@ pub fn configure_account(
|
||||||
accounts.push(AccountMeta::new_readonly(**multisig_signer, true));
|
accounts.push(AccountMeta::new_readonly(**multisig_signer, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
vec![encode_instruction(
|
Ok(vec![encode_instruction(
|
||||||
|
token_program_id,
|
||||||
accounts,
|
accounts,
|
||||||
ConfidentialTransferInstruction::ConfigureAccount,
|
ConfidentialTransferInstruction::ConfigureAccount,
|
||||||
&ConfigureAccountInstructionData {
|
&ConfigureAccountInstructionData {
|
||||||
elgamal_pk: elgamal_pk.into(),
|
elgamal_pk: elgamal_pk.into(),
|
||||||
decryptable_zero_balance: decryptable_zero_balance.into(),
|
decryptable_zero_balance: decryptable_zero_balance.into(),
|
||||||
},
|
},
|
||||||
)]
|
)])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create an `ApproveAccount` instruction
|
/// Create an `ApproveAccount` instruction
|
||||||
pub fn approve_account(
|
pub fn approve_account(
|
||||||
|
token_program_id: &Pubkey,
|
||||||
mint: &Pubkey,
|
mint: &Pubkey,
|
||||||
account_to_approve: &Pubkey,
|
account_to_approve: &Pubkey,
|
||||||
authority: &Pubkey,
|
authority: &Pubkey,
|
||||||
) -> Instruction {
|
) -> Result<Instruction, ProgramError> {
|
||||||
|
check_program_account(token_program_id)?;
|
||||||
let accounts = vec![
|
let accounts = vec![
|
||||||
AccountMeta::new(*account_to_approve, false),
|
AccountMeta::new(*account_to_approve, false),
|
||||||
AccountMeta::new_readonly(*mint, false),
|
AccountMeta::new_readonly(*mint, false),
|
||||||
AccountMeta::new_readonly(*authority, true),
|
AccountMeta::new_readonly(*authority, true),
|
||||||
];
|
];
|
||||||
encode_instruction(
|
Ok(encode_instruction(
|
||||||
|
token_program_id,
|
||||||
accounts,
|
accounts,
|
||||||
ConfidentialTransferInstruction::ApproveAccount,
|
ConfidentialTransferInstruction::ApproveAccount,
|
||||||
&(),
|
&(),
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create an inner `EmptyAccount` instruction
|
/// Create an inner `EmptyAccount` instruction
|
||||||
///
|
///
|
||||||
/// This instruction is suitable for use with a cross-program `invoke`
|
/// This instruction is suitable for use with a cross-program `invoke`
|
||||||
pub fn inner_empty_account(
|
pub fn inner_empty_account(
|
||||||
|
token_program_id: &Pubkey,
|
||||||
token_account: &Pubkey,
|
token_account: &Pubkey,
|
||||||
authority: &Pubkey,
|
authority: &Pubkey,
|
||||||
multisig_signers: &[&Pubkey],
|
multisig_signers: &[&Pubkey],
|
||||||
proof_instruction_offset: i8,
|
proof_instruction_offset: i8,
|
||||||
) -> Instruction {
|
) -> Result<Instruction, ProgramError> {
|
||||||
|
check_program_account(token_program_id)?;
|
||||||
let mut accounts = vec![
|
let mut accounts = vec![
|
||||||
AccountMeta::new_readonly(*token_account, false),
|
AccountMeta::new_readonly(*token_account, false),
|
||||||
AccountMeta::new_readonly(sysvar::instructions::id(), false),
|
AccountMeta::new_readonly(sysvar::instructions::id(), false),
|
||||||
|
@ -423,30 +441,40 @@ pub fn inner_empty_account(
|
||||||
accounts.push(AccountMeta::new_readonly(**multisig_signer, true));
|
accounts.push(AccountMeta::new_readonly(**multisig_signer, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
encode_instruction(
|
Ok(encode_instruction(
|
||||||
|
token_program_id,
|
||||||
accounts,
|
accounts,
|
||||||
ConfidentialTransferInstruction::EmptyAccount,
|
ConfidentialTransferInstruction::EmptyAccount,
|
||||||
&EmptyAccountInstructionData {
|
&EmptyAccountInstructionData {
|
||||||
proof_instruction_offset,
|
proof_instruction_offset,
|
||||||
},
|
},
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a `EmptyAccount` instruction
|
/// Create a `EmptyAccount` instruction
|
||||||
pub fn empty_account(
|
pub fn empty_account(
|
||||||
|
token_program_id: &Pubkey,
|
||||||
token_account: &Pubkey,
|
token_account: &Pubkey,
|
||||||
authority: &Pubkey,
|
authority: &Pubkey,
|
||||||
multisig_signers: &[&Pubkey],
|
multisig_signers: &[&Pubkey],
|
||||||
proof_data: &CloseAccountData,
|
proof_data: &CloseAccountData,
|
||||||
) -> Vec<Instruction> {
|
) -> Result<Vec<Instruction>, ProgramError> {
|
||||||
vec![
|
Ok(vec![
|
||||||
verify_close_account(proof_data),
|
verify_close_account(proof_data),
|
||||||
inner_empty_account(token_account, authority, multisig_signers, -1),
|
inner_empty_account(
|
||||||
]
|
token_program_id,
|
||||||
|
token_account,
|
||||||
|
authority,
|
||||||
|
multisig_signers,
|
||||||
|
-1,
|
||||||
|
)?, // calls check_program_account
|
||||||
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a `Deposit` instruction
|
/// Create a `Deposit` instruction
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn deposit(
|
pub fn deposit(
|
||||||
|
token_program_id: &Pubkey,
|
||||||
source_token_account: &Pubkey,
|
source_token_account: &Pubkey,
|
||||||
mint: &Pubkey,
|
mint: &Pubkey,
|
||||||
destination_token_account: &Pubkey,
|
destination_token_account: &Pubkey,
|
||||||
|
@ -454,7 +482,8 @@ pub fn deposit(
|
||||||
decimals: u8,
|
decimals: u8,
|
||||||
authority: &Pubkey,
|
authority: &Pubkey,
|
||||||
multisig_signers: &[&Pubkey],
|
multisig_signers: &[&Pubkey],
|
||||||
) -> Vec<Instruction> {
|
) -> Result<Vec<Instruction>, ProgramError> {
|
||||||
|
check_program_account(token_program_id)?;
|
||||||
let mut accounts = vec![
|
let mut accounts = vec![
|
||||||
AccountMeta::new(*source_token_account, false),
|
AccountMeta::new(*source_token_account, false),
|
||||||
AccountMeta::new(*destination_token_account, false),
|
AccountMeta::new(*destination_token_account, false),
|
||||||
|
@ -466,14 +495,15 @@ pub fn deposit(
|
||||||
accounts.push(AccountMeta::new_readonly(**multisig_signer, true));
|
accounts.push(AccountMeta::new_readonly(**multisig_signer, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
vec![encode_instruction(
|
Ok(vec![encode_instruction(
|
||||||
|
token_program_id,
|
||||||
accounts,
|
accounts,
|
||||||
ConfidentialTransferInstruction::Deposit,
|
ConfidentialTransferInstruction::Deposit,
|
||||||
&DepositInstructionData {
|
&DepositInstructionData {
|
||||||
amount: amount.into(),
|
amount: amount.into(),
|
||||||
decimals,
|
decimals,
|
||||||
},
|
},
|
||||||
)]
|
)])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a inner `Withdraw` instruction
|
/// Create a inner `Withdraw` instruction
|
||||||
|
@ -481,6 +511,7 @@ pub fn deposit(
|
||||||
/// This instruction is suitable for use with a cross-program `invoke`
|
/// This instruction is suitable for use with a cross-program `invoke`
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn inner_withdraw(
|
pub fn inner_withdraw(
|
||||||
|
token_program_id: &Pubkey,
|
||||||
source_token_account: &Pubkey,
|
source_token_account: &Pubkey,
|
||||||
destination_token_account: &Pubkey,
|
destination_token_account: &Pubkey,
|
||||||
mint: &Pubkey,
|
mint: &Pubkey,
|
||||||
|
@ -490,7 +521,8 @@ pub fn inner_withdraw(
|
||||||
authority: &Pubkey,
|
authority: &Pubkey,
|
||||||
multisig_signers: &[&Pubkey],
|
multisig_signers: &[&Pubkey],
|
||||||
proof_instruction_offset: i8,
|
proof_instruction_offset: i8,
|
||||||
) -> Instruction {
|
) -> Result<Instruction, ProgramError> {
|
||||||
|
check_program_account(token_program_id)?;
|
||||||
let mut accounts = vec![
|
let mut accounts = vec![
|
||||||
AccountMeta::new(*source_token_account, false),
|
AccountMeta::new(*source_token_account, false),
|
||||||
AccountMeta::new(*destination_token_account, false),
|
AccountMeta::new(*destination_token_account, false),
|
||||||
|
@ -503,7 +535,8 @@ pub fn inner_withdraw(
|
||||||
accounts.push(AccountMeta::new_readonly(**multisig_signer, true));
|
accounts.push(AccountMeta::new_readonly(**multisig_signer, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
encode_instruction(
|
Ok(encode_instruction(
|
||||||
|
token_program_id,
|
||||||
accounts,
|
accounts,
|
||||||
ConfidentialTransferInstruction::Withdraw,
|
ConfidentialTransferInstruction::Withdraw,
|
||||||
&WithdrawInstructionData {
|
&WithdrawInstructionData {
|
||||||
|
@ -512,13 +545,14 @@ pub fn inner_withdraw(
|
||||||
new_decryptable_available_balance,
|
new_decryptable_available_balance,
|
||||||
proof_instruction_offset,
|
proof_instruction_offset,
|
||||||
},
|
},
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a `Withdraw` instruction
|
/// Create a `Withdraw` instruction
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
#[cfg(not(target_arch = "bpf"))]
|
#[cfg(not(target_arch = "bpf"))]
|
||||||
pub fn withdraw(
|
pub fn withdraw(
|
||||||
|
token_program_id: &Pubkey,
|
||||||
source_token_account: &Pubkey,
|
source_token_account: &Pubkey,
|
||||||
destination_token_account: &Pubkey,
|
destination_token_account: &Pubkey,
|
||||||
mint: &Pubkey,
|
mint: &Pubkey,
|
||||||
|
@ -528,10 +562,11 @@ pub fn withdraw(
|
||||||
authority: &Pubkey,
|
authority: &Pubkey,
|
||||||
multisig_signers: &[&Pubkey],
|
multisig_signers: &[&Pubkey],
|
||||||
proof_data: &WithdrawData,
|
proof_data: &WithdrawData,
|
||||||
) -> Vec<Instruction> {
|
) -> Result<Vec<Instruction>, ProgramError> {
|
||||||
vec![
|
Ok(vec![
|
||||||
verify_withdraw(proof_data),
|
verify_withdraw(proof_data),
|
||||||
inner_withdraw(
|
inner_withdraw(
|
||||||
|
token_program_id,
|
||||||
source_token_account,
|
source_token_account,
|
||||||
destination_token_account,
|
destination_token_account,
|
||||||
mint,
|
mint,
|
||||||
|
@ -541,8 +576,8 @@ pub fn withdraw(
|
||||||
authority,
|
authority,
|
||||||
multisig_signers,
|
multisig_signers,
|
||||||
-1,
|
-1,
|
||||||
),
|
)?, // calls check_program_account
|
||||||
]
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a inner `Transfer` instruction
|
/// Create a inner `Transfer` instruction
|
||||||
|
@ -550,6 +585,7 @@ pub fn withdraw(
|
||||||
/// This instruction is suitable for use with a cross-program `invoke`
|
/// This instruction is suitable for use with a cross-program `invoke`
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn inner_transfer(
|
pub fn inner_transfer(
|
||||||
|
token_program_id: &Pubkey,
|
||||||
source_token_account: &Pubkey,
|
source_token_account: &Pubkey,
|
||||||
destination_token_account: &Pubkey,
|
destination_token_account: &Pubkey,
|
||||||
mint: &Pubkey,
|
mint: &Pubkey,
|
||||||
|
@ -557,7 +593,8 @@ pub fn inner_transfer(
|
||||||
authority: &Pubkey,
|
authority: &Pubkey,
|
||||||
multisig_signers: &[&Pubkey],
|
multisig_signers: &[&Pubkey],
|
||||||
proof_instruction_offset: i8,
|
proof_instruction_offset: i8,
|
||||||
) -> Instruction {
|
) -> Result<Instruction, ProgramError> {
|
||||||
|
check_program_account(token_program_id)?;
|
||||||
let mut accounts = vec![
|
let mut accounts = vec![
|
||||||
AccountMeta::new(*source_token_account, false),
|
AccountMeta::new(*source_token_account, false),
|
||||||
AccountMeta::new(*destination_token_account, false),
|
AccountMeta::new(*destination_token_account, false),
|
||||||
|
@ -570,20 +607,22 @@ pub fn inner_transfer(
|
||||||
accounts.push(AccountMeta::new_readonly(**multisig_signer, true));
|
accounts.push(AccountMeta::new_readonly(**multisig_signer, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
encode_instruction(
|
Ok(encode_instruction(
|
||||||
|
token_program_id,
|
||||||
accounts,
|
accounts,
|
||||||
ConfidentialTransferInstruction::Transfer,
|
ConfidentialTransferInstruction::Transfer,
|
||||||
&TransferInstructionData {
|
&TransferInstructionData {
|
||||||
new_source_decryptable_available_balance,
|
new_source_decryptable_available_balance,
|
||||||
proof_instruction_offset,
|
proof_instruction_offset,
|
||||||
},
|
},
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a `Transfer` instruction
|
/// Create a `Transfer` instruction
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
#[cfg(not(target_arch = "bpf"))]
|
#[cfg(not(target_arch = "bpf"))]
|
||||||
pub fn transfer(
|
pub fn transfer(
|
||||||
|
token_program_id: &Pubkey,
|
||||||
source_token_account: &Pubkey,
|
source_token_account: &Pubkey,
|
||||||
destination_token_account: &Pubkey,
|
destination_token_account: &Pubkey,
|
||||||
mint: &Pubkey,
|
mint: &Pubkey,
|
||||||
|
@ -591,10 +630,11 @@ pub fn transfer(
|
||||||
authority: &Pubkey,
|
authority: &Pubkey,
|
||||||
multisig_signers: &[&Pubkey],
|
multisig_signers: &[&Pubkey],
|
||||||
proof_data: &TransferData,
|
proof_data: &TransferData,
|
||||||
) -> Vec<Instruction> {
|
) -> Result<Vec<Instruction>, ProgramError> {
|
||||||
vec![
|
Ok(vec![
|
||||||
verify_transfer(proof_data),
|
verify_transfer(proof_data),
|
||||||
inner_transfer(
|
inner_transfer(
|
||||||
|
token_program_id,
|
||||||
source_token_account,
|
source_token_account,
|
||||||
destination_token_account,
|
destination_token_account,
|
||||||
mint,
|
mint,
|
||||||
|
@ -602,8 +642,8 @@ pub fn transfer(
|
||||||
authority,
|
authority,
|
||||||
multisig_signers,
|
multisig_signers,
|
||||||
-1,
|
-1,
|
||||||
),
|
)?, // calls check_program_account
|
||||||
]
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a inner `ApplyPendingBalance` instruction
|
/// Create a inner `ApplyPendingBalance` instruction
|
||||||
|
@ -611,12 +651,14 @@ pub fn transfer(
|
||||||
/// This instruction is suitable for use with a cross-program `invoke`
|
/// This instruction is suitable for use with a cross-program `invoke`
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn inner_apply_pending_balance(
|
pub fn inner_apply_pending_balance(
|
||||||
|
token_program_id: &Pubkey,
|
||||||
token_account: &Pubkey,
|
token_account: &Pubkey,
|
||||||
expected_pending_balance_credit_counter: u64,
|
expected_pending_balance_credit_counter: u64,
|
||||||
new_decryptable_available_balance: pod::AeCiphertext,
|
new_decryptable_available_balance: pod::AeCiphertext,
|
||||||
authority: &Pubkey,
|
authority: &Pubkey,
|
||||||
multisig_signers: &[&Pubkey],
|
multisig_signers: &[&Pubkey],
|
||||||
) -> Instruction {
|
) -> Result<Instruction, ProgramError> {
|
||||||
|
check_program_account(token_program_id)?;
|
||||||
let mut accounts = vec![
|
let mut accounts = vec![
|
||||||
AccountMeta::new(*token_account, false),
|
AccountMeta::new(*token_account, false),
|
||||||
AccountMeta::new_readonly(*authority, multisig_signers.is_empty()),
|
AccountMeta::new_readonly(*authority, multisig_signers.is_empty()),
|
||||||
|
@ -626,40 +668,47 @@ pub fn inner_apply_pending_balance(
|
||||||
accounts.push(AccountMeta::new_readonly(**multisig_signer, true));
|
accounts.push(AccountMeta::new_readonly(**multisig_signer, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
encode_instruction(
|
Ok(encode_instruction(
|
||||||
|
token_program_id,
|
||||||
accounts,
|
accounts,
|
||||||
ConfidentialTransferInstruction::ApplyPendingBalance,
|
ConfidentialTransferInstruction::ApplyPendingBalance,
|
||||||
&ApplyPendingBalanceData {
|
&ApplyPendingBalanceData {
|
||||||
expected_pending_balance_credit_counter: expected_pending_balance_credit_counter.into(),
|
expected_pending_balance_credit_counter: expected_pending_balance_credit_counter.into(),
|
||||||
new_decryptable_available_balance,
|
new_decryptable_available_balance,
|
||||||
},
|
},
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a `ApplyPendingBalance` instruction
|
/// Create a `ApplyPendingBalance` instruction
|
||||||
#[cfg(not(target_arch = "bpf"))]
|
#[cfg(not(target_arch = "bpf"))]
|
||||||
pub fn apply_pending_balance(
|
pub fn apply_pending_balance(
|
||||||
|
token_program_id: &Pubkey,
|
||||||
token_account: &Pubkey,
|
token_account: &Pubkey,
|
||||||
pending_balance_instructions: u64,
|
pending_balance_instructions: u64,
|
||||||
new_decryptable_available_balance: AeCiphertext,
|
new_decryptable_available_balance: AeCiphertext,
|
||||||
authority: &Pubkey,
|
authority: &Pubkey,
|
||||||
multisig_signers: &[&Pubkey],
|
multisig_signers: &[&Pubkey],
|
||||||
) -> Vec<Instruction> {
|
) -> Result<Vec<Instruction>, ProgramError> {
|
||||||
vec![inner_apply_pending_balance(
|
Ok(vec![
|
||||||
token_account,
|
inner_apply_pending_balance(
|
||||||
pending_balance_instructions,
|
token_program_id,
|
||||||
new_decryptable_available_balance.into(),
|
token_account,
|
||||||
authority,
|
pending_balance_instructions,
|
||||||
multisig_signers,
|
new_decryptable_available_balance.into(),
|
||||||
)]
|
authority,
|
||||||
|
multisig_signers,
|
||||||
|
)?, // calls check_program_account
|
||||||
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a `EnableBalanceCredits` instruction
|
/// Create a `EnableBalanceCredits` instruction
|
||||||
pub fn enable_balance_credits(
|
pub fn enable_balance_credits(
|
||||||
|
token_program_id: &Pubkey,
|
||||||
token_account: &Pubkey,
|
token_account: &Pubkey,
|
||||||
authority: &Pubkey,
|
authority: &Pubkey,
|
||||||
multisig_signers: &[&Pubkey],
|
multisig_signers: &[&Pubkey],
|
||||||
) -> Vec<Instruction> {
|
) -> Result<Vec<Instruction>, ProgramError> {
|
||||||
|
check_program_account(token_program_id)?;
|
||||||
let mut accounts = vec![
|
let mut accounts = vec![
|
||||||
AccountMeta::new(*token_account, false),
|
AccountMeta::new(*token_account, false),
|
||||||
AccountMeta::new_readonly(*authority, multisig_signers.is_empty()),
|
AccountMeta::new_readonly(*authority, multisig_signers.is_empty()),
|
||||||
|
@ -669,20 +718,23 @@ pub fn enable_balance_credits(
|
||||||
accounts.push(AccountMeta::new_readonly(**multisig_signer, true));
|
accounts.push(AccountMeta::new_readonly(**multisig_signer, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
vec![encode_instruction(
|
Ok(vec![encode_instruction(
|
||||||
|
token_program_id,
|
||||||
accounts,
|
accounts,
|
||||||
ConfidentialTransferInstruction::EnableBalanceCredits,
|
ConfidentialTransferInstruction::EnableBalanceCredits,
|
||||||
&(),
|
&(),
|
||||||
)]
|
)])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a `DisableBalanceCredits` instruction
|
/// Create a `DisableBalanceCredits` instruction
|
||||||
#[cfg(not(target_arch = "bpf"))]
|
#[cfg(not(target_arch = "bpf"))]
|
||||||
pub fn disable_balance_credits(
|
pub fn disable_balance_credits(
|
||||||
|
token_program_id: &Pubkey,
|
||||||
token_account: &Pubkey,
|
token_account: &Pubkey,
|
||||||
authority: &Pubkey,
|
authority: &Pubkey,
|
||||||
multisig_signers: &[&Pubkey],
|
multisig_signers: &[&Pubkey],
|
||||||
) -> Vec<Instruction> {
|
) -> Result<Vec<Instruction>, ProgramError> {
|
||||||
|
check_program_account(token_program_id)?;
|
||||||
let mut accounts = vec![
|
let mut accounts = vec![
|
||||||
AccountMeta::new(*token_account, false),
|
AccountMeta::new(*token_account, false),
|
||||||
AccountMeta::new_readonly(*authority, multisig_signers.is_empty()),
|
AccountMeta::new_readonly(*authority, multisig_signers.is_empty()),
|
||||||
|
@ -692,9 +744,10 @@ pub fn disable_balance_credits(
|
||||||
accounts.push(AccountMeta::new_readonly(**multisig_signer, true));
|
accounts.push(AccountMeta::new_readonly(**multisig_signer, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
vec![encode_instruction(
|
Ok(vec![encode_instruction(
|
||||||
|
token_program_id,
|
||||||
accounts,
|
accounts,
|
||||||
ConfidentialTransferInstruction::DisableBalanceCredits,
|
ConfidentialTransferInstruction::DisableBalanceCredits,
|
||||||
&(),
|
&(),
|
||||||
)]
|
)])
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use {
|
use {
|
||||||
crate::{error::TokenError, id, instruction::TokenInstruction},
|
crate::{check_program_account, error::TokenError, instruction::TokenInstruction},
|
||||||
solana_program::{
|
solana_program::{
|
||||||
instruction::{AccountMeta, Instruction},
|
instruction::{AccountMeta, Instruction},
|
||||||
program_error::ProgramError,
|
program_error::ProgramError,
|
||||||
|
@ -256,12 +256,14 @@ impl TransferFeeInstruction {
|
||||||
|
|
||||||
/// Create a `InitializeTransferFeeConfig` instruction
|
/// Create a `InitializeTransferFeeConfig` instruction
|
||||||
pub fn initialize_transfer_fee_config(
|
pub fn initialize_transfer_fee_config(
|
||||||
|
token_program_id: &Pubkey,
|
||||||
mint: &Pubkey,
|
mint: &Pubkey,
|
||||||
transfer_fee_config_authority: Option<&Pubkey>,
|
transfer_fee_config_authority: Option<&Pubkey>,
|
||||||
withdraw_withheld_authority: Option<&Pubkey>,
|
withdraw_withheld_authority: Option<&Pubkey>,
|
||||||
transfer_fee_basis_points: u16,
|
transfer_fee_basis_points: u16,
|
||||||
maximum_fee: u64,
|
maximum_fee: u64,
|
||||||
) -> Instruction {
|
) -> Result<Instruction, ProgramError> {
|
||||||
|
check_program_account(token_program_id)?;
|
||||||
let transfer_fee_config_authority = transfer_fee_config_authority.cloned().into();
|
let transfer_fee_config_authority = transfer_fee_config_authority.cloned().into();
|
||||||
let withdraw_withheld_authority = withdraw_withheld_authority.cloned().into();
|
let withdraw_withheld_authority = withdraw_withheld_authority.cloned().into();
|
||||||
let data = TokenInstruction::TransferFeeExtension(
|
let data = TokenInstruction::TransferFeeExtension(
|
||||||
|
@ -274,16 +276,17 @@ pub fn initialize_transfer_fee_config(
|
||||||
)
|
)
|
||||||
.pack();
|
.pack();
|
||||||
|
|
||||||
Instruction {
|
Ok(Instruction {
|
||||||
program_id: id(),
|
program_id: *token_program_id,
|
||||||
accounts: vec![AccountMeta::new(*mint, false)],
|
accounts: vec![AccountMeta::new(*mint, false)],
|
||||||
data,
|
data,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a `TransferCheckedWithFee` instruction
|
/// Create a `TransferCheckedWithFee` instruction
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn transfer_checked_with_fee(
|
pub fn transfer_checked_with_fee(
|
||||||
|
token_program_id: &Pubkey,
|
||||||
source: &Pubkey,
|
source: &Pubkey,
|
||||||
mint: &Pubkey,
|
mint: &Pubkey,
|
||||||
destination: &Pubkey,
|
destination: &Pubkey,
|
||||||
|
@ -292,7 +295,8 @@ pub fn transfer_checked_with_fee(
|
||||||
amount: u64,
|
amount: u64,
|
||||||
decimals: u8,
|
decimals: u8,
|
||||||
fee: u64,
|
fee: u64,
|
||||||
) -> Instruction {
|
) -> Result<Instruction, ProgramError> {
|
||||||
|
check_program_account(token_program_id)?;
|
||||||
let data =
|
let data =
|
||||||
TokenInstruction::TransferFeeExtension(TransferFeeInstruction::TransferCheckedWithFee {
|
TokenInstruction::TransferFeeExtension(TransferFeeInstruction::TransferCheckedWithFee {
|
||||||
amount,
|
amount,
|
||||||
|
@ -310,20 +314,22 @@ pub fn transfer_checked_with_fee(
|
||||||
accounts.push(AccountMeta::new_readonly(**signer, true));
|
accounts.push(AccountMeta::new_readonly(**signer, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction {
|
Ok(Instruction {
|
||||||
program_id: id(),
|
program_id: *token_program_id,
|
||||||
accounts,
|
accounts,
|
||||||
data,
|
data,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a `WithdrawWithheldTokensFromMint` instruction
|
/// Creates a `WithdrawWithheldTokensFromMint` instruction
|
||||||
pub fn withdraw_withheld_tokens_from_mint(
|
pub fn withdraw_withheld_tokens_from_mint(
|
||||||
|
token_program_id: &Pubkey,
|
||||||
mint: &Pubkey,
|
mint: &Pubkey,
|
||||||
destination: &Pubkey,
|
destination: &Pubkey,
|
||||||
authority: &Pubkey,
|
authority: &Pubkey,
|
||||||
signers: &[&Pubkey],
|
signers: &[&Pubkey],
|
||||||
) -> Instruction {
|
) -> Result<Instruction, ProgramError> {
|
||||||
|
check_program_account(token_program_id)?;
|
||||||
let mut accounts = Vec::with_capacity(3 + signers.len());
|
let mut accounts = Vec::with_capacity(3 + signers.len());
|
||||||
accounts.push(AccountMeta::new(*mint, false));
|
accounts.push(AccountMeta::new(*mint, false));
|
||||||
accounts.push(AccountMeta::new(*destination, false));
|
accounts.push(AccountMeta::new(*destination, false));
|
||||||
|
@ -332,24 +338,26 @@ pub fn withdraw_withheld_tokens_from_mint(
|
||||||
accounts.push(AccountMeta::new_readonly(**signer, true));
|
accounts.push(AccountMeta::new_readonly(**signer, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction {
|
Ok(Instruction {
|
||||||
program_id: id(),
|
program_id: *token_program_id,
|
||||||
accounts,
|
accounts,
|
||||||
data: TokenInstruction::TransferFeeExtension(
|
data: TokenInstruction::TransferFeeExtension(
|
||||||
TransferFeeInstruction::WithdrawWithheldTokensFromMint,
|
TransferFeeInstruction::WithdrawWithheldTokensFromMint,
|
||||||
)
|
)
|
||||||
.pack(),
|
.pack(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a `WithdrawWithheldTokensFromAccounts` instruction
|
/// Creates a `WithdrawWithheldTokensFromAccounts` instruction
|
||||||
pub fn withdraw_withheld_tokens_from_accounts(
|
pub fn withdraw_withheld_tokens_from_accounts(
|
||||||
|
token_program_id: &Pubkey,
|
||||||
mint: &Pubkey,
|
mint: &Pubkey,
|
||||||
destination: &Pubkey,
|
destination: &Pubkey,
|
||||||
authority: &Pubkey,
|
authority: &Pubkey,
|
||||||
signers: &[&Pubkey],
|
signers: &[&Pubkey],
|
||||||
sources: &[&Pubkey],
|
sources: &[&Pubkey],
|
||||||
) -> Instruction {
|
) -> Result<Instruction, ProgramError> {
|
||||||
|
check_program_account(token_program_id)?;
|
||||||
let mut accounts = Vec::with_capacity(3 + signers.len() + sources.len());
|
let mut accounts = Vec::with_capacity(3 + signers.len() + sources.len());
|
||||||
accounts.push(AccountMeta::new_readonly(*mint, false));
|
accounts.push(AccountMeta::new_readonly(*mint, false));
|
||||||
accounts.push(AccountMeta::new(*destination, false));
|
accounts.push(AccountMeta::new(*destination, false));
|
||||||
|
@ -361,41 +369,48 @@ pub fn withdraw_withheld_tokens_from_accounts(
|
||||||
accounts.push(AccountMeta::new(**source, false));
|
accounts.push(AccountMeta::new(**source, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction {
|
Ok(Instruction {
|
||||||
program_id: id(),
|
program_id: *token_program_id,
|
||||||
accounts,
|
accounts,
|
||||||
data: TokenInstruction::TransferFeeExtension(
|
data: TokenInstruction::TransferFeeExtension(
|
||||||
TransferFeeInstruction::WithdrawWithheldTokensFromAccounts,
|
TransferFeeInstruction::WithdrawWithheldTokensFromAccounts,
|
||||||
)
|
)
|
||||||
.pack(),
|
.pack(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a `HarvestWithheldTokensToMint` instruction
|
/// Creates a `HarvestWithheldTokensToMint` instruction
|
||||||
pub fn harvest_withheld_tokens_to_mint(mint: &Pubkey, sources: &[&Pubkey]) -> Instruction {
|
pub fn harvest_withheld_tokens_to_mint(
|
||||||
|
token_program_id: &Pubkey,
|
||||||
|
mint: &Pubkey,
|
||||||
|
sources: &[&Pubkey],
|
||||||
|
) -> Result<Instruction, ProgramError> {
|
||||||
|
check_program_account(token_program_id)?;
|
||||||
let mut accounts = Vec::with_capacity(1 + sources.len());
|
let mut accounts = Vec::with_capacity(1 + sources.len());
|
||||||
accounts.push(AccountMeta::new(*mint, false));
|
accounts.push(AccountMeta::new(*mint, false));
|
||||||
for source in sources.iter() {
|
for source in sources.iter() {
|
||||||
accounts.push(AccountMeta::new(**source, false));
|
accounts.push(AccountMeta::new(**source, false));
|
||||||
}
|
}
|
||||||
Instruction {
|
Ok(Instruction {
|
||||||
program_id: id(),
|
program_id: *token_program_id,
|
||||||
accounts,
|
accounts,
|
||||||
data: TokenInstruction::TransferFeeExtension(
|
data: TokenInstruction::TransferFeeExtension(
|
||||||
TransferFeeInstruction::HarvestWithheldTokensToMint,
|
TransferFeeInstruction::HarvestWithheldTokensToMint,
|
||||||
)
|
)
|
||||||
.pack(),
|
.pack(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a `SetTransferFee` instruction
|
/// Creates a `SetTransferFee` instruction
|
||||||
pub fn set_transfer_fee(
|
pub fn set_transfer_fee(
|
||||||
|
token_program_id: &Pubkey,
|
||||||
mint: &Pubkey,
|
mint: &Pubkey,
|
||||||
authority: &Pubkey,
|
authority: &Pubkey,
|
||||||
signers: &[&Pubkey],
|
signers: &[&Pubkey],
|
||||||
transfer_fee_basis_points: u16,
|
transfer_fee_basis_points: u16,
|
||||||
maximum_fee: u64,
|
maximum_fee: u64,
|
||||||
) -> Instruction {
|
) -> Result<Instruction, ProgramError> {
|
||||||
|
check_program_account(token_program_id)?;
|
||||||
let mut accounts = Vec::with_capacity(2 + signers.len());
|
let mut accounts = Vec::with_capacity(2 + signers.len());
|
||||||
accounts.push(AccountMeta::new(*mint, false));
|
accounts.push(AccountMeta::new(*mint, false));
|
||||||
accounts.push(AccountMeta::new_readonly(*authority, signers.is_empty()));
|
accounts.push(AccountMeta::new_readonly(*authority, signers.is_empty()));
|
||||||
|
@ -403,15 +418,15 @@ pub fn set_transfer_fee(
|
||||||
accounts.push(AccountMeta::new_readonly(**signer, true));
|
accounts.push(AccountMeta::new_readonly(**signer, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction {
|
Ok(Instruction {
|
||||||
program_id: id(),
|
program_id: *token_program_id,
|
||||||
accounts,
|
accounts,
|
||||||
data: TokenInstruction::TransferFeeExtension(TransferFeeInstruction::SetTransferFee {
|
data: TokenInstruction::TransferFeeExtension(TransferFeeInstruction::SetTransferFee {
|
||||||
transfer_fee_basis_points,
|
transfer_fee_basis_points,
|
||||||
maximum_fee,
|
maximum_fee,
|
||||||
})
|
})
|
||||||
.pack(),
|
.pack(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -6615,7 +6615,8 @@ mod tests {
|
||||||
);
|
);
|
||||||
let extended_mint_key = Pubkey::new_unique();
|
let extended_mint_key = Pubkey::new_unique();
|
||||||
do_process_instruction(
|
do_process_instruction(
|
||||||
initialize_transfer_fee_config(&extended_mint_key, None, None, 10, 4242),
|
initialize_transfer_fee_config(&program_id, &extended_mint_key, None, None, 10, 4242)
|
||||||
|
.unwrap(),
|
||||||
vec![&mut extended_mint_account],
|
vec![&mut extended_mint_account],
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
|
@ -177,12 +177,14 @@ async fn single_extension() {
|
||||||
&spl_token_2022::id(),
|
&spl_token_2022::id(),
|
||||||
),
|
),
|
||||||
transfer_fee::instruction::initialize_transfer_fee_config(
|
transfer_fee::instruction::initialize_transfer_fee_config(
|
||||||
|
&spl_token_2022::id(),
|
||||||
&mint_account.pubkey(),
|
&mint_account.pubkey(),
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
10,
|
10,
|
||||||
4242,
|
4242,
|
||||||
),
|
)
|
||||||
|
.unwrap(),
|
||||||
instruction::initialize_mint(
|
instruction::initialize_mint(
|
||||||
&spl_token_2022::id(),
|
&spl_token_2022::id(),
|
||||||
&mint_account.pubkey(),
|
&mint_account.pubkey(),
|
||||||
|
|
|
@ -441,12 +441,14 @@ async fn fail_fee_init_after_mint_init() {
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
transfer_fee::instruction::initialize_transfer_fee_config(
|
transfer_fee::instruction::initialize_transfer_fee_config(
|
||||||
|
&spl_token_2022::id(),
|
||||||
&mint_account.pubkey(),
|
&mint_account.pubkey(),
|
||||||
Some(&Pubkey::new_unique()),
|
Some(&Pubkey::new_unique()),
|
||||||
Some(&Pubkey::new_unique()),
|
Some(&Pubkey::new_unique()),
|
||||||
10,
|
10,
|
||||||
100,
|
100,
|
||||||
),
|
)
|
||||||
|
.unwrap(),
|
||||||
];
|
];
|
||||||
|
|
||||||
let tx = Transaction::new_signed_with_payer(
|
let tx = Transaction::new_signed_with_payer(
|
||||||
|
|
|
@ -69,11 +69,18 @@ impl ExtensionInitializationParams {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Generate an appropriate initialization instruction for the given mint
|
/// Generate an appropriate initialization instruction for the given mint
|
||||||
pub fn instruction(self, mint: &Pubkey) -> Instruction {
|
pub fn instruction(
|
||||||
|
self,
|
||||||
|
token_program_id: &Pubkey,
|
||||||
|
mint: &Pubkey,
|
||||||
|
) -> Result<Instruction, ProgramError> {
|
||||||
match self {
|
match self {
|
||||||
Self::MintCloseAuthority { close_authority } => {
|
Self::MintCloseAuthority { close_authority } => {
|
||||||
instruction::initialize_mint_close_authority(&id(), mint, close_authority.as_ref())
|
instruction::initialize_mint_close_authority(
|
||||||
.unwrap()
|
token_program_id,
|
||||||
|
mint,
|
||||||
|
close_authority.as_ref(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Self::TransferFeeConfig {
|
Self::TransferFeeConfig {
|
||||||
transfer_fee_config_authority,
|
transfer_fee_config_authority,
|
||||||
|
@ -81,6 +88,7 @@ impl ExtensionInitializationParams {
|
||||||
transfer_fee_basis_points,
|
transfer_fee_basis_points,
|
||||||
maximum_fee,
|
maximum_fee,
|
||||||
} => transfer_fee::instruction::initialize_transfer_fee_config(
|
} => transfer_fee::instruction::initialize_transfer_fee_config(
|
||||||
|
token_program_id,
|
||||||
mint,
|
mint,
|
||||||
transfer_fee_config_authority.as_ref(),
|
transfer_fee_config_authority.as_ref(),
|
||||||
withdraw_withheld_authority.as_ref(),
|
withdraw_withheld_authority.as_ref(),
|
||||||
|
@ -189,11 +197,9 @@ where
|
||||||
space as u64,
|
space as u64,
|
||||||
&id(),
|
&id(),
|
||||||
)];
|
)];
|
||||||
let mut init_instructions = extension_initialization_params
|
for params in extension_initialization_params {
|
||||||
.into_iter()
|
instructions.push(params.instruction(&id(), &mint_pubkey)?);
|
||||||
.map(|e| e.instruction(&mint_pubkey))
|
}
|
||||||
.collect::<Vec<_>>();
|
|
||||||
instructions.append(&mut init_instructions);
|
|
||||||
instructions.push(instruction::initialize_mint(
|
instructions.push(instruction::initialize_mint(
|
||||||
&id(),
|
&id(),
|
||||||
&mint_pubkey,
|
&mint_pubkey,
|
||||||
|
|
Loading…
Reference in New Issue