Merge pull request #148 from vacp2p/Pravdyvy/wallet-personalization

Wallet personalization
This commit is contained in:
Pravdyvy 2025-11-19 18:44:56 +02:00 committed by GitHub
commit 4847c84347
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 745 additions and 559 deletions

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,7 @@ use wallet::{
Command, SubcommandReturnValue, WalletCore,
cli::{
account::{AccountSubcommand, NewSubcommand},
config::ConfigSubcommand,
native_token_transfer_program::AuthTransferSubcommand,
pinata_program::PinataProgramAgnosticSubcommand,
token_program::TokenProgramAgnosticSubcommand,
@ -1188,11 +1189,6 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
.await
.unwrap();
let new_commitment1 = wallet_storage
.get_private_account_commitment(&from)
.unwrap();
assert_eq!(tx.message.new_commitments[0], new_commitment1);
assert_eq!(tx.message.new_commitments.len(), 2);
for commitment in tx.message.new_commitments.into_iter() {
assert!(verify_commitment_is_in_state(commitment, &seq_client).await);
@ -1589,6 +1585,34 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
info!("Success!");
}
#[nssa_integration_test]
pub async fn test_modify_config_fields() {
info!("########## test_modify_config_fields ##########");
let wallet_config = fetch_config().await.unwrap();
let old_seq_poll_retry_delay_millis = wallet_config.seq_poll_retry_delay_millis;
//Change config field
let command = Command::Config(ConfigSubcommand::Set {
key: "seq_poll_retry_delay_millis".to_string(),
value: "1000".to_string(),
});
wallet::execute_subcommand(command).await.unwrap();
let wallet_config = fetch_config().await.unwrap();
assert_eq!(wallet_config.seq_poll_retry_delay_millis, 1000);
//Return how it was at the beginning
let command = Command::Config(ConfigSubcommand::Set {
key: "seq_poll_retry_delay_millis".to_string(),
value: old_seq_poll_retry_delay_millis.to_string(),
});
wallet::execute_subcommand(command).await.unwrap();
info!("Success!");
}
println!("{function_map:#?}");
function_map

151
wallet/src/cli/config.rs Normal file
View File

@ -0,0 +1,151 @@
use anyhow::Result;
use clap::Subcommand;
use crate::{SubcommandReturnValue, WalletCore, cli::WalletSubcommand};
///Represents generic config CLI subcommand
#[derive(Subcommand, Debug, Clone)]
pub enum ConfigSubcommand {
/// Command to explicitly setup config and storage
///
/// Does nothing in case if both already present
Setup {},
/// Getter of config fields
Get { key: String },
/// Setter of config fields
Set { key: String, value: String },
/// Prints description of corresponding field
Description { key: String },
}
impl WalletSubcommand for ConfigSubcommand {
async fn handle_subcommand(
self,
wallet_core: &mut WalletCore,
) -> Result<SubcommandReturnValue> {
match self {
ConfigSubcommand::Setup {} => {
let path = wallet_core.store_persistent_data().await?;
println!("Stored persistent accounts at {path:#?}");
}
ConfigSubcommand::Get { key } => match key.as_str() {
"all" => {
let config_str =
serde_json::to_string_pretty(&wallet_core.storage.wallet_config)?;
println!("{config_str}");
}
"override_rust_log" => {
if let Some(value) = &wallet_core.storage.wallet_config.override_rust_log {
println!("{value}");
} else {
println!("Not set");
}
}
"sequencer_addr" => {
println!("{}", wallet_core.storage.wallet_config.sequencer_addr);
}
"seq_poll_timeout_millis" => {
println!(
"{}",
wallet_core.storage.wallet_config.seq_poll_timeout_millis
);
}
"seq_poll_max_blocks" => {
println!("{}", wallet_core.storage.wallet_config.seq_poll_max_blocks);
}
"seq_poll_max_retries" => {
println!("{}", wallet_core.storage.wallet_config.seq_poll_max_retries);
}
"seq_poll_retry_delay_millis" => {
println!(
"{}",
wallet_core
.storage
.wallet_config
.seq_poll_retry_delay_millis
);
}
"initial_accounts" => {
println!("{:#?}", wallet_core.storage.wallet_config.initial_accounts);
}
_ => {
println!("Unknown field");
}
},
ConfigSubcommand::Set { key, value } => {
match key.as_str() {
"override_rust_log" => {
wallet_core.storage.wallet_config.override_rust_log = Some(value);
}
"sequencer_addr" => {
wallet_core.storage.wallet_config.sequencer_addr = value;
}
"seq_poll_timeout_millis" => {
wallet_core.storage.wallet_config.seq_poll_timeout_millis =
value.parse()?;
}
"seq_poll_max_blocks" => {
wallet_core.storage.wallet_config.seq_poll_max_blocks = value.parse()?;
}
"seq_poll_max_retries" => {
wallet_core.storage.wallet_config.seq_poll_max_retries = value.parse()?;
}
"seq_poll_retry_delay_millis" => {
wallet_core
.storage
.wallet_config
.seq_poll_retry_delay_millis = value.parse()?;
}
"initial_accounts" => {
anyhow::bail!("Setting this field from wallet is not supported");
}
_ => {
anyhow::bail!("Unknown field");
}
}
let path = wallet_core.store_config_changes().await?;
println!("Stored changed config at {path:#?}");
}
ConfigSubcommand::Description { key } => match key.as_str() {
"override_rust_log" => {
println!("Value of variable RUST_LOG to override, affects logging");
}
"sequencer_addr" => {
println!("HTTP V4 address of sequencer");
}
"seq_poll_timeout_millis" => {
println!(
"Sequencer client retry variable: how much time to wait between retries in milliseconds(can be zero)"
);
}
"seq_poll_max_blocks" => {
println!(
"Sequencer client polling variable: max number of blocks to poll in parallel"
);
}
"seq_poll_max_retries" => {
println!(
"Sequencer client retry variable: MAX number of retries before failing(can be zero)"
);
}
"seq_poll_retry_delay_millis" => {
println!(
"Sequencer client polling variable: how much time to wait in milliseconds between polling retries(can be zero)"
);
}
"initial_accounts" => {
println!("List of initial accounts' keys(both public and private)");
}
_ => {
println!("Unknown field");
}
},
}
Ok(SubcommandReturnValue::Empty)
}
}

View File

@ -4,6 +4,7 @@ use crate::{SubcommandReturnValue, WalletCore};
pub mod account;
pub mod chain;
pub mod config;
pub mod native_token_transfer_program;
pub mod pinata_program;
pub mod token_program;

View File

@ -23,7 +23,7 @@ use tokio::io::AsyncWriteExt;
use crate::{
cli::{
WalletSubcommand, account::AccountSubcommand, chain::ChainSubcommand,
native_token_transfer_program::AuthTransferSubcommand,
config::ConfigSubcommand, native_token_transfer_program::AuthTransferSubcommand,
pinata_program::PinataProgramAgnosticSubcommand,
token_program::TokenProgramAgnosticSubcommand,
},
@ -93,6 +93,20 @@ impl WalletCore {
Ok(storage_path)
}
///Store persistent data at home
pub async fn store_config_changes(&self) -> Result<PathBuf> {
let home = get_home()?;
let config_path = home.join("wallet_config.json");
let config = serde_json::to_vec_pretty(&self.storage.wallet_config)?;
let mut config_file = tokio::fs::File::create(config_path.as_path()).await?;
config_file.write_all(&config).await?;
info!("Stored data at {config_path:#?}");
Ok(config_path)
}
pub fn create_new_account_public(&mut self) -> Address {
self.storage
.user_data
@ -216,10 +230,9 @@ pub enum Command {
/// Check the wallet can connect to the node and builtin local programs
/// match the remote versions
CheckHealth {},
/// Command to explicitly setup config and storage
///
/// Does nothing in case if both already present
Setup {},
/// Command to setup config, get and set config fields
#[command(subcommand)]
Config(ConfigSubcommand),
}
///To execute commands, env var NSSA_WALLET_HOME_DIR must be set into directory with config
@ -304,12 +317,10 @@ pub async fn execute_subcommand(command: Command) -> Result<SubcommandReturnValu
Command::Token(token_subcommand) => {
token_subcommand.handle_subcommand(&mut wallet_core).await?
}
Command::Setup {} => {
let path = wallet_core.store_persistent_data().await?;
println!("Stored persistent accounts at {path:#?}");
SubcommandReturnValue::Empty
Command::Config(config_subcommand) => {
config_subcommand
.handle_subcommand(&mut wallet_core)
.await?
}
};