1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
//! This code was AUTOGENERATED using the Codama library.
use {
crate::types::DecryptableBalance,
carbon_core::{account_utils::next_account, deserialize::ArrangeAccounts},
};
/// Transfer tokens confidentially with fee.
/// In order for this instruction to be successfully processed, it must be
/// accompanied by the following list of `zk_elgamal_proof` program
/// instructions:
/// - `VerifyCiphertextCommitmentEquality`
/// - `VerifyBatchedGroupedCiphertext3HandlesValidity` (transfer amount
///
/// ciphertext)
/// - `VerifyPercentageWithFee`
/// - `VerifyBatchedGroupedCiphertext2HandlesValidity` (fee ciphertext)
/// - `VerifyBatchedRangeProofU256`
///
/// These instructions can be accompanied in the same transaction or can be
/// pre-verified into a context state account, in which case, only their
/// context state account addresses need to be provided.
/// The same restrictions for the `Transfer` applies to
/// `TransferWithFee`. Namely, the instruction fails if the
/// associated mint is extended as `NonTransferable`.
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, borsh::BorshSerialize, borsh::BorshDeserialize, PartialEq)]
pub struct ConfidentialTransferWithFee {
/// The new source decryptable balance if the transfer succeeds.
pub new_source_decryptable_available_balance: DecryptableBalance,
/// Relative location of the
/// `ProofInstruction::VerifyCiphertextCommitmentEquality` instruction
/// to the `TransferWithFee` instruction in the transaction. If the offset
/// is `0`, then use a context state account for the proof.
pub equality_proof_instruction_offset: i8,
/// Relative location of the
/// `ProofInstruction::VerifyBatchedGroupedCiphertext3HandlesValidity`
/// instruction to the `TransferWithFee` instruction in the transaction.
/// If the offset is `0`, then use a context state account for the
/// proof.
pub transfer_amount_ciphertext_validity_proof_instruction_offset: i8,
/// Relative location of the `ProofInstruction::VerifyPercentageWithFee`
/// instruction to the `TransferWithFee` instruction in the transaction.
/// If the offset is `0`, then use a context state account for the
/// proof.
pub fee_sigma_proof_instruction_offset: i8,
/// Relative location of the
/// `ProofInstruction::VerifyBatchedGroupedCiphertext2HandlesValidity`
/// instruction to the `TransferWithFee` instruction in the transaction.
/// If the offset is `0`, then use a context state account for the
/// proof.
pub fee_ciphertext_validity_proof_instruction_offset: i8,
/// Relative location of the `ProofInstruction::BatchedRangeProofU256Data`
/// instruction to the `TransferWithFee` instruction in the transaction.
/// If the offset is `0`, then use a context state account for the
/// proof.
pub range_proof_instruction_offset: i8,
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ConfidentialTransferWithFeeInstructionAccounts {
pub source_token: solana_pubkey::Pubkey,
pub mint: solana_pubkey::Pubkey,
pub destination_token: solana_pubkey::Pubkey,
pub instructions_sysvar: Option<solana_pubkey::Pubkey>,
pub equality_record: Option<solana_pubkey::Pubkey>,
pub transfer_amount_ciphertext_validity_record: Option<solana_pubkey::Pubkey>,
pub fee_sigma_record: Option<solana_pubkey::Pubkey>,
pub fee_ciphertext_validity_record: Option<solana_pubkey::Pubkey>,
pub range_record: Option<solana_pubkey::Pubkey>,
pub authority: solana_pubkey::Pubkey,
pub remaining: Vec<solana_instruction::AccountMeta>,
}
impl ConfidentialTransferWithFee {
pub fn decode(data: &[u8]) -> Option<Self> {
if data.len() < 2 {
return None;
}
let discriminator = data[0];
if discriminator != 27 {
return None;
}
let confidential_transfer_discriminator = data[1];
if confidential_transfer_discriminator != 13 {
return None;
}
let mut data_slice = data;
data_slice = &data_slice[1..];
borsh::BorshDeserialize::deserialize(&mut data_slice).ok()
}
}
impl ArrangeAccounts for ConfidentialTransferWithFee {
type ArrangedAccounts = ConfidentialTransferWithFeeInstructionAccounts;
fn arrange_accounts(
accounts: &[solana_instruction::AccountMeta],
) -> Option<Self::ArrangedAccounts> {
let mut iter = accounts.iter();
let source_token = next_account(&mut iter)?;
let mint = next_account(&mut iter)?;
let destination_token = next_account(&mut iter)?;
let instructions_sysvar = next_account(&mut iter);
let equality_record = next_account(&mut iter);
let transfer_amount_ciphertext_validity_record = next_account(&mut iter);
let fee_sigma_record = next_account(&mut iter);
let fee_ciphertext_validity_record = next_account(&mut iter);
let range_record = next_account(&mut iter);
let authority = next_account(&mut iter)?;
let remaining = iter.as_slice();
Some(ConfidentialTransferWithFeeInstructionAccounts {
source_token,
mint,
destination_token,
instructions_sysvar,
equality_record,
transfer_amount_ciphertext_validity_record,
fee_sigma_record,
fee_ciphertext_validity_record,
range_record,
authority,
remaining: remaining.to_vec(),
})
}
}