refactor: move some stuff to a more suitable place

This commit is contained in:
Daniil Polyakov 2025-11-27 22:07:53 +03:00
parent fa73a0a704
commit aee6f45a8b
17 changed files with 420 additions and 398 deletions

View File

@ -56,7 +56,7 @@ fn make_private_account_input_from_str(account_id: &str) -> String {
pub async fn pre_test( pub async fn pre_test(
home_dir: PathBuf, home_dir: PathBuf,
) -> Result<(ServerHandle, JoinHandle<Result<()>>, TempDir)> { ) -> Result<(ServerHandle, JoinHandle<Result<()>>, TempDir)> {
wallet::execute_setup("test_pass".to_owned()).await?; wallet::cli::execute_setup("test_pass".to_owned()).await?;
let home_dir_sequencer = home_dir.join("sequencer"); let home_dir_sequencer = home_dir.join("sequencer");

View File

@ -16,13 +16,15 @@ use sequencer_runner::startup_sequencer;
use tempfile::TempDir; use tempfile::TempDir;
use tokio::task::JoinHandle; use tokio::task::JoinHandle;
use wallet::{ use wallet::{
Command, SubcommandReturnValue, WalletCore, WalletCore,
cli::{ cli::{
Command, SubcommandReturnValue,
account::{AccountSubcommand, NewSubcommand}, account::{AccountSubcommand, NewSubcommand},
config::ConfigSubcommand, config::ConfigSubcommand,
native_token_transfer_program::AuthTransferSubcommand, programs::{
pinata_program::PinataProgramAgnosticSubcommand, native_token_transfer::AuthTransferSubcommand, pinata::PinataProgramAgnosticSubcommand,
token_program::TokenProgramAgnosticSubcommand, token::TokenProgramAgnosticSubcommand,
},
}, },
config::PersistentStorage, config::PersistentStorage,
helperfunctions::{fetch_config, fetch_persistent_storage}, helperfunctions::{fetch_config, fetch_persistent_storage},
@ -57,7 +59,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
let seq_client = SequencerClient::new(wallet_config.sequencer_addr.clone()).unwrap(); let seq_client = SequencerClient::new(wallet_config.sequencer_addr.clone()).unwrap();
wallet::execute_subcommand(command).await.unwrap(); wallet::cli::execute_subcommand(command).await.unwrap();
info!("Waiting for next block creation"); info!("Waiting for next block creation");
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
@ -92,7 +94,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
let seq_client = SequencerClient::new(wallet_config.sequencer_addr.clone()).unwrap(); let seq_client = SequencerClient::new(wallet_config.sequencer_addr.clone()).unwrap();
wallet::execute_subcommand(command).await.unwrap(); wallet::cli::execute_subcommand(command).await.unwrap();
let PersistentStorage { let PersistentStorage {
accounts: persistent_accounts, accounts: persistent_accounts,
@ -123,7 +125,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
amount: 100, amount: 100,
}); });
wallet::execute_subcommand(command).await.unwrap(); wallet::cli::execute_subcommand(command).await.unwrap();
info!("Waiting for next block creation"); info!("Waiting for next block creation");
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
@ -162,7 +164,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
let seq_client = SequencerClient::new(wallet_config.sequencer_addr.clone()).unwrap(); let seq_client = SequencerClient::new(wallet_config.sequencer_addr.clone()).unwrap();
let failed_send = wallet::execute_subcommand(command).await; let failed_send = wallet::cli::execute_subcommand(command).await;
assert!(failed_send.is_err()); assert!(failed_send.is_err());
@ -203,7 +205,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
let seq_client = SequencerClient::new(wallet_config.sequencer_addr.clone()).unwrap(); let seq_client = SequencerClient::new(wallet_config.sequencer_addr.clone()).unwrap();
wallet::execute_subcommand(command).await.unwrap(); wallet::cli::execute_subcommand(command).await.unwrap();
info!("Waiting for next block creation"); info!("Waiting for next block creation");
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
@ -234,7 +236,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
amount: 100, amount: 100,
}); });
wallet::execute_subcommand(command).await.unwrap(); wallet::cli::execute_subcommand(command).await.unwrap();
info!("Waiting for next block creation"); info!("Waiting for next block creation");
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
@ -289,7 +291,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
// Create new account for the token definition // Create new account for the token definition
let SubcommandReturnValue::RegisterAccount { let SubcommandReturnValue::RegisterAccount {
account_id: definition_account_id, account_id: definition_account_id,
} = wallet::execute_subcommand(Command::Account(AccountSubcommand::New( } = wallet::cli::execute_subcommand(Command::Account(AccountSubcommand::New(
NewSubcommand::Public { NewSubcommand::Public {
cci: ChainIndex::root(), cci: ChainIndex::root(),
}, },
@ -302,7 +304,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
// Create new account for the token supply holder // Create new account for the token supply holder
let SubcommandReturnValue::RegisterAccount { let SubcommandReturnValue::RegisterAccount {
account_id: supply_account_id, account_id: supply_account_id,
} = wallet::execute_subcommand(Command::Account(AccountSubcommand::New( } = wallet::cli::execute_subcommand(Command::Account(AccountSubcommand::New(
NewSubcommand::Public { NewSubcommand::Public {
cci: ChainIndex::root(), cci: ChainIndex::root(),
}, },
@ -315,7 +317,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
// Create new account for receiving a token transaction // Create new account for receiving a token transaction
let SubcommandReturnValue::RegisterAccount { let SubcommandReturnValue::RegisterAccount {
account_id: recipient_account_id, account_id: recipient_account_id,
} = wallet::execute_subcommand(Command::Account(AccountSubcommand::New( } = wallet::cli::execute_subcommand(Command::Account(AccountSubcommand::New(
NewSubcommand::Public { NewSubcommand::Public {
cci: ChainIndex::root(), cci: ChainIndex::root(),
}, },
@ -335,7 +337,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
name: "A NAME".to_string(), name: "A NAME".to_string(),
total_supply: 37, total_supply: 37,
}; };
wallet::execute_subcommand(Command::Token(subcommand)) wallet::cli::execute_subcommand(Command::Token(subcommand))
.await .await
.unwrap(); .unwrap();
info!("Waiting for next block creation"); info!("Waiting for next block creation");
@ -394,7 +396,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
amount: 7, amount: 7,
}; };
wallet::execute_subcommand(Command::Token(subcommand)) wallet::cli::execute_subcommand(Command::Token(subcommand))
.await .await
.unwrap(); .unwrap();
info!("Waiting for next block creation"); info!("Waiting for next block creation");
@ -449,7 +451,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
// Create new account for the token definition (public) // Create new account for the token definition (public)
let SubcommandReturnValue::RegisterAccount { let SubcommandReturnValue::RegisterAccount {
account_id: definition_account_id, account_id: definition_account_id,
} = wallet::execute_subcommand(Command::Account(AccountSubcommand::New( } = wallet::cli::execute_subcommand(Command::Account(AccountSubcommand::New(
NewSubcommand::Public { NewSubcommand::Public {
cci: ChainIndex::root(), cci: ChainIndex::root(),
}, },
@ -462,7 +464,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
// Create new account for the token supply holder (private) // Create new account for the token supply holder (private)
let SubcommandReturnValue::RegisterAccount { let SubcommandReturnValue::RegisterAccount {
account_id: supply_account_id, account_id: supply_account_id,
} = wallet::execute_subcommand(Command::Account(AccountSubcommand::New( } = wallet::cli::execute_subcommand(Command::Account(AccountSubcommand::New(
NewSubcommand::Private { NewSubcommand::Private {
cci: ChainIndex::root(), cci: ChainIndex::root(),
}, },
@ -475,7 +477,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
// Create new account for receiving a token transaction // Create new account for receiving a token transaction
let SubcommandReturnValue::RegisterAccount { let SubcommandReturnValue::RegisterAccount {
account_id: recipient_account_id, account_id: recipient_account_id,
} = wallet::execute_subcommand(Command::Account(AccountSubcommand::New( } = wallet::cli::execute_subcommand(Command::Account(AccountSubcommand::New(
NewSubcommand::Private { NewSubcommand::Private {
cci: ChainIndex::root(), cci: ChainIndex::root(),
}, },
@ -496,7 +498,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
total_supply: 37, total_supply: 37,
}; };
wallet::execute_subcommand(Command::Token(subcommand)) wallet::cli::execute_subcommand(Command::Token(subcommand))
.await .await
.unwrap(); .unwrap();
@ -543,7 +545,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
amount: 7, amount: 7,
}; };
wallet::execute_subcommand(Command::Token(subcommand)) wallet::cli::execute_subcommand(Command::Token(subcommand))
.await .await
.unwrap(); .unwrap();
@ -577,7 +579,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
amount: 7, amount: 7,
}; };
wallet::execute_subcommand(Command::Token(subcommand)) wallet::cli::execute_subcommand(Command::Token(subcommand))
.await .await
.unwrap(); .unwrap();
@ -610,7 +612,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
// Create new account for the token definition (public) // Create new account for the token definition (public)
let SubcommandReturnValue::RegisterAccount { let SubcommandReturnValue::RegisterAccount {
account_id: definition_account_id, account_id: definition_account_id,
} = wallet::execute_subcommand(Command::Account(AccountSubcommand::New( } = wallet::cli::execute_subcommand(Command::Account(AccountSubcommand::New(
NewSubcommand::Public { NewSubcommand::Public {
cci: ChainIndex::root(), cci: ChainIndex::root(),
}, },
@ -623,7 +625,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
// Create new account for the token supply holder (private) // Create new account for the token supply holder (private)
let SubcommandReturnValue::RegisterAccount { let SubcommandReturnValue::RegisterAccount {
account_id: supply_account_id, account_id: supply_account_id,
} = wallet::execute_subcommand(Command::Account(AccountSubcommand::New( } = wallet::cli::execute_subcommand(Command::Account(AccountSubcommand::New(
NewSubcommand::Private { NewSubcommand::Private {
cci: ChainIndex::root(), cci: ChainIndex::root(),
}, },
@ -636,7 +638,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
// Create new account for receiving a token transaction // Create new account for receiving a token transaction
let SubcommandReturnValue::RegisterAccount { let SubcommandReturnValue::RegisterAccount {
account_id: recipient_account_id, account_id: recipient_account_id,
} = wallet::execute_subcommand(Command::Account(AccountSubcommand::New( } = wallet::cli::execute_subcommand(Command::Account(AccountSubcommand::New(
NewSubcommand::Private { NewSubcommand::Private {
cci: ChainIndex::root(), cci: ChainIndex::root(),
}, },
@ -657,7 +659,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
total_supply: 37, total_supply: 37,
}; };
wallet::execute_subcommand(Command::Token(subcommand)) wallet::cli::execute_subcommand(Command::Token(subcommand))
.await .await
.unwrap(); .unwrap();
@ -711,7 +713,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
}; };
let SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash: _ } = let SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash: _ } =
wallet::execute_subcommand(Command::Token(subcommand)) wallet::cli::execute_subcommand(Command::Token(subcommand))
.await .await
.unwrap() .unwrap()
else { else {
@ -723,7 +725,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
let command = Command::Account(AccountSubcommand::SyncPrivate {}); let command = Command::Account(AccountSubcommand::SyncPrivate {});
wallet::execute_subcommand(command).await.unwrap(); wallet::cli::execute_subcommand(command).await.unwrap();
let wallet_config = fetch_config().await.unwrap(); let wallet_config = fetch_config().await.unwrap();
let wallet_storage = WalletCore::start_from_config_update_chain(wallet_config) let wallet_storage = WalletCore::start_from_config_update_chain(wallet_config)
@ -752,7 +754,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
// Create new account for the token definition (public) // Create new account for the token definition (public)
let SubcommandReturnValue::RegisterAccount { let SubcommandReturnValue::RegisterAccount {
account_id: definition_account_id, account_id: definition_account_id,
} = wallet::execute_subcommand(Command::Account(AccountSubcommand::New( } = wallet::cli::execute_subcommand(Command::Account(AccountSubcommand::New(
NewSubcommand::Public { NewSubcommand::Public {
cci: ChainIndex::root(), cci: ChainIndex::root(),
}, },
@ -765,7 +767,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
// Create new account for the token supply holder (public) // Create new account for the token supply holder (public)
let SubcommandReturnValue::RegisterAccount { let SubcommandReturnValue::RegisterAccount {
account_id: supply_account_id, account_id: supply_account_id,
} = wallet::execute_subcommand(Command::Account(AccountSubcommand::New( } = wallet::cli::execute_subcommand(Command::Account(AccountSubcommand::New(
NewSubcommand::Public { NewSubcommand::Public {
cci: ChainIndex::root(), cci: ChainIndex::root(),
}, },
@ -778,7 +780,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
// Create new account for receiving a token transaction // Create new account for receiving a token transaction
let SubcommandReturnValue::RegisterAccount { let SubcommandReturnValue::RegisterAccount {
account_id: recipient_account_id, account_id: recipient_account_id,
} = wallet::execute_subcommand(Command::Account(AccountSubcommand::New( } = wallet::cli::execute_subcommand(Command::Account(AccountSubcommand::New(
NewSubcommand::Private { NewSubcommand::Private {
cci: ChainIndex::root(), cci: ChainIndex::root(),
}, },
@ -799,7 +801,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
total_supply: 37, total_supply: 37,
}; };
wallet::execute_subcommand(Command::Token(subcommand)) wallet::cli::execute_subcommand(Command::Token(subcommand))
.await .await
.unwrap(); .unwrap();
@ -836,7 +838,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
amount: 7, amount: 7,
}; };
wallet::execute_subcommand(Command::Token(subcommand)) wallet::cli::execute_subcommand(Command::Token(subcommand))
.await .await
.unwrap(); .unwrap();
@ -865,7 +867,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
amount: 7, amount: 7,
}; };
wallet::execute_subcommand(Command::Token(subcommand)) wallet::cli::execute_subcommand(Command::Token(subcommand))
.await .await
.unwrap(); .unwrap();
@ -894,7 +896,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
// Create new account for the token definition (public) // Create new account for the token definition (public)
let SubcommandReturnValue::RegisterAccount { let SubcommandReturnValue::RegisterAccount {
account_id: definition_account_id, account_id: definition_account_id,
} = wallet::execute_subcommand(Command::Account(AccountSubcommand::New( } = wallet::cli::execute_subcommand(Command::Account(AccountSubcommand::New(
NewSubcommand::Public { NewSubcommand::Public {
cci: ChainIndex::root(), cci: ChainIndex::root(),
}, },
@ -907,7 +909,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
// Create new account for the token supply holder (private) // Create new account for the token supply holder (private)
let SubcommandReturnValue::RegisterAccount { let SubcommandReturnValue::RegisterAccount {
account_id: supply_account_id, account_id: supply_account_id,
} = wallet::execute_subcommand(Command::Account(AccountSubcommand::New( } = wallet::cli::execute_subcommand(Command::Account(AccountSubcommand::New(
NewSubcommand::Private { NewSubcommand::Private {
cci: ChainIndex::root(), cci: ChainIndex::root(),
}, },
@ -920,7 +922,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
// Create new account for receiving a token transaction // Create new account for receiving a token transaction
let SubcommandReturnValue::RegisterAccount { let SubcommandReturnValue::RegisterAccount {
account_id: recipient_account_id, account_id: recipient_account_id,
} = wallet::execute_subcommand(Command::Account(AccountSubcommand::New( } = wallet::cli::execute_subcommand(Command::Account(AccountSubcommand::New(
NewSubcommand::Public { NewSubcommand::Public {
cci: ChainIndex::root(), cci: ChainIndex::root(),
}, },
@ -941,7 +943,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
total_supply: 37, total_supply: 37,
}; };
wallet::execute_subcommand(Command::Token(subcommand)) wallet::cli::execute_subcommand(Command::Token(subcommand))
.await .await
.unwrap(); .unwrap();
@ -988,7 +990,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
amount: 7, amount: 7,
}; };
wallet::execute_subcommand(Command::Token(subcommand)) wallet::cli::execute_subcommand(Command::Token(subcommand))
.await .await
.unwrap(); .unwrap();
@ -1017,7 +1019,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
amount: 7, amount: 7,
}; };
wallet::execute_subcommand(Command::Token(subcommand)) wallet::cli::execute_subcommand(Command::Token(subcommand))
.await .await
.unwrap(); .unwrap();
@ -1049,7 +1051,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
amount: 100, amount: 100,
}); });
wallet::execute_subcommand(command).await.unwrap(); wallet::cli::execute_subcommand(command).await.unwrap();
info!("Waiting for next block creation"); info!("Waiting for next block creation");
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
@ -1088,7 +1090,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
}); });
let SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash } = let SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash } =
wallet::execute_subcommand(command).await.unwrap() wallet::cli::execute_subcommand(command).await.unwrap()
else { else {
panic!("invalid subcommand return value"); panic!("invalid subcommand return value");
}; };
@ -1128,7 +1130,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
cci: ChainIndex::root(), cci: ChainIndex::root(),
})); }));
let sub_ret = wallet::execute_subcommand(command).await.unwrap(); let sub_ret = wallet::cli::execute_subcommand(command).await.unwrap();
let SubcommandReturnValue::RegisterAccount { let SubcommandReturnValue::RegisterAccount {
account_id: to_account_id, account_id: to_account_id,
} = sub_ret } = sub_ret
@ -1157,7 +1159,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
amount: 100, amount: 100,
}); });
let sub_ret = wallet::execute_subcommand(command).await.unwrap(); let sub_ret = wallet::cli::execute_subcommand(command).await.unwrap();
let SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash } = sub_ret else { let SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash } = sub_ret else {
panic!("FAILED TO SEND TX"); panic!("FAILED TO SEND TX");
}; };
@ -1165,7 +1167,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
let tx = fetch_privacy_preserving_tx(&seq_client, tx_hash.clone()).await; let tx = fetch_privacy_preserving_tx(&seq_client, tx_hash.clone()).await;
let command = Command::Account(AccountSubcommand::SyncPrivate {}); let command = Command::Account(AccountSubcommand::SyncPrivate {});
wallet::execute_subcommand(command).await.unwrap(); wallet::cli::execute_subcommand(command).await.unwrap();
let wallet_storage = WalletCore::start_from_config_update_chain(wallet_config) let wallet_storage = WalletCore::start_from_config_update_chain(wallet_config)
.await .await
.unwrap(); .unwrap();
@ -1192,13 +1194,13 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
// info!( // info!(
// "########## test_success_private_transfer_to_another_owned_account_cont_run_path // "########## test_success_private_transfer_to_another_owned_account_cont_run_path
// ##########" ); // ##########" );
// let continious_run_handle = tokio::spawn(wallet::execute_continious_run()); // let continious_run_handle = tokio::spawn(wallet::cli::execute_continious_run());
// let from: AccountId = ACC_SENDER_PRIVATE.parse().unwrap(); // let from: AccountId = ACC_SENDER_PRIVATE.parse().unwrap();
// let command = Command::Account(AccountSubcommand::New(NewSubcommand::Private {})); // let command = Command::Account(AccountSubcommand::New(NewSubcommand::Private {}));
// let sub_ret = wallet::execute_subcommand(command).await.unwrap(); // let sub_ret = wallet::cli::execute_subcommand(command).await.unwrap();
// let SubcommandReturnValue::RegisterAccount { // let SubcommandReturnValue::RegisterAccount {
// account_id: to_account_id, // account_id: to_account_id,
// } = sub_ret // } = sub_ret
@ -1228,7 +1230,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
// amount: 100, // amount: 100,
// }); // });
// let sub_ret = wallet::execute_subcommand(command).await.unwrap(); // let sub_ret = wallet::cli::execute_subcommand(command).await.unwrap();
// let SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash } = sub_ret else { // let SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash } = sub_ret else {
// panic!("FAILED TO SEND TX"); // panic!("FAILED TO SEND TX");
// }; // };
@ -1279,7 +1281,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
let from_acc = wallet_storage.get_account_private(&from).unwrap(); let from_acc = wallet_storage.get_account_private(&from).unwrap();
assert_eq!(from_acc.balance, 10000); assert_eq!(from_acc.balance, 10000);
wallet::execute_subcommand(command).await.unwrap(); wallet::cli::execute_subcommand(command).await.unwrap();
info!("Waiting for next block creation"); info!("Waiting for next block creation");
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
@ -1322,7 +1324,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
let wallet_config = fetch_config().await.unwrap(); let wallet_config = fetch_config().await.unwrap();
let seq_client = SequencerClient::new(wallet_config.sequencer_addr.clone()).unwrap(); let seq_client = SequencerClient::new(wallet_config.sequencer_addr.clone()).unwrap();
wallet::execute_subcommand(command).await.unwrap(); wallet::cli::execute_subcommand(command).await.unwrap();
info!("Waiting for next block creation"); info!("Waiting for next block creation");
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
@ -1368,7 +1370,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
let seq_client = SequencerClient::new(wallet_config.sequencer_addr.clone()).unwrap(); let seq_client = SequencerClient::new(wallet_config.sequencer_addr.clone()).unwrap();
let SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash } = let SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash } =
wallet::execute_subcommand(command).await.unwrap() wallet::cli::execute_subcommand(command).await.unwrap()
else { else {
panic!("invalid subcommand return value"); panic!("invalid subcommand return value");
}; };
@ -1414,7 +1416,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
.unwrap() .unwrap()
.balance; .balance;
wallet::execute_subcommand(command).await.unwrap(); wallet::cli::execute_subcommand(command).await.unwrap();
info!("Waiting for next block creation"); info!("Waiting for next block creation");
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
@ -1493,7 +1495,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
cci: ChainIndex::root(), cci: ChainIndex::root(),
})); }));
let SubcommandReturnValue::RegisterAccount { account_id } = let SubcommandReturnValue::RegisterAccount { account_id } =
wallet::execute_subcommand(command).await.unwrap() wallet::cli::execute_subcommand(command).await.unwrap()
else { else {
panic!("Error creating account"); panic!("Error creating account");
}; };
@ -1501,7 +1503,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
let command = Command::AuthTransfer(AuthTransferSubcommand::Init { let command = Command::AuthTransfer(AuthTransferSubcommand::Init {
account_id: make_public_account_input_from_str(&account_id.to_string()), account_id: make_public_account_input_from_str(&account_id.to_string()),
}); });
wallet::execute_subcommand(command).await.unwrap(); wallet::cli::execute_subcommand(command).await.unwrap();
info!("Checking correct execution"); info!("Checking correct execution");
let wallet_config = fetch_config().await.unwrap(); let wallet_config = fetch_config().await.unwrap();
@ -1547,7 +1549,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
.balance; .balance;
let SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash: _ } = let SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash: _ } =
wallet::execute_subcommand(command).await.unwrap() wallet::cli::execute_subcommand(command).await.unwrap()
else { else {
panic!("invalid subcommand return value"); panic!("invalid subcommand return value");
}; };
@ -1563,7 +1565,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
.balance; .balance;
let command = Command::Account(AccountSubcommand::SyncPrivate {}); let command = Command::Account(AccountSubcommand::SyncPrivate {});
wallet::execute_subcommand(command).await.unwrap(); wallet::cli::execute_subcommand(command).await.unwrap();
let wallet_config = fetch_config().await.unwrap(); let wallet_config = fetch_config().await.unwrap();
let seq_client = SequencerClient::new(wallet_config.sequencer_addr.clone()).unwrap(); let seq_client = SequencerClient::new(wallet_config.sequencer_addr.clone()).unwrap();
@ -1591,7 +1593,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
// Create new account for the token supply holder (private) // Create new account for the token supply holder (private)
let SubcommandReturnValue::RegisterAccount { let SubcommandReturnValue::RegisterAccount {
account_id: winner_account_id, account_id: winner_account_id,
} = wallet::execute_subcommand(Command::Account(AccountSubcommand::New( } = wallet::cli::execute_subcommand(Command::Account(AccountSubcommand::New(
NewSubcommand::Private { NewSubcommand::Private {
cci: ChainIndex::root(), cci: ChainIndex::root(),
}, },
@ -1617,7 +1619,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
.unwrap() .unwrap()
.balance; .balance;
wallet::execute_subcommand(command).await.unwrap(); wallet::cli::execute_subcommand(command).await.unwrap();
info!("Waiting for next block creation"); info!("Waiting for next block creation");
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
@ -1657,7 +1659,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
key: "seq_poll_retry_delay_millis".to_string(), key: "seq_poll_retry_delay_millis".to_string(),
value: "1000".to_string(), value: "1000".to_string(),
}); });
wallet::execute_subcommand(command).await.unwrap(); wallet::cli::execute_subcommand(command).await.unwrap();
let wallet_config = fetch_config().await.unwrap(); let wallet_config = fetch_config().await.unwrap();
@ -1668,7 +1670,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
key: "seq_poll_retry_delay_millis".to_string(), key: "seq_poll_retry_delay_millis".to_string(),
value: old_seq_poll_retry_delay_millis.to_string(), value: old_seq_poll_retry_delay_millis.to_string(),
}); });
wallet::execute_subcommand(command).await.unwrap(); wallet::cli::execute_subcommand(command).await.unwrap();
info!("Success!"); info!("Success!");
} }

View File

@ -7,10 +7,11 @@ use nssa::{Account, AccountId, program::Program};
use serde::Serialize; use serde::Serialize;
use crate::{ use crate::{
SubcommandReturnValue, WalletCore, WalletCore,
cli::WalletSubcommand, cli::{SubcommandReturnValue, WalletSubcommand},
helperfunctions::{AccountPrivacyKind, HumanReadableAccount, parse_addr_with_privacy_prefix}, helperfunctions::{
parse_block_range, AccountPrivacyKind, HumanReadableAccount, parse_addr_with_privacy_prefix, parse_block_range,
},
}; };
const TOKEN_DEFINITION_TYPE: u8 = 0; const TOKEN_DEFINITION_TYPE: u8 = 0;

View File

@ -1,7 +1,10 @@
use anyhow::Result; use anyhow::Result;
use clap::Subcommand; use clap::Subcommand;
use crate::{SubcommandReturnValue, WalletCore, cli::WalletSubcommand}; use crate::{
WalletCore,
cli::{SubcommandReturnValue, WalletSubcommand},
};
/// Represents generic chain CLI subcommand /// Represents generic chain CLI subcommand
#[derive(Subcommand, Debug, Clone)] #[derive(Subcommand, Debug, Clone)]

View File

@ -1,7 +1,10 @@
use anyhow::Result; use anyhow::Result;
use clap::Subcommand; use clap::Subcommand;
use crate::{SubcommandReturnValue, WalletCore, cli::WalletSubcommand}; use crate::{
WalletCore,
cli::{SubcommandReturnValue, WalletSubcommand},
};
/// Represents generic config CLI subcommand /// Represents generic config CLI subcommand
#[derive(Subcommand, Debug, Clone)] #[derive(Subcommand, Debug, Clone)]

View File

@ -1,15 +1,200 @@
use anyhow::Result; use std::sync::Arc;
use crate::{SubcommandReturnValue, WalletCore}; use anyhow::Result;
use clap::{Parser, Subcommand};
use common::sequencer_client::SequencerClient;
use nssa::program::Program;
use crate::{
WalletCore,
cli::{
account::AccountSubcommand,
chain::ChainSubcommand,
config::ConfigSubcommand,
programs::{
native_token_transfer::AuthTransferSubcommand, pinata::PinataProgramAgnosticSubcommand,
token::TokenProgramAgnosticSubcommand,
},
},
helperfunctions::{fetch_config, parse_block_range},
};
pub mod account; pub mod account;
pub mod chain; pub mod chain;
pub mod config; pub mod config;
pub mod native_token_transfer_program; pub mod programs;
pub mod pinata_program;
pub mod token_program;
pub(crate) trait WalletSubcommand { pub(crate) trait WalletSubcommand {
async fn handle_subcommand(self, wallet_core: &mut WalletCore) async fn handle_subcommand(self, wallet_core: &mut WalletCore)
-> Result<SubcommandReturnValue>; -> Result<SubcommandReturnValue>;
} }
/// Represents CLI command for a wallet
#[derive(Subcommand, Debug, Clone)]
#[clap(about)]
pub enum Command {
/// Authenticated transfer subcommand
#[command(subcommand)]
AuthTransfer(AuthTransferSubcommand),
/// Generic chain info subcommand
#[command(subcommand)]
ChainInfo(ChainSubcommand),
/// Account view and sync subcommand
#[command(subcommand)]
Account(AccountSubcommand),
/// Pinata program interaction subcommand
#[command(subcommand)]
Pinata(PinataProgramAgnosticSubcommand),
/// Token program interaction subcommand
#[command(subcommand)]
Token(TokenProgramAgnosticSubcommand),
/// Check the wallet can connect to the node and builtin local programs
/// match the remote versions
CheckHealth {},
/// Command to setup config, get and set config fields
#[command(subcommand)]
Config(ConfigSubcommand),
}
/// Represents overarching CLI command for a wallet with setup included
#[derive(Debug, Subcommand, Clone)]
#[clap(about)]
pub enum OverCommand {
/// Represents CLI command for a wallet
#[command(subcommand)]
Command(Command),
/// Setup of a storage. Initializes rots for public and private trees from `password`.
Setup {
#[arg(short, long)]
password: String,
},
}
/// To execute commands, env var NSSA_WALLET_HOME_DIR must be set into directory with config
///
/// All account adresses must be valid 32 byte base58 strings.
///
/// All account account_ids must be provided as {privacy_prefix}/{account_id},
/// where valid options for `privacy_prefix` is `Public` and `Private`
#[derive(Parser, Debug)]
#[clap(version, about)]
pub struct Args {
/// Continious run flag
#[arg(short, long)]
pub continious_run: bool,
/// Wallet command
#[command(subcommand)]
pub command: Option<OverCommand>,
}
#[derive(Debug, Clone)]
pub enum SubcommandReturnValue {
PrivacyPreservingTransfer { tx_hash: String },
RegisterAccount { account_id: nssa::AccountId },
Account(nssa::Account),
Empty,
SyncedToBlock(u64),
}
pub async fn execute_subcommand(command: Command) -> Result<SubcommandReturnValue> {
let wallet_config = fetch_config().await?;
let mut wallet_core = WalletCore::start_from_config_update_chain(wallet_config).await?;
let subcommand_ret = match command {
Command::AuthTransfer(transfer_subcommand) => {
transfer_subcommand
.handle_subcommand(&mut wallet_core)
.await?
}
Command::ChainInfo(chain_subcommand) => {
chain_subcommand.handle_subcommand(&mut wallet_core).await?
}
Command::Account(account_subcommand) => {
account_subcommand
.handle_subcommand(&mut wallet_core)
.await?
}
Command::Pinata(pinata_subcommand) => {
pinata_subcommand
.handle_subcommand(&mut wallet_core)
.await?
}
Command::CheckHealth {} => {
let remote_program_ids = wallet_core
.sequencer_client
.get_program_ids()
.await
.expect("Error fetching program ids");
let Some(authenticated_transfer_id) = remote_program_ids.get("authenticated_transfer")
else {
panic!("Missing authenticated transfer ID from remote");
};
if authenticated_transfer_id != &Program::authenticated_transfer_program().id() {
panic!("Local ID for authenticated transfer program is different from remote");
}
let Some(token_id) = remote_program_ids.get("token") else {
panic!("Missing token program ID from remote");
};
if token_id != &Program::token().id() {
panic!("Local ID for token program is different from remote");
}
let Some(circuit_id) = remote_program_ids.get("privacy_preserving_circuit") else {
panic!("Missing privacy preserving circuit ID from remote");
};
if circuit_id != &nssa::PRIVACY_PRESERVING_CIRCUIT_ID {
panic!("Local ID for privacy preserving circuit is different from remote");
}
println!("✅All looks good!");
SubcommandReturnValue::Empty
}
Command::Token(token_subcommand) => {
token_subcommand.handle_subcommand(&mut wallet_core).await?
}
Command::Config(config_subcommand) => {
config_subcommand
.handle_subcommand(&mut wallet_core)
.await?
}
};
Ok(subcommand_ret)
}
pub async fn execute_continious_run() -> Result<()> {
let config = fetch_config().await?;
let seq_client = Arc::new(SequencerClient::new(config.sequencer_addr.clone())?);
let mut wallet_core = WalletCore::start_from_config_update_chain(config.clone()).await?;
let mut latest_block_num = seq_client.get_last_block().await?.last_block;
let mut curr_last_block = latest_block_num;
loop {
parse_block_range(
curr_last_block,
latest_block_num,
seq_client.clone(),
&mut wallet_core,
)
.await?;
curr_last_block = latest_block_num + 1;
tokio::time::sleep(std::time::Duration::from_millis(
config.seq_poll_timeout_millis,
))
.await;
latest_block_num = seq_client.get_last_block().await?.last_block;
}
}
pub async fn execute_setup(password: String) -> Result<()> {
let config = fetch_config().await?;
let wallet_core = WalletCore::start_from_config_new_storage(config.clone(), password).await?;
wallet_core.store_persistent_data().await?;
Ok(())
}

View File

@ -0,0 +1,3 @@
pub mod native_token_transfer;
pub mod pinata;
pub mod token;

View File

@ -4,8 +4,8 @@ use common::transaction::NSSATransaction;
use nssa::AccountId; use nssa::AccountId;
use crate::{ use crate::{
SubcommandReturnValue, WalletCore, WalletCore,
cli::WalletSubcommand, cli::{SubcommandReturnValue, WalletSubcommand},
helperfunctions::{AccountPrivacyKind, parse_addr_with_privacy_prefix}, helperfunctions::{AccountPrivacyKind, parse_addr_with_privacy_prefix},
}; };

View File

@ -4,8 +4,8 @@ use common::{PINATA_BASE58, transaction::NSSATransaction};
use log::info; use log::info;
use crate::{ use crate::{
SubcommandReturnValue, WalletCore, WalletCore,
cli::WalletSubcommand, cli::{SubcommandReturnValue, WalletSubcommand},
helperfunctions::{AccountPrivacyKind, parse_addr_with_privacy_prefix}, helperfunctions::{AccountPrivacyKind, parse_addr_with_privacy_prefix},
}; };

View File

@ -4,8 +4,8 @@ use common::transaction::NSSATransaction;
use nssa::AccountId; use nssa::AccountId;
use crate::{ use crate::{
SubcommandReturnValue, WalletCore, WalletCore,
cli::WalletSubcommand, cli::{SubcommandReturnValue, WalletSubcommand},
helperfunctions::{AccountPrivacyKind, parse_addr_with_privacy_prefix}, helperfunctions::{AccountPrivacyKind, parse_addr_with_privacy_prefix},
}; };

View File

@ -1,16 +1,21 @@
use std::{path::PathBuf, str::FromStr}; use std::{path::PathBuf, str::FromStr, sync::Arc};
use anyhow::Result; use anyhow::Result;
use base64::{Engine, engine::general_purpose::STANDARD as BASE64}; use base64::{Engine, engine::general_purpose::STANDARD as BASE64};
use key_protocol::key_protocol_core::NSSAUserData; use common::{
use nssa::Account; block::HashableBlockData, sequencer_client::SequencerClient, transaction::NSSATransaction,
};
use key_protocol::{
key_management::key_tree::traits::KeyNode as _, key_protocol_core::NSSAUserData,
};
use nssa::{Account, privacy_preserving_transaction::message::EncryptedAccountData};
use nssa_core::account::Nonce; use nssa_core::account::Nonce;
use rand::{RngCore, rngs::OsRng}; use rand::{RngCore, rngs::OsRng};
use serde::Serialize; use serde::Serialize;
use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::io::{AsyncReadExt, AsyncWriteExt};
use crate::{ use crate::{
HOME_DIR_ENV_VAR, HOME_DIR_ENV_VAR, WalletCore,
config::{ config::{
InitialAccountData, InitialAccountDataPrivate, InitialAccountDataPublic, InitialAccountData, InitialAccountDataPrivate, InitialAccountDataPublic,
PersistentAccountDataPrivate, PersistentAccountDataPublic, PersistentStorage, WalletConfig, PersistentAccountDataPrivate, PersistentAccountDataPublic, PersistentStorage, WalletConfig,
@ -225,6 +230,125 @@ impl From<Account> for HumanReadableAccount {
} }
} }
pub async fn parse_block_range(
start: u64,
stop: u64,
seq_client: Arc<SequencerClient>,
wallet_core: &mut WalletCore,
) -> Result<()> {
for block_id in start..(stop + 1) {
let block =
borsh::from_slice::<HashableBlockData>(&seq_client.get_block(block_id).await?.block)?;
for tx in block.transactions {
let nssa_tx = NSSATransaction::try_from(&tx)?;
if let NSSATransaction::PrivacyPreserving(tx) = nssa_tx {
let mut affected_accounts = vec![];
for (acc_account_id, (key_chain, _)) in
&wallet_core.storage.user_data.default_user_private_accounts
{
let view_tag = EncryptedAccountData::compute_view_tag(
key_chain.nullifer_public_key.clone(),
key_chain.incoming_viewing_public_key.clone(),
);
for (ciph_id, encrypted_data) in tx
.message()
.encrypted_private_post_states
.iter()
.enumerate()
{
if encrypted_data.view_tag == view_tag {
let ciphertext = &encrypted_data.ciphertext;
let commitment = &tx.message.new_commitments[ciph_id];
let shared_secret = key_chain
.calculate_shared_secret_receiver(encrypted_data.epk.clone());
let res_acc = nssa_core::EncryptionScheme::decrypt(
ciphertext,
&shared_secret,
commitment,
ciph_id as u32,
);
if let Some(res_acc) = res_acc {
println!(
"Received new account for account_id {acc_account_id:#?} with account object {res_acc:#?}"
);
affected_accounts.push((*acc_account_id, res_acc));
}
}
}
}
for keys_node in wallet_core
.storage
.user_data
.private_key_tree
.key_map
.values()
{
let acc_account_id = keys_node.account_id();
let key_chain = &keys_node.value.0;
let view_tag = EncryptedAccountData::compute_view_tag(
key_chain.nullifer_public_key.clone(),
key_chain.incoming_viewing_public_key.clone(),
);
for (ciph_id, encrypted_data) in tx
.message()
.encrypted_private_post_states
.iter()
.enumerate()
{
if encrypted_data.view_tag == view_tag {
let ciphertext = &encrypted_data.ciphertext;
let commitment = &tx.message.new_commitments[ciph_id];
let shared_secret = key_chain
.calculate_shared_secret_receiver(encrypted_data.epk.clone());
let res_acc = nssa_core::EncryptionScheme::decrypt(
ciphertext,
&shared_secret,
commitment,
ciph_id as u32,
);
if let Some(res_acc) = res_acc {
println!(
"Received new account for account_id {acc_account_id:#?} with account object {res_acc:#?}"
);
affected_accounts.push((acc_account_id, res_acc));
}
}
}
}
for (affected_account_id, new_acc) in affected_accounts {
wallet_core
.storage
.insert_private_account_data(affected_account_id, new_acc);
}
}
}
wallet_core.last_synced_block = block_id;
wallet_core.store_persistent_data().await?;
println!(
"Block at id {block_id} with timestamp {} parsed",
block.timestamp
);
}
Ok(())
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

@ -3,31 +3,20 @@ use std::{path::PathBuf, sync::Arc};
use anyhow::Result; use anyhow::Result;
use base64::{Engine, engine::general_purpose::STANDARD as BASE64}; use base64::{Engine, engine::general_purpose::STANDARD as BASE64};
use chain_storage::WalletChainStore; use chain_storage::WalletChainStore;
use clap::{Parser, Subcommand};
use common::{ use common::{
block::HashableBlockData,
sequencer_client::SequencerClient, sequencer_client::SequencerClient,
transaction::{EncodedTransaction, NSSATransaction}, transaction::{EncodedTransaction, NSSATransaction},
}; };
use config::WalletConfig; use config::WalletConfig;
use key_protocol::key_management::key_tree::{chain_index::ChainIndex, traits::KeyNode}; use key_protocol::key_management::key_tree::chain_index::ChainIndex;
use log::info; use log::info;
use nssa::{ use nssa::{Account, AccountId};
Account, AccountId, privacy_preserving_transaction::message::EncryptedAccountData,
program::Program,
};
use nssa_core::{Commitment, MembershipProof}; use nssa_core::{Commitment, MembershipProof};
use tokio::io::AsyncWriteExt; use tokio::io::AsyncWriteExt;
use crate::{ use crate::{
cli::{
WalletSubcommand, account::AccountSubcommand, chain::ChainSubcommand,
config::ConfigSubcommand, native_token_transfer_program::AuthTransferSubcommand,
pinata_program::PinataProgramAgnosticSubcommand,
token_program::TokenProgramAgnosticSubcommand,
},
config::PersistentStorage, config::PersistentStorage,
helperfunctions::{fetch_config, fetch_persistent_storage, get_home, produce_data_for_storage}, helperfunctions::{fetch_persistent_storage, get_home, produce_data_for_storage},
poller::TxPoller, poller::TxPoller,
}; };
@ -37,9 +26,8 @@ pub mod chain_storage;
pub mod cli; pub mod cli;
pub mod config; pub mod config;
pub mod helperfunctions; pub mod helperfunctions;
pub mod pinata_interactions;
pub mod poller; pub mod poller;
pub mod token_program_interactions; pub mod program_interactions;
pub mod token_transfers; pub mod token_transfers;
pub mod transaction_utils; pub mod transaction_utils;
@ -219,292 +207,3 @@ impl WalletCore {
Ok(()) Ok(())
} }
} }
/// Represents CLI command for a wallet
#[derive(Subcommand, Debug, Clone)]
#[clap(about)]
pub enum Command {
/// Authenticated transfer subcommand
#[command(subcommand)]
AuthTransfer(AuthTransferSubcommand),
/// Generic chain info subcommand
#[command(subcommand)]
ChainInfo(ChainSubcommand),
/// Account view and sync subcommand
#[command(subcommand)]
Account(AccountSubcommand),
/// Pinata program interaction subcommand
#[command(subcommand)]
Pinata(PinataProgramAgnosticSubcommand),
/// Token program interaction subcommand
#[command(subcommand)]
Token(TokenProgramAgnosticSubcommand),
/// Check the wallet can connect to the node and builtin local programs
/// match the remote versions
CheckHealth {},
/// Command to setup config, get and set config fields
#[command(subcommand)]
Config(ConfigSubcommand),
}
/// Represents overarching CLI command for a wallet with setup included
#[derive(Debug, Subcommand, Clone)]
#[clap(about)]
pub enum OverCommand {
/// Represents CLI command for a wallet
#[command(subcommand)]
Command(Command),
/// Setup of a storage. Initializes rots for public and private trees from `password`.
Setup {
#[arg(short, long)]
password: String,
},
}
/// To execute commands, env var NSSA_WALLET_HOME_DIR must be set into directory with config
///
/// All account adresses must be valid 32 byte base58 strings.
///
/// All account account_ids must be provided as {privacy_prefix}/{account_id},
/// where valid options for `privacy_prefix` is `Public` and `Private`
#[derive(Parser, Debug)]
#[clap(version, about)]
pub struct Args {
/// Continious run flag
#[arg(short, long)]
pub continious_run: bool,
/// Wallet command
#[command(subcommand)]
pub command: Option<OverCommand>,
}
#[derive(Debug, Clone)]
pub enum SubcommandReturnValue {
PrivacyPreservingTransfer { tx_hash: String },
RegisterAccount { account_id: nssa::AccountId },
Account(nssa::Account),
Empty,
SyncedToBlock(u64),
}
pub async fn execute_subcommand(command: Command) -> Result<SubcommandReturnValue> {
let wallet_config = fetch_config().await?;
let mut wallet_core = WalletCore::start_from_config_update_chain(wallet_config).await?;
let subcommand_ret = match command {
Command::AuthTransfer(transfer_subcommand) => {
transfer_subcommand
.handle_subcommand(&mut wallet_core)
.await?
}
Command::ChainInfo(chain_subcommand) => {
chain_subcommand.handle_subcommand(&mut wallet_core).await?
}
Command::Account(account_subcommand) => {
account_subcommand
.handle_subcommand(&mut wallet_core)
.await?
}
Command::Pinata(pinata_subcommand) => {
pinata_subcommand
.handle_subcommand(&mut wallet_core)
.await?
}
Command::CheckHealth {} => {
let remote_program_ids = wallet_core
.sequencer_client
.get_program_ids()
.await
.expect("Error fetching program ids");
let Some(authenticated_transfer_id) = remote_program_ids.get("authenticated_transfer")
else {
panic!("Missing authenticated transfer ID from remote");
};
if authenticated_transfer_id != &Program::authenticated_transfer_program().id() {
panic!("Local ID for authenticated transfer program is different from remote");
}
let Some(token_id) = remote_program_ids.get("token") else {
panic!("Missing token program ID from remote");
};
if token_id != &Program::token().id() {
panic!("Local ID for token program is different from remote");
}
let Some(circuit_id) = remote_program_ids.get("privacy_preserving_circuit") else {
panic!("Missing privacy preserving circuit ID from remote");
};
if circuit_id != &nssa::PRIVACY_PRESERVING_CIRCUIT_ID {
panic!("Local ID for privacy preserving circuit is different from remote");
}
println!("✅All looks good!");
SubcommandReturnValue::Empty
}
Command::Token(token_subcommand) => {
token_subcommand.handle_subcommand(&mut wallet_core).await?
}
Command::Config(config_subcommand) => {
config_subcommand
.handle_subcommand(&mut wallet_core)
.await?
}
};
Ok(subcommand_ret)
}
pub async fn parse_block_range(
start: u64,
stop: u64,
seq_client: Arc<SequencerClient>,
wallet_core: &mut WalletCore,
) -> Result<()> {
for block_id in start..(stop + 1) {
let block =
borsh::from_slice::<HashableBlockData>(&seq_client.get_block(block_id).await?.block)?;
for tx in block.transactions {
let nssa_tx = NSSATransaction::try_from(&tx)?;
if let NSSATransaction::PrivacyPreserving(tx) = nssa_tx {
let mut affected_accounts = vec![];
for (acc_account_id, (key_chain, _)) in
&wallet_core.storage.user_data.default_user_private_accounts
{
let view_tag = EncryptedAccountData::compute_view_tag(
key_chain.nullifer_public_key.clone(),
key_chain.incoming_viewing_public_key.clone(),
);
for (ciph_id, encrypted_data) in tx
.message()
.encrypted_private_post_states
.iter()
.enumerate()
{
if encrypted_data.view_tag == view_tag {
let ciphertext = &encrypted_data.ciphertext;
let commitment = &tx.message.new_commitments[ciph_id];
let shared_secret = key_chain
.calculate_shared_secret_receiver(encrypted_data.epk.clone());
let res_acc = nssa_core::EncryptionScheme::decrypt(
ciphertext,
&shared_secret,
commitment,
ciph_id as u32,
);
if let Some(res_acc) = res_acc {
println!(
"Received new account for account_id {acc_account_id:#?} with account object {res_acc:#?}"
);
affected_accounts.push((*acc_account_id, res_acc));
}
}
}
}
for keys_node in wallet_core
.storage
.user_data
.private_key_tree
.key_map
.values()
{
let acc_account_id = keys_node.account_id();
let key_chain = &keys_node.value.0;
let view_tag = EncryptedAccountData::compute_view_tag(
key_chain.nullifer_public_key.clone(),
key_chain.incoming_viewing_public_key.clone(),
);
for (ciph_id, encrypted_data) in tx
.message()
.encrypted_private_post_states
.iter()
.enumerate()
{
if encrypted_data.view_tag == view_tag {
let ciphertext = &encrypted_data.ciphertext;
let commitment = &tx.message.new_commitments[ciph_id];
let shared_secret = key_chain
.calculate_shared_secret_receiver(encrypted_data.epk.clone());
let res_acc = nssa_core::EncryptionScheme::decrypt(
ciphertext,
&shared_secret,
commitment,
ciph_id as u32,
);
if let Some(res_acc) = res_acc {
println!(
"Received new account for account_id {acc_account_id:#?} with account object {res_acc:#?}"
);
affected_accounts.push((acc_account_id, res_acc));
}
}
}
}
for (affected_account_id, new_acc) in affected_accounts {
wallet_core
.storage
.insert_private_account_data(affected_account_id, new_acc);
}
}
}
wallet_core.last_synced_block = block_id;
wallet_core.store_persistent_data().await?;
println!(
"Block at id {block_id} with timestamp {} parsed",
block.timestamp
);
}
Ok(())
}
pub async fn execute_continious_run() -> Result<()> {
let config = fetch_config().await?;
let seq_client = Arc::new(SequencerClient::new(config.sequencer_addr.clone())?);
let mut wallet_core = WalletCore::start_from_config_update_chain(config.clone()).await?;
let mut latest_block_num = seq_client.get_last_block().await?.last_block;
let mut curr_last_block = latest_block_num;
loop {
parse_block_range(
curr_last_block,
latest_block_num,
seq_client.clone(),
&mut wallet_core,
)
.await?;
curr_last_block = latest_block_num + 1;
tokio::time::sleep(std::time::Duration::from_millis(
config.seq_poll_timeout_millis,
))
.await;
latest_block_num = seq_client.get_last_block().await?.last_block;
}
}
pub async fn execute_setup(password: String) -> Result<()> {
let config = fetch_config().await?;
let wallet_core = WalletCore::start_from_config_new_storage(config.clone(), password).await?;
wallet_core.store_persistent_data().await?;
Ok(())
}

View File

@ -1,14 +1,16 @@
use anyhow::Result; use anyhow::Result;
use clap::{CommandFactory, Parser}; use clap::{CommandFactory as _, Parser as _};
use tokio::runtime::Builder; use tokio::runtime::Builder;
use wallet::{Args, OverCommand, execute_continious_run, execute_setup, execute_subcommand}; use wallet::cli::{Args, OverCommand, execute_continious_run, execute_setup, execute_subcommand};
pub const NUM_THREADS: usize = 2; pub const NUM_THREADS: usize = 2;
// TODO #169: We have sample configs for sequencer, but not for wallet // TODO #169: We have sample configs for sequencer, but not for wallet
// TODO #168: Why it requires config as a directory? Maybe better to deduce directory from config // TODO #168: Why it requires config as a directory? Maybe better to deduce directory from config
// file path? TODO #172: Why it requires config as env var while sequencer_runner accepts as // file path?
// argument? TODO #171: Running pinata doesn't give output about transaction hash and etc. // TODO #172: Why it requires config as env var while sequencer_runner accepts as
// argument?
// TODO #171: Running pinata doesn't give output about transaction hash and etc.
fn main() -> Result<()> { fn main() -> Result<()> {
let runtime = Builder::new_multi_thread() let runtime = Builder::new_multi_thread()
.worker_threads(NUM_THREADS) .worker_threads(NUM_THREADS)
@ -24,19 +26,17 @@ fn main() -> Result<()> {
if let Some(overcommand) = args.command { if let Some(overcommand) = args.command {
match overcommand { match overcommand {
OverCommand::Command(command) => { OverCommand::Command(command) => {
execute_subcommand(command).await.unwrap(); let _output = execute_subcommand(command).await?;
} Ok(())
OverCommand::Setup { password } => {
execute_setup(password).await.unwrap();
} }
OverCommand::Setup { password } => execute_setup(password).await,
} }
} else if args.continious_run { } else if args.continious_run {
execute_continious_run().await.unwrap(); execute_continious_run().await
} else { } else {
let help = Args::command().render_long_help(); let help = Args::command().render_long_help();
println!("{help}"); println!("{help}");
}
});
Ok(()) Ok(())
} }
})
}

View File

@ -0,0 +1,2 @@
pub mod pinata;
pub mod token;