From 898c5e9bcfc9a45d0235d0665e1a6459373697c6 Mon Sep 17 00:00:00 2001 From: Oleksandr Pravdyvyi Date: Mon, 13 Oct 2025 17:25:36 +0300 Subject: [PATCH] fix: structured subcommand approach --- integration_tests/src/lib.rs | 43 ++-- wallet/src/cli/mod.rs | 10 + wallet/src/cli/token_program.rs | 372 ++++++++++++++++++++++++++++++++ wallet/src/lib.rs | 360 +------------------------------ 4 files changed, 420 insertions(+), 365 deletions(-) create mode 100644 wallet/src/cli/mod.rs create mode 100644 wallet/src/cli/token_program.rs diff --git a/integration_tests/src/lib.rs b/integration_tests/src/lib.rs index 3aa45f1..bcb877b 100644 --- a/integration_tests/src/lib.rs +++ b/integration_tests/src/lib.rs @@ -19,6 +19,7 @@ use tempfile::TempDir; use tokio::task::JoinHandle; use wallet::{ Command, SubcommandReturnValue, WalletCore, + cli::token_program::TokenProgramSubcommand, config::PersistentAccountData, helperfunctions::{fetch_config, fetch_persistent_accounts}, }; @@ -350,13 +351,15 @@ pub async fn test_success_token_program() { .expect("Failed to produce new account, not present in persistent accounts"); // Create new token - let command = Command::CreateNewToken { + let subcommand = TokenProgramSubcommand::CreateNewToken { definition_addr: definition_addr.to_string(), supply_addr: supply_addr.to_string(), name: "A NAME".to_string(), total_supply: 37, }; - wallet::execute_subcommand(command).await.unwrap(); + wallet::execute_subcommand(Command::TokenProgram(subcommand)) + .await + .unwrap(); info!("Waiting for next block creation"); tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; @@ -402,12 +405,14 @@ pub async fn test_success_token_program() { ); // Transfer 7 tokens from `supply_acc` to the account at address `recipient_addr` - let command = Command::TransferToken { + let subcommand = TokenProgramSubcommand::TransferToken { sender_addr: supply_addr.to_string(), recipient_addr: recipient_addr.to_string(), balance_to_move: 7, }; - wallet::execute_subcommand(command).await.unwrap(); + wallet::execute_subcommand(Command::TokenProgram(subcommand)) + .await + .unwrap(); info!("Waiting for next block creation"); tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; @@ -480,14 +485,16 @@ pub async fn test_success_token_program_private_owned() { }; // Create new token - let command = Command::CreateNewTokenPrivateOwned { + let subcommand = TokenProgramSubcommand::CreateNewTokenPrivateOwned { definition_addr: definition_addr.to_string(), supply_addr: supply_addr.to_string(), name: "A NAME".to_string(), total_supply: 37, }; - wallet::execute_subcommand(command).await.unwrap(); + wallet::execute_subcommand(Command::TokenProgram(subcommand)) + .await + .unwrap(); info!("Waiting for next block creation"); tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; @@ -520,13 +527,15 @@ pub async fn test_success_token_program_private_owned() { assert!(verify_commitment_is_in_state(new_commitment1, &seq_client).await); // Transfer 7 tokens from `supply_acc` to the account at address `recipient_addr` - let command = Command::TransferTokenPrivateOwnedNotInitialized { + let subcommand = TokenProgramSubcommand::TransferTokenPrivateOwnedNotInitialized { sender_addr: supply_addr.to_string(), recipient_addr: recipient_addr.to_string(), balance_to_move: 7, }; - wallet::execute_subcommand(command).await.unwrap(); + wallet::execute_subcommand(Command::TokenProgram(subcommand)) + .await + .unwrap(); info!("Waiting for next block creation"); tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; @@ -545,13 +554,15 @@ pub async fn test_success_token_program_private_owned() { assert!(verify_commitment_is_in_state(new_commitment2, &seq_client).await); // Transfer additional 7 tokens from `supply_acc` to the account at address `recipient_addr` - let command = Command::TransferTokenPrivateOwnedAlreadyInitialized { + let subcommand = TokenProgramSubcommand::TransferTokenPrivateOwnedAlreadyInitialized { sender_addr: supply_addr.to_string(), recipient_addr: recipient_addr.to_string(), balance_to_move: 7, }; - wallet::execute_subcommand(command).await.unwrap(); + wallet::execute_subcommand(Command::TokenProgram(subcommand)) + .await + .unwrap(); info!("Waiting for next block creation"); tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; @@ -603,14 +614,16 @@ pub async fn test_success_token_program_private_claiming_path() { }; // Create new token - let command = Command::CreateNewTokenPrivateOwned { + let subcommand = TokenProgramSubcommand::CreateNewTokenPrivateOwned { definition_addr: definition_addr.to_string(), supply_addr: supply_addr.to_string(), name: "A NAME".to_string(), total_supply: 37, }; - wallet::execute_subcommand(command).await.unwrap(); + wallet::execute_subcommand(Command::TokenProgram(subcommand)) + .await + .unwrap(); info!("Waiting for next block creation"); tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; @@ -649,7 +662,7 @@ pub async fn test_success_token_program_private_claiming_path() { .unwrap(); // Transfer 7 tokens from `supply_acc` to the account at address `recipient_addr` - let command = Command::TransferTokenPrivateForeign { + let subcommand = TokenProgramSubcommand::TransferTokenPrivateForeign { sender_addr: supply_addr.to_string(), recipient_npk: hex::encode(recipient_keys.nullifer_public_key.0), recipient_ipk: hex::encode(recipient_keys.incoming_viewing_public_key.0.clone()), @@ -657,7 +670,9 @@ pub async fn test_success_token_program_private_claiming_path() { }; let SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash } = - wallet::execute_subcommand(command).await.unwrap() + wallet::execute_subcommand(Command::TokenProgram(subcommand)) + .await + .unwrap() else { panic!("invalid subcommand return value"); }; diff --git a/wallet/src/cli/mod.rs b/wallet/src/cli/mod.rs new file mode 100644 index 0000000..5b277e0 --- /dev/null +++ b/wallet/src/cli/mod.rs @@ -0,0 +1,10 @@ +use anyhow::Result; + +use crate::{SubcommandReturnValue, WalletCore}; + +pub mod token_program; + +pub(crate) trait WalletSubcommand { + async fn handle_subcommand(self, wallet_core: &mut WalletCore) + -> Result; +} diff --git a/wallet/src/cli/token_program.rs b/wallet/src/cli/token_program.rs new file mode 100644 index 0000000..d3b42ea --- /dev/null +++ b/wallet/src/cli/token_program.rs @@ -0,0 +1,372 @@ +use anyhow::Result; +use clap::Subcommand; +use common::transaction::NSSATransaction; +use nssa::Address; + +use crate::{SubcommandReturnValue, WalletCore, cli::WalletSubcommand}; + +///Represents CLI subcommand for a wallet working with token_program +#[derive(Subcommand, Debug, Clone)] +pub enum TokenProgramSubcommand { + //Create a new token using the token program + CreateNewToken { + #[arg(short, long)] + definition_addr: String, + #[arg(short, long)] + supply_addr: String, + #[arg(short, long)] + name: String, + #[arg(short, long)] + total_supply: u128, + }, + //Transfer tokens using the token program + TransferToken { + #[arg(short, long)] + sender_addr: String, + #[arg(short, long)] + recipient_addr: String, + #[arg(short, long)] + balance_to_move: u128, + }, + //Create a new token using the token program + CreateNewTokenPrivateOwned { + #[arg(short, long)] + definition_addr: String, + #[arg(short, long)] + supply_addr: String, + #[arg(short, long)] + name: String, + #[arg(short, long)] + total_supply: u128, + }, + //Transfer tokens using the token program + TransferTokenPrivateOwnedAlreadyInitialized { + #[arg(short, long)] + sender_addr: String, + #[arg(short, long)] + recipient_addr: String, + #[arg(short, long)] + balance_to_move: u128, + }, + //Transfer tokens using the token program + TransferTokenPrivateOwnedNotInitialized { + #[arg(short, long)] + sender_addr: String, + #[arg(short, long)] + recipient_addr: String, + #[arg(short, long)] + balance_to_move: u128, + }, + //Transfer tokens using the token program + TransferTokenPrivateForeign { + #[arg(short, long)] + sender_addr: String, + ///recipient_npk - valid 32 byte hex string + #[arg(long)] + recipient_npk: String, + ///recipient_ipk - valid 33 byte hex string + #[arg(long)] + recipient_ipk: String, + #[arg(short, long)] + balance_to_move: u128, + }, +} + +impl WalletSubcommand for TokenProgramSubcommand { + async fn handle_subcommand( + self, + wallet_core: &mut WalletCore, + ) -> Result { + match self { + TokenProgramSubcommand::CreateNewToken { + definition_addr, + supply_addr, + name, + total_supply, + } => { + let name = name.as_bytes(); + if name.len() > 6 { + // TODO: return error + panic!(); + } + let mut name_bytes = [0; 6]; + name_bytes[..name.len()].copy_from_slice(name); + wallet_core + .send_new_token_definition( + definition_addr.parse().unwrap(), + supply_addr.parse().unwrap(), + name_bytes, + total_supply, + ) + .await?; + Ok(SubcommandReturnValue::Empty) + } + TokenProgramSubcommand::CreateNewTokenPrivateOwned { + definition_addr, + supply_addr, + name, + total_supply, + } => { + let name = name.as_bytes(); + if name.len() > 6 { + // TODO: return error + panic!("Name length mismatch"); + } + let mut name_bytes = [0; 6]; + name_bytes[..name.len()].copy_from_slice(name); + + let definition_addr: Address = definition_addr.parse().unwrap(); + let supply_addr: Address = supply_addr.parse().unwrap(); + + let (res, [secret_supply]) = wallet_core + .send_new_token_definition_private_owned( + definition_addr, + supply_addr, + name_bytes, + total_supply, + ) + .await?; + + println!("Results of tx send is {res:#?}"); + + let tx_hash = res.tx_hash; + let transfer_tx = wallet_core + .poll_native_token_transfer(tx_hash.clone()) + .await?; + + if let NSSATransaction::PrivacyPreserving(tx) = transfer_tx { + let supply_ebc = tx.message.encrypted_private_post_states[0].clone(); + let supply_comm = tx.message.new_commitments[0].clone(); + + let res_acc_supply = nssa_core::EncryptionScheme::decrypt( + &supply_ebc.ciphertext, + &secret_supply, + &supply_comm, + 0, + ) + .unwrap(); + + println!("Received new to acc {res_acc_supply:#?}"); + + println!("Transaction data is {:?}", tx.message); + + wallet_core + .storage + .insert_private_account_data(supply_addr, res_acc_supply); + } + + let path = wallet_core.store_persistent_accounts()?; + + println!("Stored persistent accounts at {path:#?}"); + + Ok(SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash }) + } + TokenProgramSubcommand::TransferToken { + sender_addr, + recipient_addr, + balance_to_move, + } => { + wallet_core + .send_transfer_token_transaction( + sender_addr.parse().unwrap(), + recipient_addr.parse().unwrap(), + balance_to_move, + ) + .await?; + Ok(SubcommandReturnValue::Empty) + } + TokenProgramSubcommand::TransferTokenPrivateOwnedAlreadyInitialized { + sender_addr, + recipient_addr, + balance_to_move, + } => { + let sender_addr: Address = sender_addr.parse().unwrap(); + let recipient_addr: Address = recipient_addr.parse().unwrap(); + + let (res, [secret_sender, secret_recipient]) = wallet_core + .send_transfer_token_transaction_private_owned_account_already_initialized( + sender_addr, + recipient_addr, + balance_to_move, + ) + .await?; + + println!("Results of tx send is {res:#?}"); + + let tx_hash = res.tx_hash; + let transfer_tx = wallet_core + .poll_native_token_transfer(tx_hash.clone()) + .await?; + + if let NSSATransaction::PrivacyPreserving(tx) = transfer_tx { + let sender_ebc = tx.message.encrypted_private_post_states[0].clone(); + let sender_comm = tx.message.new_commitments[0].clone(); + + let recipient_ebc = tx.message.encrypted_private_post_states[1].clone(); + let recipient_comm = tx.message.new_commitments[1].clone(); + + let res_acc_sender = nssa_core::EncryptionScheme::decrypt( + &sender_ebc.ciphertext, + &secret_sender, + &sender_comm, + 0, + ) + .unwrap(); + + let res_acc_recipient = nssa_core::EncryptionScheme::decrypt( + &recipient_ebc.ciphertext, + &secret_recipient, + &recipient_comm, + 1, + ) + .unwrap(); + + println!("Received new sender acc {res_acc_sender:#?}"); + println!("Received new recipient acc {res_acc_recipient:#?}"); + + println!("Transaction data is {:?}", tx.message); + + wallet_core + .storage + .insert_private_account_data(sender_addr, res_acc_sender); + wallet_core + .storage + .insert_private_account_data(recipient_addr, res_acc_recipient); + } + + let path = wallet_core.store_persistent_accounts()?; + + println!("Stored persistent accounts at {path:#?}"); + + Ok(SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash }) + } + TokenProgramSubcommand::TransferTokenPrivateOwnedNotInitialized { + sender_addr, + recipient_addr, + balance_to_move, + } => { + let sender_addr: Address = sender_addr.parse().unwrap(); + let recipient_addr: Address = recipient_addr.parse().unwrap(); + + let (res, [secret_sender, secret_recipient]) = wallet_core + .send_transfer_token_transaction_private_owned_account_not_initialized( + sender_addr, + recipient_addr, + balance_to_move, + ) + .await?; + + println!("Results of tx send is {res:#?}"); + + let tx_hash = res.tx_hash; + let transfer_tx = wallet_core + .poll_native_token_transfer(tx_hash.clone()) + .await?; + + if let NSSATransaction::PrivacyPreserving(tx) = transfer_tx { + let sender_ebc = tx.message.encrypted_private_post_states[0].clone(); + let sender_comm = tx.message.new_commitments[0].clone(); + + let recipient_ebc = tx.message.encrypted_private_post_states[1].clone(); + let recipient_comm = tx.message.new_commitments[1].clone(); + + let res_acc_sender = nssa_core::EncryptionScheme::decrypt( + &sender_ebc.ciphertext, + &secret_sender, + &sender_comm, + 0, + ) + .unwrap(); + + let res_acc_recipient = nssa_core::EncryptionScheme::decrypt( + &recipient_ebc.ciphertext, + &secret_recipient, + &recipient_comm, + 1, + ) + .unwrap(); + + println!("Received new sender acc {res_acc_sender:#?}"); + println!("Received new recipient acc {res_acc_recipient:#?}"); + + println!("Transaction data is {:?}", tx.message); + + wallet_core + .storage + .insert_private_account_data(sender_addr, res_acc_sender); + wallet_core + .storage + .insert_private_account_data(recipient_addr, res_acc_recipient); + } + + let path = wallet_core.store_persistent_accounts()?; + + println!("Stored persistent accounts at {path:#?}"); + + Ok(SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash }) + } + TokenProgramSubcommand::TransferTokenPrivateForeign { + sender_addr, + recipient_npk, + recipient_ipk, + balance_to_move, + } => { + let sender_addr: Address = sender_addr.parse().unwrap(); + let recipient_npk_res = hex::decode(recipient_npk)?; + let mut recipient_npk = [0; 32]; + recipient_npk.copy_from_slice(&recipient_npk_res); + let recipient_npk = nssa_core::NullifierPublicKey(recipient_npk); + + let recipient_ipk_res = hex::decode(recipient_ipk)?; + let mut recipient_ipk = [0u8; 33]; + recipient_ipk.copy_from_slice(&recipient_ipk_res); + let recipient_ipk = nssa_core::encryption::shared_key_derivation::Secp256k1Point( + recipient_ipk.to_vec(), + ); + + let (res, [secret_sender, _]) = wallet_core + .send_transfer_token_transaction_private_foreign_account( + sender_addr, + recipient_npk, + recipient_ipk, + balance_to_move, + ) + .await?; + + println!("Results of tx send is {res:#?}"); + + let tx_hash = res.tx_hash; + let transfer_tx = wallet_core + .poll_native_token_transfer(tx_hash.clone()) + .await?; + + if let NSSATransaction::PrivacyPreserving(tx) = transfer_tx { + let sender_ebc = tx.message.encrypted_private_post_states[0].clone(); + let sender_comm = tx.message.new_commitments[0].clone(); + + let res_acc_sender = nssa_core::EncryptionScheme::decrypt( + &sender_ebc.ciphertext, + &secret_sender, + &sender_comm, + 0, + ) + .unwrap(); + + println!("Received new sender acc {res_acc_sender:#?}"); + + println!("Transaction data is {:?}", tx.message); + + wallet_core + .storage + .insert_private_account_data(sender_addr, res_acc_sender); + } + + let path = wallet_core.store_persistent_accounts()?; + + println!("Stored persistent accounts at {path:#?}"); + + Ok(SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash }) + } + } + } +} diff --git a/wallet/src/lib.rs b/wallet/src/lib.rs index 2aca9fa..cdd98e6 100644 --- a/wallet/src/lib.rs +++ b/wallet/src/lib.rs @@ -15,7 +15,9 @@ use nssa::{Account, Address}; use clap::{Parser, Subcommand}; use nssa_core::Commitment; +use crate::cli::WalletSubcommand; use crate::{ + cli::token_program::TokenProgramSubcommand, helperfunctions::{ HumanReadableAccount, fetch_config, fetch_persistent_accounts, get_home, produce_data_for_storage, @@ -28,6 +30,7 @@ use crate::{ pub const HOME_DIR_ENV_VAR: &str = "NSSA_WALLET_HOME_DIR"; pub mod chain_storage; +pub mod cli; pub mod config; pub mod helperfunctions; pub mod pinata_interactions; @@ -270,26 +273,6 @@ pub enum Command { #[arg(short, long)] addr: String, }, - //Create a new token using the token program - CreateNewToken { - #[arg(short, long)] - definition_addr: String, - #[arg(short, long)] - supply_addr: String, - #[arg(short, long)] - name: String, - #[arg(short, long)] - total_supply: u128, - }, - //Transfer tokens using the token program - TransferToken { - #[arg(short, long)] - sender_addr: String, - #[arg(short, long)] - recipient_addr: String, - #[arg(short, long)] - balance_to_move: u128, - }, // TODO: Testnet only. Refactor to prevent compilation on mainnet. // Claim piƱata prize ClaimPinata { @@ -316,48 +299,9 @@ pub enum Command { #[arg(long)] solution: u128, }, - //Create a new token using the token program - CreateNewTokenPrivateOwned { - #[arg(short, long)] - definition_addr: String, - #[arg(short, long)] - supply_addr: String, - #[arg(short, long)] - name: String, - #[arg(short, long)] - total_supply: u128, - }, - //Transfer tokens using the token program - TransferTokenPrivateOwnedAlreadyInitialized { - #[arg(short, long)] - sender_addr: String, - #[arg(short, long)] - recipient_addr: String, - #[arg(short, long)] - balance_to_move: u128, - }, - //Transfer tokens using the token program - TransferTokenPrivateOwnedNotInitialized { - #[arg(short, long)] - sender_addr: String, - #[arg(short, long)] - recipient_addr: String, - #[arg(short, long)] - balance_to_move: u128, - }, - //Transfer tokens using the token program - TransferTokenPrivateForeign { - #[arg(short, long)] - sender_addr: String, - ///recipient_npk - valid 32 byte hex string - #[arg(long)] - recipient_npk: String, - ///recipient_ipk - valid 33 byte hex string - #[arg(long)] - recipient_ipk: String, - #[arg(short, long)] - balance_to_move: u128, - }, + ///Test command + #[command(subcommand)] + TokenProgram(TokenProgramSubcommand), } ///To execute commands, env var NSSA_WALLET_HOME_DIR must be set into directory with config @@ -775,295 +719,6 @@ pub async fn execute_subcommand(command: Command) -> Result { - let name = name.as_bytes(); - if name.len() > 6 { - // TODO: return error - panic!(); - } - let mut name_bytes = [0; 6]; - name_bytes[..name.len()].copy_from_slice(name); - wallet_core - .send_new_token_definition( - definition_addr.parse().unwrap(), - supply_addr.parse().unwrap(), - name_bytes, - total_supply, - ) - .await?; - SubcommandReturnValue::Empty - } - Command::CreateNewTokenPrivateOwned { - definition_addr, - supply_addr, - name, - total_supply, - } => { - let name = name.as_bytes(); - if name.len() > 6 { - // TODO: return error - panic!("Name length mismatch"); - } - let mut name_bytes = [0; 6]; - name_bytes[..name.len()].copy_from_slice(name); - - let definition_addr: Address = definition_addr.parse().unwrap(); - let supply_addr: Address = supply_addr.parse().unwrap(); - - let (res, [secret_supply]) = wallet_core - .send_new_token_definition_private_owned( - definition_addr, - supply_addr, - name_bytes, - total_supply, - ) - .await?; - - println!("Results of tx send is {res:#?}"); - - let tx_hash = res.tx_hash; - let transfer_tx = wallet_core - .poll_native_token_transfer(tx_hash.clone()) - .await?; - - if let NSSATransaction::PrivacyPreserving(tx) = transfer_tx { - let supply_ebc = tx.message.encrypted_private_post_states[0].clone(); - let supply_comm = tx.message.new_commitments[0].clone(); - - let res_acc_supply = nssa_core::EncryptionScheme::decrypt( - &supply_ebc.ciphertext, - &secret_supply, - &supply_comm, - 0, - ) - .unwrap(); - - println!("Received new to acc {res_acc_supply:#?}"); - - println!("Transaction data is {:?}", tx.message); - - wallet_core - .storage - .insert_private_account_data(supply_addr, res_acc_supply); - } - - let path = wallet_core.store_persistent_accounts()?; - - println!("Stored persistent accounts at {path:#?}"); - - SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash } - } - Command::TransferToken { - sender_addr, - recipient_addr, - balance_to_move, - } => { - wallet_core - .send_transfer_token_transaction( - sender_addr.parse().unwrap(), - recipient_addr.parse().unwrap(), - balance_to_move, - ) - .await?; - SubcommandReturnValue::Empty - } - Command::TransferTokenPrivateOwnedAlreadyInitialized { - sender_addr, - recipient_addr, - balance_to_move, - } => { - let sender_addr: Address = sender_addr.parse().unwrap(); - let recipient_addr: Address = recipient_addr.parse().unwrap(); - - let (res, [secret_sender, secret_recipient]) = wallet_core - .send_transfer_token_transaction_private_owned_account_already_initialized( - sender_addr, - recipient_addr, - balance_to_move, - ) - .await?; - - println!("Results of tx send is {res:#?}"); - - let tx_hash = res.tx_hash; - let transfer_tx = wallet_core - .poll_native_token_transfer(tx_hash.clone()) - .await?; - - if let NSSATransaction::PrivacyPreserving(tx) = transfer_tx { - let sender_ebc = tx.message.encrypted_private_post_states[0].clone(); - let sender_comm = tx.message.new_commitments[0].clone(); - - let recipient_ebc = tx.message.encrypted_private_post_states[1].clone(); - let recipient_comm = tx.message.new_commitments[1].clone(); - - let res_acc_sender = nssa_core::EncryptionScheme::decrypt( - &sender_ebc.ciphertext, - &secret_sender, - &sender_comm, - 0, - ) - .unwrap(); - - let res_acc_recipient = nssa_core::EncryptionScheme::decrypt( - &recipient_ebc.ciphertext, - &secret_recipient, - &recipient_comm, - 1, - ) - .unwrap(); - - println!("Received new sender acc {res_acc_sender:#?}"); - println!("Received new recipient acc {res_acc_recipient:#?}"); - - println!("Transaction data is {:?}", tx.message); - - wallet_core - .storage - .insert_private_account_data(sender_addr, res_acc_sender); - wallet_core - .storage - .insert_private_account_data(recipient_addr, res_acc_recipient); - } - - let path = wallet_core.store_persistent_accounts()?; - - println!("Stored persistent accounts at {path:#?}"); - - SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash } - } - Command::TransferTokenPrivateOwnedNotInitialized { - sender_addr, - recipient_addr, - balance_to_move, - } => { - let sender_addr: Address = sender_addr.parse().unwrap(); - let recipient_addr: Address = recipient_addr.parse().unwrap(); - - let (res, [secret_sender, secret_recipient]) = wallet_core - .send_transfer_token_transaction_private_owned_account_not_initialized( - sender_addr, - recipient_addr, - balance_to_move, - ) - .await?; - - println!("Results of tx send is {res:#?}"); - - let tx_hash = res.tx_hash; - let transfer_tx = wallet_core - .poll_native_token_transfer(tx_hash.clone()) - .await?; - - if let NSSATransaction::PrivacyPreserving(tx) = transfer_tx { - let sender_ebc = tx.message.encrypted_private_post_states[0].clone(); - let sender_comm = tx.message.new_commitments[0].clone(); - - let recipient_ebc = tx.message.encrypted_private_post_states[1].clone(); - let recipient_comm = tx.message.new_commitments[1].clone(); - - let res_acc_sender = nssa_core::EncryptionScheme::decrypt( - &sender_ebc.ciphertext, - &secret_sender, - &sender_comm, - 0, - ) - .unwrap(); - - let res_acc_recipient = nssa_core::EncryptionScheme::decrypt( - &recipient_ebc.ciphertext, - &secret_recipient, - &recipient_comm, - 1, - ) - .unwrap(); - - println!("Received new sender acc {res_acc_sender:#?}"); - println!("Received new recipient acc {res_acc_recipient:#?}"); - - println!("Transaction data is {:?}", tx.message); - - wallet_core - .storage - .insert_private_account_data(sender_addr, res_acc_sender); - wallet_core - .storage - .insert_private_account_data(recipient_addr, res_acc_recipient); - } - - let path = wallet_core.store_persistent_accounts()?; - - println!("Stored persistent accounts at {path:#?}"); - - SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash } - } - Command::TransferTokenPrivateForeign { - sender_addr, - recipient_npk, - recipient_ipk, - balance_to_move, - } => { - let sender_addr: Address = sender_addr.parse().unwrap(); - let recipient_npk_res = hex::decode(recipient_npk)?; - let mut recipient_npk = [0; 32]; - recipient_npk.copy_from_slice(&recipient_npk_res); - let recipient_npk = nssa_core::NullifierPublicKey(recipient_npk); - - let recipient_ipk_res = hex::decode(recipient_ipk)?; - let mut recipient_ipk = [0u8; 33]; - recipient_ipk.copy_from_slice(&recipient_ipk_res); - let recipient_ipk = nssa_core::encryption::shared_key_derivation::Secp256k1Point( - recipient_ipk.to_vec(), - ); - - let (res, [secret_sender, _]) = wallet_core - .send_transfer_token_transaction_private_foreign_account( - sender_addr, - recipient_npk, - recipient_ipk, - balance_to_move, - ) - .await?; - - println!("Results of tx send is {res:#?}"); - - let tx_hash = res.tx_hash; - let transfer_tx = wallet_core - .poll_native_token_transfer(tx_hash.clone()) - .await?; - - if let NSSATransaction::PrivacyPreserving(tx) = transfer_tx { - let sender_ebc = tx.message.encrypted_private_post_states[0].clone(); - let sender_comm = tx.message.new_commitments[0].clone(); - - let res_acc_sender = nssa_core::EncryptionScheme::decrypt( - &sender_ebc.ciphertext, - &secret_sender, - &sender_comm, - 0, - ) - .unwrap(); - - println!("Received new sender acc {res_acc_sender:#?}"); - - println!("Transaction data is {:?}", tx.message); - - wallet_core - .storage - .insert_private_account_data(sender_addr, res_acc_sender); - } - - let path = wallet_core.store_persistent_accounts()?; - - println!("Stored persistent accounts at {path:#?}"); - - SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash } - } Command::ClaimPinata { pinata_addr, winner_addr, @@ -1125,6 +780,9 @@ pub async fn execute_subcommand(command: Command) -> Result { + token_subcommand.handle_subcommand(&mut wallet_core).await? + } }; Ok(subcommand_ret)