From c24ff7bf07972f4f00461b386fcf03164be7a8ad Mon Sep 17 00:00:00 2001 From: Boris Oncev Date: Fri, 30 Aug 2024 16:57:35 +0200 Subject: [PATCH] extract runtime wallet functionality --- wallet/src/wallet/mod.rs | 2 + wallet/wallet-controller/src/helpers.rs | 27 +- wallet/wallet-controller/src/lib.rs | 196 +-- wallet/wallet-controller/src/read.rs | 199 ++- .../wallet-controller/src/runtime_wallet.rs | 1088 +++++++++++++++++ .../src/synced_controller.rs | 889 +++++--------- 6 files changed, 1507 insertions(+), 894 deletions(-) create mode 100644 wallet/wallet-controller/src/runtime_wallet.rs diff --git a/wallet/src/wallet/mod.rs b/wallet/src/wallet/mod.rs index eb0037a68..042e0b5c4 100644 --- a/wallet/src/wallet/mod.rs +++ b/wallet/src/wallet/mod.rs @@ -250,6 +250,8 @@ pub enum WalletError { MissingTokenAdditionalData(TokenId), #[error("Missmatched additional data for token {0}")] MissmatchedTokenAdditionalData(TokenId), + #[error("Unsupported operation for a Hardware wallet")] + UnsupportedHardwareWalletOperation, } /// Result type used for the wallet diff --git a/wallet/wallet-controller/src/helpers.rs b/wallet/wallet-controller/src/helpers.rs index dc856ff7e..b8a25aee1 100644 --- a/wallet/wallet-controller/src/helpers.rs +++ b/wallet/wallet-controller/src/helpers.rs @@ -40,7 +40,7 @@ use wallet_types::partially_signed_transaction::{ PartiallySignedTransaction, TokenAdditionalInfo, UtxoAdditionalInfo, UtxoWithAdditionalInfo, }; -use crate::{types::Balances, ControllerError, WalletType2}; +use crate::{runtime_wallet::RuntimeWallet, types::Balances, ControllerError}; pub async fn fetch_token_info( rpc_client: &T, @@ -58,13 +58,13 @@ pub async fn fetch_token_info( pub async fn fetch_utxo( rpc_client: &T, input: &UtxoOutPoint, - wallet: &WalletType2, + wallet: &RuntimeWallet, ) -> Result> { // search locally for the unspent utxo if let Some(out) = match &wallet { - WalletType2::Software(w) => w.find_unspent_utxo_with_destination(input), + RuntimeWallet::Software(w) => w.find_unspent_utxo_with_destination(input), #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.find_unspent_utxo_with_destination(input), + RuntimeWallet::Trezor(w) => w.find_unspent_utxo_with_destination(input), } { return Ok(out.0); } @@ -82,13 +82,13 @@ pub async fn fetch_utxo( pub async fn fetch_utxo_with_destination( rpc_client: &T, input: &UtxoOutPoint, - wallet: &WalletType2, + wallet: &RuntimeWallet, ) -> Result<(TxOutput, Destination), ControllerError> { // search locally for the unspent utxo if let Some(out) = match &wallet { - WalletType2::Software(w) => w.find_unspent_utxo_with_destination(input), + RuntimeWallet::Software(w) => w.find_unspent_utxo_with_destination(input), #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.find_unspent_utxo_with_destination(input), + RuntimeWallet::Trezor(w) => w.find_unspent_utxo_with_destination(input), } { return Ok(out); } @@ -109,7 +109,6 @@ pub async fn fetch_utxo_with_destination( .await .map_err(ControllerError::NodeCallError)? } else { - // FIXME get_tx_output_destination(&utxo, &|_| None, HtlcSpendingCondition::Skip) } .ok_or(ControllerError::WalletError(WalletError::CannotFindUtxo( @@ -229,7 +228,7 @@ pub async fn into_balances( pub async fn tx_to_partially_signed_tx( rpc_client: &T, - wallet: &WalletType2, + wallet: &RuntimeWallet, tx: Transaction, ) -> Result> { let tasks: FuturesOrdered<_> = tx @@ -266,7 +265,7 @@ pub async fn tx_to_partially_signed_tx( async fn into_utxo_and_destination( rpc_client: &T, - wallet: &WalletType2, + wallet: &RuntimeWallet, tx_inp: &TxInput, ) -> Result<(Option, Option), ControllerError> { Ok(match tx_inp { @@ -278,18 +277,18 @@ async fn into_utxo_and_destination( TxInput::Account(acc_outpoint) => { // find delegation destination let dest = match &wallet { - WalletType2::Software(w) => w.find_account_destination(acc_outpoint), + RuntimeWallet::Software(w) => w.find_account_destination(acc_outpoint), #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.find_account_destination(acc_outpoint), + RuntimeWallet::Trezor(w) => w.find_account_destination(acc_outpoint), }; (None, dest) } TxInput::AccountCommand(_, cmd) => { // find authority of the token let dest = match &wallet { - WalletType2::Software(w) => w.find_account_command_destination(cmd), + RuntimeWallet::Software(w) => w.find_account_command_destination(cmd), #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.find_account_command_destination(cmd), + RuntimeWallet::Trezor(w) => w.find_account_command_destination(cmd), }; (None, dest) } diff --git a/wallet/wallet-controller/src/lib.rs b/wallet/wallet-controller/src/lib.rs index fec9f8539..ca300b42e 100644 --- a/wallet/wallet-controller/src/lib.rs +++ b/wallet/wallet-controller/src/lib.rs @@ -18,6 +18,7 @@ mod helpers; pub mod mnemonic; pub mod read; +mod runtime_wallet; mod sync; pub mod synced_controller; pub mod types; @@ -32,6 +33,7 @@ use chainstate::tx_verifier::{ use futures::{never::Never, stream::FuturesOrdered, TryStreamExt}; use helpers::{fetch_token_info, fetch_utxo, fetch_utxo_extra_info, into_balances}; use node_comm::rpc_client::ColdWalletClient; +use runtime_wallet::RuntimeWallet; use std::{ collections::{BTreeMap, BTreeSet}, fs, @@ -90,7 +92,7 @@ use wallet::{ signer::software_signer::SoftwareSignerProvider, wallet::WalletPoolsFilter, wallet_events::WalletEvents, - Wallet, WalletError, WalletResult, + WalletError, WalletResult, }; pub use wallet_types::{ @@ -148,8 +150,6 @@ pub enum ControllerError { InvalidTxOutput(GenericCurrencyTransferToTxOutputConversionError), #[error("The specified token {0} is not a fungible token")] NotFungibleToken(TokenId), - #[error("Unsupported operation for a Hardware wallet")] - UnsupportedHardwareWalletOperation, } #[derive(Clone, Copy)] @@ -164,18 +164,12 @@ pub struct ControllerConfig { pub broadcast_to_mempool: bool, } -pub enum WalletType2 { - Software(Wallet), - #[cfg(feature = "trezor")] - Trezor(Wallet), -} - pub struct Controller { chain_config: Arc, rpc_client: T, - wallet: WalletType2, + wallet: RuntimeWallet, staking_started: BTreeSet, @@ -201,7 +195,7 @@ where pub async fn new( chain_config: Arc, rpc_client: T, - wallet: WalletType2, + wallet: RuntimeWallet, wallet_events: W, ) -> Result> { let mut controller = Self { @@ -221,7 +215,7 @@ where pub fn new_unsynced( chain_config: Arc, rpc_client: T, - wallet: WalletType2, + wallet: RuntimeWallet, wallet_events: W, ) -> Self { Self { @@ -239,7 +233,7 @@ where args: WalletTypeArgsComputed, best_block: (BlockHeight, Id), wallet_type: WalletType, - ) -> Result, ControllerError> { + ) -> Result, ControllerError> { utils::ensure!( !file_path.as_ref().exists(), ControllerError::WalletFileError( @@ -274,7 +268,7 @@ where }, ) .map_err(ControllerError::WalletError)?; - Ok(WalletType2::Software(wallet)) + Ok(RuntimeWallet::Software(wallet)) } #[cfg(feature = "trezor")] WalletTypeArgsComputed::Trezor => { @@ -286,7 +280,7 @@ where |_db_tx| Ok(TrezorSignerProvider::new().map_err(SignerError::TrezorError)?), ) .map_err(ControllerError::WalletError)?; - Ok(WalletType2::Trezor(wallet)) + Ok(RuntimeWallet::Trezor(wallet)) } } } @@ -296,7 +290,7 @@ where file_path: impl AsRef, args: WalletTypeArgsComputed, wallet_type: WalletType, - ) -> Result, ControllerError> { + ) -> Result, ControllerError> { utils::ensure!( !file_path.as_ref().exists(), ControllerError::WalletFileError( @@ -331,7 +325,7 @@ where }, ) .map_err(ControllerError::WalletError)?; - Ok(WalletType2::Software(wallet)) + Ok(RuntimeWallet::Software(wallet)) } #[cfg(feature = "trezor")] WalletTypeArgsComputed::Trezor => { @@ -342,7 +336,7 @@ where |_db_tx| Ok(TrezorSignerProvider::new().map_err(SignerError::TrezorError)?), ) .map_err(ControllerError::WalletError)?; - Ok(WalletType2::Trezor(wallet)) + Ok(RuntimeWallet::Trezor(wallet)) } } } @@ -381,7 +375,7 @@ where current_controller_mode: WalletControllerMode, force_change_wallet_type: bool, open_as_wallet_type: WalletType, - ) -> Result, ControllerError> { + ) -> Result, ControllerError> { utils::ensure!( file_path.as_ref().exists(), ControllerError::WalletFileError( @@ -405,7 +399,7 @@ where |db_tx| SoftwareSignerProvider::load_from_database(chain_config.clone(), db_tx), ) .map_err(ControllerError::WalletError)?; - Ok(WalletType2::Software(wallet)) + Ok(RuntimeWallet::Software(wallet)) } #[cfg(feature = "trezor")] WalletType::Trezor => { @@ -419,41 +413,30 @@ where |db_tx| TrezorSignerProvider::load_from_database(chain_config.clone(), db_tx), ) .map_err(ControllerError::WalletError)?; - Ok(WalletType2::Trezor(wallet)) + Ok(RuntimeWallet::Trezor(wallet)) } } } pub fn seed_phrase(&self) -> Result, ControllerError> { - match &self.wallet { - WalletType2::Software(w) => w.seed_phrase(), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.seed_phrase(), - } - .map(|opt| opt.map(SeedWithPassPhrase::from_serializable_seed_phrase)) - .map_err(ControllerError::WalletError) + self.wallet + .seed_phrase() + .map(|opt| opt.map(SeedWithPassPhrase::from_serializable_seed_phrase)) + .map_err(ControllerError::WalletError) } /// Delete the seed phrase if stored in the database pub fn delete_seed_phrase(&self) -> Result, ControllerError> { - match &self.wallet { - WalletType2::Software(w) => w.delete_seed_phrase(), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.delete_seed_phrase(), - } - .map(|opt| opt.map(SeedWithPassPhrase::from_serializable_seed_phrase)) - .map_err(ControllerError::WalletError) + self.wallet + .delete_seed_phrase() + .map(|opt| opt.map(SeedWithPassPhrase::from_serializable_seed_phrase)) + .map_err(ControllerError::WalletError) } /// Rescan the blockchain /// Resets the wallet to the genesis block pub fn reset_wallet_to_genesis(&mut self) -> Result<(), ControllerError> { - match &mut self.wallet { - WalletType2::Software(w) => w.reset_wallet_to_genesis(), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.reset_wallet_to_genesis(), - } - .map_err(ControllerError::WalletError) + self.wallet.reset_wallet_to_genesis().map_err(ControllerError::WalletError) } /// Encrypts the wallet using the specified `password`, or removes the existing encryption if `password` is `None`. @@ -466,12 +449,7 @@ where /// /// This method returns an error if the wallet is locked pub fn encrypt_wallet(&mut self, password: &Option) -> Result<(), ControllerError> { - match &mut self.wallet { - WalletType2::Software(w) => w.encrypt_wallet(password), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.encrypt_wallet(password), - } - .map_err(ControllerError::WalletError) + self.wallet.encrypt_wallet(password).map_err(ControllerError::WalletError) } /// Unlocks the wallet using the specified password. @@ -484,12 +462,7 @@ where /// /// This method returns an error if the password is incorrect pub fn unlock_wallet(&mut self, password: &String) -> Result<(), ControllerError> { - match &mut self.wallet { - WalletType2::Software(w) => w.unlock_wallet(password), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.unlock_wallet(password), - } - .map_err(ControllerError::WalletError) + self.wallet.unlock_wallet(password).map_err(ControllerError::WalletError) } /// Locks the wallet by making the encrypted private keys inaccessible. @@ -502,12 +475,7 @@ where self.staking_started.is_empty(), ControllerError::StakingRunning ); - match &mut self.wallet { - WalletType2::Software(w) => w.lock_wallet(), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.lock_wallet(), - } - .map_err(ControllerError::WalletError) + self.wallet.lock_wallet().map_err(ControllerError::WalletError) } /// Sets the lookahead size for key generation @@ -522,20 +490,13 @@ where ) -> Result<(), ControllerError> { utils::ensure!(lookahead_size > 0, ControllerError::InvalidLookaheadSize); - match &mut self.wallet { - WalletType2::Software(w) => w.set_lookahead_size(lookahead_size, force_reduce), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.set_lookahead_size(lookahead_size, force_reduce), - } - .map_err(ControllerError::WalletError) + self.wallet + .set_lookahead_size(lookahead_size, force_reduce) + .map_err(ControllerError::WalletError) } pub fn wallet_info(&self) -> WalletInfo { - let (wallet_id, account_names) = match &self.wallet { - WalletType2::Software(w) => w.wallet_info(), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.wallet_info(), - }; + let (wallet_id, account_names) = self.wallet.wallet_info(); WalletInfo { wallet_id, account_names, @@ -564,14 +525,10 @@ where transaction_ids: Vec>, packing_strategy: PackingStrategy, ) -> Result> { - let pos_data = match &self.wallet { - WalletType2::Software(w) => w.get_pos_gen_block_data(account_index, pool_id), - #[cfg(feature = "trezor")] - WalletType2::Trezor(_) => { - return Err(ControllerError::UnsupportedHardwareWalletOperation) - } - } - .map_err(ControllerError::WalletError)?; + let pos_data = self + .wallet + .get_pos_gen_block_data(account_index, pool_id) + .map_err(ControllerError::WalletError)?; let public_key = self .rpc_client @@ -608,12 +565,10 @@ where transaction_ids: Vec>, packing_strategy: PackingStrategy, ) -> Result> { - let pools = match &self.wallet { - WalletType2::Software(w) => w.get_pool_ids(account_index, WalletPoolsFilter::Stake), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.get_pool_ids(account_index, WalletPoolsFilter::Stake), - } - .map_err(ControllerError::WalletError)?; + let pools = self + .wallet + .get_pool_ids(account_index, WalletPoolsFilter::Stake) + .map_err(ControllerError::WalletError)?; let mut last_error = ControllerError::NoStakingPool; for (pool_id, _) in pools { @@ -679,14 +634,10 @@ where seconds_to_check_for_height: u64, check_all_timestamps_between_blocks: bool, ) -> Result>, ControllerError> { - let pos_data = match &self.wallet { - WalletType2::Software(w) => w.get_pos_gen_block_data_by_pool_id(pool_id), - #[cfg(feature = "trezor")] - WalletType2::Trezor(_) => { - return Err(ControllerError::UnsupportedHardwareWalletOperation) - } - } - .map_err(ControllerError::WalletError)?; + let pos_data = self + .wallet + .get_pos_gen_block_data_by_pool_id(pool_id) + .map_err(ControllerError::WalletError)?; let input_data = PoSTimestampSearchInputData::new(pool_id, pos_data.vrf_private_key().clone()); @@ -712,12 +663,7 @@ where &mut self, name: Option, ) -> Result<(U31, Option), ControllerError> { - match &mut self.wallet { - WalletType2::Software(w) => w.create_next_account(name), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.create_next_account(name), - } - .map_err(ControllerError::WalletError) + self.wallet.create_next_account(name).map_err(ControllerError::WalletError) } pub fn update_account_name( @@ -725,12 +671,9 @@ where account_index: U31, name: Option, ) -> Result<(U31, Option), ControllerError> { - match &mut self.wallet { - WalletType2::Software(w) => w.set_account_name(account_index, name), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.set_account_name(account_index, name), - } - .map_err(ControllerError::WalletError) + self.wallet + .set_account_name(account_index, name) + .map_err(ControllerError::WalletError) } pub fn stop_staking(&mut self, account_index: U31) -> Result<(), ControllerError> { @@ -744,36 +687,27 @@ where } pub fn best_block(&self) -> (Id, BlockHeight) { - *match &self.wallet { - WalletType2::Software(w) => w.get_best_block(), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.get_best_block(), - } - .values() - .min_by_key(|(_block_id, block_height)| block_height) - .expect("there must be at least one account") + *self + .wallet + .get_best_block() + .values() + .min_by_key(|(_block_id, block_height)| block_height) + .expect("there must be at least one account") } pub async fn get_stake_pool_balances( &self, account_index: U31, ) -> Result, ControllerError> { - let stake_pool_utxos = match &self.wallet { - WalletType2::Software(w) => w.get_utxos( - account_index, - UtxoType::CreateStakePool | UtxoType::ProduceBlockFromStake, - UtxoState::Confirmed.into(), - WithLocked::Unlocked, - ), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.get_utxos( + let stake_pool_utxos = self + .wallet + .get_utxos( account_index, UtxoType::CreateStakePool | UtxoType::ProduceBlockFromStake, UtxoState::Confirmed.into(), WithLocked::Unlocked, - ), - } - .map_err(ControllerError::WalletError)?; + ) + .map_err(ControllerError::WalletError)?; let pool_ids = stake_pool_utxos.into_iter().filter_map(|(_, utxo)| match utxo { TxOutput::ProduceBlockFromStake(_, pool_id) | TxOutput::CreateStakePool(pool_id, _) => { Some(pool_id) @@ -806,11 +740,11 @@ where /// Synchronize the wallet to the current node tip height and return pub async fn sync_once(&mut self) -> Result<(), ControllerError> { let res = match &mut self.wallet { - WalletType2::Software(w) => { + RuntimeWallet::Software(w) => { sync::sync_once(&self.chain_config, &self.rpc_client, w, &self.wallet_events).await } #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => { + RuntimeWallet::Trezor(w) => { sync::sync_once(&self.chain_config, &self.rpc_client, w, &self.wallet_events).await } }?; @@ -823,12 +757,12 @@ where pub async fn try_sync_once(&mut self) -> Result<(), ControllerError> { match &mut self.wallet { - WalletType2::Software(w) => { + RuntimeWallet::Software(w) => { sync::sync_once(&self.chain_config, &self.rpc_client, w, &self.wallet_events) .await?; } #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => { + RuntimeWallet::Trezor(w) => { sync::sync_once(&self.chain_config, &self.rpc_client, w, &self.wallet_events) .await?; } @@ -1277,11 +1211,7 @@ where /// Rebroadcast not confirmed transactions async fn rebroadcast_txs(&mut self, rebroadcast_txs_again_at: &mut Time) { if get_time() >= *rebroadcast_txs_again_at { - let txs = match &self.wallet { - WalletType2::Software(w) => w.get_transactions_to_be_broadcast(), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.get_transactions_to_be_broadcast(), - }; + let txs = self.wallet.get_transactions_to_be_broadcast(); match txs { Err(error) => { log::error!("Fetching transactions for rebroadcasting failed: {error}"); diff --git a/wallet/wallet-controller/src/read.rs b/wallet/wallet-controller/src/read.rs index 8d5ae20f6..3336f1405 100644 --- a/wallet/wallet-controller/src/read.rs +++ b/wallet/wallet-controller/src/read.rs @@ -45,12 +45,13 @@ use wallet_types::{ }; use crate::{ + runtime_wallet::RuntimeWallet, types::{AccountStandaloneKeyDetails, Balances, CreatedBlockInfo}, - ControllerError, WalletType2, + ControllerError, }; pub struct ReadOnlyController<'a, T, B: storage::Backend + 'static> { - wallet: &'a WalletType2, + wallet: &'a RuntimeWallet, rpc_client: T, chain_config: &'a ChainConfig, account_index: U31, @@ -65,7 +66,7 @@ where B: storage::Backend + 'static, { pub fn new( - wallet: &'a WalletType2, + wallet: &'a RuntimeWallet, rpc_client: T, chain_config: &'a ChainConfig, account_index: U31, @@ -87,12 +88,9 @@ where utxo_states: UtxoStates, with_locked: WithLocked, ) -> Result, ControllerError> { - match &self.wallet { - WalletType2::Software(w) => w.get_balance(self.account_index, utxo_states, with_locked), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.get_balance(self.account_index, utxo_states, with_locked), - } - .map_err(ControllerError::WalletError) + self.wallet + .get_balance(self.account_index, utxo_states, with_locked) + .map_err(ControllerError::WalletError) } pub async fn get_decimal_balance( @@ -110,17 +108,10 @@ where utxo_states: UtxoStates, with_locked: WithLocked, ) -> Result, ControllerError> { - match &self.wallet { - WalletType2::Software(w) => { - w.get_multisig_utxos(self.account_index, utxo_types, utxo_states, with_locked) - } - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => { - w.get_multisig_utxos(self.account_index, utxo_types, utxo_states, with_locked) - } - } - .map(|utxos| utxos.into_iter().collect()) - .map_err(ControllerError::WalletError) + self.wallet + .get_multisig_utxos(self.account_index, utxo_types, utxo_states, with_locked) + .map(|utxos| utxos.into_iter().collect()) + .map_err(ControllerError::WalletError) } pub fn get_utxos( @@ -129,25 +120,15 @@ where utxo_states: UtxoStates, with_locked: WithLocked, ) -> Result, ControllerError> { - match &self.wallet { - WalletType2::Software(w) => { - w.get_utxos(self.account_index, utxo_types, utxo_states, with_locked) - } - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => { - w.get_utxos(self.account_index, utxo_types, utxo_states, with_locked) - } - } - .map_err(ControllerError::WalletError) + self.wallet + .get_utxos(self.account_index, utxo_types, utxo_states, with_locked) + .map_err(ControllerError::WalletError) } pub fn pending_transactions(&self) -> Result>, ControllerError> { - match &self.wallet { - WalletType2::Software(w) => w.pending_transactions(self.account_index), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.pending_transactions(self.account_index), - } - .map_err(ControllerError::WalletError) + self.wallet + .pending_transactions(self.account_index) + .map_err(ControllerError::WalletError) } pub fn mainchain_transactions( @@ -155,16 +136,9 @@ where destination: Option, limit: usize, ) -> Result, ControllerError> { - match &self.wallet { - WalletType2::Software(w) => { - w.mainchain_transactions(self.account_index, destination, limit) - } - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => { - w.mainchain_transactions(self.account_index, destination, limit) - } - } - .map_err(ControllerError::WalletError) + self.wallet + .mainchain_transactions(self.account_index, destination, limit) + .map_err(ControllerError::WalletError) } pub fn get_transaction_list( @@ -172,68 +146,46 @@ where skip: usize, count: usize, ) -> Result> { - match &self.wallet { - WalletType2::Software(w) => w.get_transaction_list(self.account_index, skip, count), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.get_transaction_list(self.account_index, skip, count), - } - .map_err(ControllerError::WalletError) + self.wallet + .get_transaction_list(self.account_index, skip, count) + .map_err(ControllerError::WalletError) } pub fn get_transaction( &self, transaction_id: Id, ) -> Result<&TxData, ControllerError> { - match &self.wallet { - WalletType2::Software(w) => w.get_transaction(self.account_index, transaction_id), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.get_transaction(self.account_index, transaction_id), - } - .map_err(ControllerError::WalletError) + self.wallet + .get_transaction(self.account_index, transaction_id) + .map_err(ControllerError::WalletError) } pub fn get_all_issued_addresses( &self, ) -> Result>, ControllerError> { - match &self.wallet { - WalletType2::Software(w) => w.get_all_issued_addresses(self.account_index), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.get_all_issued_addresses(self.account_index), - } - .map_err(ControllerError::WalletError) + self.wallet + .get_all_issued_addresses(self.account_index) + .map_err(ControllerError::WalletError) } pub fn get_all_issued_vrf_public_keys( &self, ) -> Result, ControllerError> { - match &self.wallet { - WalletType2::Software(w) => w.get_all_issued_vrf_public_keys(self.account_index), - #[cfg(feature = "trezor")] - WalletType2::Trezor(_) => { - return Err(ControllerError::UnsupportedHardwareWalletOperation) - } - } - .map_err(ControllerError::WalletError) + self.wallet + .get_all_issued_vrf_public_keys(self.account_index) + .map_err(ControllerError::WalletError) } pub fn get_legacy_vrf_public_key(&self) -> Result, ControllerError> { - match &self.wallet { - WalletType2::Software(w) => w.get_legacy_vrf_public_key(self.account_index), - #[cfg(feature = "trezor")] - WalletType2::Trezor(_) => { - return Err(ControllerError::UnsupportedHardwareWalletOperation) - } - } - .map_err(ControllerError::WalletError) + self.wallet + .get_legacy_vrf_public_key(self.account_index) + .map_err(ControllerError::WalletError) } pub fn get_addresses_usage(&self) -> Result<&'a KeychainUsageState, ControllerError> { - match &self.wallet { - WalletType2::Software(w) => w.get_addresses_usage(self.account_index), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.get_addresses_usage(self.account_index), - } - .map_err(ControllerError::WalletError) + self.wallet + .get_addresses_usage(self.account_index) + .map_err(ControllerError::WalletError) } /// Get all addresses with usage information @@ -258,12 +210,9 @@ where /// Get all standalone addresses with their labels pub fn get_standalone_addresses(&self) -> Result> { - match &self.wallet { - WalletType2::Software(w) => w.get_all_standalone_addresses(self.account_index), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.get_all_standalone_addresses(self.account_index), - } - .map_err(ControllerError::WalletError) + self.wallet + .get_all_standalone_addresses(self.account_index) + .map_err(ControllerError::WalletError) } /// Get all standalone addresses with their labels and balances @@ -271,16 +220,10 @@ where &self, address: Destination, ) -> Result> { - let (address, balances, details) = match &self.wallet { - WalletType2::Software(w) => { - w.get_all_standalone_address_details(self.account_index, address) - } - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => { - w.get_all_standalone_address_details(self.account_index, address) - } - } - .map_err(ControllerError::WalletError)?; + let (address, balances, details) = self + .wallet + .get_all_standalone_address_details(self.account_index, address) + .map_err(ControllerError::WalletError)?; let balances = super::into_balances(&self.rpc_client, self.chain_config, balances).await?; @@ -320,12 +263,10 @@ where &self, filter: WalletPoolsFilter, ) -> Result, ControllerError> { - let pools = match &self.wallet { - WalletType2::Software(w) => w.get_pool_ids(self.account_index, filter), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.get_pool_ids(self.account_index, filter), - } - .map_err(ControllerError::WalletError)?; + let pools = self + .wallet + .get_pool_ids(self.account_index, filter) + .map_err(ControllerError::WalletError)?; let tasks: FuturesUnordered<_> = pools .into_iter() @@ -371,7 +312,7 @@ where &self, ) -> Result, ControllerError> { let delegations = match &self.wallet { - WalletType2::Software(w) => { + RuntimeWallet::Software(w) => { let delegations = w.get_delegations(self.account_index).map_err(ControllerError::WalletError)?; let tasks: FuturesUnordered<_> = delegations @@ -390,7 +331,7 @@ where tasks.try_collect::>().await?.into_iter().flatten().collect() } #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => { + RuntimeWallet::Trezor(w) => { let delegations = w.get_delegations(self.account_index).map_err(ControllerError::WalletError)?; let tasks: FuturesUnordered<_> = delegations @@ -414,26 +355,24 @@ where } pub fn get_created_blocks(&self) -> Result, ControllerError> { - match &self.wallet { - WalletType2::Software(w) => w.get_created_blocks(self.account_index), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.get_created_blocks(self.account_index), - } - .map_err(ControllerError::WalletError) - .map(|blocks| { - blocks - .into_iter() - .map(|(height, id, pool_id)| { - let pool_id = Address::new(self.chain_config, pool_id).expect("addressable"); - - CreatedBlockInfo { - height, - id, - pool_id: pool_id.to_string(), - } - }) - .collect() - }) + self.wallet + .get_created_blocks(self.account_index) + .map_err(ControllerError::WalletError) + .map(|blocks| { + blocks + .into_iter() + .map(|(height, id, pool_id)| { + let pool_id = + Address::new(self.chain_config, pool_id).expect("addressable"); + + CreatedBlockInfo { + height, + id, + pool_id: pool_id.to_string(), + } + }) + .collect() + }) } async fn get_delegation_share( diff --git a/wallet/wallet-controller/src/runtime_wallet.rs b/wallet/wallet-controller/src/runtime_wallet.rs new file mode 100644 index 000000000..406cb0471 --- /dev/null +++ b/wallet/wallet-controller/src/runtime_wallet.rs @@ -0,0 +1,1088 @@ +// Copyright (c) 2023 RBB S.r.l +// opensource@mintlayer.org +// SPDX-License-Identifier: MIT +// Licensed under the MIT License; +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://github.com/mintlayer/mintlayer-core/blob/master/LICENSE +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::collections::{BTreeMap, BTreeSet}; + +use common::address::pubkeyhash::PublicKeyHash; +use common::address::Address; +use common::chain::classic_multisig::ClassicMultisigChallenge; +use common::chain::htlc::HashedTimelockContract; +use common::chain::output_value::OutputValue; +use common::chain::signature::inputsig::arbitrary_message::ArbitraryMessageSignature; +use common::chain::tokens::{ + IsTokenUnfreezable, Metadata, RPCFungibleTokenInfo, TokenId, TokenIssuance, +}; +use common::chain::{ + DelegationId, Destination, GenBlock, PoolId, SignedTransaction, Transaction, TxOutput, + UtxoOutPoint, +}; +use common::primitives::id::WithId; +use common::primitives::{Amount, BlockHeight, Id, H256}; +use crypto::key::hdkd::child_number::ChildNumber; +use crypto::key::hdkd::u31::U31; +use crypto::key::{PrivateKey, PublicKey}; +use crypto::vrf::VRFPublicKey; +use mempool::FeeRate; +use wallet::account::currency_grouper::Currency; +use wallet::account::transaction_list::TransactionList; +use wallet::account::{CoinSelectionAlgo, DelegationData, PoolData, TxInfo, UnconfirmedTokenInfo}; +use wallet::send_request::{PoolOrTokenId, SelectedInputs, StakePoolDataArguments}; +use wallet::signer::software_signer::SoftwareSignerProvider; + +use wallet::wallet::WalletPoolsFilter; +use wallet::wallet_events::WalletEvents; +use wallet::{Wallet, WalletError, WalletResult}; +use wallet_types::account_info::{StandaloneAddressDetails, StandaloneAddresses}; +use wallet_types::partially_signed_transaction::{PartiallySignedTransaction, UtxoAdditionalInfo}; +use wallet_types::seed_phrase::SerializableSeedPhrase; +use wallet_types::signature_status::SignatureStatus; +use wallet_types::utxo_types::{UtxoStates, UtxoTypes}; +use wallet_types::wallet_tx::TxData; +use wallet_types::with_locked::WithLocked; +use wallet_types::KeychainUsageState; + +#[cfg(feature = "trezor")] +use wallet::signer::trezor_signer::TrezorSignerProvider; + +pub enum RuntimeWallet { + Software(Wallet), + #[cfg(feature = "trezor")] + Trezor(Wallet), +} + +impl RuntimeWallet { + pub fn seed_phrase(&self) -> Result, WalletError> { + match self { + RuntimeWallet::Software(w) => w.seed_phrase(), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.seed_phrase(), + } + } + + pub fn delete_seed_phrase(&self) -> Result, WalletError> { + match self { + RuntimeWallet::Software(w) => w.delete_seed_phrase(), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.delete_seed_phrase(), + } + } + + pub fn reset_wallet_to_genesis(&mut self) -> Result<(), WalletError> { + match self { + RuntimeWallet::Software(w) => w.reset_wallet_to_genesis(), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.reset_wallet_to_genesis(), + } + } + + pub fn encrypt_wallet(&mut self, password: &Option) -> Result<(), WalletError> { + match self { + RuntimeWallet::Software(w) => w.encrypt_wallet(password), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.encrypt_wallet(password), + } + } + + pub fn unlock_wallet(&mut self, password: &String) -> Result<(), WalletError> { + match self { + RuntimeWallet::Software(w) => w.unlock_wallet(password), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.unlock_wallet(password), + } + } + + pub fn lock_wallet(&mut self) -> Result<(), WalletError> { + match self { + RuntimeWallet::Software(w) => w.lock_wallet(), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.lock_wallet(), + } + } + + pub fn set_lookahead_size( + &mut self, + lookahead_size: u32, + force_reduce: bool, + ) -> Result<(), WalletError> { + match self { + RuntimeWallet::Software(w) => w.set_lookahead_size(lookahead_size, force_reduce), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.set_lookahead_size(lookahead_size, force_reduce), + } + } + + pub fn wallet_info(&self) -> (H256, Vec>) { + match self { + RuntimeWallet::Software(w) => w.wallet_info(), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.wallet_info(), + } + } + + pub fn create_next_account( + &mut self, + name: Option, + ) -> Result<(U31, Option), WalletError> { + match self { + RuntimeWallet::Software(w) => w.create_next_account(name), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.create_next_account(name), + } + } + + pub fn set_account_name( + &mut self, + account_index: U31, + name: Option, + ) -> Result<(U31, Option), WalletError> { + match self { + RuntimeWallet::Software(w) => w.set_account_name(account_index, name), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.set_account_name(account_index, name), + } + } + + pub fn get_pos_gen_block_data( + &self, + account_index: U31, + pool_id: PoolId, + ) -> Result { + match self { + RuntimeWallet::Software(w) => w.get_pos_gen_block_data(account_index, pool_id), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(_) => Err(WalletError::UnsupportedHardwareWalletOperation), + } + } + + pub fn get_pos_gen_block_data_by_pool_id( + &self, + pool_id: PoolId, + ) -> Result { + match self { + RuntimeWallet::Software(w) => w.get_pos_gen_block_data_by_pool_id(pool_id), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(_) => Err(WalletError::UnsupportedHardwareWalletOperation), + } + } + + pub fn get_pool_ids( + &self, + account_index: U31, + filter: WalletPoolsFilter, + ) -> WalletResult> { + match self { + RuntimeWallet::Software(w) => w.get_pool_ids(account_index, filter), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.get_pool_ids(account_index, filter), + } + } + + pub fn get_best_block(&self) -> BTreeMap, BlockHeight)> { + match self { + RuntimeWallet::Software(w) => w.get_best_block(), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.get_best_block(), + } + } + + pub fn is_locked(&self) -> bool { + match self { + RuntimeWallet::Software(w) => w.is_locked(), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.is_locked(), + } + } + + pub fn get_utxos( + &self, + account_index: U31, + utxo_types: UtxoTypes, + utxo_states: UtxoStates, + with_locked: WithLocked, + ) -> Result, WalletError> { + match self { + RuntimeWallet::Software(w) => { + w.get_utxos(account_index, utxo_types, utxo_states, with_locked) + } + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => { + w.get_utxos(account_index, utxo_types, utxo_states, with_locked) + } + } + } + + pub fn get_transactions_to_be_broadcast( + &mut self, + ) -> Result, WalletError> { + match self { + RuntimeWallet::Software(w) => w.get_transactions_to_be_broadcast(), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.get_transactions_to_be_broadcast(), + } + } + + pub fn get_balance( + &self, + account_index: U31, + utxo_states: UtxoStates, + with_locked: WithLocked, + ) -> WalletResult> { + match self { + RuntimeWallet::Software(w) => w.get_balance(account_index, utxo_states, with_locked), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.get_balance(account_index, utxo_states, with_locked), + } + } + + pub fn get_multisig_utxos( + &self, + account_index: U31, + utxo_types: UtxoTypes, + utxo_states: UtxoStates, + with_locked: WithLocked, + ) -> WalletResult> { + match self { + RuntimeWallet::Software(w) => { + w.get_multisig_utxos(account_index, utxo_types, utxo_states, with_locked) + } + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => { + w.get_multisig_utxos(account_index, utxo_types, utxo_states, with_locked) + } + } + } + + pub fn pending_transactions( + &self, + account_index: U31, + ) -> WalletResult>> { + match self { + RuntimeWallet::Software(w) => w.pending_transactions(account_index), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.pending_transactions(account_index), + } + } + + pub fn mainchain_transactions( + &self, + account_index: U31, + destination: Option, + limit: usize, + ) -> WalletResult> { + match self { + RuntimeWallet::Software(w) => { + w.mainchain_transactions(account_index, destination, limit) + } + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.mainchain_transactions(account_index, destination, limit), + } + } + + pub fn get_transaction_list( + &self, + account_index: U31, + skip: usize, + count: usize, + ) -> WalletResult { + match self { + RuntimeWallet::Software(w) => w.get_transaction_list(account_index, skip, count), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.get_transaction_list(account_index, skip, count), + } + } + + pub fn get_transaction( + &self, + account_index: U31, + transaction_id: Id, + ) -> WalletResult<&TxData> { + match self { + RuntimeWallet::Software(w) => w.get_transaction(account_index, transaction_id), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.get_transaction(account_index, transaction_id), + } + } + + pub fn get_all_issued_addresses( + &self, + account_index: U31, + ) -> WalletResult>> { + match self { + RuntimeWallet::Software(w) => w.get_all_issued_addresses(account_index), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.get_all_issued_addresses(account_index), + } + } + + pub fn get_all_issued_vrf_public_keys( + &self, + account_index: U31, + ) -> WalletResult, bool)>> { + match self { + RuntimeWallet::Software(w) => w.get_all_issued_vrf_public_keys(account_index), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(_) => Err(WalletError::UnsupportedHardwareWalletOperation), + } + } + + pub fn get_legacy_vrf_public_key( + &self, + account_index: U31, + ) -> WalletResult> { + match self { + RuntimeWallet::Software(w) => w.get_legacy_vrf_public_key(account_index), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(_) => Err(WalletError::UnsupportedHardwareWalletOperation), + } + } + + pub fn get_addresses_usage(&self, account_index: U31) -> WalletResult<&KeychainUsageState> { + match self { + RuntimeWallet::Software(w) => w.get_addresses_usage(account_index), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.get_addresses_usage(account_index), + } + } + + pub fn get_all_standalone_addresses( + &self, + account_index: U31, + ) -> WalletResult { + match self { + RuntimeWallet::Software(w) => w.get_all_standalone_addresses(account_index), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.get_all_standalone_addresses(account_index), + } + } + + pub fn get_all_standalone_address_details( + &self, + account_index: U31, + address: Destination, + ) -> WalletResult<( + Destination, + BTreeMap, + StandaloneAddressDetails, + )> { + match self { + RuntimeWallet::Software(w) => { + w.get_all_standalone_address_details(account_index, address) + } + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => { + w.get_all_standalone_address_details(account_index, address) + } + } + } + + pub fn get_created_blocks( + &self, + account_index: U31, + ) -> WalletResult, PoolId)>> { + match self { + RuntimeWallet::Software(w) => w.get_created_blocks(account_index), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.get_created_blocks(account_index), + } + } + + pub fn find_used_tokens( + &self, + account_index: U31, + input_utxos: &[UtxoOutPoint], + ) -> WalletResult> { + match self { + RuntimeWallet::Software(w) => w.find_used_tokens(account_index, input_utxos), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.find_used_tokens(account_index, input_utxos), + } + } + + pub fn get_token_unconfirmed_info( + &self, + account_index: U31, + token_info: RPCFungibleTokenInfo, + ) -> WalletResult { + match self { + RuntimeWallet::Software(w) => w.get_token_unconfirmed_info(account_index, token_info), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.get_token_unconfirmed_info(account_index, token_info), + } + } + + pub fn abandon_transaction( + &mut self, + account_index: U31, + tx_id: Id, + ) -> WalletResult<()> { + match self { + RuntimeWallet::Software(w) => w.abandon_transaction(account_index, tx_id), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.abandon_transaction(account_index, tx_id), + } + } + + pub fn standalone_address_label_rename( + &mut self, + account_index: U31, + address: Destination, + label: Option, + ) -> WalletResult<()> { + match self { + RuntimeWallet::Software(w) => { + w.standalone_address_label_rename(account_index, address, label) + } + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => { + w.standalone_address_label_rename(account_index, address, label) + } + } + } + + pub fn add_standalone_address( + &mut self, + account_index: U31, + address: PublicKeyHash, + label: Option, + ) -> WalletResult<()> { + match self { + RuntimeWallet::Software(w) => w.add_standalone_address(account_index, address, label), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.add_standalone_address(account_index, address, label), + } + } + + pub fn add_standalone_private_key( + &mut self, + account_index: U31, + private_key: PrivateKey, + label: Option, + ) -> WalletResult<()> { + match self { + RuntimeWallet::Software(w) => { + w.add_standalone_private_key(account_index, private_key, label) + } + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => { + w.add_standalone_private_key(account_index, private_key, label) + } + } + } + + pub fn add_standalone_multisig( + &mut self, + account_index: U31, + challenge: ClassicMultisigChallenge, + label: Option, + ) -> WalletResult { + match self { + RuntimeWallet::Software(w) => { + w.add_standalone_multisig(account_index, challenge, label) + } + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.add_standalone_multisig(account_index, challenge, label), + } + } + + pub fn get_new_address( + &mut self, + account_index: U31, + ) -> WalletResult<(ChildNumber, Address)> { + match self { + RuntimeWallet::Software(w) => w.get_new_address(account_index), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.get_new_address(account_index), + } + } + + pub fn find_public_key( + &mut self, + account_index: U31, + address: Destination, + ) -> WalletResult { + match self { + RuntimeWallet::Software(w) => w.find_public_key(account_index, address), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.find_public_key(account_index, address), + } + } + + pub fn get_vrf_key( + &mut self, + account_index: U31, + ) -> WalletResult<(ChildNumber, Address)> { + match self { + RuntimeWallet::Software(w) => w.get_vrf_key(account_index), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(_) => Err(WalletError::UnsupportedHardwareWalletOperation), + } + } + + pub fn issue_new_token( + &mut self, + account_index: U31, + token_issuance: TokenIssuance, + current_fee_rate: FeeRate, + consolidate_fee_rate: FeeRate, + ) -> WalletResult<(TokenId, SignedTransaction)> { + match self { + RuntimeWallet::Software(w) => w.issue_new_token( + account_index, + token_issuance, + current_fee_rate, + consolidate_fee_rate, + ), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.issue_new_token( + account_index, + token_issuance, + current_fee_rate, + consolidate_fee_rate, + ), + } + } + + pub fn issue_new_nft( + &mut self, + account_index: U31, + address: Address, + metadata: Metadata, + current_fee_rate: FeeRate, + consolidate_fee_rate: FeeRate, + ) -> WalletResult<(TokenId, SignedTransaction)> { + match self { + RuntimeWallet::Software(w) => w.issue_new_nft( + account_index, + address, + metadata, + current_fee_rate, + consolidate_fee_rate, + ), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.issue_new_nft( + account_index, + address, + metadata, + current_fee_rate, + consolidate_fee_rate, + ), + } + } + + pub fn mint_tokens( + &mut self, + account_index: U31, + token_info: &UnconfirmedTokenInfo, + amount: Amount, + address: Address, + current_fee_rate: FeeRate, + consolidate_fee_rate: FeeRate, + ) -> Result { + match self { + RuntimeWallet::Software(w) => w.mint_tokens( + account_index, + token_info, + amount, + address, + current_fee_rate, + consolidate_fee_rate, + ), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.mint_tokens( + account_index, + token_info, + amount, + address, + current_fee_rate, + consolidate_fee_rate, + ), + } + } + + pub fn unmint_tokens( + &mut self, + account_index: U31, + token_info: &UnconfirmedTokenInfo, + amount: Amount, + current_fee_rate: FeeRate, + consolidate_fee_rate: FeeRate, + ) -> Result { + match self { + RuntimeWallet::Software(w) => w.unmint_tokens( + account_index, + token_info, + amount, + current_fee_rate, + consolidate_fee_rate, + ), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.unmint_tokens( + account_index, + token_info, + amount, + current_fee_rate, + consolidate_fee_rate, + ), + } + } + + pub fn lock_token_supply( + &mut self, + account_index: U31, + token_info: &UnconfirmedTokenInfo, + current_fee_rate: FeeRate, + consolidate_fee_rate: FeeRate, + ) -> Result { + match self { + RuntimeWallet::Software(w) => w.lock_token_supply( + account_index, + token_info, + current_fee_rate, + consolidate_fee_rate, + ), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.lock_token_supply( + account_index, + token_info, + current_fee_rate, + consolidate_fee_rate, + ), + } + } + + pub fn freeze_token( + &mut self, + account_index: U31, + token_info: &UnconfirmedTokenInfo, + is_token_unfreezable: IsTokenUnfreezable, + current_fee_rate: FeeRate, + consolidate_fee_rate: FeeRate, + ) -> Result { + match self { + RuntimeWallet::Software(w) => w.freeze_token( + account_index, + token_info, + is_token_unfreezable, + current_fee_rate, + consolidate_fee_rate, + ), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.freeze_token( + account_index, + token_info, + is_token_unfreezable, + current_fee_rate, + consolidate_fee_rate, + ), + } + } + + pub fn unfreeze_token( + &mut self, + account_index: U31, + token_info: &UnconfirmedTokenInfo, + current_fee_rate: FeeRate, + consolidate_fee_rate: FeeRate, + ) -> Result { + match self { + RuntimeWallet::Software(w) => w.unfreeze_token( + account_index, + token_info, + current_fee_rate, + consolidate_fee_rate, + ), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.unfreeze_token( + account_index, + token_info, + current_fee_rate, + consolidate_fee_rate, + ), + } + } + + pub fn change_token_authority( + &mut self, + account_index: U31, + token_info: &UnconfirmedTokenInfo, + address: Address, + current_fee_rate: FeeRate, + consolidate_fee_rate: FeeRate, + ) -> Result { + match self { + RuntimeWallet::Software(w) => w.change_token_authority( + account_index, + token_info, + address, + current_fee_rate, + consolidate_fee_rate, + ), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.change_token_authority( + account_index, + token_info, + address, + current_fee_rate, + consolidate_fee_rate, + ), + } + } + + #[allow(clippy::too_many_arguments)] + pub fn create_transaction_to_addresses( + &mut self, + account_index: U31, + outputs: impl IntoIterator, + inputs: SelectedInputs, + change_addresses: BTreeMap>, + current_fee_rate: FeeRate, + consolidate_fee_rate: FeeRate, + additional_utxo_infos: &BTreeMap, + ) -> WalletResult { + match self { + RuntimeWallet::Software(w) => w.create_transaction_to_addresses( + account_index, + outputs, + inputs, + change_addresses, + current_fee_rate, + consolidate_fee_rate, + additional_utxo_infos, + ), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.create_transaction_to_addresses( + account_index, + outputs, + inputs, + change_addresses, + current_fee_rate, + consolidate_fee_rate, + additional_utxo_infos, + ), + } + } + + pub fn create_sweep_transaction( + &mut self, + account_index: U31, + destination_address: Destination, + filtered_inputs: Vec<(UtxoOutPoint, TxOutput)>, + current_fee_rate: FeeRate, + additional_utxo_infos: BTreeMap, + ) -> WalletResult { + match self { + RuntimeWallet::Software(w) => w.create_sweep_transaction( + account_index, + destination_address, + filtered_inputs, + current_fee_rate, + &additional_utxo_infos, + ), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.create_sweep_transaction( + account_index, + destination_address, + filtered_inputs, + current_fee_rate, + &additional_utxo_infos, + ), + } + } + + pub fn get_delegation( + &self, + account_index: U31, + delegation_id: DelegationId, + ) -> WalletResult<&DelegationData> { + match self { + RuntimeWallet::Software(w) => w.get_delegation(account_index, delegation_id), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.get_delegation(account_index, delegation_id), + } + } + + pub fn create_sweep_from_delegation_transaction( + &mut self, + account_index: U31, + destination_address: Address, + delegation_id: DelegationId, + delegation_share: Amount, + current_fee_rate: FeeRate, + ) -> WalletResult { + match self { + RuntimeWallet::Software(w) => w.create_sweep_from_delegation_transaction( + account_index, + destination_address, + delegation_id, + delegation_share, + current_fee_rate, + ), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.create_sweep_from_delegation_transaction( + account_index, + destination_address, + delegation_id, + delegation_share, + current_fee_rate, + ), + } + } + + #[allow(clippy::too_many_arguments)] + pub fn create_unsigned_transaction_to_addresses( + &mut self, + account_index: U31, + outputs: impl IntoIterator, + selected_inputs: SelectedInputs, + selection_algo: Option, + change_addresses: BTreeMap>, + current_fee_rate: FeeRate, + consolidate_fee_rate: FeeRate, + ) -> WalletResult<(PartiallySignedTransaction, BTreeMap)> { + match self { + RuntimeWallet::Software(w) => w.create_unsigned_transaction_to_addresses( + account_index, + outputs, + selected_inputs, + selection_algo, + change_addresses, + current_fee_rate, + consolidate_fee_rate, + ), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.create_unsigned_transaction_to_addresses( + account_index, + outputs, + selected_inputs, + selection_algo, + change_addresses, + current_fee_rate, + consolidate_fee_rate, + ), + } + } + + pub fn create_delegation( + &mut self, + account_index: U31, + output: TxOutput, + current_fee_rate: FeeRate, + consolidate_fee_rate: FeeRate, + ) -> WalletResult<(DelegationId, SignedTransaction)> { + match self { + RuntimeWallet::Software(w) => w.create_delegation( + account_index, + vec![output], + current_fee_rate, + consolidate_fee_rate, + ), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.create_delegation( + account_index, + vec![output], + current_fee_rate, + consolidate_fee_rate, + ), + } + } + + pub fn create_transaction_to_addresses_from_delegation( + &mut self, + account_index: U31, + address: Address, + amount: Amount, + delegation_id: DelegationId, + delegation_share: Amount, + current_fee_rate: FeeRate, + ) -> WalletResult { + match self { + RuntimeWallet::Software(w) => w.create_transaction_to_addresses_from_delegation( + account_index, + address, + amount, + delegation_id, + delegation_share, + current_fee_rate, + ), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.create_transaction_to_addresses_from_delegation( + account_index, + address, + amount, + delegation_id, + delegation_share, + current_fee_rate, + ), + } + } + + pub fn create_stake_pool_tx( + &mut self, + account_index: U31, + current_fee_rate: FeeRate, + consolidate_fee_rate: FeeRate, + stake_pool_arguments: StakePoolDataArguments, + ) -> WalletResult { + match self { + RuntimeWallet::Software(w) => w.create_stake_pool_tx( + account_index, + current_fee_rate, + consolidate_fee_rate, + stake_pool_arguments, + ), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(_) => Err(WalletError::UnsupportedHardwareWalletOperation), + } + } + + pub fn decommission_stake_pool( + &mut self, + account_index: U31, + pool_id: PoolId, + staker_balance: Amount, + output_address: Option, + current_fee_rate: FeeRate, + ) -> WalletResult { + match self { + RuntimeWallet::Software(w) => w.decommission_stake_pool( + account_index, + pool_id, + staker_balance, + output_address, + current_fee_rate, + ), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.decommission_stake_pool( + account_index, + pool_id, + staker_balance, + output_address, + current_fee_rate, + ), + } + } + + pub fn decommission_stake_pool_request( + &mut self, + account_index: U31, + pool_id: PoolId, + staker_balance: Amount, + output_address: Option, + current_fee_rate: FeeRate, + ) -> WalletResult { + match self { + RuntimeWallet::Software(w) => w.decommission_stake_pool_request( + account_index, + pool_id, + staker_balance, + output_address, + current_fee_rate, + ), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.decommission_stake_pool_request( + account_index, + pool_id, + staker_balance, + output_address, + current_fee_rate, + ), + } + } + + pub fn create_htlc_tx( + &mut self, + account_index: U31, + output_value: OutputValue, + htlc: HashedTimelockContract, + current_fee_rate: FeeRate, + consolidate_fee_rate: FeeRate, + ) -> WalletResult { + match self { + RuntimeWallet::Software(w) => w.create_htlc_tx( + account_index, + output_value, + htlc, + current_fee_rate, + consolidate_fee_rate, + ), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.create_htlc_tx( + account_index, + output_value, + htlc, + current_fee_rate, + consolidate_fee_rate, + ), + } + } + + pub fn sign_raw_transaction( + &mut self, + account_index: U31, + ptx: PartiallySignedTransaction, + ) -> WalletResult<( + PartiallySignedTransaction, + Vec, + Vec, + )> { + match self { + RuntimeWallet::Software(w) => w.sign_raw_transaction(account_index, ptx), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.sign_raw_transaction(account_index, ptx), + } + } + + pub fn sign_challenge( + &mut self, + account_index: U31, + challenge: Vec, + destination: Destination, + ) -> WalletResult { + match self { + RuntimeWallet::Software(w) => w.sign_challenge(account_index, challenge, destination), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.sign_challenge(account_index, challenge, destination), + } + } + + pub fn add_unconfirmed_tx( + &mut self, + tx: SignedTransaction, + wallet_events: &impl WalletEvents, + ) -> WalletResult<()> { + match self { + RuntimeWallet::Software(w) => w.add_unconfirmed_tx(tx, wallet_events), + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => w.add_unconfirmed_tx(tx, wallet_events), + } + } + + pub fn add_account_unconfirmed_tx( + &mut self, + account_index: U31, + tx: &SignedTransaction, + wallet_events: &impl WalletEvents, + ) -> WalletResult<()> { + match self { + RuntimeWallet::Software(w) => { + w.add_account_unconfirmed_tx(account_index, tx.clone(), wallet_events) + } + #[cfg(feature = "trezor")] + RuntimeWallet::Trezor(w) => { + w.add_account_unconfirmed_tx(account_index, tx.clone(), wallet_events) + } + } + } +} diff --git a/wallet/wallet-controller/src/synced_controller.rs b/wallet/wallet-controller/src/synced_controller.rs index c8fa401fe..6c0c412d6 100644 --- a/wallet/wallet-controller/src/synced_controller.rs +++ b/wallet/wallet-controller/src/synced_controller.rs @@ -68,12 +68,13 @@ use wallet_types::{ use crate::{ helpers::{fetch_token_info, fetch_utxo, into_balances, tx_to_partially_signed_tx}, + runtime_wallet::RuntimeWallet, types::{Balances, GenericCurrencyTransfer}, - ControllerConfig, ControllerError, WalletType2, + ControllerConfig, ControllerError, }; pub struct SyncedController<'a, T, W, B: storage::Backend + 'static> { - wallet: &'a mut WalletType2, + wallet: &'a mut RuntimeWallet, rpc_client: T, chain_config: &'a ChainConfig, wallet_events: &'a W, @@ -89,7 +90,7 @@ where W: WalletEvents, { pub fn new( - wallet: &'a mut WalletType2, + wallet: &'a mut RuntimeWallet, rpc_client: T, chain_config: &'a ChainConfig, wallet_events: &'a W, @@ -124,12 +125,10 @@ where &self, input_utxos: &[UtxoOutPoint], ) -> Result<(), ControllerError> { - let token_ids = match &self.wallet { - WalletType2::Software(w) => w.find_used_tokens(self.account_index, input_utxos), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.find_used_tokens(self.account_index, input_utxos), - } - .map_err(ControllerError::WalletError)?; + let token_ids = self + .wallet + .find_used_tokens(self.account_index, input_utxos) + .map_err(ControllerError::WalletError)?; for token_info in self.fetch_token_infos(token_ids).await? { match token_info { @@ -146,16 +145,11 @@ where &self, token_info: RPCFungibleTokenInfo, ) -> Result<(), ControllerError> { - match &self.wallet { - WalletType2::Software(w) => { - w.get_token_unconfirmed_info(self.account_index, token_info) - } - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.get_token_unconfirmed_info(self.account_index, token_info), - } - .map_err(ControllerError::WalletError)? - .check_can_be_used() - .map_err(ControllerError::WalletError)?; + self.wallet + .get_token_unconfirmed_info(self.account_index, token_info) + .map_err(ControllerError::WalletError)? + .check_can_be_used() + .map_err(ControllerError::WalletError)?; Ok(()) } @@ -184,20 +178,15 @@ where |all_ok, token_info| -> Result> { let all_ok = all_ok && match &token_info { - RPCTokenInfo::FungibleToken(token_info) => match &self.wallet { - WalletType2::Software(w) => w.get_token_unconfirmed_info( + RPCTokenInfo::FungibleToken(token_info) => self + .wallet + .get_token_unconfirmed_info( self.account_index, token_info.clone(), - ), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.get_token_unconfirmed_info( - self.account_index, - token_info.clone(), - ), - } - .map_err(ControllerError::WalletError)? - .check_can_be_used() - .is_ok(), + ) + .map_err(ControllerError::WalletError)? + .check_can_be_used() + .is_ok(), RPCTokenInfo::NonFungibleToken(_) => true, }; Ok(all_ok) @@ -226,12 +215,9 @@ where &mut self, tx_id: Id, ) -> Result<(), ControllerError> { - match &mut self.wallet { - WalletType2::Software(w) => w.abandon_transaction(self.account_index, tx_id), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.abandon_transaction(self.account_index, tx_id), - } - .map_err(ControllerError::WalletError) + self.wallet + .abandon_transaction(self.account_index, tx_id) + .map_err(ControllerError::WalletError) } pub fn standalone_address_label_rename( @@ -239,16 +225,9 @@ where address: Destination, label: Option, ) -> Result<(), ControllerError> { - match &mut self.wallet { - WalletType2::Software(w) => { - w.standalone_address_label_rename(self.account_index, address, label) - } - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => { - w.standalone_address_label_rename(self.account_index, address, label) - } - } - .map_err(ControllerError::WalletError) + self.wallet + .standalone_address_label_rename(self.account_index, address, label) + .map_err(ControllerError::WalletError) } pub fn add_standalone_address( @@ -256,14 +235,9 @@ where address: PublicKeyHash, label: Option, ) -> Result<(), ControllerError> { - match &mut self.wallet { - WalletType2::Software(w) => { - w.add_standalone_address(self.account_index, address, label) - } - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.add_standalone_address(self.account_index, address, label), - } - .map_err(ControllerError::WalletError) + self.wallet + .add_standalone_address(self.account_index, address, label) + .map_err(ControllerError::WalletError) } pub fn add_standalone_private_key( @@ -271,16 +245,9 @@ where private_key: PrivateKey, label: Option, ) -> Result<(), ControllerError> { - match &mut self.wallet { - WalletType2::Software(w) => { - w.add_standalone_private_key(self.account_index, private_key, label) - } - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => { - w.add_standalone_private_key(self.account_index, private_key, label) - } - } - .map_err(ControllerError::WalletError) + self.wallet + .add_standalone_private_key(self.account_index, private_key, label) + .map_err(ControllerError::WalletError) } pub fn add_standalone_multisig( @@ -288,51 +255,34 @@ where challenge: ClassicMultisigChallenge, label: Option, ) -> Result> { - match &mut self.wallet { - WalletType2::Software(w) => { - w.add_standalone_multisig(self.account_index, challenge, label) - } - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => { - w.add_standalone_multisig(self.account_index, challenge, label) - } - } - .map_err(ControllerError::WalletError) + self.wallet + .add_standalone_multisig(self.account_index, challenge, label) + .map_err(ControllerError::WalletError) } pub fn new_address( &mut self, ) -> Result<(ChildNumber, Address), ControllerError> { - match &mut self.wallet { - WalletType2::Software(w) => w.get_new_address(self.account_index), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.get_new_address(self.account_index), - } - .map_err(ControllerError::WalletError) + self.wallet + .get_new_address(self.account_index) + .map_err(ControllerError::WalletError) } pub fn find_public_key( &mut self, address: Destination, ) -> Result> { - match &mut self.wallet { - WalletType2::Software(w) => w.find_public_key(self.account_index, address), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.find_public_key(self.account_index, address), - } - .map_err(ControllerError::WalletError) + self.wallet + .find_public_key(self.account_index, address) + .map_err(ControllerError::WalletError) } pub fn new_vrf_key( &mut self, ) -> Result<(ChildNumber, Address), ControllerError> { - match &mut self.wallet { - WalletType2::Software(w) => { - w.get_vrf_key(self.account_index).map_err(ControllerError::WalletError) - } - #[cfg(feature = "trezor")] - WalletType2::Trezor(_) => Err(ControllerError::UnsupportedHardwareWalletOperation), - } + self.wallet + .get_vrf_key(self.account_index) + .map_err(ControllerError::WalletError) } pub async fn issue_new_token( @@ -347,37 +297,21 @@ where self.create_and_send_tx_with_id( move |current_fee_rate: FeeRate, consolidate_fee_rate: FeeRate, - wallet: &mut WalletType2, + wallet: &mut RuntimeWallet, account_index: U31| { - match wallet { - WalletType2::Software(w) => w.issue_new_token( - account_index, - TokenIssuance::V1(TokenIssuanceV1 { - token_ticker, - number_of_decimals, - metadata_uri, - total_supply: token_total_supply, - authority: address.into_object(), - is_freezable, - }), - current_fee_rate, - consolidate_fee_rate, - ), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.issue_new_token( - account_index, - TokenIssuance::V1(TokenIssuanceV1 { - token_ticker, - number_of_decimals, - metadata_uri, - total_supply: token_total_supply, - authority: address.into_object(), - is_freezable, - }), - current_fee_rate, - consolidate_fee_rate, - ), - } + wallet.issue_new_token( + account_index, + TokenIssuance::V1(TokenIssuanceV1 { + token_ticker, + number_of_decimals, + metadata_uri, + total_supply: token_total_supply, + authority: address.into_object(), + is_freezable, + }), + current_fee_rate, + consolidate_fee_rate, + ) }, ) .await @@ -391,25 +325,15 @@ where self.create_and_send_tx_with_id( move |current_fee_rate: FeeRate, consolidate_fee_rate: FeeRate, - wallet: &mut WalletType2, + wallet: &mut RuntimeWallet, account_index: U31| { - match wallet { - WalletType2::Software(w) => w.issue_new_nft( - account_index, - address, - metadata, - current_fee_rate, - consolidate_fee_rate, - ), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.issue_new_nft( - account_index, - address, - metadata, - current_fee_rate, - consolidate_fee_rate, - ), - } + wallet.issue_new_nft( + account_index, + address, + metadata, + current_fee_rate, + consolidate_fee_rate, + ) }, ) .await @@ -425,29 +349,18 @@ where token_info, move |current_fee_rate: FeeRate, consolidate_fee_rate: FeeRate, - wallet: &mut WalletType2, + wallet: &mut RuntimeWallet, account_index: U31, token_info: &UnconfirmedTokenInfo| { token_info.check_can_be_used()?; - match wallet { - WalletType2::Software(w) => w.mint_tokens( - account_index, - token_info, - amount, - address, - current_fee_rate, - consolidate_fee_rate, - ), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.mint_tokens( - account_index, - token_info, - amount, - address, - current_fee_rate, - consolidate_fee_rate, - ), - } + wallet.mint_tokens( + account_index, + token_info, + amount, + address, + current_fee_rate, + consolidate_fee_rate, + ) }, ) .await @@ -461,27 +374,17 @@ where token_info, move |current_fee_rate: FeeRate, consolidate_fee_rate: FeeRate, - wallet: &mut WalletType2, + wallet: &mut RuntimeWallet, account_index: U31, token_info: &UnconfirmedTokenInfo| { token_info.check_can_be_used()?; - match wallet { - WalletType2::Software(w) => w.unmint_tokens( - account_index, - token_info, - amount, - current_fee_rate, - consolidate_fee_rate, - ), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.unmint_tokens( - account_index, - token_info, - amount, - current_fee_rate, - consolidate_fee_rate, - ), - } + wallet.unmint_tokens( + account_index, + token_info, + amount, + current_fee_rate, + consolidate_fee_rate, + ) }, ) .await @@ -495,25 +398,16 @@ where token_info, move |current_fee_rate: FeeRate, consolidate_fee_rate: FeeRate, - wallet: &mut WalletType2, + wallet: &mut RuntimeWallet, account_index: U31, token_info: &UnconfirmedTokenInfo| { token_info.check_can_be_used()?; - match wallet { - WalletType2::Software(w) => w.lock_token_supply( - account_index, - token_info, - current_fee_rate, - consolidate_fee_rate, - ), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.lock_token_supply( - account_index, - token_info, - current_fee_rate, - consolidate_fee_rate, - ), - } + wallet.lock_token_supply( + account_index, + token_info, + current_fee_rate, + consolidate_fee_rate, + ) }, ) .await @@ -530,26 +424,16 @@ where token_info, move |current_fee_rate: FeeRate, consolidate_fee_rate: FeeRate, - wallet: &mut WalletType2, + wallet: &mut RuntimeWallet, account_index: U31, token_info: &UnconfirmedTokenInfo| { - match wallet { - WalletType2::Software(w) => w.freeze_token( - account_index, - token_info, - is_token_unfreezable, - current_fee_rate, - consolidate_fee_rate, - ), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.freeze_token( - account_index, - token_info, - is_token_unfreezable, - current_fee_rate, - consolidate_fee_rate, - ), - } + wallet.freeze_token( + account_index, + token_info, + is_token_unfreezable, + current_fee_rate, + consolidate_fee_rate, + ) }, ) .await @@ -564,24 +448,15 @@ where token_info, move |current_fee_rate: FeeRate, consolidate_fee_rate: FeeRate, - wallet: &mut WalletType2, + wallet: &mut RuntimeWallet, account_index: U31, token_info: &UnconfirmedTokenInfo| { - match wallet { - WalletType2::Software(w) => w.unfreeze_token( - account_index, - token_info, - current_fee_rate, - consolidate_fee_rate, - ), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.unfreeze_token( - account_index, - token_info, - current_fee_rate, - consolidate_fee_rate, - ), - } + wallet.unfreeze_token( + account_index, + token_info, + current_fee_rate, + consolidate_fee_rate, + ) }, ) .await @@ -598,26 +473,16 @@ where token_info, move |current_fee_rate: FeeRate, consolidate_fee_rate: FeeRate, - wallet: &mut WalletType2, + wallet: &mut RuntimeWallet, account_index: U31, token_info: &UnconfirmedTokenInfo| { - match wallet { - WalletType2::Software(w) => w.change_token_authority( - account_index, - token_info, - address, - current_fee_rate, - consolidate_fee_rate, - ), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.change_token_authority( - account_index, - token_info, - address, - current_fee_rate, - consolidate_fee_rate, - ), - } + wallet.change_token_authority( + account_index, + token_info, + address, + current_fee_rate, + consolidate_fee_rate, + ) }, ) .await @@ -633,29 +498,17 @@ where self.create_and_send_tx( move |current_fee_rate: FeeRate, consolidate_fee_rate: FeeRate, - wallet: &mut WalletType2, + wallet: &mut RuntimeWallet, account_index: U31| { - match wallet { - WalletType2::Software(w) => w.create_transaction_to_addresses( - account_index, - outputs, - SelectedInputs::Utxos(vec![]), - BTreeMap::new(), - current_fee_rate, - consolidate_fee_rate, - &BTreeMap::new(), - ), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.create_transaction_to_addresses( - account_index, - outputs, - SelectedInputs::Utxos(vec![]), - BTreeMap::new(), - current_fee_rate, - consolidate_fee_rate, - &BTreeMap::new(), - ), - } + wallet.create_transaction_to_addresses( + account_index, + outputs, + SelectedInputs::Utxos(vec![]), + BTreeMap::new(), + current_fee_rate, + consolidate_fee_rate, + &BTreeMap::new(), + ) }, ) .await @@ -677,29 +530,17 @@ where self.create_and_send_tx( move |current_fee_rate: FeeRate, consolidate_fee_rate: FeeRate, - wallet: &mut WalletType2, + wallet: &mut RuntimeWallet, account_index: U31| { - match wallet { - WalletType2::Software(w) => w.create_transaction_to_addresses( - account_index, - [output], - SelectedInputs::Utxos(selected_utxos), - BTreeMap::new(), - current_fee_rate, - consolidate_fee_rate, - &BTreeMap::new(), - ), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.create_transaction_to_addresses( - account_index, - [output], - SelectedInputs::Utxos(selected_utxos), - BTreeMap::new(), - current_fee_rate, - consolidate_fee_rate, - &BTreeMap::new(), - ), - } + wallet.create_transaction_to_addresses( + account_index, + [output], + SelectedInputs::Utxos(selected_utxos), + BTreeMap::new(), + current_fee_rate, + consolidate_fee_rate, + &BTreeMap::new(), + ) }, ) .await @@ -712,22 +553,12 @@ where destination_address: Destination, from_addresses: BTreeSet, ) -> Result> { - let selected_utxos = match &self.wallet { - WalletType2::Software(w) => w.get_utxos( - self.account_index, - UtxoType::Transfer | UtxoType::LockThenTransfer | UtxoType::IssueNft, - UtxoState::Confirmed | UtxoState::Inactive, - WithLocked::Unlocked, - ), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.get_utxos( - self.account_index, - UtxoType::Transfer | UtxoType::LockThenTransfer | UtxoType::IssueNft, - UtxoState::Confirmed | UtxoState::Inactive, - WithLocked::Unlocked, - ), - } - .map_err(ControllerError::WalletError)?; + let selected_utxos = self.wallet.get_utxos( + self.account_index, + UtxoType::Transfer | UtxoType::LockThenTransfer | UtxoType::IssueNft, + UtxoState::Confirmed | UtxoState::Inactive, + WithLocked::Unlocked, + )?; let (inputs, additional_utxo_infos) = self.filter_out_utxos_with_frozen_tokens(selected_utxos).await?; @@ -743,25 +574,15 @@ where self.create_and_send_tx( move |current_fee_rate: FeeRate, _consolidate_fee_rate: FeeRate, - wallet: &mut WalletType2, + wallet: &mut RuntimeWallet, account_index: U31| { - match wallet { - WalletType2::Software(w) => w.create_sweep_transaction( - account_index, - destination_address, - filtered_inputs, - current_fee_rate, - &additional_utxo_infos, - ), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.create_sweep_transaction( - account_index, - destination_address, - filtered_inputs, - current_fee_rate, - &additional_utxo_infos, - ), - } + wallet.create_sweep_transaction( + account_index, + destination_address, + filtered_inputs, + current_fee_rate, + additional_utxo_infos, + ) }, ) .await @@ -774,13 +595,11 @@ where destination_address: Address, delegation_id: DelegationId, ) -> Result> { - let pool_id = match &self.wallet { - WalletType2::Software(w) => w.get_delegation(self.account_index, delegation_id), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.get_delegation(self.account_index, delegation_id), - } - .map_err(ControllerError::WalletError)? - .pool_id; + let pool_id = self + .wallet + .get_delegation(self.account_index, delegation_id) + .map_err(ControllerError::WalletError)? + .pool_id; let delegation_share = self .rpc_client @@ -794,25 +613,15 @@ where self.create_and_send_tx( move |current_fee_rate: FeeRate, _consolidate_fee_rate: FeeRate, - wallet: &mut WalletType2, + wallet: &mut RuntimeWallet, account_index: U31| { - match wallet { - WalletType2::Software(w) => w.create_sweep_from_delegation_transaction( - account_index, - destination_address, - delegation_id, - delegation_share, - current_fee_rate, - ), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.create_sweep_from_delegation_transaction( - account_index, - destination_address, - delegation_id, - delegation_share, - current_fee_rate, - ), - } + wallet.create_sweep_from_delegation_transaction( + account_index, + destination_address, + delegation_id, + delegation_share, + current_fee_rate, + ) }, ) .await @@ -851,18 +660,9 @@ where let (current_fee_rate, consolidate_fee_rate) = self.get_current_and_consolidation_fee_rate().await?; - let (req, fees) = match &mut self.wallet { - WalletType2::Software(w) => w.create_unsigned_transaction_to_addresses( - self.account_index, - [output], - selected_inputs, - None, - [(Currency::Coin, change_address)].into(), - current_fee_rate, - consolidate_fee_rate, - ), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.create_unsigned_transaction_to_addresses( + let (req, fees) = self + .wallet + .create_unsigned_transaction_to_addresses( self.account_index, [output], selected_inputs, @@ -870,9 +670,8 @@ where [(Currency::Coin, change_address)].into(), current_fee_rate, consolidate_fee_rate, - ), - } - .map_err(ControllerError::WalletError)?; + ) + .map_err(ControllerError::WalletError)?; let fees = into_balances(&self.rpc_client, self.chain_config, fees).await?; @@ -943,22 +742,12 @@ where let mut inputs = inputs; let mut change_addresses = change_addresses; - let all_utxos = match &self.wallet { - WalletType2::Software(w) => w.get_utxos( - self.account_index, - UtxoType::Transfer | UtxoType::LockThenTransfer, - UtxoState::Confirmed | UtxoState::InMempool | UtxoState::Inactive, - WithLocked::Unlocked, - ), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.get_utxos( - self.account_index, - UtxoType::Transfer | UtxoType::LockThenTransfer, - UtxoState::Confirmed | UtxoState::InMempool | UtxoState::Inactive, - WithLocked::Unlocked, - ), - } - .map_err(ControllerError::WalletError)?; + let all_utxos = self.wallet.get_utxos( + self.account_index, + UtxoType::Transfer | UtxoType::LockThenTransfer, + UtxoState::Confirmed | UtxoState::InMempool | UtxoState::Inactive, + WithLocked::Unlocked, + )?; let all_coin_utxos = all_utxos .into_iter() @@ -1016,28 +805,15 @@ where let (current_fee_rate, consolidate_fee_rate) = self.get_current_and_consolidation_fee_rate().await?; - let (tx, fees) = match &mut self.wallet { - WalletType2::Software(w) => w.create_unsigned_transaction_to_addresses( - self.account_index, - outputs, - selected_inputs, - Some(CoinSelectionAlgo::Randomize), - change_addresses, - current_fee_rate, - consolidate_fee_rate, - ), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.create_unsigned_transaction_to_addresses( - self.account_index, - outputs, - selected_inputs, - Some(CoinSelectionAlgo::Randomize), - change_addresses, - current_fee_rate, - consolidate_fee_rate, - ), - } - .map_err(ControllerError::WalletError)?; + let (tx, fees) = self.wallet.create_unsigned_transaction_to_addresses( + self.account_index, + outputs, + selected_inputs, + Some(CoinSelectionAlgo::Randomize), + change_addresses, + current_fee_rate, + consolidate_fee_rate, + )?; let fees = into_balances(&self.rpc_client, self.chain_config, fees).await?; @@ -1056,23 +832,14 @@ where self.create_and_send_tx_with_id( move |current_fee_rate: FeeRate, consolidate_fee_rate: FeeRate, - wallet: &mut WalletType2, + wallet: &mut RuntimeWallet, account_index: U31| { - match wallet { - WalletType2::Software(w) => w.create_delegation( - account_index, - vec![output], - current_fee_rate, - consolidate_fee_rate, - ), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.create_delegation( - account_index, - vec![output], - current_fee_rate, - consolidate_fee_rate, - ), - } + wallet.create_delegation( + account_index, + output, + current_fee_rate, + consolidate_fee_rate, + ) }, ) .await @@ -1089,29 +856,17 @@ where self.create_and_send_tx( move |current_fee_rate: FeeRate, consolidate_fee_rate: FeeRate, - wallet: &mut WalletType2, + wallet: &mut RuntimeWallet, account_index: U31| { - match wallet { - WalletType2::Software(w) => w.create_transaction_to_addresses( - account_index, - [output], - SelectedInputs::Utxos(vec![]), - BTreeMap::new(), - current_fee_rate, - consolidate_fee_rate, - &BTreeMap::new(), - ), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.create_transaction_to_addresses( - account_index, - [output], - SelectedInputs::Utxos(vec![]), - BTreeMap::new(), - current_fee_rate, - consolidate_fee_rate, - &BTreeMap::new(), - ), - } + wallet.create_transaction_to_addresses( + account_index, + [output], + SelectedInputs::Utxos(vec![]), + BTreeMap::new(), + current_fee_rate, + consolidate_fee_rate, + &BTreeMap::new(), + ) }, ) .await @@ -1125,13 +880,7 @@ where amount: Amount, delegation_id: DelegationId, ) -> Result> { - let pool_id = match &self.wallet { - WalletType2::Software(w) => w.get_delegation(self.account_index, delegation_id), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.get_delegation(self.account_index, delegation_id), - } - .map_err(ControllerError::WalletError)? - .pool_id; + let pool_id = self.wallet.get_delegation(self.account_index, delegation_id)?.pool_id; let delegation_share = self .rpc_client @@ -1145,27 +894,16 @@ where self.create_and_send_tx( move |current_fee_rate: FeeRate, _consolidate_fee_rate: FeeRate, - wallet: &mut WalletType2, + wallet: &mut RuntimeWallet, account_index: U31| { - match wallet { - WalletType2::Software(w) => w.create_transaction_to_addresses_from_delegation( - account_index, - address, - amount, - delegation_id, - delegation_share, - current_fee_rate, - ), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.create_transaction_to_addresses_from_delegation( - account_index, - address, - amount, - delegation_id, - delegation_share, - current_fee_rate, - ), - } + wallet.create_transaction_to_addresses_from_delegation( + account_index, + address, + amount, + delegation_id, + delegation_share, + current_fee_rate, + ) }, ) .await @@ -1184,7 +922,7 @@ where token_info, move |current_fee_rate: FeeRate, consolidate_fee_rate: FeeRate, - wallet: &mut WalletType2, + wallet: &mut RuntimeWallet, account_index: U31, token_info: &UnconfirmedTokenInfo| { token_info.check_can_be_used()?; @@ -1195,27 +933,15 @@ where ticker: token_info.token_ticker().to_vec(), }), )]); - match wallet { - WalletType2::Software(w) => w.create_transaction_to_addresses( - account_index, - [output], - SelectedInputs::Utxos(vec![]), - BTreeMap::new(), - current_fee_rate, - consolidate_fee_rate, - &additional_info, - ), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.create_transaction_to_addresses( - account_index, - [output], - SelectedInputs::Utxos(vec![]), - BTreeMap::new(), - current_fee_rate, - consolidate_fee_rate, - &additional_info, - ), - } + wallet.create_transaction_to_addresses( + account_index, + [output], + SelectedInputs::Utxos(vec![]), + BTreeMap::new(), + current_fee_rate, + consolidate_fee_rate, + &additional_info, + ) }, ) .await @@ -1232,27 +958,19 @@ where self.create_and_send_tx( move |current_fee_rate: FeeRate, consolidate_fee_rate: FeeRate, - wallet: &mut WalletType2, + wallet: &mut RuntimeWallet, account_index: U31| { - match wallet { - WalletType2::Software(w) => w - .create_stake_pool_tx( - account_index, - current_fee_rate, - consolidate_fee_rate, - StakePoolDataArguments { - amount, - margin_ratio_per_thousand, - cost_per_block, - decommission_key, - }, - ) - .map_err(ControllerError::WalletError), - #[cfg(feature = "trezor")] - WalletType2::Trezor(_) => { - Err(ControllerError::UnsupportedHardwareWalletOperation) - } - } + wallet.create_stake_pool_tx( + account_index, + current_fee_rate, + consolidate_fee_rate, + StakePoolDataArguments { + amount, + margin_ratio_per_thousand, + cost_per_block, + decommission_key, + }, + ) }, ) .await @@ -1276,25 +994,15 @@ where self.create_and_send_tx( move |current_fee_rate: FeeRate, _consolidate_fee_rate: FeeRate, - wallet: &mut WalletType2, + wallet: &mut RuntimeWallet, account_index: U31| { - match wallet { - WalletType2::Software(w) => w.decommission_stake_pool( - account_index, - pool_id, - staker_balance, - output_address, - current_fee_rate, - ), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.decommission_stake_pool( - account_index, - pool_id, - staker_balance, - output_address, - current_fee_rate, - ), - } + wallet.decommission_stake_pool( + account_index, + pool_id, + staker_balance, + output_address, + current_fee_rate, + ) }, ) .await @@ -1317,24 +1025,15 @@ where let (current_fee_rate, _) = self.get_current_and_consolidation_fee_rate().await?; - match &mut self.wallet { - WalletType2::Software(w) => w.decommission_stake_pool_request( + self.wallet + .decommission_stake_pool_request( self.account_index, pool_id, staker_balance, output_address, current_fee_rate, - ), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.decommission_stake_pool_request( - self.account_index, - pool_id, - staker_balance, - output_address, - current_fee_rate, - ), - } - .map_err(ControllerError::WalletError) + ) + .map_err(ControllerError::WalletError) } pub async fn create_htlc_tx( @@ -1345,45 +1044,21 @@ where let (current_fee_rate, consolidate_fee_rate) = self.get_current_and_consolidation_fee_rate().await?; - let result = match self.wallet { - WalletType2::Software(w) => w.create_htlc_tx( - self.account_index, - output_value, - htlc, - current_fee_rate, - consolidate_fee_rate, - )?, - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.create_htlc_tx( - self.account_index, - output_value, - htlc, - current_fee_rate, - consolidate_fee_rate, - )?, - }; + let result = self.wallet.create_htlc_tx( + self.account_index, + output_value, + htlc, + current_fee_rate, + consolidate_fee_rate, + )?; Ok(result) } /// Checks if the wallet has stake pools and marks this account for staking. pub fn start_staking(&mut self) -> Result<(), ControllerError> { - utils::ensure!( - !match &self.wallet { - WalletType2::Software(w) => w.is_locked(), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.is_locked(), - }, - ControllerError::WalletIsLocked - ); + utils::ensure!(!self.wallet.is_locked(), ControllerError::WalletIsLocked); // Make sure that account_index is valid and that pools exist - let pool_ids = match &mut self.wallet { - WalletType2::Software(w) => { - w.get_pool_ids(self.account_index, WalletPoolsFilter::Stake) - } - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.get_pool_ids(self.account_index, WalletPoolsFilter::Stake), - } - .map_err(ControllerError::WalletError)?; + let pool_ids = self.wallet.get_pool_ids(self.account_index, WalletPoolsFilter::Stake)?; utils::ensure!(!pool_ids.is_empty(), ControllerError::NoStakingPool); log::info!("Start staking, account_index: {}", self.account_index); self.staking_started.insert(self.account_index); @@ -1410,12 +1085,9 @@ where } }; - match &mut self.wallet { - WalletType2::Software(w) => w.sign_raw_transaction(self.account_index, ptx), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.sign_raw_transaction(self.account_index, ptx), - } - .map_err(ControllerError::WalletError) + self.wallet + .sign_raw_transaction(self.account_index, ptx) + .map_err(ControllerError::WalletError) } pub fn sign_challenge( @@ -1423,23 +1095,15 @@ where challenge: Vec, destination: Destination, ) -> Result> { - match &mut self.wallet { - WalletType2::Software(w) => { - w.sign_challenge(self.account_index, challenge, destination) - } - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.sign_challenge(self.account_index, challenge, destination), - } - .map_err(ControllerError::WalletError) + self.wallet + .sign_challenge(self.account_index, challenge, destination) + .map_err(ControllerError::WalletError) } pub fn add_unconfirmed_tx(&mut self, tx: SignedTransaction) -> Result<(), ControllerError> { - match &mut self.wallet { - WalletType2::Software(w) => w.add_unconfirmed_tx(tx, self.wallet_events), - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => w.add_unconfirmed_tx(tx, self.wallet_events), - } - .map_err(ControllerError::WalletError) + self.wallet + .add_unconfirmed_tx(tx, self.wallet_events) + .map_err(ControllerError::WalletError) } async fn get_current_and_consolidation_fee_rate( @@ -1460,16 +1124,9 @@ where &mut self, tx: SignedTransaction, ) -> Result> { - match &mut self.wallet { - WalletType2::Software(w) => { - w.add_account_unconfirmed_tx(self.account_index, tx.clone(), self.wallet_events) - } - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => { - w.add_account_unconfirmed_tx(self.account_index, tx.clone(), self.wallet_events) - } - } - .map_err(ControllerError::WalletError)?; + self.wallet + .add_account_unconfirmed_tx(self.account_index, &tx, self.wallet_events) + .map_err(ControllerError::WalletError)?; self.rpc_client .submit_transaction(tx.clone(), Default::default()) @@ -1498,7 +1155,7 @@ where tx_maker: F, ) -> Result> where - F: FnOnce(FeeRate, FeeRate, &mut WalletType2, U31) -> Result, + F: FnOnce(FeeRate, FeeRate, &mut RuntimeWallet, U31) -> Result, ControllerError: From, { let (current_fee_rate, consolidate_fee_rate) = @@ -1520,7 +1177,7 @@ where F: FnOnce( FeeRate, FeeRate, - &mut WalletType2, + &mut RuntimeWallet, U31, &UnconfirmedTokenInfo, ) -> WalletResult, @@ -1531,16 +1188,9 @@ where ) -> Result> { // make sure we can use the token before create an tx using it let token_freezable_info = match token_info { - RPCTokenInfo::FungibleToken(token_info) => match &self.wallet { - WalletType2::Software(w) => { - w.get_token_unconfirmed_info(self.account_index, token_info) - } - #[cfg(feature = "trezor")] - WalletType2::Trezor(w) => { - w.get_token_unconfirmed_info(self.account_index, token_info) - } + RPCTokenInfo::FungibleToken(token_info) => { + self.wallet.get_token_unconfirmed_info(self.account_index, token_info)? } - .map_err(ControllerError::WalletError)?, RPCTokenInfo::NonFungibleToken(info) => { UnconfirmedTokenInfo::NonFungibleToken(info.token_id, info.as_ref().into()) } @@ -1565,7 +1215,12 @@ where /// e.g. newly issued token, nft or delegation id async fn create_and_send_tx_with_id< ID, - F: FnOnce(FeeRate, FeeRate, &mut WalletType2, U31) -> WalletResult<(ID, SignedTransaction)>, + F: FnOnce( + FeeRate, + FeeRate, + &mut RuntimeWallet, + U31, + ) -> WalletResult<(ID, SignedTransaction)>, >( &mut self, tx_maker: F,