From ed4efc1dfa22d5431716907fcfbee8a672df6581 Mon Sep 17 00:00:00 2001 From: Herr Seppia Date: Tue, 19 Mar 2024 15:41:01 +0100 Subject: [PATCH 1/4] Add support for `WALLET_MAX_ADDR=1` Resolves #244 --- src/bin/interactive.rs | 6 ++++-- src/lib.rs | 7 +++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/bin/interactive.rs b/src/bin/interactive.rs index b7d2995..3c935aa 100644 --- a/src/bin/interactive.rs +++ b/src/bin/interactive.rs @@ -144,12 +144,14 @@ fn menu_addr(wallet: &Wallet) -> anyhow::Result { .add(AddrSelect::Address(Box::new(addr.clone())), preview); } + let remaining_addresses = + MAX_ADDRESSES.saturating_sub(wallet.addresses().len()); let mut action_menu = Menu::new() .separator() .add(AddrSelect::NewAddress, "New address"); - // show warning early on at 250 addresses - if wallet.addresses().len() >= MAX_ADDRESSES - 5 { + // show warning if less than + if remaining_addresses < 5 { action_menu = action_menu.separator().separator_msg(format!( "\x1b[93m{}\x1b[0m This wallet only supports up to {MAX_ADDRESSES} addresses, you have {} addresses ", "Warning:", diff --git a/src/lib.rs b/src/lib.rs index 473a9d9..ab967a9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -49,12 +49,11 @@ const DEFAULT_MAX_ADDRESSES: usize = 25; const fn get_max_addresses() -> usize { match option_env!("WALLET_MAX_ADDR") { Some(v) => match konst::primitive::parse_usize(v) { - Ok(e) if e > DEFAULT_MAX_ADDRESSES => { + Ok(e) if e > 255 => { panic!("WALLET_MAX_ADDR must be lower or equal to 255") } - Ok(e) if e > 5 => e, - Ok(_) => panic!("WALLET_MAX_ADDR must be greater than 5"), - Err(_) => panic!("Invalid WALLET_MAX_ADDR"), + Ok(e) if e > 0 => e, + _ => panic!("Invalid WALLET_MAX_ADDR"), }, None => DEFAULT_MAX_ADDRESSES, } From 211a33883c5742be78f87d7998b84c9c611823b3 Mon Sep 17 00:00:00 2001 From: Herr Seppia Date: Fri, 22 Mar 2024 19:14:00 +0100 Subject: [PATCH 2/4] Change rusk-wallet to wait for tx to be included --- src/bin/io/gql.rs | 11 ++--------- src/bin/io/status.rs | 10 +--------- 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/src/bin/io/gql.rs b/src/bin/io/gql.rs index 43ca42a..b3ca063 100644 --- a/src/bin/io/gql.rs +++ b/src/bin/io/gql.rs @@ -71,9 +71,7 @@ impl GraphQL { /// Wait for a transaction to be confirmed (included in a block) pub async fn wait_for(&self, tx_id: &str) -> anyhow::Result<()> { - const TIMEOUT_SECS: i32 = 30; - let mut i = 1; - while i <= TIMEOUT_SECS { + loop { let status = self.tx_status(tx_id).await?; match status { @@ -81,14 +79,9 @@ impl GraphQL { TxStatus::Error(err) => return Err(Error::Transaction(err))?, TxStatus::NotFound => { (self.status)( - format!( - "Waiting for confirmation... ({}/{})", - i, TIMEOUT_SECS - ) - .as_str(), + "Waiting for tx to be included into a block...", ); sleep(Duration::from_millis(1000)).await; - i += 1; } } } diff --git a/src/bin/io/status.rs b/src/bin/io/status.rs index e47a535..d24b714 100644 --- a/src/bin/io/status.rs +++ b/src/bin/io/status.rs @@ -10,17 +10,9 @@ use std::time::Duration; use tracing::info; -const STATUS_SIZE: usize = 35; - /// Prints an interactive status message pub(crate) fn interactive(status: &str) { - let filln = STATUS_SIZE - status.len(); - let fill = if filln > 0 { - " ".repeat(filln) - } else { - "".to_string() - }; - print!("{}{}\r", status, fill); + print!("\r{status: <50}\r"); let mut stdout = stdout(); stdout.flush().unwrap(); thread::sleep(Duration::from_millis(85)); From f5a1c3199aa8dcb71fd36724bbcf36c436481eee Mon Sep 17 00:00:00 2001 From: Herr Seppia Date: Tue, 26 Mar 2024 12:26:16 +0100 Subject: [PATCH 3/4] bin: improve tx history performance - Remove the additional call for gas_spent - Remove the tx_id computation Resolves #243 --- src/bin/command/history.rs | 15 ++++++--------- src/bin/io/gql.rs | 36 +++++++++++++----------------------- 2 files changed, 19 insertions(+), 32 deletions(-) diff --git a/src/bin/command/history.rs b/src/bin/command/history.rs index 60103e3..7304577 100644 --- a/src/bin/command/history.rs +++ b/src/bin/command/history.rs @@ -8,11 +8,9 @@ use std::collections::hash_map::Entry; use std::collections::HashMap; use std::fmt::{self, Display}; -use dusk_plonk::prelude::BlsScalar; use dusk_wallet::DecodedNote; use dusk_wallet_core::Transaction; use rusk_abi::dusk; -use rusk_abi::hash::Hasher; use crate::io::{self, GraphQL}; use crate::settings::Settings; @@ -23,7 +21,7 @@ pub struct TransactionHistory { amount: f64, fee: u64, pub tx: Transaction, - id: BlsScalar, + id: String, } impl TransactionHistory { @@ -52,7 +50,7 @@ impl Display for TransactionHistory { } }; - let tx_id = hex::encode(self.id.to_bytes()); + let tx_id = &self.id; let heigth = self.height; write!( @@ -96,11 +94,11 @@ pub(crate) async fn transaction_from_notes( let note_hash = decoded_note.note.hash(); // Looking for the transaction which created the note - let note_creator = txs.iter().find(|(t, _)| { + let note_creator = txs.iter().find(|(t, _, _)| { t.outputs().iter().any(|&n| n.hash().eq(¬e_hash)) }); - if let Some((t, gas_spent)) = note_creator { + if let Some((t, tx_id, gas_spent)) = note_creator { let inputs_amount: f64 = t .nullifiers() .iter() @@ -113,8 +111,7 @@ pub(crate) async fn transaction_from_notes( true => TransactionDirection::Out, false => TransactionDirection::In, }; - let hash_to_find = Hasher::digest(t.to_hash_input_bytes()); - match ret.iter_mut().find(|th| th.id == hash_to_find) { + match ret.iter_mut().find(|th| &th.id == tx_id) { Some(tx) => tx.amount += note_amount, None => ret.push(TransactionHistory { direction, @@ -122,7 +119,7 @@ pub(crate) async fn transaction_from_notes( amount: note_amount - inputs_amount, fee: gas_spent * t.fee().gas_price, tx: t.clone(), - id: hash_to_find, + id: tx_id.clone(), }), } } else { diff --git a/src/bin/io/gql.rs b/src/bin/io/gql.rs index b3ca063..d1fafc6 100644 --- a/src/bin/io/gql.rs +++ b/src/bin/io/gql.rs @@ -20,23 +20,18 @@ pub struct GraphQL { status: fn(&str), } -// helper structs to deserialize response #[derive(Deserialize)] struct SpentTx { - pub err: Option, - #[serde(alias = "gasSpent", default)] - pub gas_spent: f64, -} - -#[derive(Deserialize)] -struct Tx { pub id: String, #[serde(default)] pub raw: String, + pub err: Option, + #[serde(alias = "gasSpent", default)] + pub gas_spent: f64, } #[derive(Deserialize)] struct Block { - pub transactions: Vec, + pub transactions: Vec, } #[derive(Deserialize)] @@ -94,7 +89,7 @@ impl GraphQL { tx_id: &str, ) -> anyhow::Result { let query = - "query { tx(hash: \"####\") { err }}".replace("####", tx_id); + "query { tx(hash: \"####\") { id, err }}".replace("####", tx_id); let response = self.query(&query).await?; let response = serde_json::from_slice::(&response)?.tx; @@ -109,8 +104,8 @@ impl GraphQL { pub async fn txs_for_block( &self, block_height: u64, - ) -> anyhow::Result, GraphQLError> { - let query = "query { block(height: ####) { transactions {id, raw}}}" + ) -> anyhow::Result, GraphQLError> { + let query = "query { block(height: ####) { transactions {id, raw, gasSpent, err}}}" .replace("####", block_height.to_string().as_str()); let response = self.query(&query).await?; @@ -119,17 +114,11 @@ impl GraphQL { let block = response.ok_or(GraphQLError::BlockInfo)?; let mut ret = vec![]; - for tx in block.transactions { - let tx_raw = - hex::decode(&tx.raw).map_err(|_| GraphQLError::TxStatus)?; + for spent_tx in block.transactions { + let tx_raw = hex::decode(&spent_tx.raw) + .map_err(|_| GraphQLError::TxStatus)?; let ph_tx = Transaction::from_slice(&tx_raw).unwrap(); - let query = "query { tx(hash: \"####\") { gasSpent, err }}" - .replace("####", &tx.id); - let response = self.query(&query).await?; - let response = - serde_json::from_slice::(&response)?.tx; - let spent_tx = response.ok_or(GraphQLError::TxStatus)?; - ret.push((ph_tx, spent_tx.gas_spent as u64)); + ret.push((ph_tx, spent_tx.id, spent_tx.gas_spent as u64)); } Ok(ret) } @@ -187,9 +176,10 @@ async fn test() -> Result<(), Box> { ) .await?; let block_txs = gql.txs_for_block(90).await?; - block_txs.iter().for_each(|(t, _)| { + block_txs.into_iter().for_each(|(t, chain_txid, _)| { let hash = rusk_abi::hash::Hasher::digest(t.to_hash_input_bytes()); let tx_id = hex::encode(hash.to_bytes()); + assert_eq!(chain_txid, tx_id); println!("txid: {tx_id}"); }); Ok(()) From 5860a923ca97d711198f3dfc25a14f2cb2477087 Mon Sep 17 00:00:00 2001 From: Herr Seppia Date: Fri, 22 Mar 2024 19:16:48 +0100 Subject: [PATCH 4/4] Update `CHANGELOG.md` --- CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d773d7..c28797f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Add support for `WALLET_MAX_ADDR` lower than `6` [#244] + +### Changed + +- Change rusk-wallet to wait for tx to be included + +### Fixed + +- Fix tx history to avoid useless calls [#243] + ## [0.22.0] - 2024-2-28 ### Changed @@ -480,6 +492,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Implementation of `Store` trait from `wallet-core` - Implementation of `State` and `Prover` traits from `wallet-core` +[#244]: https://github.com/dusk-network/wallet-cli/issues/244 +[#243]: https://github.com/dusk-network/wallet-cli/issues/243 [#238]: https://github.com/dusk-network/wallet-cli/issues/238 [#235]: https://github.com/dusk-network/wallet-cli/issues/235 [#231]: https://github.com/dusk-network/wallet-cli/issues/231