From 8d115f1f6dba94b3630864bb9cbf702a69f9727a Mon Sep 17 00:00:00 2001 From: Hrushikesh Date: Fri, 2 Aug 2024 02:53:38 +0530 Subject: [PATCH] token-cli: create transfer-fee-basis-points and transfer-fee-maximum-fee flags (#7053) * create transfer-fee-basis-points and transfer-fee-maximum-fee flags Signed-off-by: Hrushi20 * revert unused import change Signed-off-by: Hrushi20 remove unwanted space Signed-off-by: Hrushi20 added missing comma Signed-off-by: Hrushi20 * update style, refactor code Signed-off-by: Hrushi20 * fix clippy error, add validation Signed-off-by: Hrushi20 --------- Signed-off-by: Hrushi20 --- token/cli/src/clap_app.rs | 31 ++++++++++++++++++++++++ token/cli/src/command.rs | 8 +++++++ token/cli/tests/command.rs | 49 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+) diff --git a/token/cli/src/clap_app.rs b/token/cli/src/clap_app.rs index 94d67ef87c7..acb2b62fc36 100644 --- a/token/cli/src/clap_app.rs +++ b/token/cli/src/clap_app.rs @@ -763,11 +763,42 @@ pub fn app<'a, 'b>( .value_names(&["FEE_IN_BASIS_POINTS", "MAXIMUM_FEE"]) .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.", ), ) + .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) + .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.", + ), + ) + .arg( + Arg::with_name("transfer_fee_maximum_fee") + .long("transfer-fee-maximum-fee") + .value_names(&["MAXIMUM_FEE"]) + .takes_value(true) + .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" + ) + ) .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 1faf086127a..b08725c0d30 100644 --- a/token/cli/src/command.rs +++ b/token/cli/src/command.rs @@ -3473,6 +3473,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 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,6 +3486,13 @@ pub async fn process_command<'a>( ) }); + 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) .unwrap_or_else(new_throwaway_signer); diff --git a/token/cli/tests/command.rs b/token/cli/tests/command.rs index 1b66cfaa0e7..705c37caf7b 100644 --- a/token/cli/tests/command.rs +++ b/token/cli/tests/command.rs @@ -123,6 +123,7 @@ 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!(confidential_transfer, test_validator, payer), async_trial!(multisig_transfer, test_validator, payer), async_trial!(offline_multisig_transfer_with_nonce, test_validator, payer), @@ -2521,6 +2522,54 @@ 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).unwrap(); + 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;