naive implementation of sending multiple transactions

Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
This commit is contained in:
Uncle Stretch 2025-01-22 15:32:58 +03:00
parent 8b302a0814
commit b922aa75f7
Signed by: str3tch
GPG Key ID: 84F3190747EE79AA
5 changed files with 66 additions and 11 deletions

View File

@ -28,6 +28,7 @@ pub enum Action {
UsedAccount(String), UsedAccount(String),
NewAccount(String), NewAccount(String),
NewAddressBookRecord(String, String), NewAddressBookRecord(String, String),
SetSender(String, Option<u32>),
ClosePopup, ClosePopup,

View File

@ -2,7 +2,7 @@
use subxt::{ use subxt::{
Config, blocks::Block, client::OnlineClient, Config, blocks::Block, client::OnlineClient,
config::{DefaultExtrinsicParams, SubstrateConfig}, config::{DefaultExtrinsicParamsBuilder, DefaultExtrinsicParams, SubstrateConfig},
}; };
/// Default set of commonly used type by Casper nodes. /// Default set of commonly used type by Casper nodes.
@ -26,9 +26,9 @@ pub type CasperAccountId = subxt::utils::AccountId32;
pub type CasperBlock = Block<CasperConfig, OnlineClient<CasperConfig>>; pub type CasperBlock = Block<CasperConfig, OnlineClient<CasperConfig>>;
/// A struct representing the signed extra and additional parameters required to construct a /// A struct representing the signed extra and additional parameters required to construct a
/// transaction for a polkadot node. /// transaction for a casper node.
pub type CasperExtrinsicParams<T> = DefaultExtrinsicParams<T>; pub type CasperExtrinsicParams<T> = DefaultExtrinsicParams<T>;
///// A builder which leads to [`CasperExtrinsicParams`] being constructed. This is what we provide /// A builder which leads to [`CasperExtrinsicParams`] being constructed. This is what we provide
///// to methods like `sign_and_submit()`. /// to methods like `sign_and_submit()`.
//pub type CasperExtrinsicParamsBuilder<T> = DefaultExtrinsicParamsBuilder<T>; pub type CasperExtrinsicParamsBuilder<T> = DefaultExtrinsicParamsBuilder<T>;

View File

@ -75,13 +75,25 @@ impl Accounts {
} }
} }
fn set_used_account(&mut self, index: usize) { fn set_sender_nonce(&mut self, index: usize) {
if let Some(action_tx) = &self.action_tx { if let Some(network_tx) = &self.network_tx {
let _ = action_tx.send(Action::UsedAccount( let used_seed = self.wallet_keys[index].seed.clone();
self.wallet_keys[index].seed.clone())); let account_id = self.wallet_keys[index].account_id;
let used_nonce = self.balances
.get(&account_id)
.map(|info| info.nonce);
let _ = network_tx.send(Action::SetSender(used_seed, used_nonce));
} }
} }
fn set_used_account(&mut self, index: usize) {
let used_seed = self.wallet_keys[index].seed.clone();
if let Some(action_tx) = &self.action_tx {
let _ = action_tx.send(Action::UsedAccount(used_seed.clone()));
}
self.set_sender_nonce(index);
}
fn log_event(&mut self, message: String, level: ActionLevel) { fn log_event(&mut self, message: String, level: ActionLevel) {
if let Some(action_tx) = &self.action_tx { if let Some(action_tx) = &self.action_tx {
let _ = action_tx.send(Action::WalletLog(message, level)); let _ = action_tx.send(Action::WalletLog(message, level));
@ -419,6 +431,7 @@ impl Component for Accounts {
if let Some(index) = self.table_state.selected() { if let Some(index) = self.table_state.selected() {
if self.wallet_keys[index].account_id == account_id { if self.wallet_keys[index].account_id == account_id {
self.set_balance_active(index); self.set_balance_active(index);
self.set_sender_nonce(index);
} }
} }
} }

View File

@ -33,6 +33,7 @@ pub struct Network {
stash_to_watch: Option<[u8; 32]>, stash_to_watch: Option<[u8; 32]>,
accounts_to_watch: std::collections::HashSet<[u8; 32]>, accounts_to_watch: std::collections::HashSet<[u8; 32]>,
transactions_to_watch: Vec<TxProgress<CasperConfig, OnlineClient<CasperConfig>>>, transactions_to_watch: Vec<TxProgress<CasperConfig, OnlineClient<CasperConfig>>>,
senders: std::collections::HashMap<String, u32>,
} }
impl Network { impl Network {
@ -50,6 +51,7 @@ impl Network {
stash_to_watch: None, stash_to_watch: None,
accounts_to_watch: Default::default(), accounts_to_watch: Default::default(),
transactions_to_watch: Default::default(), transactions_to_watch: Default::default(),
senders: Default::default(),
} }
} }
@ -60,6 +62,21 @@ impl Network {
} }
} }
fn store_sender_nonce(&mut self, seed: &str, maybe_nonce: Option<u32>) {
if let Some(current_nonce) = maybe_nonce {
self.senders
.entry(seed.to_string())
.and_modify(|stored_nonce| {
if *stored_nonce < current_nonce {
*stored_nonce = current_nonce;
}
})
.or_insert(current_nonce);
} else {
let _ = self.senders.remove(seed);
}
}
pub async fn handle_network_event(&mut self, io_event: Action) -> Result<()> { pub async fn handle_network_event(&mut self, io_event: Action) -> Result<()> {
match io_event { match io_event {
Action::NewBestHash(hash) => { Action::NewBestHash(hash) => {
@ -141,6 +158,11 @@ impl Network {
Action::GetNominatorsNumber => predefined_calls::get_nominators_number(&self.action_tx, &self.online_client_api).await, Action::GetNominatorsNumber => predefined_calls::get_nominators_number(&self.action_tx, &self.online_client_api).await,
Action::GetInflation => predefined_calls::get_inflation(&self.action_tx, &self.online_client_api).await, Action::GetInflation => predefined_calls::get_inflation(&self.action_tx, &self.online_client_api).await,
Action::SetSender(seed, maybe_nonce) => {
self.store_sender_nonce(&seed, maybe_nonce);
Ok(())
}
Action::GetValidatorLedger(stash) => { Action::GetValidatorLedger(stash) => {
self.store_stash_if_possible(stash); self.store_stash_if_possible(stash);
predefined_calls::get_validators_ledger(&self.action_tx, &self.online_client_api, &stash).await predefined_calls::get_validators_ledger(&self.action_tx, &self.online_client_api, &stash).await
@ -183,6 +205,8 @@ impl Network {
} }
} }
Action::TransferBalance(sender, receiver, amount) => { Action::TransferBalance(sender, receiver, amount) => {
let maybe_nonce = self.senders.get_mut(&sender);
let sender: [u8; 32] = hex::decode(sender) let sender: [u8; 32] = hex::decode(sender)
.expect("stored seed is valid hex string; qed") .expect("stored seed is valid hex string; qed")
.as_slice() .as_slice()
@ -195,6 +219,7 @@ impl Network {
&sender, &sender,
&receiver, &receiver,
&amount, &amount,
maybe_nonce,
).await { ).await {
self.transactions_to_watch.push(tx_progress); self.transactions_to_watch.push(tx_progress);
} }

View File

@ -6,7 +6,12 @@ use subxt::{
}; };
use tokio::sync::mpsc::UnboundedSender; use tokio::sync::mpsc::UnboundedSender;
use crate::{action::Action, casper::CasperConfig, casper_network, types::ActionLevel}; use crate::{
action::Action,
types::ActionLevel,
casper::{CasperExtrinsicParamsBuilder, CasperConfig},
casper_network,
};
pub async fn transfer_balance( pub async fn transfer_balance(
action_tx: &UnboundedSender<Action>, action_tx: &UnboundedSender<Action>,
@ -14,6 +19,7 @@ pub async fn transfer_balance(
sender: &[u8; 32], sender: &[u8; 32],
receiver: &[u8; 32], receiver: &[u8; 32],
amount: &u128, amount: &u128,
mut maybe_nonce: Option<&mut u32>,
) -> Result<TxProgress<CasperConfig, OnlineClient<CasperConfig>>> { ) -> Result<TxProgress<CasperConfig, OnlineClient<CasperConfig>>> {
let receiver_id = subxt::utils::MultiAddress::Id( let receiver_id = subxt::utils::MultiAddress::Id(
subxt::utils::AccountId32::from(*receiver) subxt::utils::AccountId32::from(*receiver)
@ -23,12 +29,22 @@ pub async fn transfer_balance(
.balances() .balances()
.transfer_allow_death(receiver_id, *amount); .transfer_allow_death(receiver_id, *amount);
let tx_params = match maybe_nonce {
Some(ref mut nonce) => {
**nonce = nonce.saturating_add(1);
CasperExtrinsicParamsBuilder::new()
.nonce(nonce.saturating_sub(1) as u64)
.build()
},
None => CasperExtrinsicParamsBuilder::new().build(),
};
let pair = Pair::from_seed(sender); let pair = Pair::from_seed(sender);
let signer = PairSigner::<CasperConfig, Pair>::new(pair); let signer = PairSigner::<CasperConfig, Pair>::new(pair);
match api match api
.tx() .tx()
.sign_and_submit_then_watch_default(&transfer_tx, &signer) .sign_and_submit_then_watch(&transfer_tx, &signer, tx_params)
.await { .await {
Ok(tx_progress) => { Ok(tx_progress) => {
action_tx.send(Action::WalletLog( action_tx.send(Action::WalletLog(