From 813868f16fe7b23a022b7656e5be4c219ebce477 Mon Sep 17 00:00:00 2001 From: Oleksandr Pravdyvyi Date: Wed, 29 Oct 2025 13:23:07 +0200 Subject: [PATCH 1/4] feat: linux default config paths --- wallet/src/chain_storage/mod.rs | 10 +- wallet/src/config.rs | 559 +++++++++++++++++++++++++++++++- wallet/src/helperfunctions.rs | 62 +++- wallet/src/lib.rs | 10 +- 4 files changed, 626 insertions(+), 15 deletions(-) diff --git a/wallet/src/chain_storage/mod.rs b/wallet/src/chain_storage/mod.rs index 8fc8805..4a845af 100644 --- a/wallet/src/chain_storage/mod.rs +++ b/wallet/src/chain_storage/mod.rs @@ -71,8 +71,6 @@ mod tests { use crate::config::InitialAccountData; use super::*; - use std::path::PathBuf; - use tempfile::tempdir; fn create_initial_accounts() -> Vec { let initial_acc1 = serde_json::from_str( @@ -166,9 +164,8 @@ mod tests { initial_accounts } - fn create_sample_wallet_config(home: PathBuf) -> WalletConfig { + fn create_sample_wallet_config() -> WalletConfig { WalletConfig { - home, override_rust_log: None, sequencer_addr: "http://127.0.0.1".to_string(), seq_poll_timeout_millis: 12000, @@ -181,10 +178,7 @@ mod tests { #[test] fn test_new_initializes_correctly() { - let temp_dir = tempdir().unwrap(); - let path = temp_dir.path(); - - let config = create_sample_wallet_config(path.to_path_buf()); + let config = create_sample_wallet_config(); let _ = WalletChainStore::new(config.clone()).unwrap(); } diff --git a/wallet/src/config.rs b/wallet/src/config.rs index af1f493..bf7f5d2 100644 --- a/wallet/src/config.rs +++ b/wallet/src/config.rs @@ -1,6 +1,5 @@ use key_protocol::key_management::KeyChain; use serde::{Deserialize, Serialize}; -use std::path::PathBuf; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct InitialAccountDataPublic { @@ -114,8 +113,6 @@ pub struct GasConfig { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct WalletConfig { - ///Home dir of sequencer storage - pub home: PathBuf, ///Override rust log (env var logging level) pub override_rust_log: Option, ///Sequencer URL @@ -131,3 +128,559 @@ pub struct WalletConfig { ///Initial accounts for wallet pub initial_accounts: Vec, } + +impl Default for WalletConfig { + fn default() -> Self { + Self { + override_rust_log: None, + sequencer_addr: "http://127.0.0.1:3040".to_string(), + seq_poll_timeout_millis: 12000, + seq_poll_max_blocks: 5, + seq_poll_max_retries: 5, + seq_poll_retry_delay_millis: 500, + initial_accounts: { + let init_acc_json = r#" + [ + { + "Public": { + "address": "BLgCRDXYdQPMMWVHYRFGQZbgeHx9frkipa8GtpG2Syqy", + "pub_sign_key": [ + 16, + 162, + 106, + 154, + 236, + 125, + 52, + 184, + 35, + 100, + 238, + 174, + 69, + 197, + 41, + 77, + 187, + 10, + 118, + 75, + 0, + 11, + 148, + 238, + 185, + 181, + 133, + 17, + 220, + 72, + 124, + 77 + ] + } + }, + { + "Public": { + "address": "Gj1mJy5W7J5pfmLRujmQaLfLMWidNxQ6uwnhb666ZwHw", + "pub_sign_key": [ + 113, + 121, + 64, + 177, + 204, + 85, + 229, + 214, + 178, + 6, + 109, + 191, + 29, + 154, + 63, + 38, + 242, + 18, + 244, + 219, + 8, + 208, + 35, + 136, + 23, + 127, + 207, + 237, + 216, + 169, + 190, + 27 + ] + } + }, + { + "Private": { + "address": "3oCG8gqdKLMegw4rRfyaMQvuPHpcASt7xwttsmnZLSkw", + "account": { + "program_owner": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "balance": 10000, + "data": [], + "nonce": 0 + }, + "key_chain": { + "secret_spending_key": [ + 251, + 82, + 235, + 1, + 146, + 96, + 30, + 81, + 162, + 234, + 33, + 15, + 123, + 129, + 116, + 0, + 84, + 136, + 176, + 70, + 190, + 224, + 161, + 54, + 134, + 142, + 154, + 1, + 18, + 251, + 242, + 189 + ], + "private_key_holder": { + "nullifier_secret_key": [ + 29, + 250, + 10, + 187, + 35, + 123, + 180, + 250, + 246, + 97, + 216, + 153, + 44, + 156, + 16, + 93, + 241, + 26, + 174, + 219, + 72, + 84, + 34, + 247, + 112, + 101, + 217, + 243, + 189, + 173, + 75, + 20 + ], + "incoming_viewing_secret_key": [ + 251, + 201, + 22, + 154, + 100, + 165, + 218, + 108, + 163, + 190, + 135, + 91, + 145, + 84, + 69, + 241, + 46, + 117, + 217, + 110, + 197, + 248, + 91, + 193, + 14, + 104, + 88, + 103, + 67, + 153, + 182, + 158 + ], + "outgoing_viewing_secret_key": [ + 25, + 67, + 121, + 76, + 175, + 100, + 30, + 198, + 105, + 123, + 49, + 169, + 75, + 178, + 75, + 210, + 100, + 143, + 210, + 243, + 228, + 243, + 21, + 18, + 36, + 84, + 164, + 186, + 139, + 113, + 214, + 12 + ] + }, + "nullifer_public_key": [ + 63, + 202, + 178, + 231, + 183, + 82, + 237, + 212, + 216, + 221, + 215, + 255, + 153, + 101, + 177, + 161, + 254, + 210, + 128, + 122, + 54, + 190, + 230, + 151, + 183, + 64, + 225, + 229, + 113, + 1, + 228, + 97 + ], + "incoming_viewing_public_key": [ + 3, + 235, + 139, + 131, + 237, + 177, + 122, + 189, + 6, + 177, + 167, + 178, + 202, + 117, + 246, + 58, + 28, + 65, + 132, + 79, + 220, + 139, + 119, + 243, + 187, + 160, + 212, + 121, + 61, + 247, + 116, + 72, + 205 + ] + } + } + }, + { + "Private": { + "address": "AKTcXgJ1xoynta1Ec7y6Jso1z1JQtHqd7aPQ1h9er6xX", + "account": { + "program_owner": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "balance": 20000, + "data": [], + "nonce": 0 + }, + "key_chain": { + "secret_spending_key": [ + 238, + 171, + 241, + 69, + 111, + 217, + 85, + 64, + 19, + 82, + 18, + 189, + 32, + 91, + 78, + 175, + 107, + 7, + 109, + 60, + 52, + 44, + 243, + 230, + 72, + 244, + 192, + 92, + 137, + 33, + 118, + 254 + ], + "private_key_holder": { + "nullifier_secret_key": [ + 25, + 211, + 215, + 119, + 57, + 223, + 247, + 37, + 245, + 144, + 122, + 29, + 118, + 245, + 83, + 228, + 23, + 9, + 101, + 120, + 88, + 33, + 238, + 207, + 128, + 61, + 110, + 2, + 89, + 62, + 164, + 13 + ], + "incoming_viewing_secret_key": [ + 193, + 181, + 14, + 196, + 142, + 84, + 15, + 65, + 128, + 101, + 70, + 196, + 241, + 47, + 130, + 221, + 23, + 146, + 161, + 237, + 221, + 40, + 19, + 126, + 59, + 15, + 169, + 236, + 25, + 105, + 104, + 231 + ], + "outgoing_viewing_secret_key": [ + 20, + 170, + 220, + 108, + 41, + 23, + 155, + 217, + 247, + 190, + 175, + 168, + 247, + 34, + 105, + 134, + 114, + 74, + 104, + 91, + 211, + 62, + 126, + 13, + 130, + 100, + 241, + 214, + 250, + 236, + 38, + 150 + ] + }, + "nullifer_public_key": [ + 192, + 251, + 166, + 243, + 167, + 236, + 84, + 249, + 35, + 136, + 130, + 172, + 219, + 225, + 161, + 139, + 229, + 89, + 243, + 125, + 194, + 213, + 209, + 30, + 23, + 174, + 100, + 244, + 124, + 74, + 140, + 47 + ], + "incoming_viewing_public_key": [ + 2, + 181, + 98, + 93, + 216, + 241, + 241, + 110, + 58, + 198, + 119, + 174, + 250, + 184, + 1, + 204, + 200, + 173, + 44, + 238, + 37, + 247, + 170, + 156, + 100, + 254, + 116, + 242, + 28, + 183, + 187, + 77, + 255 + ] + } + } + } + ] + "#; + serde_json::from_str(init_acc_json).unwrap() + }, + } + } +} diff --git a/wallet/src/helperfunctions.rs b/wallet/src/helperfunctions.rs index 1d35efb..a261e6c 100644 --- a/wallet/src/helperfunctions.rs +++ b/wallet/src/helperfunctions.rs @@ -1,8 +1,11 @@ use base64::{Engine, engine::general_purpose::STANDARD as BASE64}; use nssa_core::account::Nonce; use rand::{RngCore, rngs::OsRng}; -use std::{path::PathBuf, str::FromStr}; -use tokio::io::AsyncReadExt; +use std::{ + path::{Path, PathBuf}, + str::FromStr, +}; +use tokio::io::{AsyncReadExt, AsyncWriteExt}; use anyhow::Result; use key_protocol::key_protocol_core::NSSAUserData; @@ -21,6 +24,61 @@ pub fn get_home() -> Result { Ok(PathBuf::from_str(&std::env::var(HOME_DIR_ENV_VAR)?)?) } +pub fn get_home_default_path_linux() -> PathBuf { + let home = std::env::var("HOME").unwrap(); + Path::new(&home).join(".nssa").join("wallet") +} + +/// Fetch config from `NSSA_WALLET_HOME_DIR` +pub async fn fetch_config_default_path_linux() -> Result { + let config_home = get_home_default_path_linux(); + let mut config_needs_setup = false; + + let config = match tokio::fs::OpenOptions::new() + .read(true) + .open(config_home.join("wallet_config.json")) + .await + { + Ok(mut file) => { + let mut config_contents = vec![]; + file.read_to_end(&mut config_contents).await?; + + serde_json::from_slice(&config_contents)? + } + Err(err) => match err.kind() { + std::io::ErrorKind::NotFound => { + config_needs_setup = true; + + println!("Config not found, setting up default config"); + + WalletConfig::default() + } + _ => anyhow::bail!("IO error {err:#?}"), + }, + }; + + if config_needs_setup { + tokio::fs::create_dir_all(&config_home).await?; + + println!("Created configs dir at path {config_home:#?}"); + + let mut file = tokio::fs::OpenOptions::new() + .write(true) + .create(true) + .open(config_home.join("wallet_config.json")) + .await?; + + let default_config_serialized = + serde_json::to_vec_pretty(&WalletConfig::default()).unwrap(); + + file.write_all(&default_config_serialized).await?; + + println!("Configs setted up"); + } + + Ok(config) +} + /// Fetch config from `NSSA_WALLET_HOME_DIR` pub async fn fetch_config() -> Result { let config_home = get_home()?; diff --git a/wallet/src/lib.rs b/wallet/src/lib.rs index 3beac67..94be7e3 100644 --- a/wallet/src/lib.rs +++ b/wallet/src/lib.rs @@ -28,7 +28,7 @@ use crate::{ token_program::TokenProgramAgnosticSubcommand, }, config::PersistentStorage, - helperfunctions::fetch_persistent_storage, + helperfunctions::{fetch_config_default_path_linux, fetch_persistent_storage}, }; use crate::{ helperfunctions::{fetch_config, get_home, produce_data_for_storage}, @@ -216,6 +216,7 @@ pub enum Command { /// Check the wallet can connect to the node and builtin local programs /// match the remote versions CheckHealth {}, + TestCommand {}, } ///To execute commands, env var NSSA_WALLET_HOME_DIR must be set into directory with config @@ -245,7 +246,7 @@ pub enum SubcommandReturnValue { } pub async fn execute_subcommand(command: Command) -> Result { - let wallet_config = fetch_config().await?; + let wallet_config = fetch_config_default_path_linux().await?; let mut wallet_core = WalletCore::start_from_config_update_chain(wallet_config).await?; let subcommand_ret = match command { @@ -300,6 +301,11 @@ pub async fn execute_subcommand(command: Command) -> Result { token_subcommand.handle_subcommand(&mut wallet_core).await? } + Command::TestCommand {} => { + println!("Hello from test"); + + SubcommandReturnValue::Empty + } }; Ok(subcommand_ret) From 2c21abc2d945d1a10eb247e03ac36f3221bad5c1 Mon Sep 17 00:00:00 2001 From: Oleksandr Pravdyvyi Date: Thu, 30 Oct 2025 15:33:58 +0200 Subject: [PATCH 2/4] fix: default config paths agnostic --- wallet/src/helperfunctions.rs | 40 +++++++++++++++++------------------ wallet/src/lib.rs | 15 ++++++++----- 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/wallet/src/helperfunctions.rs b/wallet/src/helperfunctions.rs index a261e6c..e602b02 100644 --- a/wallet/src/helperfunctions.rs +++ b/wallet/src/helperfunctions.rs @@ -1,10 +1,7 @@ use base64::{Engine, engine::general_purpose::STANDARD as BASE64}; use nssa_core::account::Nonce; use rand::{RngCore, rngs::OsRng}; -use std::{ - path::{Path, PathBuf}, - str::FromStr, -}; +use std::{path::PathBuf, str::FromStr}; use tokio::io::{AsyncReadExt, AsyncWriteExt}; use anyhow::Result; @@ -20,18 +17,29 @@ use crate::{ }; /// Get home dir for wallet. Env var `NSSA_WALLET_HOME_DIR` must be set before execution to succeed. -pub fn get_home() -> Result { +pub fn get_home_nssa_var() -> Result { Ok(PathBuf::from_str(&std::env::var(HOME_DIR_ENV_VAR)?)?) } -pub fn get_home_default_path_linux() -> PathBuf { - let home = std::env::var("HOME").unwrap(); - Path::new(&home).join(".nssa").join("wallet") +/// Get home dir for wallet. Env var `HOME` must be set before execution to succeed. +pub fn get_home_default_path() -> Result { + std::env::home_dir() + .map(|path| path.join(".nssa").join("wallet")) + .ok_or(anyhow::anyhow!("Failed to get HOME")) } -/// Fetch config from `NSSA_WALLET_HOME_DIR` -pub async fn fetch_config_default_path_linux() -> Result { - let config_home = get_home_default_path_linux(); +/// Get home dir for wallet. +pub fn get_home() -> Result { + if let Ok(home) = get_home_nssa_var() { + Ok(home) + } else { + get_home_default_path() + } +} + +/// Fetch config from default home +pub async fn fetch_config() -> Result { + let config_home = get_home()?; let mut config_needs_setup = false; let config = match tokio::fs::OpenOptions::new() @@ -79,15 +87,7 @@ pub async fn fetch_config_default_path_linux() -> Result { Ok(config) } -/// Fetch config from `NSSA_WALLET_HOME_DIR` -pub async fn fetch_config() -> Result { - let config_home = get_home()?; - let config_contents = tokio::fs::read(config_home.join("wallet_config.json")).await?; - - Ok(serde_json::from_slice(&config_contents)?) -} - -/// Fetch data stored at `NSSA_WALLET_HOME_DIR/storage.json` +/// Fetch data stored at home /// /// If file not present, it is considered as empty list of persistent accounts pub async fn fetch_persistent_storage() -> Result { diff --git a/wallet/src/lib.rs b/wallet/src/lib.rs index 94be7e3..bfc2e54 100644 --- a/wallet/src/lib.rs +++ b/wallet/src/lib.rs @@ -28,7 +28,7 @@ use crate::{ token_program::TokenProgramAgnosticSubcommand, }, config::PersistentStorage, - helperfunctions::{fetch_config_default_path_linux, fetch_persistent_storage}, + helperfunctions::fetch_persistent_storage, }; use crate::{ helperfunctions::{fetch_config, get_home, produce_data_for_storage}, @@ -216,7 +216,10 @@ pub enum Command { /// Check the wallet can connect to the node and builtin local programs /// match the remote versions CheckHealth {}, - TestCommand {}, + /// Command to explicitly setup config and storage + /// + /// Does nothing in case if both already present + Setup {}, } ///To execute commands, env var NSSA_WALLET_HOME_DIR must be set into directory with config @@ -246,7 +249,7 @@ pub enum SubcommandReturnValue { } pub async fn execute_subcommand(command: Command) -> Result { - let wallet_config = fetch_config_default_path_linux().await?; + let wallet_config = fetch_config().await?; let mut wallet_core = WalletCore::start_from_config_update_chain(wallet_config).await?; let subcommand_ret = match command { @@ -301,8 +304,10 @@ pub async fn execute_subcommand(command: Command) -> Result { token_subcommand.handle_subcommand(&mut wallet_core).await? } - Command::TestCommand {} => { - println!("Hello from test"); + Command::Setup {} => { + let path = wallet_core.store_persistent_data().await?; + + println!("Stored persistent accounts at {path:#?}"); SubcommandReturnValue::Empty } From 228f7591d5a54a666bcacdb7db98c3ca1e34df79 Mon Sep 17 00:00:00 2001 From: Oleksandr Pravdyvyi Date: Thu, 30 Oct 2025 17:23:50 +0200 Subject: [PATCH 3/4] fix: lint and fmt --- wallet/src/helperfunctions.rs | 1 + wallet/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/wallet/src/helperfunctions.rs b/wallet/src/helperfunctions.rs index e602b02..f959d17 100644 --- a/wallet/src/helperfunctions.rs +++ b/wallet/src/helperfunctions.rs @@ -73,6 +73,7 @@ pub async fn fetch_config() -> Result { let mut file = tokio::fs::OpenOptions::new() .write(true) .create(true) + .truncate(true) .open(config_home.join("wallet_config.json")) .await?; diff --git a/wallet/src/lib.rs b/wallet/src/lib.rs index bfc2e54..500ec45 100644 --- a/wallet/src/lib.rs +++ b/wallet/src/lib.rs @@ -217,7 +217,7 @@ pub enum Command { /// match the remote versions CheckHealth {}, /// Command to explicitly setup config and storage - /// + /// /// Does nothing in case if both already present Setup {}, } From e40d3874750b963bb4c636ad29712b7015bece48 Mon Sep 17 00:00:00 2001 From: Oleksandr Pravdyvyi Date: Fri, 31 Oct 2025 10:14:12 +0200 Subject: [PATCH 4/4] fix: sequencer config update --- .../configs/debug/sequencer_config.json | 126 +++++++++--------- 1 file changed, 63 insertions(+), 63 deletions(-) diff --git a/sequencer_runner/configs/debug/sequencer_config.json b/sequencer_runner/configs/debug/sequencer_config.json index 19ff458..acd0caa 100644 --- a/sequencer_runner/configs/debug/sequencer_config.json +++ b/sequencer_runner/configs/debug/sequencer_config.json @@ -8,49 +8,49 @@ "port": 3040, "initial_accounts": [ { - "addr": "d07ad2e84b27fa00c262f0a1eea0ff35ca0973547e6a106f72f193c2dc838b44", + "addr": "BLgCRDXYdQPMMWVHYRFGQZbgeHx9frkipa8GtpG2Syqy", "balance": 10000 }, { - "addr": "e7ae77c5ef1a05999344af499fc78a1705398d62ed06cf2e1479f6def89a39bc", + "addr": "Gj1mJy5W7J5pfmLRujmQaLfLMWidNxQ6uwnhb666ZwHw", "balance": 20000 } ], "initial_commitments": [ { "npk": [ - 193, - 209, - 150, - 113, - 47, - 241, - 48, - 145, - 250, - 79, - 235, - 51, - 119, - 40, - 184, - 232, - 5, + 63, + 202, + 178, + 231, + 183, + 82, + 237, + 212, + 216, 221, - 36, - 21, - 201, - 106, - 90, - 210, - 129, - 106, - 71, - 99, - 208, + 215, + 255, 153, - 75, - 215 + 101, + 177, + 161, + 254, + 210, + 128, + 122, + 54, + 190, + 230, + 151, + 183, + 64, + 225, + 229, + 113, + 1, + 228, + 97 ], "account": { "program_owner": [ @@ -70,38 +70,38 @@ }, { "npk": [ - 27, - 250, + 192, + 251, + 166, + 243, + 167, + 236, + 84, + 249, + 35, 136, - 142, - 88, - 128, - 138, - 21, - 49, - 183, - 118, - 160, - 117, - 114, - 110, - 47, - 136, - 87, - 60, - 70, - 59, - 60, - 18, - 223, - 23, - 147, - 241, - 5, - 184, - 103, + 130, + 172, + 219, 225, - 105 + 161, + 139, + 229, + 89, + 243, + 125, + 194, + 213, + 209, + 30, + 23, + 174, + 100, + 244, + 124, + 74, + 140, + 47 ], "account": { "program_owner": [ @@ -154,4 +154,4 @@ 37, 37 ] -} +} \ No newline at end of file