@@ -2,6 +2,7 @@ use crate::client::{ProgramClient, ProgramClientError, SendTransaction};
2
2
use solana_program_test:: tokio:: time;
3
3
use solana_sdk:: {
4
4
account:: Account as BaseAccount ,
5
+ epoch_info:: EpochInfo ,
5
6
hash:: Hash ,
6
7
instruction:: Instruction ,
7
8
program_error:: ProgramError ,
@@ -22,6 +23,7 @@ use spl_token_2022::{
22
23
solana_zk_token_sdk:: {
23
24
encryption:: { auth_encryption:: * , elgamal:: * } ,
24
25
errors:: ProofError ,
26
+ instruction:: transfer_with_fee:: FeeParameters ,
25
27
} ,
26
28
state:: { Account , AccountState , Mint } ,
27
29
} ;
@@ -1148,6 +1150,80 @@ where
1148
1150
. await
1149
1151
}
1150
1152
1153
+ /// Transfer tokens confidentially with fee
1154
+ #[ allow( clippy:: too_many_arguments) ]
1155
+ pub async fn confidential_transfer_transfer_with_fee < S2 : Signer > (
1156
+ & self ,
1157
+ source_token_account : & Pubkey ,
1158
+ destination_token_account : & Pubkey ,
1159
+ source_token_authority : & S2 ,
1160
+ amount : u64 ,
1161
+ source_available_balance : u64 ,
1162
+ source_elgamal_keypair : & ElGamalKeypair ,
1163
+ new_source_decryptable_available_balance : AeCiphertext ,
1164
+ epoch_info : & EpochInfo ,
1165
+ ) -> TokenResult < T :: Output > {
1166
+ let source_state = self . get_account_info ( source_token_account) . await . unwrap ( ) ;
1167
+ let source_extension =
1168
+ source_state. get_extension :: < confidential_transfer:: ConfidentialTransferAccount > ( ) ?;
1169
+
1170
+ let destination_state = self
1171
+ . get_account_info ( destination_token_account)
1172
+ . await
1173
+ . unwrap ( ) ;
1174
+ let destination_extension = destination_state
1175
+ . get_extension :: < confidential_transfer:: ConfidentialTransferAccount > (
1176
+ ) ?;
1177
+
1178
+ let mint_state = self . get_mint_info ( ) . await . unwrap ( ) ;
1179
+ let transfer_fee_config = mint_state
1180
+ . get_extension :: < transfer_fee:: TransferFeeConfig > ( )
1181
+ . unwrap ( ) ;
1182
+
1183
+ let fee_parameters = transfer_fee_config. get_epoch_fee ( epoch_info. epoch ) ;
1184
+
1185
+ let ct_mint = mint_state
1186
+ . get_extension :: < confidential_transfer:: ConfidentialTransferMint > ( )
1187
+ . unwrap ( ) ;
1188
+
1189
+ let proof_data = confidential_transfer:: instruction:: TransferWithFeeData :: new (
1190
+ amount,
1191
+ (
1192
+ source_available_balance,
1193
+ & source_extension. available_balance . try_into ( ) . unwrap ( ) ,
1194
+ ) ,
1195
+ source_elgamal_keypair,
1196
+ (
1197
+ & destination_extension. encryption_pubkey . try_into ( ) . unwrap ( ) ,
1198
+ & ct_mint. auditor_pubkey . try_into ( ) . unwrap ( ) ,
1199
+ ) ,
1200
+ FeeParameters {
1201
+ fee_rate_basis_points : u16:: from ( fee_parameters. transfer_fee_basis_points ) ,
1202
+ maximum_fee : u64:: from ( fee_parameters. maximum_fee ) ,
1203
+ } ,
1204
+ & ct_mint
1205
+ . withdraw_withheld_authority_pubkey
1206
+ . try_into ( )
1207
+ . unwrap ( ) ,
1208
+ )
1209
+ . map_err ( TokenError :: Proof ) ?;
1210
+
1211
+ self . process_ixs (
1212
+ & confidential_transfer:: instruction:: transfer_with_fee (
1213
+ & self . program_id ,
1214
+ source_token_account,
1215
+ destination_token_account,
1216
+ & self . pubkey ,
1217
+ new_source_decryptable_available_balance,
1218
+ & source_token_authority. pubkey ( ) ,
1219
+ & [ ] ,
1220
+ & proof_data,
1221
+ ) ?,
1222
+ & [ source_token_authority] ,
1223
+ )
1224
+ . await
1225
+ }
1226
+
1151
1227
/// Applies the confidential transfer pending balance to the available balance
1152
1228
pub async fn confidential_transfer_apply_pending_balance < S2 : Signer > (
1153
1229
& self ,
0 commit comments