From d23565293fe614b962015e081d2c428b38a45e56 Mon Sep 17 00:00:00 2001 From: Hrushi20 Date: Fri, 26 Jul 2024 14:59:13 +0530 Subject: [PATCH 1/4] create transfer-fee-basis-points and transfer-fee-maximum-fee flags Signed-off-by: Hrushi20 --- token/cli/src/clap_app.rs | 23 ++++++++++++++++++ token/cli/src/command.rs | 43 +++++++++++++++++++++++++++++++-- token/cli/tests/command.rs | 49 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 113 insertions(+), 2 deletions(-) diff --git a/token/cli/src/clap_app.rs b/token/cli/src/clap_app.rs index 94d67ef87c7..ea25b97b92a 100644 --- a/token/cli/src/clap_app.rs +++ b/token/cli/src/clap_app.rs @@ -763,11 +763,34 @@ pub fn app<'a, 'b>( .value_names(&["FEE_IN_BASIS_POINTS", "MAXIMUM_FEE"]) .takes_value(true) .number_of_values(2) + .hidden(true) .help( "Add a transfer fee to the mint. \ The mint authority can set the fee and withdraw collected fees.", ), ) + .arg( + Arg::with_name("transfer_fee_basis_points") + .long("transfer-fee-basis-points") + .value_names(&["FEE_IN_BASIS_POINTS"]) + .takes_value(true) + .number_of_values(1) + .help( + "Add transfer fee to the mint. \ + The mint authority can set the fee.", + ), + ) + .arg( + Arg::with_name("transfer_fee_maximum_fee") + .long("transfer-fee-maximum-fee") + .value_names(&["MAXIMUM_FEE"]) + .takes_value(true) + .number_of_values(1) + .help( + "Add a UI amount transfer fee to the mint. \ + The mint authority can set the fee and collected fee" + ) + ) .arg( Arg::with_name("enable_permanent_delegate") .long("enable-permanent-delegate") diff --git a/token/cli/src/command.rs b/token/cli/src/command.rs index 82abe3910f7..295a8d9285d 100644 --- a/token/cli/src/command.rs +++ b/token/cli/src/command.rs @@ -62,8 +62,7 @@ use { encryption::{ auth_encryption::AeKey, elgamal::{self, ElGamalKeypair}, - }, - zk_token_elgamal::pod::ElGamalPubkey, + }, instruction::transfer, zk_token_elgamal::pod::ElGamalPubkey }, state::{Account, AccountState, Mint}, }, @@ -3472,6 +3471,7 @@ pub async fn process_command<'a>( let member_address = value_t!(arg_matches, "member_address", Pubkey).ok(); let transfer_fee = arg_matches.values_of("transfer_fee").map(|mut v| { + println_display(config,"transfer_fee flag has been deprecated".to_string()); ( v.next() .unwrap() @@ -3484,6 +3484,45 @@ pub async fn process_command<'a>( ) }); + let transfer_fee_basis_point = arg_matches.values_of("transfer_fee_basis_points").map(|mut v| { + v.next() + .unwrap() + .parse::() + .unwrap_or_else(print_error_and_exit) + }); + + let transfer_fee_maximum_fee = arg_matches.values_of("transfer_fee_maximum_fee").map(|mut v| { + v.next() + .unwrap() + .parse::() + .unwrap_or_else(print_error_and_exit) + }); + + let transfer_fee = match transfer_fee.is_some() { + true => match transfer_fee_basis_point.is_some() || transfer_fee_maximum_fee.is_some() { + true => Err("transfer-fee-basis-point and transfer-fee-maximum-fee flag disable when using transfer-fee flag"), + false => Ok(transfer_fee) + }, + false => match transfer_fee_basis_point.is_some() && transfer_fee_maximum_fee.is_some() { + true => Ok(Some((transfer_fee_basis_point.unwrap(), (transfer_fee_maximum_fee.unwrap() * (u64::pow(10, decimals.into())) as f64) as u64))), + false => if transfer_fee_basis_point.is_some() { + Err("Missing transfer_fee_maximum_fee flag") + }else if transfer_fee_maximum_fee.is_some() { + Err("Missing transfer_fee_basis_point") + }else{ + Ok(None) + } + } + }; + + let transfer_fee = match transfer_fee { + Ok(result) => result, + Err(e) => { + eprintln!("{}",e); + exit(1); + } + }; + let (token_signer, token) = get_signer(arg_matches, "token_keypair", &mut wallet_manager) .unwrap_or_else(new_throwaway_signer); diff --git a/token/cli/tests/command.rs b/token/cli/tests/command.rs index 1b66cfaa0e7..93f34ab93f5 100644 --- a/token/cli/tests/command.rs +++ b/token/cli/tests/command.rs @@ -123,6 +123,8 @@ async fn main() { async_trial!(non_transferable, test_validator, payer), async_trial!(default_account_state, test_validator, payer), async_trial!(transfer_fee, test_validator, payer), + async_trial!(transfer_fee_basis_point, test_validator, payer), + // async_trial!(transfer_fee_maximum_fee, test_validator, payer), async_trial!(confidential_transfer, test_validator, payer), async_trial!(multisig_transfer, test_validator, payer), async_trial!(offline_multisig_transfer_with_nonce, test_validator, payer), @@ -2521,6 +2523,53 @@ async fn transfer_fee(test_validator: &TestValidator, payer: &Keypair) { ); } +async fn transfer_fee_basis_point(test_validator: &TestValidator, payer: &Keypair) { + let config = test_config_with_default_signer(test_validator, payer, &spl_token_2022::id()); + + let transfer_fee_basis_points = 100; + let maximum_fee = 1.2; + let decimal = 9; + + let token = Keypair::new(); + let token_keypair_file = NamedTempFile::new().unwrap(); + write_keypair_file(&token, &token_keypair_file); + let token_pubkey = token.pubkey(); + process_test_command( + &config, + payer, + &[ + "spl-token", + CommandName::CreateToken.into(), + token_keypair_file.path().to_str().unwrap(), + "--transfer-fee-basis-points", + &transfer_fee_basis_points.to_string(), + "--transfer-fee-maximum-fee", + &maximum_fee.to_string() + ] + ).await + .unwrap(); + + let account = config.rpc_client.get_account(&token_pubkey).await.unwrap(); + let test_mint = StateWithExtensionsOwned::::unpack(account.data).unwrap(); + let extension = test_mint.get_extension::().unwrap(); + assert_eq!( + u16::from(extension.older_transfer_fee.transfer_fee_basis_points), + transfer_fee_basis_points + ); + assert_eq!( + u64::from(extension.older_transfer_fee.maximum_fee), + (maximum_fee * i32::pow(10,decimal) as f64) as u64 + ); + assert_eq!( + u16::from(extension.newer_transfer_fee.transfer_fee_basis_points), + transfer_fee_basis_points + ); + assert_eq!( + u64::from(extension.newer_transfer_fee.maximum_fee), + (maximum_fee * i32::pow(10, decimal) as f64) as u64 + ); +} + async fn confidential_transfer(test_validator: &TestValidator, payer: &Keypair) { use spl_token_2022::solana_zk_token_sdk::encryption::elgamal::ElGamalKeypair; From b6937387902066305aec9b73aae06ea5854e1a32 Mon Sep 17 00:00:00 2001 From: Hrushi20 Date: Fri, 26 Jul 2024 15:05:18 +0530 Subject: [PATCH 2/4] revert unused import change Signed-off-by: Hrushi20 remove unwanted space Signed-off-by: Hrushi20 added missing comma Signed-off-by: Hrushi20 --- token/cli/src/command.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/token/cli/src/command.rs b/token/cli/src/command.rs index 295a8d9285d..fcbeb70c3fa 100644 --- a/token/cli/src/command.rs +++ b/token/cli/src/command.rs @@ -62,7 +62,8 @@ use { encryption::{ auth_encryption::AeKey, elgamal::{self, ElGamalKeypair}, - }, instruction::transfer, zk_token_elgamal::pod::ElGamalPubkey + }, + zk_token_elgamal::pod::ElGamalPubkey, }, state::{Account, AccountState, Mint}, }, From 36408989451507513cbbf41db6d2f8102c68461f Mon Sep 17 00:00:00 2001 From: Hrushi20 Date: Thu, 1 Aug 2024 01:36:42 +0530 Subject: [PATCH 3/4] update style, refactor code Signed-off-by: Hrushi20 --- token/cli/src/clap_app.rs | 10 +++++++-- token/cli/src/command.rs | 46 ++++++-------------------------------- token/cli/tests/command.rs | 12 +++++----- 3 files changed, 21 insertions(+), 47 deletions(-) diff --git a/token/cli/src/clap_app.rs b/token/cli/src/clap_app.rs index ea25b97b92a..f3d74780bfc 100644 --- a/token/cli/src/clap_app.rs +++ b/token/cli/src/clap_app.rs @@ -764,6 +764,8 @@ pub fn app<'a, 'b>( .takes_value(true) .number_of_values(2) .hidden(true) + .conflicts_with("transfer_fee_basis_points") + .conflicts_with("transfer_fee_maximum_fee") .help( "Add a transfer fee to the mint. \ The mint authority can set the fee and withdraw collected fees.", @@ -775,6 +777,8 @@ pub fn app<'a, 'b>( .value_names(&["FEE_IN_BASIS_POINTS"]) .takes_value(true) .number_of_values(1) + .conflicts_with("transfer_fee") + .requires("transfer_fee_maximum_fee") .help( "Add transfer fee to the mint. \ The mint authority can set the fee.", @@ -786,9 +790,11 @@ pub fn app<'a, 'b>( .value_names(&["MAXIMUM_FEE"]) .takes_value(true) .number_of_values(1) + .conflicts_with("transfer_fee") + .requires("transfer_fee_basis_points") .help( - "Add a UI amount transfer fee to the mint. \ - The mint authority can set the fee and collected fee" + "Add a UI amount maximum transfer fee to the mint. \ + The mint authority can set and collect fees" ) ) .arg( diff --git a/token/cli/src/command.rs b/token/cli/src/command.rs index fcbeb70c3fa..e76438a35e7 100644 --- a/token/cli/src/command.rs +++ b/token/cli/src/command.rs @@ -3472,7 +3472,7 @@ pub async fn process_command<'a>( let member_address = value_t!(arg_matches, "member_address", Pubkey).ok(); let transfer_fee = arg_matches.values_of("transfer_fee").map(|mut v| { - println_display(config,"transfer_fee flag has been deprecated".to_string()); + println_display(config,"transfer-fee has been deprecated and will be removed in a future release. Please specify --transfer-fee-basis-points and --transfer-fee-maximum-fee with a UI amount".to_string()); ( v.next() .unwrap() @@ -3485,44 +3485,12 @@ pub async fn process_command<'a>( ) }); - let transfer_fee_basis_point = arg_matches.values_of("transfer_fee_basis_points").map(|mut v| { - v.next() - .unwrap() - .parse::() - .unwrap_or_else(print_error_and_exit) - }); - - let transfer_fee_maximum_fee = arg_matches.values_of("transfer_fee_maximum_fee").map(|mut v| { - v.next() - .unwrap() - .parse::() - .unwrap_or_else(print_error_and_exit) - }); - - let transfer_fee = match transfer_fee.is_some() { - true => match transfer_fee_basis_point.is_some() || transfer_fee_maximum_fee.is_some() { - true => Err("transfer-fee-basis-point and transfer-fee-maximum-fee flag disable when using transfer-fee flag"), - false => Ok(transfer_fee) - }, - false => match transfer_fee_basis_point.is_some() && transfer_fee_maximum_fee.is_some() { - true => Ok(Some((transfer_fee_basis_point.unwrap(), (transfer_fee_maximum_fee.unwrap() * (u64::pow(10, decimals.into())) as f64) as u64))), - false => if transfer_fee_basis_point.is_some() { - Err("Missing transfer_fee_maximum_fee flag") - }else if transfer_fee_maximum_fee.is_some() { - Err("Missing transfer_fee_basis_point") - }else{ - Ok(None) - } - } - }; - - let transfer_fee = match transfer_fee { - Ok(result) => result, - Err(e) => { - eprintln!("{}",e); - exit(1); - } - }; + let tranfer_fee_basis_point = value_of::(arg_matches, "transfer_fee_basis_points"); + let transfer_fee_maximum_fee = value_of::(arg_matches, "transfer_fee_maximum_fee") + .map(|v| spl_token::ui_amount_to_amount(v, decimals)); + let transfer_fee = tranfer_fee_basis_point + .map(|v| (v, transfer_fee_maximum_fee.unwrap())) + .or(transfer_fee); let (token_signer, token) = get_signer(arg_matches, "token_keypair", &mut wallet_manager) diff --git a/token/cli/tests/command.rs b/token/cli/tests/command.rs index 93f34ab93f5..f5d7490acf9 100644 --- a/token/cli/tests/command.rs +++ b/token/cli/tests/command.rs @@ -124,7 +124,6 @@ async fn main() { async_trial!(default_account_state, test_validator, payer), async_trial!(transfer_fee, test_validator, payer), async_trial!(transfer_fee_basis_point, test_validator, payer), - // async_trial!(transfer_fee_maximum_fee, test_validator, payer), async_trial!(confidential_transfer, test_validator, payer), async_trial!(multisig_transfer, test_validator, payer), async_trial!(offline_multisig_transfer_with_nonce, test_validator, payer), @@ -2535,7 +2534,7 @@ async fn transfer_fee_basis_point(test_validator: &TestValidator, payer: &Keypai write_keypair_file(&token, &token_keypair_file); let token_pubkey = token.pubkey(); process_test_command( - &config, + &config, payer, &[ "spl-token", @@ -2544,9 +2543,10 @@ async fn transfer_fee_basis_point(test_validator: &TestValidator, payer: &Keypai "--transfer-fee-basis-points", &transfer_fee_basis_points.to_string(), "--transfer-fee-maximum-fee", - &maximum_fee.to_string() - ] - ).await + &maximum_fee.to_string(), + ], + ) + .await .unwrap(); let account = config.rpc_client.get_account(&token_pubkey).await.unwrap(); @@ -2558,7 +2558,7 @@ async fn transfer_fee_basis_point(test_validator: &TestValidator, payer: &Keypai ); assert_eq!( u64::from(extension.older_transfer_fee.maximum_fee), - (maximum_fee * i32::pow(10,decimal) as f64) as u64 + (maximum_fee * i32::pow(10, decimal) as f64) as u64 ); assert_eq!( u16::from(extension.newer_transfer_fee.transfer_fee_basis_points), From 8dea843191def0c4a6293447feb00e83d030e3eb Mon Sep 17 00:00:00 2001 From: Hrushi20 Date: Fri, 2 Aug 2024 00:47:46 +0530 Subject: [PATCH 4/4] fix clippy error, add validation Signed-off-by: Hrushi20 --- token/cli/src/clap_app.rs | 2 ++ token/cli/tests/command.rs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/token/cli/src/clap_app.rs b/token/cli/src/clap_app.rs index f3d74780bfc..acb2b62fc36 100644 --- a/token/cli/src/clap_app.rs +++ b/token/cli/src/clap_app.rs @@ -779,6 +779,7 @@ pub fn app<'a, 'b>( .number_of_values(1) .conflicts_with("transfer_fee") .requires("transfer_fee_maximum_fee") + .validator(is_parsable::) .help( "Add transfer fee to the mint. \ The mint authority can set the fee.", @@ -792,6 +793,7 @@ pub fn app<'a, 'b>( .number_of_values(1) .conflicts_with("transfer_fee") .requires("transfer_fee_basis_points") + .validator(is_amount) .help( "Add a UI amount maximum transfer fee to the mint. \ The mint authority can set and collect fees" diff --git a/token/cli/tests/command.rs b/token/cli/tests/command.rs index f5d7490acf9..705c37caf7b 100644 --- a/token/cli/tests/command.rs +++ b/token/cli/tests/command.rs @@ -2531,7 +2531,7 @@ async fn transfer_fee_basis_point(test_validator: &TestValidator, payer: &Keypai let token = Keypair::new(); let token_keypair_file = NamedTempFile::new().unwrap(); - write_keypair_file(&token, &token_keypair_file); + write_keypair_file(&token, &token_keypair_file).unwrap(); let token_pubkey = token.pubkey(); process_test_command( &config,