@@ -44,11 +44,16 @@ use {
4444 client:: {
4545 ProgramClient , ProgramOfflineClient , ProgramRpcClient , ProgramRpcClientSendTransaction ,
4646 } ,
47- token:: Token ,
47+ token:: { ComputeUnitLimit , Token } ,
4848 } ,
4949 spl_token_group_interface:: state:: { TokenGroup , TokenGroupMember } ,
5050 spl_token_metadata_interface:: state:: TokenMetadata ,
51- std:: { ffi:: OsString , path:: PathBuf , str:: FromStr , sync:: Arc } ,
51+ std:: {
52+ ffi:: { OsStr , OsString } ,
53+ path:: PathBuf ,
54+ str:: FromStr ,
55+ sync:: Arc ,
56+ } ,
5257 tempfile:: NamedTempFile ,
5358} ;
5459
@@ -201,7 +206,7 @@ fn test_config_with_default_signer<'a>(
201206 program_id : * program_id,
202207 restrict_to_program_id : true ,
203208 compute_unit_price : None ,
204- compute_unit_limit : None ,
209+ compute_unit_limit : ComputeUnitLimit :: Simulated ,
205210 }
206211}
207212
@@ -230,7 +235,7 @@ fn test_config_without_default_signer<'a>(
230235 program_id : * program_id,
231236 restrict_to_program_id : true ,
232237 compute_unit_price : None ,
233- compute_unit_limit : None ,
238+ compute_unit_limit : ComputeUnitLimit :: Simulated ,
234239 }
235240}
236241
@@ -441,7 +446,7 @@ where
441446 process_command ( & sub_command, matches, config, wallet_manager, bulk_signers) . await
442447}
443448
444- async fn exec_test_cmd ( config : & Config < ' _ > , args : & [ & str ] ) -> CommandResult {
449+ async fn exec_test_cmd < T : AsRef < OsStr > > ( config : & Config < ' _ > , args : & [ T ] ) -> CommandResult {
445450 let default_decimals = format ! ( "{}" , spl_token_2022:: native_mint:: DECIMALS ) ;
446451 let minimum_signers_help = minimum_signers_help_string ( ) ;
447452 let multisig_member_help = multisig_member_help_string ( ) ;
@@ -2974,10 +2979,17 @@ async fn multisig_transfer(test_validator: &TestValidator, payer: &Keypair) {
29742979 }
29752980}
29762981
2977- async fn offline_multisig_transfer_with_nonce ( test_validator : & TestValidator , payer : & Keypair ) {
2982+ async fn do_offline_multisig_transfer (
2983+ test_validator : & TestValidator ,
2984+ payer : & Keypair ,
2985+ compute_unit_price : Option < u64 > ,
2986+ ) {
29782987 let m = 2 ;
29792988 let n = 3u8 ;
29802989
2990+ let fee_payer_keypair_file = NamedTempFile :: new ( ) . unwrap ( ) ;
2991+ write_keypair_file ( payer, & fee_payer_keypair_file) . unwrap ( ) ;
2992+
29812993 let ( multisig_members, multisig_paths) : ( Vec < _ > , Vec < _ > ) = std:: iter:: repeat_with ( Keypair :: new)
29822994 . take ( n as usize )
29832995 . map ( |s| {
@@ -2988,6 +3000,7 @@ async fn offline_multisig_transfer_with_nonce(test_validator: &TestValidator, pa
29883000 . unzip ( ) ;
29893001 for program_id in VALID_TOKEN_PROGRAM_IDS . iter ( ) {
29903002 let mut config = test_config_with_default_signer ( test_validator, payer, program_id) ;
3003+ config. compute_unit_limit = ComputeUnitLimit :: Default ;
29913004 let token = create_token ( & config, payer) . await ;
29923005 let nonce = create_nonce ( & config, payer) . await ;
29933006
@@ -3032,58 +3045,121 @@ async fn offline_multisig_transfer_with_nonce(test_validator: &TestValidator, pa
30323045 let program_client: Arc < dyn ProgramClient < ProgramRpcClientSendTransaction > > = Arc :: new (
30333046 ProgramOfflineClient :: new ( blockhash, ProgramRpcClientSendTransaction ) ,
30343047 ) ;
3048+ let mut args = vec ! [
3049+ "spl-token" . to_string( ) ,
3050+ CommandName :: Transfer . as_ref( ) . to_string( ) ,
3051+ token. to_string( ) ,
3052+ "10" . to_string( ) ,
3053+ destination. to_string( ) ,
3054+ "--blockhash" . to_string( ) ,
3055+ blockhash. to_string( ) ,
3056+ "--nonce" . to_string( ) ,
3057+ nonce. to_string( ) ,
3058+ "--nonce-authority" . to_string( ) ,
3059+ payer. pubkey( ) . to_string( ) ,
3060+ "--sign-only" . to_string( ) ,
3061+ "--mint-decimals" . to_string( ) ,
3062+ format!( "{}" , TEST_DECIMALS ) ,
3063+ "--multisig-signer" . to_string( ) ,
3064+ multisig_paths[ 1 ] . path( ) . to_str( ) . unwrap( ) . to_string( ) ,
3065+ "--multisig-signer" . to_string( ) ,
3066+ multisig_members[ 2 ] . to_string( ) ,
3067+ "--from" . to_string( ) ,
3068+ source. to_string( ) ,
3069+ "--owner" . to_string( ) ,
3070+ multisig_pubkey. to_string( ) ,
3071+ "--fee-payer" . to_string( ) ,
3072+ payer. pubkey( ) . to_string( ) ,
3073+ "--program-id" . to_string( ) ,
3074+ program_id. to_string( ) ,
3075+ ] ;
3076+ if let Some ( compute_unit_price) = compute_unit_price {
3077+ args. push ( "--with-compute-unit-price" . to_string ( ) ) ;
3078+ args. push ( compute_unit_price. to_string ( ) ) ;
3079+ args. push ( "--with-compute-unit-limit" . to_string ( ) ) ;
3080+ args. push ( 10_000 . to_string ( ) ) ;
3081+ }
30353082 config. program_client = program_client;
3036- let result = exec_test_cmd (
3037- & config,
3038- & [
3039- "spl-token" ,
3040- CommandName :: Transfer . into ( ) ,
3041- & token. to_string ( ) ,
3042- "10" ,
3043- & destination. to_string ( ) ,
3044- "--blockhash" ,
3045- & blockhash. to_string ( ) ,
3046- "--nonce" ,
3047- & nonce. to_string ( ) ,
3048- "--nonce-authority" ,
3049- & payer. pubkey ( ) . to_string ( ) ,
3050- "--sign-only" ,
3051- "--mint-decimals" ,
3052- & format ! ( "{}" , TEST_DECIMALS ) ,
3053- "--multisig-signer" ,
3054- multisig_paths[ 1 ] . path ( ) . to_str ( ) . unwrap ( ) ,
3055- "--multisig-signer" ,
3056- & multisig_members[ 2 ] . to_string ( ) ,
3057- "--from" ,
3058- & source. to_string ( ) ,
3059- "--owner" ,
3060- & multisig_pubkey. to_string ( ) ,
3061- "--fee-payer" ,
3062- & multisig_members[ 0 ] . to_string ( ) ,
3063- ] ,
3064- )
3065- . await
3066- . unwrap ( ) ;
3083+ let result = exec_test_cmd ( & config, & args) . await . unwrap ( ) ;
30673084 // the provided signer has a signature, denoted by the pubkey followed
30683085 // by "=" and the signature
3069- assert ! ( result. contains( & format!( "{}=" , multisig_members[ 1 ] ) ) ) ;
3086+ let member_prefix = format ! ( "{}=" , multisig_members[ 1 ] ) ;
3087+ let signature_position = result. find ( & member_prefix) . unwrap ( ) ;
3088+ let end_position = result[ signature_position..] . find ( '\n' ) . unwrap ( ) ;
3089+ let signer = result[ signature_position..] . get ( ..end_position) . unwrap ( ) ;
30703090
30713091 // other three expected signers are absent
30723092 let absent_signers_position = result. find ( "Absent Signers" ) . unwrap ( ) ;
30733093 let absent_signers = result. get ( absent_signers_position..) . unwrap ( ) ;
3074- assert ! ( absent_signers. contains( & multisig_members[ 0 ] . to_string( ) ) ) ;
30753094 assert ! ( absent_signers. contains( & multisig_members[ 2 ] . to_string( ) ) ) ;
30763095 assert ! ( absent_signers. contains( & payer. pubkey( ) . to_string( ) ) ) ;
30773096
30783097 // and nothing else is marked a signer
3098+ assert ! ( !absent_signers. contains( & multisig_members[ 0 ] . to_string( ) ) ) ;
30793099 assert ! ( !absent_signers. contains( & multisig_pubkey. to_string( ) ) ) ;
30803100 assert ! ( !absent_signers. contains( & nonce. to_string( ) ) ) ;
30813101 assert ! ( !absent_signers. contains( & source. to_string( ) ) ) ;
30823102 assert ! ( !absent_signers. contains( & destination. to_string( ) ) ) ;
30833103 assert ! ( !absent_signers. contains( & token. to_string( ) ) ) ;
3104+
3105+ // now send the transaction
3106+ let program_client: Arc < dyn ProgramClient < ProgramRpcClientSendTransaction > > = Arc :: new (
3107+ ProgramRpcClient :: new ( config. rpc_client . clone ( ) , ProgramRpcClientSendTransaction ) ,
3108+ ) ;
3109+ config. program_client = program_client;
3110+ let mut args = vec ! [
3111+ "spl-token" . to_string( ) ,
3112+ CommandName :: Transfer . as_ref( ) . to_string( ) ,
3113+ token. to_string( ) ,
3114+ "10" . to_string( ) ,
3115+ destination. to_string( ) ,
3116+ "--blockhash" . to_string( ) ,
3117+ blockhash. to_string( ) ,
3118+ "--nonce" . to_string( ) ,
3119+ nonce. to_string( ) ,
3120+ "--nonce-authority" . to_string( ) ,
3121+ fee_payer_keypair_file. path( ) . to_str( ) . unwrap( ) . to_string( ) ,
3122+ "--mint-decimals" . to_string( ) ,
3123+ format!( "{}" , TEST_DECIMALS ) ,
3124+ "--multisig-signer" . to_string( ) ,
3125+ multisig_members[ 1 ] . to_string( ) ,
3126+ "--multisig-signer" . to_string( ) ,
3127+ multisig_paths[ 2 ] . path( ) . to_str( ) . unwrap( ) . to_string( ) ,
3128+ "--from" . to_string( ) ,
3129+ source. to_string( ) ,
3130+ "--owner" . to_string( ) ,
3131+ multisig_pubkey. to_string( ) ,
3132+ "--fee-payer" . to_string( ) ,
3133+ fee_payer_keypair_file. path( ) . to_str( ) . unwrap( ) . to_string( ) ,
3134+ "--program-id" . to_string( ) ,
3135+ program_id. to_string( ) ,
3136+ "--signer" . to_string( ) ,
3137+ signer. to_string( ) ,
3138+ ] ;
3139+ if let Some ( compute_unit_price) = compute_unit_price {
3140+ args. push ( "--with-compute-unit-price" . to_string ( ) ) ;
3141+ args. push ( compute_unit_price. to_string ( ) ) ;
3142+ args. push ( "--with-compute-unit-limit" . to_string ( ) ) ;
3143+ args. push ( 10_000 . to_string ( ) ) ;
3144+ }
3145+ exec_test_cmd ( & config, & args) . await . unwrap ( ) ;
3146+
3147+ let account = config. rpc_client . get_account ( & source) . await . unwrap ( ) ;
3148+ let token_account = StateWithExtensionsOwned :: < Account > :: unpack ( account. data ) . unwrap ( ) ;
3149+ let amount = spl_token:: ui_amount_to_amount ( 90.0 , TEST_DECIMALS ) ;
3150+ assert_eq ! ( token_account. base. amount, amount) ;
3151+ let account = config. rpc_client . get_account ( & destination) . await . unwrap ( ) ;
3152+ let token_account = StateWithExtensionsOwned :: < Account > :: unpack ( account. data ) . unwrap ( ) ;
3153+ let amount = spl_token:: ui_amount_to_amount ( 10.0 , TEST_DECIMALS ) ;
3154+ assert_eq ! ( token_account. base. amount, amount) ;
30843155 }
30853156}
30863157
3158+ async fn offline_multisig_transfer_with_nonce ( test_validator : & TestValidator , payer : & Keypair ) {
3159+ do_offline_multisig_transfer ( test_validator, payer, None ) . await ;
3160+ do_offline_multisig_transfer ( test_validator, payer, Some ( 10 ) ) . await ;
3161+ }
3162+
30873163async fn withdraw_excess_lamports_from_multisig ( test_validator : & TestValidator , payer : & Keypair ) {
30883164 let m = 3 ;
30893165 let n = 5u8 ;
@@ -4024,7 +4100,7 @@ async fn compute_budget(test_validator: &TestValidator, payer: &Keypair) {
40244100 for program_id in VALID_TOKEN_PROGRAM_IDS . iter ( ) {
40254101 let mut config = test_config_with_default_signer ( test_validator, payer, program_id) ;
40264102 config. compute_unit_price = Some ( 42 ) ;
4027- config. compute_unit_limit = Some ( 30_000 ) ;
4103+ config. compute_unit_limit = ComputeUnitLimit :: Static ( 30_000 ) ;
40284104 run_transfer_test ( & config, payer) . await ;
40294105 }
40304106}
0 commit comments