diff --git a/mm2src/coins/coin_balance.rs b/mm2src/coins/coin_balance.rs index 3ec047ee80..d985b274ed 100644 --- a/mm2src/coins/coin_balance.rs +++ b/mm2src/coins/coin_balance.rs @@ -337,7 +337,8 @@ pub trait HDWalletBalanceOps: HDWalletCoinOps { // Derive HD addresses and split addresses and their derivation paths into two collections. let (addresses, der_paths): (Vec<_>, Vec<_>) = self .derive_addresses(hd_account, address_ids) - .await? + .await + .map_mm_err()? .into_iter() .map(|hd_address| (hd_address.address(), hd_address.derivation_path().clone())) .unzip(); @@ -428,11 +429,12 @@ pub mod common_impl { HDCoinAddress: fmt::Display, { let gap_limit = hd_wallet.gap_limit(); - let mut addresses = coin.all_known_addresses_balances(hd_account).await?; + let mut addresses = coin.all_known_addresses_balances(hd_account).await.map_mm_err()?; if scan_new_addresses { addresses.extend( coin.scan_for_new_addresses(hd_wallet, hd_account, address_scanner, gap_limit) - .await?, + .await + .map_mm_err()?, ); } @@ -474,7 +476,7 @@ pub mod common_impl { HDCoinHDAccount: HDAccountStorageOps, { let mut accounts = hd_wallet.get_accounts_mut().await; - let address_scanner = coin.produce_hd_address_scanner().await?; + let address_scanner = coin.produce_hd_address_scanner().await.map_mm_err()?; let mut result = HDWalletBalance { accounts: Vec::with_capacity(accounts.len() + 1), @@ -489,8 +491,9 @@ pub mod common_impl { ); // Create new HD account. - let mut new_account = - create_new_account(coin, hd_wallet, xpub_extractor, Some(path_to_address.account_id)).await?; + let mut new_account = create_new_account(coin, hd_wallet, xpub_extractor, Some(path_to_address.account_id)) + .await + .map_mm_err()?; let scan_new_addresses = matches!( params.scan_policy, EnableCoinScanPolicy::ScanIfNewWallet | EnableCoinScanPolicy::Scan @@ -576,7 +579,10 @@ pub mod common_impl { let mut new_addresses = Vec::with_capacity(to_generate); let mut addresses_to_request = Vec::with_capacity(to_generate); for _ in 0..to_generate { - let hd_address = coin.generate_new_address(hd_wallet, hd_account, chain).await?; + let hd_address = coin + .generate_new_address(hd_wallet, hd_account, chain) + .await + .map_mm_err()?; new_addresses.push(HDAddressBalance { address: hd_address.address().display_address(), @@ -589,7 +595,8 @@ pub mod common_impl { let to_extend = coin .known_addresses_balances(addresses_to_request) - .await? + .await + .map_mm_err()? .into_iter() // The balances are guaranteed to be in the same order as they were requests. .zip(new_addresses) diff --git a/mm2src/coins/eth.rs b/mm2src/coins/eth.rs index 91c3294c2d..8f0fc3d385 100644 --- a/mm2src/coins/eth.rs +++ b/mm2src/coins/eth.rs @@ -1120,12 +1120,14 @@ impl InitWithdrawCoin for EthCoin { /// `withdraw_erc1155` function returns details of `ERC-1155` transaction including tx hex, /// which should be sent to`send_raw_transaction` RPC to broadcast the transaction. pub async fn withdraw_erc1155(ctx: MmArc, withdraw_type: WithdrawErc1155) -> WithdrawNftResult { - let coin = lp_coinfind_or_err(&ctx, withdraw_type.chain.to_ticker()).await?; + let coin = lp_coinfind_or_err(&ctx, withdraw_type.chain.to_ticker()) + .await + .map_mm_err()?; let (to_addr, token_addr, eth_coin) = - get_valid_nft_addr_to_withdraw(coin, &withdraw_type.to, &withdraw_type.token_address)?; + get_valid_nft_addr_to_withdraw(coin, &withdraw_type.to, &withdraw_type.token_address).map_mm_err()?; let token_id_str = &withdraw_type.token_id.to_string(); - let wallet_erc1155_amount = eth_coin.erc1155_balance(token_addr, token_id_str).await?; + let wallet_erc1155_amount = eth_coin.erc1155_balance(token_addr, token_id_str).await.map_mm_err()?; let amount_uint = if withdraw_type.max { wallet_erc1155_amount.clone() @@ -1142,14 +1144,16 @@ pub async fn withdraw_erc1155(ctx: MmArc, withdraw_type: WithdrawErc1155) -> Wit }); } - let my_address = eth_coin.derivation_method.single_addr_or_err().await?; + let my_address = eth_coin.derivation_method.single_addr_or_err().await.map_mm_err()?; let (eth_value, data, call_addr, fee_coin) = match eth_coin.coin_type { EthCoinType::Eth => { let function = ERC1155_CONTRACT.function("safeTransferFrom")?; - let token_id_u256 = - U256::from_dec_str(token_id_str).map_to_mm(|e| NumConversError::new(format!("{:?}", e)))?; - let amount_u256 = - U256::from_dec_str(&amount_uint.to_string()).map_to_mm(|e| NumConversError::new(format!("{:?}", e)))?; + let token_id_u256 = U256::from_dec_str(token_id_str) + .map_to_mm(|e| NumConversError::new(format!("{:?}", e))) + .map_mm_err()?; + let amount_u256 = U256::from_dec_str(&amount_uint.to_string()) + .map_to_mm(|e| NumConversError::new(format!("{:?}", e))) + .map_mm_err()?; let data = function.encode_input(&[ Token::Address(my_address), Token::Address(to_addr), @@ -1175,7 +1179,8 @@ pub async fn withdraw_erc1155(ctx: MmArc, withdraw_type: WithdrawErc1155) -> Wit call_addr, false, ) - .await?; + .await + .map_mm_err()?; let address_lock = eth_coin.get_address_lock(my_address.to_string()).await; let _nonce_lock = address_lock.lock().await; let (nonce, _) = eth_coin @@ -1190,12 +1195,6 @@ pub async fn withdraw_erc1155(ctx: MmArc, withdraw_type: WithdrawErc1155) -> Wit if !eth_coin.is_tx_type_supported(&tx_type) { return MmError::err(WithdrawError::TxTypeNotSupported); } - let tx_builder = UnSignedEthTxBuilder::new(tx_type, nonce, gas, Action::Call(call_addr), eth_value, data); - let tx_builder = tx_builder_with_pay_for_gas_option(ð_coin, tx_builder, &pay_for_gas_option)?; - let tx = tx_builder - .build() - .map_to_mm(|e| WithdrawError::InternalError(e.to_string()))?; - let secret = eth_coin.priv_key_policy.activated_key_or_err()?.secret(); let chain_id = match eth_coin.chain_spec { ChainSpec::Evm { chain_id } => chain_id, // Todo: Add support for Tron NFTs @@ -1205,9 +1204,15 @@ pub async fn withdraw_erc1155(ctx: MmArc, withdraw_type: WithdrawErc1155) -> Wit )) }, }; + let tx_builder = UnSignedEthTxBuilder::new(tx_type, nonce, gas, Action::Call(call_addr), eth_value, data); + let tx_builder = tx_builder_with_pay_for_gas_option(ð_coin, tx_builder, &pay_for_gas_option)?; + let tx = tx_builder + .build() + .map_to_mm(|e| WithdrawError::InternalError(e.to_string()))?; + let secret = eth_coin.priv_key_policy.activated_key_or_err().map_mm_err()?.secret(); let signed = tx.sign(secret, Some(chain_id))?; let signed_bytes = rlp::encode(&signed); - let fee_details = EthTxFeeDetails::new(gas, pay_for_gas_option, fee_coin)?; + let fee_details = EthTxFeeDetails::new(gas, pay_for_gas_option, fee_coin).map_mm_err()?; Ok(TransactionNftDetails { tx_hex: BytesJson::from(signed_bytes.to_vec()), // TODO: should we return tx_hex 0x-prefixed (everywhere)? @@ -1230,13 +1235,15 @@ pub async fn withdraw_erc1155(ctx: MmArc, withdraw_type: WithdrawErc1155) -> Wit /// `withdraw_erc721` function returns details of `ERC-721` transaction including tx hex, /// which should be sent to`send_raw_transaction` RPC to broadcast the transaction. pub async fn withdraw_erc721(ctx: MmArc, withdraw_type: WithdrawErc721) -> WithdrawNftResult { - let coin = lp_coinfind_or_err(&ctx, withdraw_type.chain.to_ticker()).await?; + let coin = lp_coinfind_or_err(&ctx, withdraw_type.chain.to_ticker()) + .await + .map_mm_err()?; let (to_addr, token_addr, eth_coin) = - get_valid_nft_addr_to_withdraw(coin, &withdraw_type.to, &withdraw_type.token_address)?; + get_valid_nft_addr_to_withdraw(coin, &withdraw_type.to, &withdraw_type.token_address).map_mm_err()?; let token_id_str = &withdraw_type.token_id.to_string(); - let token_owner = eth_coin.erc721_owner(token_addr, token_id_str).await?; - let my_address = eth_coin.derivation_method.single_addr_or_err().await?; + let token_owner = eth_coin.erc721_owner(token_addr, token_id_str).await.map_mm_err()?; + let my_address = eth_coin.derivation_method.single_addr_or_err().await.map_mm_err()?; if token_owner != my_address { return MmError::err(WithdrawError::MyAddressNotNftOwner { my_address: my_address.display_address(), @@ -1244,12 +1251,13 @@ pub async fn withdraw_erc721(ctx: MmArc, withdraw_type: WithdrawErc721) -> Withd }); } - let my_address = eth_coin.derivation_method.single_addr_or_err().await?; + let my_address = eth_coin.derivation_method.single_addr_or_err().await.map_mm_err()?; let (eth_value, data, call_addr, fee_coin) = match eth_coin.coin_type { EthCoinType::Eth => { let function = ERC721_CONTRACT.function("safeTransferFrom")?; let token_id_u256 = U256::from_dec_str(&withdraw_type.token_id.to_string()) - .map_to_mm(|e| NumConversError::new(format!("{:?}", e)))?; + .map_to_mm(|e| NumConversError::new(format!("{:?}", e))) + .map_mm_err()?; let data = function.encode_input(&[ Token::Address(my_address), Token::Address(to_addr), @@ -1274,7 +1282,8 @@ pub async fn withdraw_erc721(ctx: MmArc, withdraw_type: WithdrawErc721) -> Withd call_addr, false, ) - .await?; + .await + .map_mm_err()?; let address_lock = eth_coin.get_address_lock(my_address.to_string()).await; let _nonce_lock = address_lock.lock().await; @@ -1295,7 +1304,7 @@ pub async fn withdraw_erc721(ctx: MmArc, withdraw_type: WithdrawErc721) -> Withd let tx = tx_builder .build() .map_to_mm(|e| WithdrawError::InternalError(e.to_string()))?; - let secret = eth_coin.priv_key_policy.activated_key_or_err()?.secret(); + let secret = eth_coin.priv_key_policy.activated_key_or_err().map_mm_err()?.secret(); let chain_id = match eth_coin.chain_spec { ChainSpec::Evm { chain_id } => chain_id, // Todo: Add support for Tron NFTs @@ -1307,7 +1316,7 @@ pub async fn withdraw_erc721(ctx: MmArc, withdraw_type: WithdrawErc721) -> Withd }; let signed = tx.sign(secret, Some(chain_id))?; let signed_bytes = rlp::encode(&signed); - let fee_details = EthTxFeeDetails::new(gas, pay_for_gas_option, fee_coin)?; + let fee_details = EthTxFeeDetails::new(gas, pay_for_gas_option, fee_coin).map_mm_err()?; Ok(TransactionNftDetails { tx_hex: BytesJson::from(signed_bytes.to_vec()), @@ -1731,23 +1740,25 @@ impl WatcherOps for EthCoin { .watcher_reward .clone() .ok_or_else(|| ValidatePaymentError::WatcherRewardError("Watcher reward not found".to_string()))); - let expected_reward_amount = try_f!(wei_from_big_decimal(&watcher_reward.amount, ETH_DECIMALS)); + let expected_reward_amount = try_f!(wei_from_big_decimal(&watcher_reward.amount, ETH_DECIMALS).map_mm_err()); let expected_swap_contract_address = try_f!(input .swap_contract_address .try_to_address() - .map_to_mm(ValidatePaymentError::InvalidParameter)); + .map_to_mm(ValidatePaymentError::InvalidParameter) + .map_mm_err()); let unsigned: UnverifiedTransactionWrapper = try_f!(rlp::decode(&input.payment_tx)); - let tx = - try_f!(SignedEthTx::new(unsigned) - .map_to_mm(|err| ValidatePaymentError::TxDeserializationError(err.to_string()))); + let tx = try_f!(SignedEthTx::new(unsigned) + .map_to_mm(|err| ValidatePaymentError::TxDeserializationError(err.to_string())) + .map_mm_err()); let selfi = self.clone(); let time_lock = try_f!(input .time_lock .try_into() - .map_to_mm(ValidatePaymentError::TimelockOverflow)); + .map_to_mm(ValidatePaymentError::TimelockOverflow) + .map_mm_err()); let swap_id = selfi.etomic_swap_id(time_lock, &input.secret_hash); let decimals = self.decimals; let secret_hash = if input.secret_hash.len() == 32 { @@ -1755,10 +1766,11 @@ impl WatcherOps for EthCoin { } else { input.secret_hash.to_vec() }; - let maker_addr = - try_f!(addr_from_raw_pubkey(&input.maker_pub).map_to_mm(ValidatePaymentError::InvalidParameter)); + let maker_addr = try_f!(addr_from_raw_pubkey(&input.maker_pub) + .map_to_mm(ValidatePaymentError::InvalidParameter) + .map_mm_err()); - let trade_amount = try_f!(wei_from_big_decimal(&(input.amount), decimals)); + let trade_amount = try_f!(wei_from_big_decimal(&(input.amount), decimals).map_mm_err()); let fut = async move { match tx.unsigned().action() { Call(contract_address) => { @@ -1780,7 +1792,8 @@ impl WatcherOps for EthCoin { .payment_status(expected_swap_contract_address, Token::FixedBytes(swap_id.clone())) .compat() .await - .map_to_mm(ValidatePaymentError::Transport)?; + .map_to_mm(ValidatePaymentError::Transport) + .map_mm_err()?; let expected_status = match input.spend_type { WatcherSpendType::MakerPaymentSpend => U256::from(PaymentState::Spent as u8), WatcherSpendType::TakerPaymentRefund => U256::from(PaymentState::Refunded as u8), @@ -1804,7 +1817,8 @@ impl WatcherOps for EthCoin { .map_to_mm(|err| ValidatePaymentError::TxDeserializationError(err.to_string()))?; let swap_id_input = get_function_input_data(&decoded, function, 0) - .map_to_mm(ValidatePaymentError::TxDeserializationError)?; + .map_to_mm(ValidatePaymentError::TxDeserializationError) + .map_mm_err()?; if swap_id_input != Token::FixedBytes(swap_id.clone()) { return MmError::err(ValidatePaymentError::WrongPaymentTx(format!( "Transaction invalid swap_id arg {:?}, expected {:?}", @@ -1816,7 +1830,8 @@ impl WatcherOps for EthCoin { let hash_input = match input.spend_type { WatcherSpendType::MakerPaymentSpend => { let secret_input = get_function_input_data(&decoded, function, 2) - .map_to_mm(ValidatePaymentError::TxDeserializationError)? + .map_to_mm(ValidatePaymentError::TxDeserializationError) + .map_mm_err()? .into_fixed_bytes() .ok_or_else(|| { ValidatePaymentError::WrongPaymentTx("Invalid type for secret hash argument".to_string()) @@ -1824,7 +1839,8 @@ impl WatcherOps for EthCoin { dhash160(&secret_input).to_vec() }, WatcherSpendType::TakerPaymentRefund => get_function_input_data(&decoded, function, 2) - .map_to_mm(ValidatePaymentError::TxDeserializationError)? + .map_to_mm(ValidatePaymentError::TxDeserializationError) + .map_mm_err()? .into_fixed_bytes() .ok_or_else(|| { ValidatePaymentError::WrongPaymentTx("Invalid type for secret argument".to_string()) @@ -1838,9 +1854,10 @@ impl WatcherOps for EthCoin { ))); } - let my_address = selfi.derivation_method.single_addr_or_err().await?; + let my_address = selfi.derivation_method.single_addr_or_err().await.map_mm_err()?; let sender_input = get_function_input_data(&decoded, function, 4) - .map_to_mm(ValidatePaymentError::TxDeserializationError)?; + .map_to_mm(ValidatePaymentError::TxDeserializationError) + .map_mm_err()?; let expected_sender = match input.spend_type { WatcherSpendType::MakerPaymentSpend => maker_addr, WatcherSpendType::TakerPaymentRefund => my_address, @@ -1868,7 +1885,8 @@ impl WatcherOps for EthCoin { } let reward_target_input = get_function_input_data(&decoded, function, 6) - .map_to_mm(ValidatePaymentError::TxDeserializationError)?; + .map_to_mm(ValidatePaymentError::TxDeserializationError) + .map_mm_err()?; if reward_target_input != Token::Uint(U256::from(watcher_reward.reward_target as u8)) { return MmError::err(ValidatePaymentError::WrongPaymentTx(format!( "Transaction reward target arg {:?} is invalid, expected {:?}", @@ -1878,7 +1896,8 @@ impl WatcherOps for EthCoin { } let contract_reward_input = get_function_input_data(&decoded, function, 7) - .map_to_mm(ValidatePaymentError::TxDeserializationError)?; + .map_to_mm(ValidatePaymentError::TxDeserializationError) + .map_mm_err()?; if contract_reward_input != Token::Bool(watcher_reward.send_contract_reward_on_spend) { return MmError::err(ValidatePaymentError::WrongPaymentTx(format!( "Transaction sends contract reward on spend arg {:?} is invalid, expected {:?}", @@ -1888,7 +1907,8 @@ impl WatcherOps for EthCoin { } let reward_amount_input = get_function_input_data(&decoded, function, 8) - .map_to_mm(ValidatePaymentError::TxDeserializationError)?; + .map_to_mm(ValidatePaymentError::TxDeserializationError) + .map_mm_err()?; if reward_amount_input != Token::Uint(expected_reward_amount) { return MmError::err(ValidatePaymentError::WrongPaymentTx(format!( "Transaction watcher reward amount arg {:?} is invalid, expected {:?}", @@ -1907,7 +1927,8 @@ impl WatcherOps for EthCoin { match &selfi.coin_type { EthCoinType::Eth => { let amount_input = get_function_input_data(&decoded, function, 1) - .map_to_mm(ValidatePaymentError::TxDeserializationError)?; + .map_to_mm(ValidatePaymentError::TxDeserializationError) + .map_mm_err()?; let total_amount = match input.spend_type { WatcherSpendType::MakerPaymentSpend => { if !matches!(watcher_reward.reward_target, RewardTarget::None) @@ -1929,7 +1950,8 @@ impl WatcherOps for EthCoin { } let token_address_input = get_function_input_data(&decoded, function, 3) - .map_to_mm(ValidatePaymentError::TxDeserializationError)?; + .map_to_mm(ValidatePaymentError::TxDeserializationError) + .map_mm_err()?; if token_address_input != Token::Address(Address::default()) { return MmError::err(ValidatePaymentError::WrongPaymentTx(format!( "Transaction token address arg {:?} is invalid, expected {:?}", @@ -1943,7 +1965,8 @@ impl WatcherOps for EthCoin { token_addr, } => { let amount_input = get_function_input_data(&decoded, function, 1) - .map_to_mm(ValidatePaymentError::TxDeserializationError)?; + .map_to_mm(ValidatePaymentError::TxDeserializationError) + .map_mm_err()?; if amount_input != Token::Uint(trade_amount) { return MmError::err(ValidatePaymentError::WrongPaymentTx(format!( "Transaction amount arg {:?} is invalid, expected {:?}", @@ -1953,7 +1976,8 @@ impl WatcherOps for EthCoin { } let token_address_input = get_function_input_data(&decoded, function, 3) - .map_to_mm(ValidatePaymentError::TxDeserializationError)?; + .map_to_mm(ValidatePaymentError::TxDeserializationError) + .map_mm_err()?; if token_address_input != Token::Address(*token_addr) { return MmError::err(ValidatePaymentError::WrongPaymentTx(format!( "Transaction token address arg {:?} is invalid, expected {:?}", @@ -1976,15 +2000,20 @@ impl WatcherOps for EthCoin { fn watcher_validate_taker_payment(&self, input: WatcherValidatePaymentInput) -> ValidatePaymentFut<()> { let unsigned: UnverifiedTransactionWrapper = try_f!(rlp::decode(&input.payment_tx)); - let tx = - try_f!(SignedEthTx::new(unsigned) - .map_to_mm(|err| ValidatePaymentError::TxDeserializationError(err.to_string()))); - let sender = try_f!(addr_from_raw_pubkey(&input.taker_pub).map_to_mm(ValidatePaymentError::InvalidParameter)); - let receiver = try_f!(addr_from_raw_pubkey(&input.maker_pub).map_to_mm(ValidatePaymentError::InvalidParameter)); + let tx = try_f!(SignedEthTx::new(unsigned) + .map_to_mm(|err| ValidatePaymentError::TxDeserializationError(err.to_string())) + .map_mm_err()); + let sender = try_f!(addr_from_raw_pubkey(&input.taker_pub) + .map_to_mm(ValidatePaymentError::InvalidParameter) + .map_mm_err()); + let receiver = try_f!(addr_from_raw_pubkey(&input.maker_pub) + .map_to_mm(ValidatePaymentError::InvalidParameter) + .map_mm_err()); let time_lock = try_f!(input .time_lock .try_into() - .map_to_mm(ValidatePaymentError::TimelockOverflow)); + .map_to_mm(ValidatePaymentError::TimelockOverflow) + .map_mm_err()); let selfi = self.clone(); let swap_id = selfi.etomic_swap_id(time_lock, &input.secret_hash); @@ -2027,7 +2056,8 @@ impl WatcherOps for EthCoin { .payment_status(swap_contract_address, Token::FixedBytes(swap_id.clone())) .compat() .await - .map_to_mm(ValidatePaymentError::Transport)?; + .map_to_mm(ValidatePaymentError::Transport) + .map_mm_err()?; if status != U256::from(PaymentState::Sent as u8) && status != U256::from(PaymentState::Spent as u8) { return MmError::err(ValidatePaymentError::UnexpectedPaymentState(format!( "{INVALID_PAYMENT_STATE_ERR_LOG}: Payment state is not PAYMENT_STATE_SENT or PAYMENT_STATE_SPENT, got {status}" @@ -2038,19 +2068,22 @@ impl WatcherOps for EthCoin { .get_taker_watcher_reward(&input.maker_coin, None, None, None, input.wait_until) .await .map_err(|err| ValidatePaymentError::WatcherRewardError(err.into_inner().to_string()))?; - let expected_reward_amount = wei_from_big_decimal(&watcher_reward.amount, ETH_DECIMALS)?; + let expected_reward_amount = wei_from_big_decimal(&watcher_reward.amount, ETH_DECIMALS).map_mm_err()?; match &selfi.coin_type { EthCoinType::Eth => { let function_name = get_function_name("ethPayment", true); let function = SWAP_CONTRACT .function(&function_name) - .map_to_mm(|err| ValidatePaymentError::InternalError(err.to_string()))?; + .map_to_mm(|err| ValidatePaymentError::InternalError(err.to_string())) + .map_mm_err()?; let decoded = decode_contract_call(function, &tx_from_rpc.input.0) - .map_to_mm(|err| ValidatePaymentError::TxDeserializationError(err.to_string()))?; + .map_to_mm(|err| ValidatePaymentError::TxDeserializationError(err.to_string())) + .map_mm_err()?; let swap_id_input = get_function_input_data(&decoded, function, 0) - .map_to_mm(ValidatePaymentError::TxDeserializationError)?; + .map_to_mm(ValidatePaymentError::TxDeserializationError) + .map_mm_err()?; if swap_id_input != Token::FixedBytes(swap_id.clone()) { return MmError::err(ValidatePaymentError::WrongPaymentTx(format!( "{INVALID_SWAP_ID_ERR_LOG}: Invalid 'swap_id' {decoded:?}, expected {swap_id:?}" @@ -2058,7 +2091,8 @@ impl WatcherOps for EthCoin { } let receiver_input = get_function_input_data(&decoded, function, 1) - .map_to_mm(ValidatePaymentError::TxDeserializationError)?; + .map_to_mm(ValidatePaymentError::TxDeserializationError) + .map_mm_err()?; if receiver_input != Token::Address(receiver) { return MmError::err(ValidatePaymentError::WrongPaymentTx(format!( "{INVALID_RECEIVER_ERR_LOG}: Payment tx receiver arg {receiver_input:?} is invalid, expected {:?}", Token::Address(receiver) @@ -2066,7 +2100,8 @@ impl WatcherOps for EthCoin { } let secret_hash_input = get_function_input_data(&decoded, function, 2) - .map_to_mm(ValidatePaymentError::TxDeserializationError)?; + .map_to_mm(ValidatePaymentError::TxDeserializationError) + .map_mm_err()?; if secret_hash_input != Token::FixedBytes(secret_hash.to_vec()) { return MmError::err(ValidatePaymentError::WrongPaymentTx(format!( "Payment tx secret_hash arg {:?} is invalid, expected {:?}", @@ -2076,7 +2111,8 @@ impl WatcherOps for EthCoin { } let time_lock_input = get_function_input_data(&decoded, function, 3) - .map_to_mm(ValidatePaymentError::TxDeserializationError)?; + .map_to_mm(ValidatePaymentError::TxDeserializationError) + .map_mm_err()?; if time_lock_input != Token::Uint(U256::from(input.time_lock)) { return MmError::err(ValidatePaymentError::WrongPaymentTx(format!( "Payment tx time_lock arg {:?} is invalid, expected {:?}", @@ -2086,7 +2122,8 @@ impl WatcherOps for EthCoin { } let reward_target_input = get_function_input_data(&decoded, function, 4) - .map_to_mm(ValidatePaymentError::TxDeserializationError)?; + .map_to_mm(ValidatePaymentError::TxDeserializationError) + .map_mm_err()?; let expected_reward_target = watcher_reward.reward_target as u8; if reward_target_input != Token::Uint(U256::from(expected_reward_target)) { return MmError::err(ValidatePaymentError::WrongPaymentTx(format!( @@ -2096,7 +2133,8 @@ impl WatcherOps for EthCoin { } let sends_contract_reward_input = get_function_input_data(&decoded, function, 5) - .map_to_mm(ValidatePaymentError::TxDeserializationError)?; + .map_to_mm(ValidatePaymentError::TxDeserializationError) + .map_mm_err()?; if sends_contract_reward_input != Token::Bool(watcher_reward.send_contract_reward_on_spend) { return MmError::err(ValidatePaymentError::WrongPaymentTx(format!( "Payment tx sends_contract_reward_on_spend arg {:?} is invalid, expected {:?}", @@ -2105,13 +2143,15 @@ impl WatcherOps for EthCoin { } let reward_amount_input = get_function_input_data(&decoded, function, 6) - .map_to_mm(ValidatePaymentError::TxDeserializationError)? + .map_to_mm(ValidatePaymentError::TxDeserializationError) + .map_mm_err()? .into_uint() .ok_or_else(|| { ValidatePaymentError::WrongPaymentTx("Invalid type for reward amount argument".to_string()) })?; - validate_watcher_reward(expected_reward_amount.as_u64(), reward_amount_input.as_u64(), false)?; + validate_watcher_reward(expected_reward_amount.as_u64(), reward_amount_input.as_u64(), false) + .map_mm_err()?; // TODO: Validate the value }, @@ -2122,12 +2162,15 @@ impl WatcherOps for EthCoin { let function_name = get_function_name("erc20Payment", true); let function = SWAP_CONTRACT .function(&function_name) - .map_to_mm(|err| ValidatePaymentError::InternalError(err.to_string()))?; + .map_to_mm(|err| ValidatePaymentError::InternalError(err.to_string())) + .map_mm_err()?; let decoded = decode_contract_call(function, &tx_from_rpc.input.0) - .map_to_mm(|err| ValidatePaymentError::TxDeserializationError(err.to_string()))?; + .map_to_mm(|err| ValidatePaymentError::TxDeserializationError(err.to_string())) + .map_mm_err()?; let swap_id_input = get_function_input_data(&decoded, function, 0) - .map_to_mm(ValidatePaymentError::TxDeserializationError)?; + .map_to_mm(ValidatePaymentError::TxDeserializationError) + .map_mm_err()?; if swap_id_input != Token::FixedBytes(swap_id.clone()) { return MmError::err(ValidatePaymentError::WrongPaymentTx(format!( "{INVALID_SWAP_ID_ERR_LOG}: Invalid 'swap_id' {decoded:?}, expected {swap_id:?}" @@ -2135,7 +2178,8 @@ impl WatcherOps for EthCoin { } let token_addr_input = get_function_input_data(&decoded, function, 2) - .map_to_mm(ValidatePaymentError::TxDeserializationError)?; + .map_to_mm(ValidatePaymentError::TxDeserializationError) + .map_mm_err()?; if token_addr_input != Token::Address(*token_addr) { return MmError::err(ValidatePaymentError::WrongPaymentTx(format!( "Payment tx token_addr arg {:?} is invalid, expected {:?}", @@ -2145,7 +2189,8 @@ impl WatcherOps for EthCoin { } let receiver_addr_input = get_function_input_data(&decoded, function, 3) - .map_to_mm(ValidatePaymentError::TxDeserializationError)?; + .map_to_mm(ValidatePaymentError::TxDeserializationError) + .map_mm_err()?; if receiver_addr_input != Token::Address(receiver) { return MmError::err(ValidatePaymentError::WrongPaymentTx(format!( "{INVALID_RECEIVER_ERR_LOG}: Payment tx receiver arg {receiver_addr_input:?} is invalid, expected {:?}", Token::Address(receiver), @@ -2153,7 +2198,8 @@ impl WatcherOps for EthCoin { } let secret_hash_input = get_function_input_data(&decoded, function, 4) - .map_to_mm(ValidatePaymentError::TxDeserializationError)?; + .map_to_mm(ValidatePaymentError::TxDeserializationError) + .map_mm_err()?; if secret_hash_input != Token::FixedBytes(secret_hash.to_vec()) { return MmError::err(ValidatePaymentError::WrongPaymentTx(format!( "Payment tx secret_hash arg {:?} is invalid, expected {:?}", @@ -2163,7 +2209,8 @@ impl WatcherOps for EthCoin { } let time_lock_input = get_function_input_data(&decoded, function, 5) - .map_to_mm(ValidatePaymentError::TxDeserializationError)?; + .map_to_mm(ValidatePaymentError::TxDeserializationError) + .map_mm_err()?; if time_lock_input != Token::Uint(U256::from(input.time_lock)) { return MmError::err(ValidatePaymentError::WrongPaymentTx(format!( "Payment tx time_lock arg {:?} is invalid, expected {:?}", @@ -2173,7 +2220,8 @@ impl WatcherOps for EthCoin { } let reward_target_input = get_function_input_data(&decoded, function, 6) - .map_to_mm(ValidatePaymentError::TxDeserializationError)?; + .map_to_mm(ValidatePaymentError::TxDeserializationError) + .map_mm_err()?; let expected_reward_target = watcher_reward.reward_target as u8; if reward_target_input != Token::Uint(U256::from(expected_reward_target)) { return MmError::err(ValidatePaymentError::WrongPaymentTx(format!( @@ -2183,7 +2231,8 @@ impl WatcherOps for EthCoin { } let sends_contract_reward_input = get_function_input_data(&decoded, function, 7) - .map_to_mm(ValidatePaymentError::TxDeserializationError)?; + .map_to_mm(ValidatePaymentError::TxDeserializationError) + .map_mm_err()?; if sends_contract_reward_input != Token::Bool(watcher_reward.send_contract_reward_on_spend) { return MmError::err(ValidatePaymentError::WrongPaymentTx(format!( "Payment tx sends_contract_reward_on_spend arg {:?} is invalid, expected {:?}", @@ -2192,13 +2241,15 @@ impl WatcherOps for EthCoin { } let reward_amount_input = get_function_input_data(&decoded, function, 8) - .map_to_mm(ValidatePaymentError::TxDeserializationError)? + .map_to_mm(ValidatePaymentError::TxDeserializationError) + .map_mm_err()? .into_uint() .ok_or_else(|| { ValidatePaymentError::WrongPaymentTx("Invalid type for reward amount argument".to_string()) })?; - validate_watcher_reward(expected_reward_amount.as_u64(), reward_amount_input.as_u64(), false)?; + validate_watcher_reward(expected_reward_amount.as_u64(), reward_amount_input.as_u64(), false) + .map_mm_err()?; if tx_from_rpc.value != reward_amount_input { return MmError::err(ValidatePaymentError::WrongPaymentTx(format!( @@ -2395,18 +2446,24 @@ impl MarketCoinOps for EthCoin { let message_hash = self.sign_message_hash(message).ok_or(SignatureError::PrefixNotFound)?; let secret = if let Some(address) = address { - let path_to_coin = self.priv_key_policy.path_to_coin_or_err()?; + let path_to_coin = self.priv_key_policy.path_to_coin_or_err().map_mm_err()?; let derivation_path = address .valid_derivation_path(path_to_coin) - .mm_err(|err| SignatureError::InvalidRequest(err.to_string()))?; + .mm_err(|err| SignatureError::InvalidRequest(err.to_string())) + .map_mm_err()?; let privkey = self .priv_key_policy - .hd_wallet_derived_priv_key_or_err(&derivation_path)?; + .hd_wallet_derived_priv_key_or_err(&derivation_path) + .map_mm_err()?; ethkey::Secret::from_slice(privkey.as_slice()).ok_or(MmError::new(SignatureError::InternalError( "failed to derive ethkey::Secret".to_string(), )))? } else { - self.priv_key_policy.activated_key_or_err()?.secret().clone() + self.priv_key_policy + .activated_key_or_err() + .map_mm_err()? + .secret() + .clone() }; let signature = sign(&secret, &H256::from(message_hash))?; @@ -2429,7 +2486,7 @@ impl MarketCoinOps for EthCoin { let decimals = self.decimals; let fut = self .get_balance() - .and_then(move |result| Ok(u256_to_big_decimal(result, decimals)?)) + .and_then(move |result| u256_to_big_decimal(result, decimals).map_mm_err()) .map(|spendable| CoinBalance { spendable, unspendable: BigDecimal::from(0), @@ -2440,7 +2497,7 @@ impl MarketCoinOps for EthCoin { fn base_coin_balance(&self) -> BalanceFut { Box::new( self.eth_balance() - .and_then(move |result| Ok(u256_to_big_decimal(result, ETH_DECIMALS)?)), + .and_then(move |result| u256_to_big_decimal(result, ETH_DECIMALS).map_mm_err()), ) } @@ -2826,7 +2883,8 @@ async fn sign_and_send_transaction_with_metamask( /// Sign eth transaction async fn sign_raw_eth_tx(coin: &EthCoin, args: &SignEthTransactionParams) -> RawTransactionResult { - let value = wei_from_big_decimal(args.value.as_ref().unwrap_or(&BigDecimal::from(0)), coin.decimals)?; + let value = + wei_from_big_decimal(args.value.as_ref().unwrap_or(&BigDecimal::from(0)), coin.decimals).map_mm_err()?; let action = if let Some(to) = &args.to { Call(Address::from_str(to).map_to_mm(|err| RawTransactionError::InvalidParam(err.to_string()))?) } else { @@ -2848,11 +2906,11 @@ async fn sign_raw_eth_tx(coin: &EthCoin, args: &SignEthTransactionParams) -> Raw let address_lock = coin.get_address_lock(my_address.to_string()).await; let _nonce_lock = address_lock.lock().await; let pay_for_gas_option = if let Some(ref pay_for_gas) = args.pay_for_gas { - pay_for_gas.clone().try_into()? + pay_for_gas.clone().try_into().map_mm_err()? } else { // use legacy gas_price() if not set info!(target: "sign-and-send", "get_gas_price…"); - let gas_price = coin.get_gas_price().await?; + let gas_price = coin.get_gas_price().await.map_mm_err()?; PayForGasOption::Legacy(LegacyGasPrice { gas_price }) }; sign_transaction_with_keypair( @@ -2892,11 +2950,11 @@ async fn sign_raw_eth_tx(coin: &EthCoin, args: &SignEthTransactionParams) -> Raw let address_lock = coin.get_address_lock(my_address.to_string()).await; let _nonce_lock = address_lock.lock().await; let pay_for_gas_option = if let Some(ref pay_for_gas) = args.pay_for_gas { - pay_for_gas.clone().try_into()? + pay_for_gas.clone().try_into().map_mm_err()? } else { // use legacy gas_price() if not set info!(target: "sign-and-send", "get_gas_price…"); - let gas_price = coin.get_gas_price().await?; + let gas_price = coin.get_gas_price().await.map_mm_err()?; PayForGasOption::Legacy(LegacyGasPrice { gas_price }) }; let (nonce, _) = coin @@ -4615,7 +4673,7 @@ impl EthCoin { fn get_balance(&self) -> BalanceFut { let coin = self.clone(); let fut = async move { - let my_address = coin.derivation_method.single_addr_or_err().await?; + let my_address = coin.derivation_method.single_addr_or_err().await.map_mm_err()?; coin.address_balance(my_address).compat().await }; Box::new(fut.boxed().compat()) @@ -4635,7 +4693,7 @@ impl EthCoin { let balance_as_u256 = coin() .get_token_balance_for_address(address, info.token_address) .await?; - let balance_as_big_decimal = u256_to_big_decimal(balance_as_u256, info.decimals)?; + let balance_as_big_decimal = u256_to_big_decimal(balance_as_u256, info.decimals).map_mm_err()?; let balance = CoinBalance::new(balance_as_big_decimal); Ok((token_ticker, balance)) }; @@ -4646,7 +4704,7 @@ impl EthCoin { } pub async fn get_tokens_balance_list(&self) -> Result> { - let my_address = self.derivation_method.single_addr_or_err().await?; + let my_address = self.derivation_method.single_addr_or_err().await.map_mm_err()?; self.get_tokens_balance_list_for_address(my_address).await } @@ -4672,7 +4730,7 @@ impl EthCoin { } async fn get_token_balance(&self, token_address: Address) -> Result> { - let my_address = self.derivation_method.single_addr_or_err().await?; + let my_address = self.derivation_method.single_addr_or_err().await.map_mm_err()?; self.get_token_balance_for_address(my_address, token_address).await } @@ -4680,9 +4738,10 @@ impl EthCoin { let wallet_amount_uint = match self.coin_type { EthCoinType::Eth | EthCoinType::Nft { .. } => { let function = ERC1155_CONTRACT.function("balanceOf")?; - let token_id_u256 = - U256::from_dec_str(token_id).map_to_mm(|e| NumConversError::new(format!("{:?}", e)))?; - let my_address = self.derivation_method.single_addr_or_err().await?; + let token_id_u256 = U256::from_dec_str(token_id) + .map_to_mm(|e| NumConversError::new(format!("{:?}", e))) + .map_mm_err()?; + let my_address = self.derivation_method.single_addr_or_err().await.map_mm_err()?; let data = function.encode_input(&[Token::Address(my_address), Token::Uint(token_id_u256)])?; let result = self .call_request(my_address, token_addr, None, Some(data.into()), BlockNumber::Latest) @@ -4711,10 +4770,11 @@ impl EthCoin { let owner_address = match self.coin_type { EthCoinType::Eth | EthCoinType::Nft { .. } => { let function = ERC721_CONTRACT.function("ownerOf")?; - let token_id_u256 = - U256::from_dec_str(token_id).map_to_mm(|e| NumConversError::new(format!("{:?}", e)))?; + let token_id_u256 = U256::from_dec_str(token_id) + .map_to_mm(|e| NumConversError::new(format!("{:?}", e))) + .map_mm_err()?; let data = function.encode_input(&[Token::Uint(token_id_u256)])?; - let my_address = self.derivation_method.single_addr_or_err().await?; + let my_address = self.derivation_method.single_addr_or_err().await.map_mm_err()?; let result = self .call_request(my_address, token_addr, None, Some(data.into()), BlockNumber::Latest) .await?; @@ -4757,7 +4817,7 @@ impl EthCoin { /// because [`CallRequest::from`] is set to [`EthCoinImpl::my_address`]. async fn estimate_gas_for_contract_call(&self, contract_addr: Address, call_data: Bytes) -> Web3RpcResult { let coin = self.clone(); - let my_address = coin.derivation_method.single_addr_or_err().await?; + let my_address = coin.derivation_method.single_addr_or_err().await.map_mm_err()?; let fee_policy_for_estimate = get_swap_fee_policy_for_estimate(self.get_swap_transaction_fee_policy()); let pay_for_gas_option = coin.get_swap_pay_for_gas_option(fee_policy_for_estimate).await?; let eth_value = U256::zero(); @@ -4780,7 +4840,7 @@ impl EthCoin { fn eth_balance(&self) -> BalanceFut { let coin = self.clone(); let fut = async move { - let my_address = coin.derivation_method.single_addr_or_err().await?; + let my_address = coin.derivation_method.single_addr_or_err().await.map_mm_err()?; coin.balance(my_address, Some(BlockNumber::Latest)) .await .map_to_mm(BalanceError::from) @@ -4818,7 +4878,7 @@ impl EthCoin { )), EthCoinType::Erc20 { ref token_addr, .. } => { let function = ERC20_CONTRACT.function("allowance")?; - let my_address = coin.derivation_method.single_addr_or_err().await?; + let my_address = coin.derivation_method.single_addr_or_err().await.map_mm_err()?; let data = function.encode_input(&[Token::Address(my_address), Token::Address(spender)])?; let res = coin @@ -4972,7 +5032,7 @@ impl EthCoin { } else { input.secret_hash.to_vec() }; - let trade_amount = try_f!(wei_from_big_decimal(&(input.amount), decimals)); + let trade_amount = try_f!(wei_from_big_decimal(&(input.amount), decimals).map_mm_err()); let fut = async move { let status = selfi .payment_status(expected_swap_contract_address, Token::FixedBytes(swap_id.clone())) @@ -4998,7 +5058,7 @@ impl EthCoin { ))); } - let my_address = selfi.derivation_method.single_addr_or_err().await?; + let my_address = selfi.derivation_method.single_addr_or_err().await.map_mm_err()?; match &selfi.coin_type { EthCoinType::Eth => { let mut expected_value = trade_amount; @@ -5064,7 +5124,8 @@ impl EthCoin { ))); } - let expected_reward_amount = wei_from_big_decimal(&watcher_reward.amount, decimals)?; + let expected_reward_amount = + wei_from_big_decimal(&watcher_reward.amount, decimals).map_mm_err()?; let actual_reward_amount = decoded[6].clone().into_uint().ok_or_else(|| { ValidatePaymentError::WrongPaymentTx("Invalid type for watcher reward argument".to_string()) })?; @@ -5170,15 +5231,15 @@ impl EthCoin { let expected_reward_amount = match watcher_reward.reward_target { RewardTarget::Contract | RewardTarget::PaymentSender => { - wei_from_big_decimal(&watcher_reward.amount, ETH_DECIMALS)? + wei_from_big_decimal(&watcher_reward.amount, ETH_DECIMALS).map_mm_err()? }, RewardTarget::PaymentSpender => { - wei_from_big_decimal(&watcher_reward.amount, selfi.decimals)? + wei_from_big_decimal(&watcher_reward.amount, selfi.decimals).map_mm_err()? }, _ => { // TODO tests passed without this change, need to research on how it worked if watcher_reward.send_contract_reward_on_spend { - wei_from_big_decimal(&watcher_reward.amount, ETH_DECIMALS)? + wei_from_big_decimal(&watcher_reward.amount, ETH_DECIMALS).map_mm_err()? } else { 0.into() } @@ -5867,7 +5928,8 @@ impl MmCoin for EthCoin { ) -> TradePreimageResult { let pay_for_gas_option = self .get_swap_pay_for_gas_option(self.get_swap_transaction_fee_policy()) - .await?; + .await + .map_mm_err()?; let pay_for_gas_option = increase_gas_price_by_stage(pay_for_gas_option, &stage); let gas_limit = match self.coin_type { EthCoinType::Eth => { @@ -5882,20 +5944,21 @@ impl MmCoin for EthCoin { let mut gas = U256::from(self.gas_limit.erc20_payment); let value = match value { TradePreimageValue::Exact(value) | TradePreimageValue::UpperBound(value) => { - wei_from_big_decimal(&value, self.decimals)? + wei_from_big_decimal(&value, self.decimals).map_mm_err()? }, }; - let allowed = self.allowance(self.swap_contract_address).compat().await?; + let allowed = self.allowance(self.swap_contract_address).compat().await.map_mm_err()?; if allowed < value { // estimate gas for the `approve` contract call // Pass a dummy spender. Let's use `my_address`. - let spender = self.derivation_method.single_addr_or_err().await?; + let spender = self.derivation_method.single_addr_or_err().await.map_mm_err()?; let approve_function = ERC20_CONTRACT.function("approve")?; let approve_data = approve_function.encode_input(&[Token::Address(spender), Token::Uint(value)])?; let approve_gas_limit = self .estimate_gas_for_contract_call(token_addr, Bytes::from(approve_data)) - .await?; + .await + .map_mm_err()?; // this gas_limit includes gas for `approve`, `erc20Payment` contract calls gas += approve_gas_limit; @@ -5909,8 +5972,8 @@ impl MmCoin for EthCoin { EthCoinType::Nft { .. } => return MmError::err(TradePreimageError::NftProtocolNotSupported), }; - let total_fee = calc_total_fee(gas_limit, &pay_for_gas_option)?; - let amount = u256_to_big_decimal(total_fee, ETH_DECIMALS)?; + let total_fee = calc_total_fee(gas_limit, &pay_for_gas_option).map_mm_err()?; + let amount = u256_to_big_decimal(total_fee, ETH_DECIMALS).map_mm_err()?; let fee_coin = match &self.coin_type { EthCoinType::Eth => &self.ticker, EthCoinType::Erc20 { platform, .. } => platform, @@ -5928,20 +5991,22 @@ impl MmCoin for EthCoin { let fut = async move { let pay_for_gas_option = coin .get_swap_pay_for_gas_option(coin.get_swap_transaction_fee_policy()) - .await?; + .await + .map_mm_err()?; let pay_for_gas_option = increase_gas_price_by_stage(pay_for_gas_option, &stage); let (fee_coin, total_fee) = match &coin.coin_type { EthCoinType::Eth => ( &coin.ticker, - calc_total_fee(U256::from(coin.gas_limit.eth_receiver_spend), &pay_for_gas_option)?, + calc_total_fee(U256::from(coin.gas_limit.eth_receiver_spend), &pay_for_gas_option).map_mm_err()?, ), EthCoinType::Erc20 { platform, .. } => ( platform, - calc_total_fee(U256::from(coin.gas_limit.erc20_receiver_spend), &pay_for_gas_option)?, + calc_total_fee(U256::from(coin.gas_limit.erc20_receiver_spend), &pay_for_gas_option) + .map_mm_err()?, ), EthCoinType::Nft { .. } => return MmError::err(TradePreimageError::NftProtocolNotSupported), }; - let amount = u256_to_big_decimal(total_fee, ETH_DECIMALS)?; + let amount = u256_to_big_decimal(total_fee, ETH_DECIMALS).map_mm_err()?; Ok(TradeFee { coin: fee_coin.into(), amount: amount.into(), @@ -5956,11 +6021,11 @@ impl MmCoin for EthCoin { dex_fee_amount: DexFee, stage: FeeApproxStage, ) -> TradePreimageResult { - let dex_fee_amount = wei_from_big_decimal(&dex_fee_amount.fee_amount().into(), self.decimals)?; + let dex_fee_amount = wei_from_big_decimal(&dex_fee_amount.fee_amount().into(), self.decimals).map_mm_err()?; // pass the dummy params let to_addr = addr_from_raw_pubkey(&DEX_FEE_ADDR_RAW_PUBKEY) .expect("addr_from_raw_pubkey should never fail with DEX_FEE_ADDR_RAW_PUBKEY"); - let my_address = self.derivation_method.single_addr_or_err().await?; + let my_address = self.derivation_method.single_addr_or_err().await.map_mm_err()?; let (eth_value, data, call_addr, fee_coin) = match &self.coin_type { EthCoinType::Eth => (dex_fee_amount, Vec::new(), &to_addr, &self.ticker), EthCoinType::Erc20 { platform, token_addr } => { @@ -5971,7 +6036,10 @@ impl MmCoin for EthCoin { EthCoinType::Nft { .. } => return MmError::err(TradePreimageError::NftProtocolNotSupported), }; let fee_policy_for_estimate = get_swap_fee_policy_for_estimate(self.get_swap_transaction_fee_policy()); - let pay_for_gas_option = self.get_swap_pay_for_gas_option(fee_policy_for_estimate).await?; + let pay_for_gas_option = self + .get_swap_pay_for_gas_option(fee_policy_for_estimate) + .await + .map_mm_err()?; let pay_for_gas_option = increase_gas_price_by_stage(pay_for_gas_option, &stage); let estimate_gas_req = CallRequest { value: Some(eth_value), @@ -5987,8 +6055,8 @@ impl MmCoin for EthCoin { // Please note if the wallet's balance is insufficient to withdraw, then `estimate_gas` may fail with the `Exception` error. // Ideally we should determine the case when we have the insufficient balance and return `TradePreimageError::NotSufficientBalance` error. let gas_limit = self.estimate_gas_wrapper(estimate_gas_req).compat().await?; - let total_fee = calc_total_fee(gas_limit, &pay_for_gas_option)?; - let amount = u256_to_big_decimal(total_fee, ETH_DECIMALS)?; + let total_fee = calc_total_fee(gas_limit, &pay_for_gas_option).map_mm_err()?; + let amount = u256_to_big_decimal(total_fee, ETH_DECIMALS).map_mm_err()?; Ok(TradeFee { coin: fee_coin.into(), amount: amount.into(), @@ -6084,7 +6152,7 @@ fn validate_fee_impl(coin: EthCoin, validate_fee_args: EthValidateFeeArgs<'_>) - let min_block_number = validate_fee_args.min_block_number; let fut = async move { - let expected_value = wei_from_big_decimal(&amount, coin.decimals)?; + let expected_value = wei_from_big_decimal(&amount, coin.decimals).map_mm_err()?; let tx_from_rpc = coin.transaction(TransactionId::Hash(fee_tx_hash)).await?; let tx_from_rpc = tx_from_rpc.as_ref().ok_or_else(|| { @@ -6790,17 +6858,19 @@ pub async fn get_eth_address( ticker: &str, path_to_address: &HDPathAccountToAddressId, ) -> MmResult { - let crypto_ctx = CryptoCtx::from_ctx(ctx)?; + let crypto_ctx = CryptoCtx::from_ctx(ctx).map_mm_err()?; let priv_key_policy = if crypto_ctx.hw_ctx().is_some() { PrivKeyBuildPolicy::Trezor } else { - PrivKeyBuildPolicy::detect_priv_key_policy(ctx)? + PrivKeyBuildPolicy::detect_priv_key_policy(ctx).map_mm_err()? } .into(); let (_, derivation_method) = - build_address_and_priv_key_policy(ctx, ticker, conf, priv_key_policy, path_to_address, None).await?; - let my_address = derivation_method.single_addr_or_err().await?; + build_address_and_priv_key_policy(ctx, ticker, conf, priv_key_policy, path_to_address, None) + .await + .map_mm_err()?; + let my_address = derivation_method.single_addr_or_err().await.map_mm_err()?; Ok(MyWalletAddress { coin: ticker.to_owned(), @@ -6880,7 +6950,7 @@ async fn get_eth_gas_details_from_withdraw_fee( ) -> MmResult { let pay_for_gas_option = match fee { Some(WithdrawFee::EthGas { gas_price, gas }) => { - let gas_price = wei_from_big_decimal(&gas_price, ETH_GWEI_DECIMALS)?; + let gas_price = wei_from_big_decimal(&gas_price, ETH_GWEI_DECIMALS).map_mm_err()?; return Ok((gas.into(), PayForGasOption::Legacy(LegacyGasPrice { gas_price }))); }, Some(WithdrawFee::EthGasEip1559 { @@ -6888,8 +6958,9 @@ async fn get_eth_gas_details_from_withdraw_fee( max_priority_fee_per_gas, gas_option: gas_limit, }) => { - let max_fee_per_gas = wei_from_big_decimal(&max_fee_per_gas, ETH_GWEI_DECIMALS)?; - let max_priority_fee_per_gas = wei_from_big_decimal(&max_priority_fee_per_gas, ETH_GWEI_DECIMALS)?; + let max_fee_per_gas = wei_from_big_decimal(&max_fee_per_gas, ETH_GWEI_DECIMALS).map_mm_err()?; + let max_priority_fee_per_gas = + wei_from_big_decimal(&max_priority_fee_per_gas, ETH_GWEI_DECIMALS).map_mm_err()?; match gas_limit { EthGasLimitOption::Set(gas) => { return Ok(( @@ -6916,7 +6987,7 @@ async fn get_eth_gas_details_from_withdraw_fee( }, None => { // If WithdrawFee not set use legacy gas price (?) - let gas_price = eth_coin.get_gas_price().await?; + let gas_price = eth_coin.get_gas_price().await.map_mm_err()?; // go to gas estimate code PayForGasOption::Legacy(LegacyGasPrice { gas_price }) }, @@ -6924,7 +6995,7 @@ async fn get_eth_gas_details_from_withdraw_fee( // covering edge case by deducting the standard transfer fee when we want to max withdraw ETH let eth_value_for_estimate = if fungible_max && eth_coin.coin_type == EthCoinType::Eth { - eth_value - calc_total_fee(U256::from(eth_coin.gas_limit.eth_send_coins), &pay_for_gas_option)? + eth_value - calc_total_fee(U256::from(eth_coin.gas_limit.eth_send_coins), &pay_for_gas_option).map_mm_err()? } else { eth_value }; diff --git a/mm2src/coins/eth/eth_balance_events.rs b/mm2src/coins/eth/eth_balance_events.rs index a991dab101..7ff25321b0 100644 --- a/mm2src/coins/eth/eth_balance_events.rs +++ b/mm2src/coins/eth/eth_balance_events.rs @@ -3,7 +3,7 @@ use crate::{eth::{u256_to_big_decimal, Erc20TokenDetails}, hd_wallet::AddrToString, BalanceError, CoinWithDerivationMethod}; use common::{executor::Timer, log, Future01CompatExt}; -use mm2_err_handle::prelude::MmError; +use mm2_err_handle::prelude::*; use mm2_event_stream::{Broadcaster, Event, EventStreamer, NoDataIn, StreamHandlerInput, StreamerId}; use mm2_number::BigDecimal; @@ -133,7 +133,7 @@ async fn fetch_balance( let balance_as_big_decimal = u256_to_big_decimal(balance_as_u256, decimals).map_err(|e| BalanceFetchError { ticker: token_ticker.clone(), address: address.addr_to_string(), - error: e.into(), + error: e.map(BalanceError::from), })?; Ok(BalanceData { diff --git a/mm2src/coins/eth/eth_hd_wallet.rs b/mm2src/coins/eth/eth_hd_wallet.rs index 1b1f2e1a6e..be5eb688b0 100644 --- a/mm2src/coins/eth/eth_hd_wallet.rs +++ b/mm2src/coins/eth/eth_hd_wallet.rs @@ -144,7 +144,7 @@ impl HDWalletBalanceOps for EthCoin { async fn known_address_balance(&self, address: &Address) -> BalanceResult { let balance = self .address_balance(*address) - .and_then(move |result| Ok(u256_to_big_decimal(result, self.decimals())?)) + .and_then(move |result| u256_to_big_decimal(result, self.decimals()).map_mm_err()) .compat() .await?; diff --git a/mm2src/coins/eth/eth_swap_v2/eth_maker_swap_v2.rs b/mm2src/coins/eth/eth_swap_v2/eth_maker_swap_v2.rs index d576ee43f6..ec4f69b31a 100644 --- a/mm2src/coins/eth/eth_swap_v2/eth_maker_swap_v2.rs +++ b/mm2src/coins/eth/eth_swap_v2/eth_maker_swap_v2.rs @@ -10,7 +10,7 @@ use ethereum_types::{Address, Public, U256}; use ethkey::public_to_address; use futures::compat::Future01CompatExt; use mm2_err_handle::mm_error::MmError; -use mm2_err_handle::prelude::MapToMmResult; +use mm2_err_handle::prelude::{MapToMmResult, MmResultExt}; use std::convert::TryInto; use web3::types::TransactionId; @@ -137,10 +137,10 @@ impl EthCoin { )) })?; let maker_address = public_to_address(args.maker_pub); - validate_from_to_addresses(tx_from_rpc, maker_address, maker_swap_v2_contract)?; + validate_from_to_addresses(tx_from_rpc, maker_address, maker_swap_v2_contract).map_mm_err()?; let validation_args = { - let amount = wei_from_big_decimal(&args.amount, self.decimals)?; + let amount = wei_from_big_decimal(&args.amount, self.decimals).map_mm_err()?; MakerValidationArgs { swap_id, amount, diff --git a/mm2src/coins/eth/eth_swap_v2/eth_taker_swap_v2.rs b/mm2src/coins/eth/eth_swap_v2/eth_taker_swap_v2.rs index ac0594cfa7..3792e12526 100644 --- a/mm2src/coins/eth/eth_swap_v2/eth_taker_swap_v2.rs +++ b/mm2src/coins/eth/eth_swap_v2/eth_taker_swap_v2.rs @@ -12,7 +12,7 @@ use ethcore_transaction::Action; use ethereum_types::{Address, Public, U256}; use ethkey::public_to_address; use futures::compat::Future01CompatExt; -use mm2_err_handle::prelude::{MapToMmResult, MmError, MmResult}; +use mm2_err_handle::prelude::{MapToMmResult, MmError, MmResult, MmResultExt}; use std::convert::TryInto; use web3::types::{BlockNumber, TransactionId}; @@ -166,11 +166,12 @@ impl EthCoin { )) })?; let taker_address = public_to_address(args.taker_pub); - validate_from_to_addresses(tx_from_rpc, taker_address, taker_swap_v2_contract)?; + validate_from_to_addresses(tx_from_rpc, taker_address, taker_swap_v2_contract).map_mm_err()?; let validation_args = { - let dex_fee = wei_from_big_decimal(&args.dex_fee.fee_amount().into(), self.decimals)?; - let payment_amount = wei_from_big_decimal(&(args.trading_amount + args.premium_amount), self.decimals)?; + let dex_fee = wei_from_big_decimal(&args.dex_fee.fee_amount().into(), self.decimals).map_mm_err()?; + let payment_amount = + wei_from_big_decimal(&(args.trading_amount + args.premium_amount), self.decimals).map_mm_err()?; TakerValidationArgs { swap_id, amount: payment_amount, diff --git a/mm2src/coins/eth/eth_withdraw.rs b/mm2src/coins/eth/eth_withdraw.rs index c9822619d6..534882f538 100644 --- a/mm2src/coins/eth/eth_withdraw.rs +++ b/mm2src/coins/eth/eth_withdraw.rs @@ -21,7 +21,7 @@ use kdf_walletconnect::{WalletConnectCtx, WalletConnectOps}; use mm2_core::mm_ctx::MmArc; use mm2_err_handle::map_mm_error::MapMmError; use mm2_err_handle::mm_error::MmResult; -use mm2_err_handle::prelude::{MapToMmResult, MmError, OrMmError}; +use mm2_err_handle::prelude::{MapToMmResult, MmError, MmResultExt, OrMmError}; use std::ops::Deref; use std::sync::Arc; #[cfg(target_arch = "wasm32")] @@ -59,8 +59,8 @@ where async fn get_from_address(&self, req: &WithdrawRequest) -> Result> { let coin = self.coin(); match req.from { - Some(_) => Ok(coin.get_withdraw_sender_address(req).await?.address), - None => Ok(coin.derivation_method.single_addr_or_err().await?), + Some(_) => Ok(coin.get_withdraw_sender_address(req).await.map_mm_err()?.address), + None => Ok(coin.derivation_method.single_addr_or_err().await.map_mm_err()?), } } @@ -77,7 +77,8 @@ where let derivation_path = self.get_from_derivation_path(from)?; let raw_priv_key = coin .priv_key_policy - .hd_wallet_derived_priv_key_or_err(&derivation_path)?; + .hd_wallet_derived_priv_key_or_err(&derivation_path) + .map_mm_err()?; KeyPair::from_secret_slice(raw_priv_key.as_slice()) .map_to_mm(|e| WithdrawError::InternalError(e.to_string())) }, @@ -93,11 +94,17 @@ where #[allow(clippy::result_large_err)] fn get_from_derivation_path(&self, from: &HDAddressSelector) -> Result> { let coin = self.coin(); - let path_to_coin = &coin.deref().derivation_method.hd_wallet_or_err()?.derivation_path; + let path_to_coin = &coin + .deref() + .derivation_method + .hd_wallet_or_err() + .map_mm_err()? + .derivation_path; let path_to_address = from .to_address_path(path_to_coin.coin_type()) - .mm_err(|err| WithdrawError::UnexpectedFromAddress(err.to_string()))?; - let derivation_path = path_to_address.to_derivation_path(path_to_coin)?; + .mm_err(|err| WithdrawError::UnexpectedFromAddress(err.to_string())) + .map_mm_err()?; + let derivation_path = path_to_address.to_derivation_path(path_to_coin).map_mm_err()?; Ok(derivation_path) } @@ -113,7 +120,8 @@ where let default_hd_address = &coin .deref() .derivation_method - .hd_wallet_or_err()? + .hd_wallet_or_err() + .map_mm_err()? .get_enabled_address() .await .ok_or_else(|| WithdrawError::InternalError("no enabled address".to_owned()))?; @@ -187,7 +195,8 @@ where let signed_tx = coin .wait_for_tx_appears_on_rpc(tx_hash, wait_rpc_timeout, check_every) - .await?; + .await + .map_mm_err()?; let tx_hex = signed_tx .map(|signed_tx| BytesJson::from(rlp::encode(&signed_tx).to_vec())) // Return an empty `tx_hex` if the transaction is still not appeared on the RPC node. @@ -216,13 +225,13 @@ where self.on_generating_transaction()?; - let my_balance = coin.address_balance(my_address).compat().await?; - let my_balance_dec = u256_to_big_decimal(my_balance, coin.decimals)?; + let my_balance = coin.address_balance(my_address).compat().await.map_mm_err()?; + let my_balance_dec = u256_to_big_decimal(my_balance, coin.decimals).map_mm_err()?; let (mut wei_amount, dec_amount) = if req.max { (my_balance, my_balance_dec.clone()) } else { - let wei_amount = wei_from_big_decimal(&req.amount, coin.decimals)?; + let wei_amount = wei_from_big_decimal(&req.amount, coin.decimals).map_mm_err()?; (wei_amount, req.amount.clone()) }; if wei_amount > my_balance { @@ -241,7 +250,7 @@ where }, EthCoinType::Nft { .. } => return MmError::err(WithdrawError::NftProtocolNotSupported), }; - let eth_value_dec = u256_to_big_decimal(eth_value, coin.decimals)?; + let eth_value_dec = u256_to_big_decimal(eth_value, coin.decimals).map_mm_err()?; let (gas, pay_for_gas_option) = get_eth_gas_details_from_withdraw_fee( coin, @@ -252,9 +261,10 @@ where call_addr, false, ) - .await?; - let total_fee = calc_total_fee(gas, &pay_for_gas_option)?; - let total_fee_dec = u256_to_big_decimal(total_fee, coin.decimals)?; + .await + .map_mm_err()?; + let total_fee = calc_total_fee(gas, &pay_for_gas_option).map_mm_err()?; + let total_fee_dec = u256_to_big_decimal(total_fee, coin.decimals).map_mm_err()?; if req.max && coin.coin_type == EthCoinType::Eth { if eth_value < total_fee || wei_amount < total_fee { @@ -362,14 +372,14 @@ where let tx_hash_bytes = BytesJson::from(tx_hash.0.to_vec()); let tx_hash_str = format!("{:02x}", tx_hash_bytes); - let amount_decimal = u256_to_big_decimal(wei_amount, coin.decimals)?; + let amount_decimal = u256_to_big_decimal(wei_amount, coin.decimals).map_mm_err()?; let mut spent_by_me = amount_decimal.clone(); let received_by_me = if to_addr == my_address { amount_decimal.clone() } else { 0.into() }; - let fee_details = EthTxFeeDetails::new(gas, pay_for_gas_option, fee_coin)?; + let fee_details = EthTxFeeDetails::new(gas, pay_for_gas_option, fee_coin).map_mm_err()?; if coin.coin_type == EthCoinType::Eth { spent_by_me += &fee_details.total_fee; } @@ -408,15 +418,15 @@ impl EthWithdraw for InitEthWithdraw { fn request(&self) -> &WithdrawRequest { &self.req } fn on_generating_transaction(&self) -> Result<(), MmError> { - Ok(self - .task_handle - .update_in_progress_status(WithdrawInProgressStatus::GeneratingTransaction)?) + self.task_handle + .update_in_progress_status(WithdrawInProgressStatus::GeneratingTransaction) + .map_mm_err() } fn on_finishing(&self) -> Result<(), MmError> { - Ok(self - .task_handle - .update_in_progress_status(WithdrawInProgressStatus::Finishing)?) + self.task_handle + .update_in_progress_status(WithdrawInProgressStatus::Finishing) + .map_mm_err() } async fn sign_tx_with_trezor( @@ -425,7 +435,7 @@ impl EthWithdraw for InitEthWithdraw { unsigned_tx: &TransactionWrapper, ) -> Result> { let coin = self.coin(); - let crypto_ctx = CryptoCtx::from_ctx(&self.ctx)?; + let crypto_ctx = CryptoCtx::from_ctx(&self.ctx).map_mm_err()?; let hw_ctx = crypto_ctx .hw_ctx() .or_mm_err(|| WithdrawError::HwError(HwRpcError::NoTrezorDeviceAvailable))?; @@ -437,7 +447,7 @@ impl EthWithdraw for InitEthWithdraw { }; let sign_processor = TrezorRpcTaskProcessor::new(self.task_handle.clone(), trezor_statuses); let sign_processor = Arc::new(sign_processor); - let mut trezor_session = hw_ctx.trezor(sign_processor).await?; + let mut trezor_session = hw_ctx.trezor(sign_processor).await.map_mm_err()?; let chain_id = match coin.chain_spec { ChainSpec::Evm { chain_id } => chain_id, // Todo: Add support for Tron signing with Trezor @@ -449,7 +459,9 @@ impl EthWithdraw for InitEthWithdraw { }; let unverified_tx = trezor_session .sign_eth_tx(derivation_path, unsigned_tx, chain_id) - .await?; + .await + .map_mm_err()?; + Ok(SignedEthTx::new(unverified_tx).map_to_mm(|err| WithdrawError::InternalError(err.to_string()))?) } } diff --git a/mm2src/coins/eth/fee_estimation/eip1559/simple.rs b/mm2src/coins/eth/fee_estimation/eip1559/simple.rs index 995d27447c..fe42b03b8d 100644 --- a/mm2src/coins/eth/fee_estimation/eip1559/simple.rs +++ b/mm2src/coins/eth/fee_estimation/eip1559/simple.rs @@ -3,6 +3,7 @@ use crate::eth::web3_transport::FeeHistoryResult; use crate::eth::{wei_from_gwei_decimal, wei_to_gwei_decimal, EthCoin, Web3RpcError, Web3RpcResult}; use mm2_err_handle::mm_error::MmError; use mm2_err_handle::or_mm_error::OrMmError; +use mm2_err_handle::prelude::MmResultExt; use mm2_number::BigDecimal; use ethereum_types::U256; @@ -101,7 +102,7 @@ impl FeePerGasSimpleEstimator { Ok(FeePerGasLevel { max_priority_fee_per_gas, - max_fee_per_gas: wei_from_gwei_decimal(&max_fee_per_gas_dec)?, + max_fee_per_gas: wei_from_gwei_decimal(&max_fee_per_gas_dec).map_mm_err()?, // TODO: Consider adding default wait times if applicable (and mark them as uncertain). min_wait_time: None, max_wait_time: None, diff --git a/mm2src/coins/eth/nft_swap_v2/mod.rs b/mm2src/coins/eth/nft_swap_v2/mod.rs index ab81124792..d0e4ca8163 100644 --- a/mm2src/coins/eth/nft_swap_v2/mod.rs +++ b/mm2src/coins/eth/nft_swap_v2/mod.rs @@ -3,7 +3,7 @@ use ethcore_transaction::Action; use ethereum_types::U256; use ethkey::public_to_address; use futures::compat::Future01CompatExt; -use mm2_err_handle::prelude::{MapToMmResult, MmError, MmResult}; +use mm2_err_handle::prelude::{MapToMmResult, MmError, MmResult, MmResultExt}; use mm2_number::BigDecimal; use num_traits::Signed; use web3::types::TransactionId; @@ -89,7 +89,7 @@ impl EthCoin { args.maker_payment_tx.tx_hash() )) })?; - validate_from_to_addresses(tx_from_rpc, maker_address, *token_address)?; + validate_from_to_addresses(tx_from_rpc, maker_address, *token_address).map_mm_err()?; let (decoded, bytes_index) = get_decoded_tx_data_and_bytes_index(contract_type, &tx_from_rpc.input.0)?; @@ -116,7 +116,7 @@ impl EthCoin { maker_secret_hash: args.maker_secret_hash.to_vec(), time_lock: U256::from(args.time_lock), }; - decode_and_validate_htlc_params(decoded, bytes_index, htlc_params)?; + decode_and_validate_htlc_params(decoded, bytes_index, htlc_params).map_mm_err()?; }, EthCoinType::Eth | EthCoinType::Erc20 { .. } => { return MmError::err(ValidatePaymentError::InternalError( diff --git a/mm2src/coins/eth/v2_activation.rs b/mm2src/coins/eth/v2_activation.rs index 9bcd2d6c57..6267feef92 100644 --- a/mm2src/coins/eth/v2_activation.rs +++ b/mm2src/coins/eth/v2_activation.rs @@ -460,9 +460,11 @@ impl EthCoin { }; let max_eth_tx_type = get_max_eth_tx_type_conf(&ctx, &token_conf, &coin_type).await?; let gas_limit: EthGasLimit = extract_gas_limit_from_conf(&token_conf) - .map_to_mm(|e| EthTokenActivationError::InternalError(format!("invalid gas_limit config {}", e)))?; + .map_to_mm(|e| EthTokenActivationError::InternalError(format!("invalid gas_limit config {}", e))) + .map_mm_err()?; let gas_limit_v2: EthGasLimitV2 = extract_gas_limit_from_conf(&token_conf) - .map_to_mm(|e| EthTokenActivationError::InternalError(format!("invalid gas_limit config {}", e)))?; + .map_to_mm(|e| EthTokenActivationError::InternalError(format!("invalid gas_limit config {}", e))) + .map_mm_err()?; let token = EthCoinImpl { priv_key_policy: self.priv_key_policy.clone(), @@ -532,7 +534,7 @@ impl EthCoin { let abortable_system = self.abortable_system.create_subsystem()?; // Todo: support HD wallet for NFTs, currently we get nfts for enabled address only and there might be some issues when activating NFTs while ETH is activated with HD wallet - let my_address = self.derivation_method.single_addr_or_err().await?; + let my_address = self.derivation_method.single_addr_or_err().await.map_mm_err()?; let proxy_sign = if komodo_proxy { let uri = Uri::from_str(original_url.as_ref()) @@ -544,7 +546,9 @@ impl EthCoin { None }; - let nft_infos = get_nfts_for_activation(&chain, &my_address, original_url, proxy_sign).await?; + let nft_infos = get_nfts_for_activation(&chain, &my_address, original_url, proxy_sign) + .await + .map_mm_err()?; let coin_type = EthCoinType::Nft { platform: self.ticker.clone(), }; @@ -763,7 +767,9 @@ pub(crate) async fn build_address_and_priv_key_policy( let hd_wallet_storage = HDWalletCoinStorage::init_with_rmd160(ctx, ticker.to_string(), hd_wallet_rmd160) .await .mm_err(EthActivationV2Error::from)?; - let accounts = load_hd_accounts_from_storage(&hd_wallet_storage, &path_to_coin).await?; + let accounts = load_hd_accounts_from_storage(&hd_wallet_storage, &path_to_coin) + .await + .map_mm_err()?; let gap_limit = gap_limit.unwrap_or(DEFAULT_GAP_LIMIT); let hd_wallet = EthHDWallet { hd_wallet_rmd160, @@ -791,7 +797,7 @@ pub(crate) async fn build_address_and_priv_key_policy( if trezor_coin.is_none() { return MmError::err(EthActivationV2Error::CoinDoesntSupportTrezor); } - let crypto_ctx = CryptoCtx::from_ctx(ctx)?; + let crypto_ctx = CryptoCtx::from_ctx(ctx).map_mm_err()?; let hw_ctx = crypto_ctx .hw_ctx() .or_mm_err(|| EthActivationV2Error::HwContextNotInitialized)?; @@ -799,7 +805,9 @@ pub(crate) async fn build_address_and_priv_key_policy( let hd_wallet_storage = HDWalletCoinStorage::init_with_rmd160(ctx, ticker.to_string(), hd_wallet_rmd160) .await .mm_err(EthActivationV2Error::from)?; - let accounts = load_hd_accounts_from_storage(&hd_wallet_storage, &path_to_coin).await?; + let accounts = load_hd_accounts_from_storage(&hd_wallet_storage, &path_to_coin) + .await + .map_mm_err()?; let gap_limit = gap_limit.unwrap_or(DEFAULT_GAP_LIMIT); let hd_wallet = EthHDWallet { hd_wallet_rmd160, @@ -814,7 +822,7 @@ pub(crate) async fn build_address_and_priv_key_policy( }, #[cfg(target_arch = "wasm32")] EthPrivKeyBuildPolicy::Metamask(metamask_ctx) => { - let address = *metamask_ctx.check_active_eth_account().await?; + let address = *metamask_ctx.check_active_eth_account().await.map_mm_err()?; let public_key_uncompressed = metamask_ctx.eth_account_pubkey_uncompressed(); let public_key = compress_public_key(public_key_uncompressed)?; Ok(( @@ -963,14 +971,13 @@ async fn build_metamask_transport( let event_handlers = rpc_event_handlers_for_eth_transport(ctx, coin_ticker.clone()); let eth_config = web3_transport::metamask_transport::MetamaskEthConfig { chain_id }; - let web3 = Web3::new(Web3Transport::new_metamask_with_event_handlers( - eth_config, - event_handlers, - )?); + let web3 = Web3::new(Web3Transport::new_metamask_with_event_handlers(eth_config, event_handlers).map_mm_err()?); // Check if MetaMask supports the given `chain_id`. // Please note that this request may take a long time. - check_metamask_supports_chain_id(coin_ticker, &web3, chain_id).await?; + check_metamask_supports_chain_id(coin_ticker, &web3, chain_id) + .await + .map_mm_err()?; // MetaMask doesn't use Parity nodes. So `MetamaskTransport` doesn't support `parity_nextNonce` RPC. // An example of the `web3_clientVersion` RPC - `MetaMask/v10.22.1`. @@ -1013,7 +1020,8 @@ async fn check_metamask_supports_chain_id( fn compress_public_key(uncompressed: H520) -> MmResult { let public_key = PublicKey::from_slice(uncompressed.as_bytes()) - .map_to_mm(|e| EthActivationV2Error::InternalError(e.to_string()))?; + .map_to_mm(|e| EthActivationV2Error::InternalError(e.to_string())) + .map_mm_err()?; let compressed = public_key.serialize(); Ok(H264::from(compressed)) diff --git a/mm2src/coins/eth/wallet_connect.rs b/mm2src/coins/eth/wallet_connect.rs index 2bc241342e..1ab2590644 100644 --- a/mm2src/coins/eth/wallet_connect.rs +++ b/mm2src/coins/eth/wallet_connect.rs @@ -113,7 +113,9 @@ impl WalletConnectOps for EthCoin { }, }; let chain_id = WcChainId::new_eip155(chain_id.to_string()); - wc.validate_update_active_chain_id(session_topic, &chain_id).await?; + wc.validate_update_active_chain_id(session_topic, &chain_id) + .await + .map_mm_err()?; Ok(chain_id) } @@ -129,7 +131,8 @@ impl WalletConnectOps for EthCoin { let session_topic = self.session_topic()?; let tx_hex: String = wc .send_session_request_and_wait(session_topic, &chain_id, WcRequestMethods::EthSignTransaction, tx_json) - .await?; + .await + .map_mm_err()?; // if tx_hex.len() < 4 { // return MmError::err(EthWalletConnectError::TxDecodingFailed( // "invalid transaction hex returned from wallet".to_string(), @@ -157,7 +160,8 @@ impl WalletConnectOps for EthCoin { let tx_json = params.prepare_wc_tx_format()?; let session_topic = self.session_topic()?; wc.send_session_request_and_wait(session_topic, &chain_id, WcRequestMethods::EthSendTransaction, tx_json) - .await? + .await + .map_mm_err()? }; let tx_hash = tx_hash.strip_prefix("0x").unwrap_or(&tx_hash); @@ -192,9 +196,13 @@ pub async fn eth_request_wc_personal_sign( chain_id: u64, ) -> MmResult<(H520, Address), EthWalletConnectError> { let chain_id = WcChainId::new_eip155(chain_id.to_string()); - wc.validate_update_active_chain_id(session_topic, &chain_id).await?; + wc.validate_update_active_chain_id(session_topic, &chain_id) + .await + .map_mm_err()?; - let (account_str, _) = wc.get_account_and_properties_for_chain_id(session_topic, &chain_id)?; + let (account_str, _) = wc + .get_account_and_properties_for_chain_id(session_topic, &chain_id) + .map_mm_err()?; let message = "Authenticate with KDF"; let params = { let message_hex = format!("0x{}", hex::encode(message)); @@ -202,10 +210,12 @@ pub async fn eth_request_wc_personal_sign( }; let data = wc .send_session_request_and_wait::(session_topic, &chain_id, WcRequestMethods::PersonalSign, params) - .await?; + .await + .map_mm_err()?; - Ok(extract_pubkey_from_signature(&data, message, &account_str) - .mm_err(|err| WalletConnectError::SessionError(err.to_string()))?) + extract_pubkey_from_signature(&data, message, &account_str) + .mm_err(|err| WalletConnectError::SessionError(err.to_string())) + .map_mm_err() } fn extract_pubkey_from_signature( diff --git a/mm2src/coins/hd_wallet/coin_ops.rs b/mm2src/coins/hd_wallet/coin_ops.rs index 27b92d0aa6..bb6b2d9f64 100644 --- a/mm2src/coins/hd_wallet/coin_ops.rs +++ b/mm2src/coins/hd_wallet/coin_ops.rs @@ -6,7 +6,8 @@ use async_trait::async_trait; use bip32::{ChildNumber, DerivationPath}; use crypto::Bip44Chain; use itertools::Itertools; -use mm2_err_handle::mm_error::{MmError, MmResult}; +use mm2_err_handle::{mm_error::{MmError, MmResult}, + prelude::MmResultExt}; use std::collections::HashMap; type AddressDerivingResult = MmResult; @@ -137,7 +138,7 @@ pub trait HDWalletCoinOps { hd_account: &HDCoinHDAccount, chain: Bip44Chain, ) -> AddressDerivingResult>> { - let known_addresses_number = hd_account.known_addresses_number(chain)?; + let known_addresses_number = hd_account.known_addresses_number(chain).map_mm_err()?; let address_ids = (0..known_addresses_number).map(|address_id| HDAddressId { chain, address_id }); self.derive_addresses(hd_account, address_ids).await } @@ -155,7 +156,8 @@ pub trait HDWalletCoinOps { } = inner_impl::generate_new_address_immutable(self, hd_account, chain).await?; self.set_known_addresses_number(hd_wallet, hd_account, chain, new_known_addresses_number) - .await?; + .await + .map_mm_err()?; Ok(address) } @@ -178,22 +180,26 @@ pub trait HDWalletCoinOps { let inner_impl::NewAddress { hd_address, new_known_addresses_number, - } = inner_impl::generate_new_address_immutable(self, hd_account, chain).await?; + } = inner_impl::generate_new_address_immutable(self, hd_account, chain) + .await + .map_mm_err()?; - let trezor_coin = self.trezor_coin()?; + let trezor_coin = self.trezor_coin().map_mm_err()?; let derivation_path = hd_address.derivation_path().clone(); let expected_address = hd_address.address().display_address(); // Ask the user to confirm if the given `expected_address` is the same as on the HW display. confirm_address .confirm_address(trezor_coin, derivation_path, expected_address) - .await?; + .await + .map_mm_err()?; - let actual_known_addresses_number = hd_account.known_addresses_number(chain)?; + let actual_known_addresses_number = hd_account.known_addresses_number(chain).map_mm_err()?; // Check if the actual `known_addresses_number` hasn't been changed while we waited for the user confirmation. // If the actual value is greater than the new one, we don't need to update. if actual_known_addresses_number < new_known_addresses_number { self.set_known_addresses_number(hd_wallet, hd_account, chain, new_known_addresses_number) - .await?; + .await + .map_mm_err()?; } Ok(hd_address) @@ -213,16 +219,14 @@ pub trait HDWalletCoinOps { return MmError::err(AccountUpdatingError::AddressLimitReached { max_addresses_number }); } match chain { - Bip44Chain::External => { - hd_wallet - .update_external_addresses_number(hd_account.account_id(), new_known_addresses_number) - .await? - }, - Bip44Chain::Internal => { - hd_wallet - .update_internal_addresses_number(hd_account.account_id(), new_known_addresses_number) - .await? - }, + Bip44Chain::External => hd_wallet + .update_external_addresses_number(hd_account.account_id(), new_known_addresses_number) + .await + .map_mm_err()?, + Bip44Chain::Internal => hd_wallet + .update_internal_addresses_number(hd_account.account_id(), new_known_addresses_number) + .await + .map_mm_err()?, } hd_account.set_known_addresses_number(chain, new_known_addresses_number); diff --git a/mm2src/coins/hd_wallet/confirm_address.rs b/mm2src/coins/hd_wallet/confirm_address.rs index 39bb286322..0bbfcd7cde 100644 --- a/mm2src/coins/hd_wallet/confirm_address.rs +++ b/mm2src/coins/hd_wallet/confirm_address.rs @@ -125,7 +125,7 @@ where statuses: HwConnectStatuses, trezor_message_type: TrezorMessageType, ) -> MmResult, HDConfirmAddressError> { - let crypto_ctx = CryptoCtx::from_ctx(ctx)?; + let crypto_ctx = CryptoCtx::from_ctx(ctx).map_mm_err()?; let hw_ctx = crypto_ctx .hw_ctx() .or_mm_err(|| HDConfirmAddressError::HwContextNotInitialized)?; @@ -153,20 +153,22 @@ where let pubkey_processor = TrezorRpcTaskProcessor::new(task_handle, confirm_statuses); let pubkey_processor = Arc::new(pubkey_processor); - let mut trezor_session = hw_ctx.trezor(pubkey_processor.clone()).await?; + let mut trezor_session = hw_ctx.trezor(pubkey_processor.clone()).await.map_mm_err()?; let address = match trezor_message_type { - TrezorMessageType::Bitcoin => { - trezor_session - .get_utxo_address(derivation_path, trezor_coin, SHOW_ADDRESS_ON_DISPLAY) - .await? - .process(pubkey_processor.clone()) - .await? - }, + TrezorMessageType::Bitcoin => trezor_session + .get_utxo_address(derivation_path, trezor_coin, SHOW_ADDRESS_ON_DISPLAY) + .await + .map_mm_err()? + .process(pubkey_processor.clone()) + .await + .map_mm_err()?, TrezorMessageType::Ethereum => trezor_session .get_eth_address(derivation_path, SHOW_ADDRESS_ON_DISPLAY) - .await? + .await + .map_mm_err()? .process(pubkey_processor.clone()) - .await? + .await + .map_mm_err()? .or_mm_err(|| HDConfirmAddressError::NoAddressReceived)?, }; diff --git a/mm2src/coins/hd_wallet/mod.rs b/mm2src/coins/hd_wallet/mod.rs index 1fedf35fcd..17bae275a1 100644 --- a/mm2src/coins/hd_wallet/mod.rs +++ b/mm2src/coins/hd_wallet/mod.rs @@ -216,7 +216,8 @@ where let account_child = ChildNumber::new(account_info.account_id, ACCOUNT_CHILD_HARDENED)?; let account_derivation_path = wallet_der_path .derive(account_child) - .map_to_mm(StandardHDPathError::from)?; + .map_to_mm(StandardHDPathError::from) + .map_mm_err()?; let extended_pubkey = ExtendedPublicKey::from_str(&account_info.account_xpub) .map_err(|e| HDWalletStorageError::ErrorDeserializing(e.to_string()))?; let capacity = @@ -416,7 +417,8 @@ where let account_derivation_path: HDPathToAccount = hd_wallet.derivation_path().derive(account_child)?; let account_pubkey = coin .extract_extended_pubkey(xpub_extractor, account_derivation_path.to_derivation_path()) - .await?; + .await + .map_mm_err()?; let new_account = HDAccount::new(new_account_id, account_pubkey, account_derivation_path); @@ -429,7 +431,10 @@ where return MmError::err(NewAccountCreationError::Internal(error)); } - hd_wallet.upload_new_account(new_account.to_storage_item()).await?; + hd_wallet + .upload_new_account(new_account.to_storage_item()) + .await + .map_mm_err()?; Ok(AsyncMutexGuard::map(accounts, |accounts| { accounts @@ -564,14 +569,17 @@ pub(crate) mod inner_impl { where Coin: HDWalletCoinOps + ?Sized + Sync, { - let known_addresses_number = hd_account.known_addresses_number(chain)?; + let known_addresses_number = hd_account.known_addresses_number(chain).map_mm_err()?; // Address IDs start from 0, so the `known_addresses_number = last_known_address_id + 1`. let new_address_id = known_addresses_number; let max_addresses_number = hd_account.address_limit(); if new_address_id >= max_addresses_number { return MmError::err(NewAddressDerivingError::AddressLimitReached { max_addresses_number }); } - let address = coin.derive_address(hd_account, chain, new_address_id).await?; + let address = coin + .derive_address(hd_account, chain, new_address_id) + .await + .map_mm_err()?; Ok(NewAddress { hd_address: address, new_known_addresses_number: known_addresses_number + 1, diff --git a/mm2src/coins/hd_wallet/pubkey.rs b/mm2src/coins/hd_wallet/pubkey.rs index 64b24e2abd..c7489761bb 100644 --- a/mm2src/coins/hd_wallet/pubkey.rs +++ b/mm2src/coins/hd_wallet/pubkey.rs @@ -122,7 +122,7 @@ where statuses: HwConnectStatuses, coin_protocol: CoinProtocol, ) -> MmResult, HDExtractPubkeyError> { - let crypto_ctx = CryptoCtx::from_ctx(ctx)?; + let crypto_ctx = CryptoCtx::from_ctx(ctx).map_mm_err()?; let hw_ctx = crypto_ctx .hw_ctx() .or_mm_err(|| HDExtractPubkeyError::HwContextNotInitialized)?; @@ -150,7 +150,7 @@ where ) -> MmResult { let pubkey_processor = TrezorRpcTaskProcessor::new(task_handle, statuses.to_trezor_request_statuses()); let pubkey_processor = Arc::new(pubkey_processor); - let mut trezor_session = hw_ctx.trezor(pubkey_processor.clone()).await?; + let mut trezor_session = hw_ctx.trezor(pubkey_processor.clone()).await.map_mm_err()?; let xpub = trezor_session .get_public_key( derivation_path, @@ -159,9 +159,11 @@ where SHOW_PUBKEY_ON_DISPLAY, IGNORE_XPUB_MAGIC, ) - .await? + .await + .map_mm_err()? .process(pubkey_processor.clone()) - .await?; + .await + .map_mm_err()?; // Despite we pass `IGNORE_XPUB_MAGIC` to the [`TrezorSession::get_public_key`] method, // Trezor sometimes returns pubkeys with magic prefixes like `dgub` prefix for DOGE coin. // So we need to replace the magic prefix manually. @@ -176,10 +178,11 @@ where ) -> MmResult { let pubkey_processor = TrezorRpcTaskProcessor::new(task_handle, statuses.to_trezor_request_statuses()); let pubkey_processor = Arc::new(pubkey_processor); - let mut trezor_session = hw_ctx.trezor(pubkey_processor.clone()).await?; + let mut trezor_session = hw_ctx.trezor(pubkey_processor.clone()).await.map_mm_err()?; trezor_session .get_eth_public_key(&derivation_path, SHOW_PUBKEY_ON_DISPLAY) - .await? + .await + .map_mm_err()? .process(pubkey_processor) .await .mm_err(HDExtractPubkeyError::from) diff --git a/mm2src/coins/hd_wallet/storage/mod.rs b/mm2src/coins/hd_wallet/storage/mod.rs index cb8f11b01d..c01712bfc9 100644 --- a/mm2src/coins/hd_wallet/storage/mod.rs +++ b/mm2src/coins/hd_wallet/storage/mod.rs @@ -229,7 +229,7 @@ impl Default for HDWalletCoinStorage { impl HDWalletCoinStorage { pub async fn init(ctx: &MmArc, coin: String) -> HDWalletStorageResult { let inner = Box::new(HDWalletStorageInstance::init(ctx).await?); - let crypto_ctx = CryptoCtx::from_ctx(ctx)?; + let crypto_ctx = CryptoCtx::from_ctx(ctx).map_mm_err()?; let hd_wallet_rmd160 = crypto_ctx .hw_wallet_rmd160() .or_mm_err(|| HDWalletStorageError::HDWalletUnavailable)?; diff --git a/mm2src/coins/hd_wallet/storage/wasm_storage.rs b/mm2src/coins/hd_wallet/storage/wasm_storage.rs index 4654474236..5c7b57b77d 100644 --- a/mm2src/coins/hd_wallet/storage/wasm_storage.rs +++ b/mm2src/coins/hd_wallet/storage/wasm_storage.rs @@ -173,15 +173,18 @@ impl HDWalletStorageInternalOps for HDWalletIndexedDbStorage { let shared_db = self.get_shared_db()?; let locked_db = Self::lock_db_mutex(&shared_db).await?; - let transaction = locked_db.inner.transaction().await?; - let table = transaction.table::().await?; + let transaction = locked_db.inner.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; let index_keys = MultiIndex::new(WALLET_ID_INDEX) - .with_value(wallet_id.coin)? - .with_value(wallet_id.hd_wallet_rmd160)?; + .with_value(wallet_id.coin) + .map_mm_err()? + .with_value(wallet_id.hd_wallet_rmd160) + .map_mm_err()?; Ok(table .get_items_by_multi_index(index_keys) - .await? + .await + .map_mm_err()? .into_iter() .map(|(_item_id, item)| HDAccountStorageItem::from(item)) .collect()) @@ -195,8 +198,8 @@ impl HDWalletStorageInternalOps for HDWalletIndexedDbStorage { let shared_db = self.get_shared_db()?; let locked_db = Self::lock_db_mutex(&shared_db).await?; - let transaction = locked_db.inner.transaction().await?; - let table = transaction.table::().await?; + let transaction = locked_db.inner.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; let maybe_account = Self::find_account(&table, wallet_id, account_id).await?; match maybe_account { @@ -237,8 +240,8 @@ impl HDWalletStorageInternalOps for HDWalletIndexedDbStorage { let shared_db = self.get_shared_db()?; let locked_db = Self::lock_db_mutex(&shared_db).await?; - let transaction = locked_db.inner.transaction().await?; - let table = transaction.table::().await?; + let transaction = locked_db.inner.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; let new_account = HDAccountTable::new(wallet_id, account); table @@ -252,13 +255,15 @@ impl HDWalletStorageInternalOps for HDWalletIndexedDbStorage { let shared_db = self.get_shared_db()?; let locked_db = Self::lock_db_mutex(&shared_db).await?; - let transaction = locked_db.inner.transaction().await?; - let table = transaction.table::().await?; + let transaction = locked_db.inner.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; let index_keys = MultiIndex::new(WALLET_ID_INDEX) - .with_value(wallet_id.coin)? - .with_value(wallet_id.hd_wallet_rmd160)?; - table.delete_items_by_multi_index(index_keys).await?; + .with_value(wallet_id.coin) + .map_mm_err()? + .with_value(wallet_id.hd_wallet_rmd160) + .map_mm_err()?; + table.delete_items_by_multi_index(index_keys).await.map_mm_err()?; Ok(()) } } @@ -280,9 +285,12 @@ impl HDWalletIndexedDbStorage { account_id: u32, ) -> HDWalletStorageResult> { let index_keys = MultiIndex::new(WALLET_ACCOUNT_ID_INDEX) - .with_value(wallet_id.coin)? - .with_value(wallet_id.hd_wallet_rmd160)? - .with_value(account_id)?; + .with_value(wallet_id.coin) + .map_mm_err()? + .with_value(wallet_id.hd_wallet_rmd160) + .map_mm_err()? + .with_value(account_id) + .map_mm_err()?; table .get_item_by_unique_multi_index(index_keys) .await @@ -296,8 +304,8 @@ impl HDWalletIndexedDbStorage { let shared_db = self.get_shared_db()?; let locked_db = Self::lock_db_mutex(&shared_db).await?; - let transaction = locked_db.inner.transaction().await?; - let table = transaction.table::().await?; + let transaction = locked_db.inner.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; let (account_item_id, mut account) = Self::find_account(&table, wallet_id.clone(), account_id) .await? diff --git a/mm2src/coins/hd_wallet/withdraw_ops.rs b/mm2src/coins/hd_wallet/withdraw_ops.rs index 3b3d6ac7d9..6fc70e1630 100644 --- a/mm2src/coins/hd_wallet/withdraw_ops.rs +++ b/mm2src/coins/hd_wallet/withdraw_ops.rs @@ -42,7 +42,7 @@ pub trait HDCoinWithdrawOps: HDWalletCoinOps { // If [`HDWalletCoinOps::derive_address`] succeeds, [`HDAccountOps::is_address_activated`] shouldn't fails with an `InvalidBip44ChainError`. .mm_err(|e| HDWithdrawError::InternalError(e.to_string()))?; - let hd_address = self.derive_address(&hd_account, chain, address_id).await?; + let hd_address = self.derive_address(&hd_account, chain, address_id).await.map_mm_err()?; let address = hd_address.address(); if !is_address_activated { let error = format!("'{}' address is not activated", address.display_address()); diff --git a/mm2src/coins/lightning.rs b/mm2src/coins/lightning.rs index d9c48ecbf3..c5ae7501b3 100644 --- a/mm2src/coins/lightning.rs +++ b/mm2src/coins/lightning.rs @@ -487,7 +487,7 @@ impl LightningCoin { min_final_cltv_expiry: u64, ) -> Result, MmError> { // lightning decimals should be 11 in config since the smallest divisible unit in lightning coin is msat - let amt_msat = sat_from_big_decimal(&amount, self.decimals())?; + let amt_msat = sat_from_big_decimal(&amount, self.decimals()).map_mm_err()?; let payment_hash = payment_hash_from_slice(secret_hash).map_to_mm(|e| PaymentInstructionsErr::InternalError(e.to_string()))?; // note: No description is provided in the invoice to reduce the payload @@ -563,7 +563,7 @@ impl LightningCoin { .map_to_mm(|e| ValidatePaymentError::TxDeserializationError(e.to_string()))); let payment_hex = hex::encode(payment_hash.0); - let amt_msat = try_f!(sat_from_big_decimal(&input.amount, self.decimals())); + let amt_msat = try_f!(sat_from_big_decimal(&input.amount, self.decimals()).map_mm_err()); let coin = self.clone(); let fut = async move { diff --git a/mm2src/coins/lightning/ln_utils.rs b/mm2src/coins/lightning/ln_utils.rs index 68f3c7f7ab..93c86c8e5d 100644 --- a/mm2src/coins/lightning/ln_utils.rs +++ b/mm2src/coins/lightning/ln_utils.rs @@ -110,7 +110,8 @@ pub fn init_keys_manager(platform: &Platform) -> EnableLightningResult BalanceFut; @@ -4149,7 +4154,7 @@ impl CoinsContext { #[cfg(target_arch = "wasm32")] async fn tx_history_db(&self) -> TxHistoryResult> { - Ok(self.tx_history_db.get_or_initialize().await?) + self.tx_history_db.get_or_initialize().await.map_mm_err() } #[inline(always)] @@ -4333,7 +4338,7 @@ where { match xpub_extractor { Some(xpub_extractor) => { - let trezor_coin = coin.trezor_coin()?; + let trezor_coin = coin.trezor_coin().map_mm_err()?; let xpub = xpub_extractor.extract_xpub(trezor_coin, derivation_path).await?; Secp256k1ExtendedPublicKey::from_str(&xpub).map_to_mm(|e| HDExtractPubkeyError::InvalidXpub(e.to_string())) }, @@ -5140,12 +5145,12 @@ pub async fn validate_address(ctx: MmArc, req: Json) -> Result> } pub async fn withdraw(ctx: MmArc, req: WithdrawRequest) -> WithdrawResult { - let coin = lp_coinfind_or_err(&ctx, &req.coin).await?; + let coin = lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()?; coin.withdraw(req).compat().await } pub async fn get_raw_transaction(ctx: MmArc, req: RawTransactionRequest) -> RawTransactionResult { - let coin = lp_coinfind_or_err(&ctx, &req.coin).await?; + let coin = lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()?; coin.get_raw_transaction(req).compat().await } @@ -5155,14 +5160,14 @@ pub async fn sign_message(ctx: MmArc, req: SignatureRequest) -> SignatureResult< "You need to enable kdf with enable_hd to sign messages with a specific account/address".to_string(), )); }; - let coin = lp_coinfind_or_err(&ctx, &req.coin).await?; + let coin = lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()?; let signature = coin.sign_message(&req.message, req.address)?; Ok(SignatureResponse { signature }) } pub async fn verify_message(ctx: MmArc, req: VerificationRequest) -> VerificationResult { - let coin = lp_coinfind_or_err(&ctx, &req.coin).await?; + let coin = lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()?; let validate_address_result = coin.validate_address(&req.address); if !validate_address_result.is_valid { @@ -5177,12 +5182,12 @@ pub async fn verify_message(ctx: MmArc, req: VerificationRequest) -> Verificatio } pub async fn sign_raw_transaction(ctx: MmArc, req: SignRawTransactionRequest) -> RawTransactionResult { - let coin = lp_coinfind_or_err(&ctx, &req.coin).await?; + let coin = lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()?; coin.sign_raw_tx(&req).await } pub async fn remove_delegation(ctx: MmArc, req: RemoveDelegateRequest) -> DelegationResult { - let coin = lp_coinfind_or_err(&ctx, &req.coin).await?; + let coin = lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()?; match req.staking_details { Some(StakingDetails::Cosmos(req)) => { @@ -5217,7 +5222,7 @@ pub async fn remove_delegation(ctx: MmArc, req: RemoveDelegateRequest) -> Delega } pub async fn delegations_info(ctx: MmArc, req: DelegationsInfo) -> Result> { - let coin = lp_coinfind_or_err(&ctx, &req.coin).await?; + let coin = lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()?; match req.info_details { DelegationsInfoDetails::Qtum => { @@ -5231,7 +5236,7 @@ pub async fn delegations_info(ctx: MmArc, req: DelegationsInfo) -> Result match coin { - MmCoinEnum::Tendermint(t) => Ok(t.delegations_list(r.paging).await.map(|v| json!(v))?), + MmCoinEnum::Tendermint(t) => Ok(t.delegations_list(r.paging).await.map(|v| json!(v)).map_mm_err()?), MmCoinEnum::TendermintToken(_) => MmError::err(StakingInfoError::InvalidPayload { reason: "Tokens are not supported for delegation".into(), }), @@ -5243,11 +5248,15 @@ pub async fn delegations_info(ctx: MmArc, req: DelegationsInfo) -> Result Result> { - let coin = lp_coinfind_or_err(&ctx, &req.coin).await?; + let coin = lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()?; match req.info_details { UndelegationsInfoDetails::Cosmos(r) => match coin { - MmCoinEnum::Tendermint(t) => Ok(t.ongoing_undelegations_list(r.paging).await.map(|v| json!(v))?), + MmCoinEnum::Tendermint(t) => Ok(t + .ongoing_undelegations_list(r.paging) + .await + .map(|v| json!(v)) + .map_mm_err()?), MmCoinEnum::TendermintToken(_) => MmError::err(StakingInfoError::InvalidPayload { reason: "Tokens are not supported for delegation".into(), }), @@ -5259,7 +5268,7 @@ pub async fn ongoing_undelegations_info(ctx: MmArc, req: UndelegationsInfo) -> R } pub async fn validators_info(ctx: MmArc, req: ValidatorsInfo) -> Result> { - let coin = lp_coinfind_or_err(&ctx, &req.coin).await?; + let coin = lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()?; match req.info_details { ValidatorsInfoDetails::Cosmos(payload) => rpc_command::tendermint::staking::validators_rpc(coin, payload) @@ -5269,7 +5278,7 @@ pub async fn validators_info(ctx: MmArc, req: ValidatorsInfo) -> Result DelegationResult { - let coin = lp_coinfind_or_err(&ctx, &req.coin).await?; + let coin = lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()?; match req.staking_details { StakingDetails::Qtum(req) => { @@ -5296,7 +5305,7 @@ pub async fn add_delegation(ctx: MmArc, req: AddDelegateRequest) -> DelegationRe pub async fn claim_staking_rewards(ctx: MmArc, req: ClaimStakingRewardsRequest) -> DelegationResult { match req.claiming_details { ClaimingDetails::Cosmos(r) => { - let coin = lp_coinfind_or_err(&ctx, &req.coin).await?; + let coin = lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()?; let MmCoinEnum::Tendermint(tendermint) = coin else { return MmError::err(DelegationError::InvalidPayload { @@ -5611,7 +5620,7 @@ where { let ctx = ctx.clone(); let ticker = coin.ticker().to_owned(); - let my_address = try_f!(coin.my_address()); + let my_address = try_f!(coin.my_address().map_mm_err()); let fut = async move { let coins_ctx = CoinsContext::from_ctx(&ctx).unwrap(); @@ -5685,7 +5694,7 @@ where { let ctx = ctx.clone(); let ticker = coin.ticker().to_owned(); - let my_address = try_f!(coin.my_address()); + let my_address = try_f!(coin.my_address().map_mm_err()); history.sort_unstable_by(compare_transaction_details); @@ -5835,7 +5844,9 @@ pub async fn get_my_address(ctx: MmArc, req: MyAddressReq) -> MmResult get_eth_address(&ctx, &conf, ticker, &req.path_to_address).await?, + CoinProtocol::ETH { .. } => get_eth_address(&ctx, &conf, ticker, &req.path_to_address) + .await + .map_mm_err()?, _ => { return MmError::err(GetMyAddressError::CoinIsNotSupported(format!( "{} doesn't support get_my_address", @@ -5892,7 +5903,7 @@ pub trait Eip1559Ops { /// Get eip 1559 transaction fee per gas policy (low, medium, high) set for the coin pub async fn get_swap_transaction_fee_policy(ctx: MmArc, req: SwapTxFeePolicyRequest) -> SwapTxFeePolicyResult { - let coin = lp_coinfind_or_err(&ctx, &req.coin).await?; + let coin = lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()?; match coin { MmCoinEnum::EthCoin(eth_coin) => Ok(eth_coin.get_swap_transaction_fee_policy()), MmCoinEnum::Qrc20Coin(qrc20_coin) => Ok(qrc20_coin.get_swap_transaction_fee_policy()), @@ -5902,7 +5913,7 @@ pub async fn get_swap_transaction_fee_policy(ctx: MmArc, req: SwapTxFeePolicyReq /// Set eip 1559 transaction fee per gas policy (low, medium, high) pub async fn set_swap_transaction_fee_policy(ctx: MmArc, req: SwapTxFeePolicyRequest) -> SwapTxFeePolicyResult { - let coin = lp_coinfind_or_err(&ctx, &req.coin).await?; + let coin = lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()?; match coin { MmCoinEnum::EthCoin(eth_coin) => { eth_coin.set_swap_transaction_fee_policy(req.swap_tx_fee_policy); @@ -5940,7 +5951,10 @@ where let mut unused_addresses_counter = 0; let max_addresses_number = hd_account.address_limit(); while checking_address_id < max_addresses_number && unused_addresses_counter <= gap_limit { - let hd_address = coin.derive_address(hd_account, chain, checking_address_id).await?; + let hd_address = coin + .derive_address(hd_account, chain, checking_address_id) + .await + .map_mm_err()?; let checking_address = hd_address.address(); let checking_address_der_path = hd_address.derivation_path(); @@ -5953,16 +5967,17 @@ where // First, derive all empty addresses and put it into `balances` with default balance. let address_ids = (last_non_empty_address_id..checking_address_id) .map(|address_id| HDAddressId { chain, address_id }); - let empty_addresses = - coin.derive_addresses(hd_account, address_ids) - .await? - .into_iter() - .map(|empty_address| HDAddressBalance { - address: empty_address.address().display_address(), - derivation_path: RpcDerivationPath(empty_address.derivation_path().clone()), - chain, - balance: HDWalletBalanceObject::::new(), - }); + let empty_addresses = coin + .derive_addresses(hd_account, address_ids) + .await + .map_mm_err()? + .into_iter() + .map(|empty_address| HDAddressBalance { + address: empty_address.address().display_address(), + derivation_path: RpcDerivationPath(empty_address.derivation_path().clone()), + chain, + balance: HDWalletBalanceObject::::new(), + }); balances.extend(empty_addresses); // Then push this non-empty address. @@ -5987,7 +6002,8 @@ where chain, checking_address_id - unused_addresses_counter, ) - .await?; + .await + .map_mm_err()?; Ok(balances) } diff --git a/mm2src/coins/lp_price.rs b/mm2src/coins/lp_price.rs index 1a720d3e3d..f7cd971415 100644 --- a/mm2src/coins/lp_price.rs +++ b/mm2src/coins/lp_price.rs @@ -1,6 +1,6 @@ use common::log::{debug, error, info}; use common::StatusCode; -use mm2_err_handle::prelude::{MmError, OrMmError}; +use mm2_err_handle::prelude::*; use mm2_net::transport::SlurpError; #[cfg(not(feature = "run-docker-tests"))] use mm2_number::bigdecimal_custom::CheckedDivision; @@ -188,7 +188,7 @@ impl TickerInfosRegistry { #[cfg(not(target_arch = "wasm32"))] async fn process_price_request(price_url: &str) -> Result> { debug!("Fetching price from: {}", price_url); - let (status, headers, body) = mm2_net::native_http::slurp_url(price_url).await?; + let (status, headers, body) = mm2_net::native_http::slurp_url(price_url).await.map_mm_err()?; let (status_code, body, _) = (status, std::str::from_utf8(&body)?.trim().into(), headers); if status_code != StatusCode::OK { return MmError::err(PriceServiceRequestError::HttpProcessError(body)); @@ -200,7 +200,7 @@ async fn process_price_request(price_url: &str) -> Result Result> { debug!("Fetching price from: {}", price_url); - let (status, headers, body) = mm2_net::wasm::http::slurp_url(price_url).await?; + let (status, headers, body) = mm2_net::wasm::http::slurp_url(price_url).await.map_mm_err()?; let (status_code, body, _) = (status, std::str::from_utf8(&body)?.trim().into(), headers); if status_code != StatusCode::OK { return MmError::err(PriceServiceRequestError::HttpProcessError(body)); diff --git a/mm2src/coins/my_tx_history_v2.rs b/mm2src/coins/my_tx_history_v2.rs index 9bd5877ff5..02ed54d214 100644 --- a/mm2src/coins/my_tx_history_v2.rs +++ b/mm2src/coins/my_tx_history_v2.rs @@ -36,7 +36,7 @@ pub struct GetHistoryResult { pub total: usize, } -pub trait TxHistoryStorageError: std::fmt::Debug + NotMmError + NotEqual + Send {} +pub trait TxHistoryStorageError: std::fmt::Debug + NotMmError + Send {} #[async_trait] pub trait TxHistoryStorage: Send + Sync + 'static { @@ -365,7 +365,7 @@ pub async fn my_tx_history_v2_rpc( ctx: MmArc, request: MyTxHistoryRequestV2, ) -> Result, MmError> { - match lp_coinfind_or_err(&ctx, &request.coin).await? { + match lp_coinfind_or_err(&ctx, &request.coin).await.map_mm_err()? { MmCoinEnum::Bch(bch) => my_tx_history_v2_impl(ctx, &bch, request).await, MmCoinEnum::SlpToken(slp_token) => my_tx_history_v2_impl(ctx, &slp_token, request).await, MmCoinEnum::UtxoCoin(utxo) => my_tx_history_v2_impl(ctx, &utxo, request).await, @@ -384,10 +384,10 @@ pub(crate) async fn my_tx_history_v2_impl( where Coin: CoinWithTxHistoryV2 + MmCoin, { - let tx_history_storage = TxHistoryStorageBuilder::new(&ctx).build()?; + let tx_history_storage = TxHistoryStorageBuilder::new(&ctx).build().map_mm_err()?; let wallet_id = coin.history_wallet_id(); - let is_storage_init = tx_history_storage.is_initialized_for(&wallet_id).await?; + let is_storage_init = tx_history_storage.is_initialized_for(&wallet_id).await.map_mm_err()?; if !is_storage_init { let msg = format!("Storage is not initialized for {:?}", wallet_id); return MmError::err(MyTxHistoryErrorV2::StorageIsNotInitialized(msg)); @@ -401,7 +401,8 @@ where let filters = coin.get_tx_history_filters(request.target.clone()).await?; let history = tx_history_storage .get_history(&wallet_id, filters, request.paging_options.clone(), request.limit) - .await?; + .await + .map_mm_err()?; let coin_conf = coin_conf(&ctx, coin.ticker()); let protocol_type = coin_conf["protocol"]["type"].as_str().unwrap_or_default(); @@ -500,7 +501,7 @@ pub async fn z_coin_tx_history_rpc( ctx: MmArc, request: MyTxHistoryRequestV2, ) -> Result, MmError> { - match lp_coinfind_or_err(&ctx, &request.coin).await? { + match lp_coinfind_or_err(&ctx, &request.coin).await.map_mm_err()? { MmCoinEnum::ZCoin(z_coin) => z_coin.tx_history(request).await, other => MmError::err(MyTxHistoryErrorV2::NotSupportedFor(other.ticker().to_owned())), } diff --git a/mm2src/coins/nft.rs b/mm2src/coins/nft.rs index ebd4c83146..9c7ad4fa09 100644 --- a/mm2src/coins/nft.rs +++ b/mm2src/coins/nft.rs @@ -1,6 +1,6 @@ use http::Uri; use mm2_core::mm_ctx::MmArc; -use mm2_err_handle::prelude::{MmError, MmResult}; +use mm2_err_handle::prelude::{MmError, MmResult, MmResultExt}; use mm2_p2p::p2p_ctx::P2PContext; use proxy_signature::{ProxySign, RawMessage}; use url::Url; @@ -89,18 +89,19 @@ pub type WithdrawNftResult = Result MmResult { let nft_ctx = NftCtx::from_ctx(&ctx).map_to_mm(GetNftInfoError::Internal)?; - let storage = nft_ctx.lock_db().await?; + let storage = nft_ctx.lock_db().await.map_mm_err()?; for chain in req.chains.iter() { - if !NftListStorageOps::is_initialized(&storage, chain).await? { - NftListStorageOps::init(&storage, chain).await?; + if !NftListStorageOps::is_initialized(&storage, chain).await.map_mm_err()? { + NftListStorageOps::init(&storage, chain).await.map_mm_err()?; } } let mut nft_list = storage .get_nft_list(req.chains, req.max, req.limit, req.page_number, req.filters) - .await?; + .await + .map_mm_err()?; if req.protect_from_spam { for nft in &mut nft_list.nfts { - protect_from_nft_spam_links(nft, true)?; + protect_from_nft_spam_links(nft, true).map_mm_err()?; } } Ok(nft_list) @@ -114,19 +115,23 @@ pub async fn get_nft_list(ctx: MmArc, req: NftListReq) -> MmResult MmResult { let nft_ctx = NftCtx::from_ctx(&ctx).map_to_mm(GetNftInfoError::Internal)?; - let storage = nft_ctx.lock_db().await?; - if !NftListStorageOps::is_initialized(&storage, &req.chain).await? { - NftListStorageOps::init(&storage, &req.chain).await?; + let storage = nft_ctx.lock_db().await.map_mm_err()?; + if !NftListStorageOps::is_initialized(&storage, &req.chain) + .await + .map_mm_err()? + { + NftListStorageOps::init(&storage, &req.chain).await.map_mm_err()?; } let mut nft = storage .get_nft(&req.chain, format!("{:#02x}", req.token_address), req.token_id.clone()) - .await? + .await + .map_mm_err()? .ok_or_else(|| GetNftInfoError::TokenNotFoundInWallet { token_address: format!("{:#02x}", req.token_address), token_id: req.token_id.to_string(), })?; if req.protect_from_spam { - protect_from_nft_spam_links(&mut nft, true)?; + protect_from_nft_spam_links(&mut nft, true).map_mm_err()?; } Ok(nft) } @@ -154,24 +159,32 @@ pub async fn get_nft_metadata(ctx: MmArc, req: NftMetadataReq) -> MmResult MmResult { let nft_ctx = NftCtx::from_ctx(&ctx).map_to_mm(GetNftInfoError::Internal)?; - let storage = nft_ctx.lock_db().await?; + let storage = nft_ctx.lock_db().await.map_mm_err()?; for chain in req.chains.iter() { - if !NftTransferHistoryStorageOps::is_initialized(&storage, chain).await? { - NftTransferHistoryStorageOps::init(&storage, chain).await?; + if !NftTransferHistoryStorageOps::is_initialized(&storage, chain) + .await + .map_mm_err()? + { + NftTransferHistoryStorageOps::init(&storage, chain).await.map_mm_err()?; } else { #[cfg(not(target_arch = "wasm32"))] - NftMigrationOps::migrate_tx_history_if_needed(&storage, chain).await?; + NftMigrationOps::migrate_tx_history_if_needed(&storage, chain) + .await + .map_mm_err()?; } } let mut transfer_history_list = storage .get_transfer_history(req.chains.clone(), req.max, req.limit, req.page_number, req.filters) - .await?; + .await + .map_mm_err()?; if req.protect_from_spam { for transfer in &mut transfer_history_list.transfer_history { - protect_from_history_spam_links(transfer, true)?; + protect_from_history_spam_links(transfer, true).map_mm_err()?; } } - process_transfers_confirmations(&ctx, req.chains, &mut transfer_history_list).await?; + process_transfers_confirmations(&ctx, req.chains, &mut transfer_history_list) + .await + .map_mm_err()?; Ok(transfer_history_list) } @@ -189,7 +202,7 @@ async fn process_transfers_confirmations( let futures = chains.into_iter().map(|chain| async move { let ticker = chain.to_ticker(); - let coin_enum = lp_coinfind_or_err(ctx, ticker).await?; + let coin_enum = lp_coinfind_or_err(ctx, ticker).await.map_mm_err()?; match coin_enum { MmCoinEnum::EthCoin(eth_coin) => { let current_block = current_block_impl(eth_coin).await?; @@ -222,23 +235,31 @@ async fn process_transfers_confirmations( /// data fetched from the provided `url`. The function ensures the local cache is in /// sync with the latest data from the source, validates against spam contract addresses and phishing domains. pub async fn update_nft(ctx: MmArc, req: UpdateNftReq) -> MmResult<(), UpdateNftError> { - let nft_ctx = NftCtx::from_ctx(&ctx).map_to_mm(GetNftInfoError::Internal)?; + let nft_ctx = NftCtx::from_ctx(&ctx) + .map_to_mm(GetNftInfoError::Internal) + .map_mm_err()?; let p2p_ctx = P2PContext::fetch_from_mm_arc(&ctx); - let storage = nft_ctx.lock_db().await?; + let storage = nft_ctx.lock_db().await.map_mm_err()?; for chain in req.chains.iter() { - let transfer_history_initialized = NftTransferHistoryStorageOps::is_initialized(&storage, chain).await?; + let transfer_history_initialized = NftTransferHistoryStorageOps::is_initialized(&storage, chain) + .await + .map_mm_err()?; let from_block = if transfer_history_initialized { #[cfg(not(target_arch = "wasm32"))] - NftMigrationOps::migrate_tx_history_if_needed(&storage, chain).await?; - let last_transfer_block = NftTransferHistoryStorageOps::get_last_block_number(&storage, chain).await?; + NftMigrationOps::migrate_tx_history_if_needed(&storage, chain) + .await + .map_mm_err()?; + let last_transfer_block = NftTransferHistoryStorageOps::get_last_block_number(&storage, chain) + .await + .map_mm_err()?; last_transfer_block.map(|b| b + 1) } else { - NftTransferHistoryStorageOps::init(&storage, chain).await?; + NftTransferHistoryStorageOps::init(&storage, chain).await.map_mm_err()?; None }; - let coin_enum = lp_coinfind_or_err(&ctx, chain.to_nft_ticker()).await?; + let coin_enum = lp_coinfind_or_err(&ctx, chain.to_nft_ticker()).await.map_mm_err()?; let global_nft = match coin_enum { MmCoinEnum::EthCoin(eth_coin) => eth_coin, _ => { @@ -247,7 +268,7 @@ pub async fn update_nft(ctx: MmArc, req: UpdateNftReq) -> MmResult<(), UpdateNft }) }, }; - let my_address = global_nft.derivation_method().single_addr_or_err().await?; + let my_address = global_nft.derivation_method().single_addr_or_err().await.map_mm_err()?; let my_address_str = my_address.addr_to_string(); let proxy_sign = if req.komodo_proxy { let uri = Uri::from_str(req.url.as_ref()).map_err(|e| UpdateNftError::Internal(e.to_string()))?; @@ -265,8 +286,13 @@ pub async fn update_nft(ctx: MmArc, req: UpdateNftReq) -> MmResult<(), UpdateNft proxy_sign, }; - let nft_transfers = get_moralis_nft_transfers(from_block, global_nft, &my_address_str, &wrapper).await?; - storage.add_transfers_to_history(*chain, nft_transfers).await?; + let nft_transfers = get_moralis_nft_transfers(from_block, global_nft, &my_address_str, &wrapper) + .await + .map_mm_err()?; + storage + .add_transfers_to_history(*chain, nft_transfers) + .await + .map_mm_err()?; let nft_block = match NftListStorageOps::get_last_block_number(&storage, chain).await { Ok(Some(block)) => block, @@ -275,28 +301,28 @@ pub async fn update_nft(ctx: MmArc, req: UpdateNftReq) -> MmResult<(), UpdateNft let nft_list = cache_nfts_from_moralis(&my_address_str, &storage, &wrapper).await?; update_meta_in_transfers(&storage, chain, nft_list).await?; update_transfers_with_empty_meta(&storage, &wrapper).await?; - update_spam(&storage, *chain, &req.url_antispam).await?; - update_phishing(&storage, chain, &req.url_antispam).await?; + update_spam(&storage, *chain, &req.url_antispam).await.map_mm_err()?; + update_phishing(&storage, chain, &req.url_antispam).await.map_mm_err()?; continue; }, Err(_) => { // if there is an error, then NFT LIST table doesn't exist, so we need to cache nft list from moralis. - NftListStorageOps::init(&storage, chain).await?; + NftListStorageOps::init(&storage, chain).await.map_mm_err()?; let nft_list = cache_nfts_from_moralis(&my_address_str, &storage, &wrapper).await?; update_meta_in_transfers(&storage, chain, nft_list).await?; update_transfers_with_empty_meta(&storage, &wrapper).await?; - update_spam(&storage, *chain, &req.url_antispam).await?; - update_phishing(&storage, chain, &req.url_antispam).await?; + update_spam(&storage, *chain, &req.url_antispam).await.map_mm_err()?; + update_phishing(&storage, chain, &req.url_antispam).await.map_mm_err()?; continue; }, }; - let scanned_block = - storage - .get_last_scanned_block(chain) - .await? - .ok_or_else(|| UpdateNftError::LastScannedBlockNotFound { - last_nft_block: nft_block.to_string(), - })?; + let scanned_block = storage + .get_last_scanned_block(chain) + .await + .map_mm_err()? + .ok_or_else(|| UpdateNftError::LastScannedBlockNotFound { + last_nft_block: nft_block.to_string(), + })?; // if both block numbers exist, last scanned block should be equal // or higher than last block number from NFT LIST table. if scanned_block < nft_block { @@ -308,8 +334,8 @@ pub async fn update_nft(ctx: MmArc, req: UpdateNftReq) -> MmResult<(), UpdateNft update_nft_list(&storage, scanned_block + 1, &my_address_str, &wrapper).await?; update_nft_global_in_coins_ctx(&ctx, &storage, *chain).await?; update_transfers_with_empty_meta(&storage, &wrapper).await?; - update_spam(&storage, *chain, &req.url_antispam).await?; - update_phishing(&storage, chain, &req.url_antispam).await?; + update_spam(&storage, *chain, &req.url_antispam).await.map_mm_err()?; + update_phishing(&storage, chain, &req.url_antispam).await.map_mm_err()?; } Ok(()) } @@ -331,7 +357,10 @@ where .. }) = coins.get_mut(ticker) { - let nft_list = storage.get_nft_list(vec![chain], true, 1, None, None).await?; + let nft_list = storage + .get_nft_list(vec![chain], true, 1, None, None) + .await + .map_mm_err()?; update_nft_infos(nft_global, nft_list.nfts).await; return Ok(()); } @@ -376,7 +405,7 @@ async fn update_spam(storage: &T, chain: Chain, url_antispam: &Url) -> MmResu where T: NftListStorageOps + NftTransferHistoryStorageOps, { - let token_addresses = storage.get_token_addresses(chain).await?; + let token_addresses = storage.get_token_addresses(chain).await.map_mm_err()?; if !token_addresses.is_empty() { let addresses = token_addresses .iter() @@ -389,10 +418,12 @@ where let address_hex = address.addr_to_string(); storage .update_nft_spam_by_token_address(&chain, address_hex.clone(), is_spam) - .await?; + .await + .map_mm_err()?; storage .update_transfer_spam_by_token_address(&chain, address_hex, is_spam) - .await?; + .await + .map_mm_err()?; } } } @@ -403,8 +434,8 @@ async fn update_phishing(storage: &T, chain: &Chain, url_antispam: &Url) -> M where T: NftListStorageOps + NftTransferHistoryStorageOps, { - let transfer_domains = storage.get_domains(chain).await?; - let nft_domains = storage.get_animation_external_domains(chain).await?; + let transfer_domains = storage.get_domains(chain).await.map_mm_err()?; + let nft_domains = storage.get_animation_external_domains(chain).await.map_mm_err()?; let domains: HashSet = transfer_domains.union(&nft_domains).cloned().collect(); if !domains.is_empty() { let domains = domains.into_iter().collect::>().join(","); @@ -413,10 +444,12 @@ where if is_phishing { storage .update_nft_phishing_by_domain(chain, domain.clone(), is_phishing) - .await?; + .await + .map_mm_err()?; storage .update_transfer_phishing_by_domain(chain, domain, is_phishing) - .await?; + .await + .map_mm_err()?; } } } @@ -435,7 +468,9 @@ async fn send_spam_request( addresses, }; let req_spam_json = serde_json::to_string(&req_spam)?; - let scan_contract_res = send_post_request_to_uri(scan_contract_uri.as_str(), req_spam_json).await?; + let scan_contract_res = send_post_request_to_uri(scan_contract_uri.as_str(), req_spam_json) + .await + .map_mm_err()?; let spam_res: SpamContractRes = serde_json::from_slice(&scan_contract_res)?; Ok(spam_res) } @@ -448,7 +483,9 @@ async fn send_phishing_request( let scan_contract_uri = prepare_uri_for_blocklist_endpoint(url_antispam, BLOCKLIST_DOMAIN, BLOCKLIST_SCAN)?; let req_phishing = PhishingDomainReq { domains }; let req_phishing_json = serde_json::to_string(&req_phishing)?; - let scan_domains_res = send_post_request_to_uri(scan_contract_uri.as_str(), req_phishing_json).await?; + let scan_domains_res = send_post_request_to_uri(scan_contract_uri.as_str(), req_phishing_json) + .await + .map_mm_err()?; let phishing_res: PhishingDomainRes = serde_json::from_slice(&scan_domains_res)?; Ok(phishing_res) } @@ -477,10 +514,12 @@ fn prepare_uri_for_blocklist_endpoint( /// is identified as spam or matches with any phishing domains, the NFT's `possible_spam` and/or /// `possible_phishing` flags are set to true. pub async fn refresh_nft_metadata(ctx: MmArc, req: RefreshMetadataReq) -> MmResult<(), UpdateNftError> { - let nft_ctx = NftCtx::from_ctx(&ctx).map_to_mm(GetNftInfoError::Internal)?; + let nft_ctx = NftCtx::from_ctx(&ctx) + .map_to_mm(GetNftInfoError::Internal) + .map_mm_err()?; let p2p_ctx = P2PContext::fetch_from_mm_arc(&ctx); - let storage = nft_ctx.lock_db().await?; + let storage = nft_ctx.lock_db().await.map_mm_err()?; let proxy_sign = if req.komodo_proxy { let uri = Uri::from_str(req.url.as_ref()).map_err(|e| UpdateNftError::Internal(e.to_string()))?; @@ -503,23 +542,26 @@ pub async fn refresh_nft_metadata(ctx: MmArc, req: RefreshMetadataReq) -> MmResu Err(_) => { storage .update_nft_spam_by_token_address(&req.chain, token_address_str.clone(), true) - .await?; + .await + .map_mm_err()?; storage .update_transfer_spam_by_token_address(&req.chain, token_address_str.clone(), true) - .await?; + .await + .map_mm_err()?; return Ok(()); }, }; let mut nft_db = storage .get_nft(&req.chain, token_address_str.clone(), req.token_id.clone()) - .await? + .await + .map_mm_err()? .ok_or_else(|| GetNftInfoError::TokenNotFoundInWallet { token_address: token_address_str, token_id: req.token_id.to_string(), })?; let token_uri = check_moralis_ipfs_bafy(moralis_meta.common.token_uri.as_deref()); let token_domain = get_domain_from_url(token_uri.as_deref()); - check_token_uri(&mut moralis_meta.common.possible_spam, token_uri.as_deref())?; + check_token_uri(&mut moralis_meta.common.possible_spam, token_uri.as_deref()).map_mm_err()?; drop_mutability!(moralis_meta); let uri_meta = get_uri_meta( token_uri.as_deref(), @@ -548,7 +590,8 @@ pub async fn refresh_nft_metadata(ctx: MmArc, req: RefreshMetadataReq) -> MmResu }; storage .refresh_nft_metadata(&moralis_meta.chain, nft_db.clone()) - .await?; + .await + .map_mm_err()?; update_transfer_meta_using_nft(&storage, &req.chain, &mut nft_db).await?; Ok(()) } @@ -562,7 +605,8 @@ where let transfer_meta = TransferMeta::from(nft.clone()); storage .update_transfers_meta_by_token_addr_id(chain, transfer_meta, nft.common.possible_spam) - .await?; + .await + .map_mm_err()?; Ok(()) } @@ -595,15 +639,19 @@ where T: NftListStorageOps + NftTransferHistoryStorageOps, { let address_hex = nft_db.common.token_address.addr_to_string(); - let spam_res = send_spam_request(chain, url_antispam, address_hex.clone()).await?; + let spam_res = send_spam_request(chain, url_antispam, address_hex.clone()) + .await + .map_mm_err()?; if let Some(true) = spam_res.result.get(&nft_db.common.token_address) { nft_db.common.possible_spam = true; storage .update_nft_spam_by_token_address(chain, address_hex.clone(), true) - .await?; + .await + .map_mm_err()?; storage .update_transfer_spam_by_token_address(chain, address_hex, true) - .await?; + .await + .map_mm_err()?; } Ok(()) } @@ -621,16 +669,18 @@ where { if !domains.is_empty() { let domain_list = domains.into_iter().collect::>().join(","); - let domain_res = send_phishing_request(url_antispam, domain_list).await?; + let domain_res = send_phishing_request(url_antispam, domain_list).await.map_mm_err()?; for (domain, is_phishing) in domain_res.result.into_iter() { if is_phishing { nft_db.possible_phishing = true; storage .update_transfer_phishing_by_domain(chain, domain.clone(), is_phishing) - .await?; + .await + .map_mm_err()?; storage .update_nft_phishing_by_domain(chain, domain, is_phishing) - .await?; + .await + .map_mm_err()?; } } } @@ -659,7 +709,7 @@ async fn get_moralis_nft_list( None => continue, }; let mut nft = build_nft_from_moralis(*chain, nft_moralis, contract_type, wrapper.url_antispam).await; - protect_from_nft_spam_links(&mut nft, false)?; + protect_from_nft_spam_links(&mut nft, false).map_mm_err()?; // collect NFTs from the page res_list.push(nft); } @@ -917,7 +967,7 @@ async fn get_moralis_metadata( None => return MmError::err(GetNftInfoError::ContractTypeIsNull), }; let mut nft_metadata = build_nft_from_moralis(*chain, nft_moralis, contract_type, wrapper.url_antispam).await; - protect_from_nft_spam_links(&mut nft_metadata, false)?; + protect_from_nft_spam_links(&mut nft_metadata, false).map_mm_err()?; Ok(nft_metadata) } @@ -988,7 +1038,7 @@ fn construct_camo_url_with_token(token_uri: &str, url_antispam: &Url) -> Option< } async fn fetch_meta_from_url(url: Url) -> MmResult { - let response_meta = send_request_to_uri(url.as_str(), None).await?; + let response_meta = send_request_to_uri(url.as_str(), None).await.map_mm_err()?; serde_json::from_value(response_meta).map_err(|e| e.into()) } @@ -1019,7 +1069,10 @@ async fn update_nft_list( wrapper: &UrlSignWrapper<'_>, ) -> MmResult<(), UpdateNftError> { let chain = wrapper.chain; - let transfers = storage.get_transfers_from_block(*chain, scan_from_block).await?; + let transfers = storage + .get_transfers_from_block(*chain, scan_from_block) + .await + .map_mm_err()?; for transfer in transfers.into_iter() { handle_nft_transfer(storage, wrapper, transfer, wallet_address).await?; } @@ -1056,7 +1109,8 @@ async fn handle_send_erc721 transfer.common.token_address.addr_to_string(), transfer.token_id.clone(), ) - .await? + .await + .map_mm_err()? .ok_or_else(|| UpdateNftError::TokenNotFoundInWallet { token_address: transfer.common.token_address.addr_to_string(), token_id: transfer.token_id.to_string(), @@ -1068,7 +1122,8 @@ async fn handle_send_erc721 transfer.token_id, transfer.block_number, ) - .await?; + .await + .map_mm_err()?; Ok(()) } @@ -1082,7 +1137,8 @@ async fn handle_receive_erc721 { // An error is raised if user tries to receive an identical ERC-721 token they already own @@ -1095,7 +1151,8 @@ async fn handle_receive_erc721 { @@ -1116,7 +1173,8 @@ async fn handle_receive_erc721 { storage .remove_nft_from_list(chain, token_address_str, transfer.token_id, transfer.block_number) - .await?; + .await + .map_mm_err()?; }, Ordering::Greater => { nft_db.common.amount -= transfer.common.amount; storage .update_nft_amount(chain, nft_db.clone(), transfer.block_number) - .await?; + .await + .map_mm_err()?; }, Ordering::Less => { return MmError::err(UpdateNftError::InsufficientAmountInCache { @@ -1168,7 +1229,8 @@ async fn handle_receive_erc1155 { // if owner address == from address, then owner sent tokens to themself, @@ -1180,7 +1242,8 @@ async fn handle_receive_erc1155 MmResult { let token_uri = check_moralis_ipfs_bafy(moralis_meta.common.token_uri.as_deref()); let token_domain = get_domain_from_url(token_uri.as_deref()); - check_token_uri(&mut moralis_meta.common.possible_spam, token_uri.as_deref())?; + check_token_uri(&mut moralis_meta.common.possible_spam, token_uri.as_deref()).map_mm_err()?; let uri_meta = get_uri_meta( token_uri.as_deref(), moralis_meta.common.metadata.as_deref(), @@ -1268,10 +1332,12 @@ async fn mark_as_spam_and_build_empty_meta MmResult { storage .update_nft_spam_by_token_address(chain, token_address_str.clone(), true) - .await?; + .await + .map_mm_err()?; storage .update_transfer_spam_by_token_address(chain, token_address_str, true) - .await?; + .await + .map_mm_err()?; Ok(build_nft_with_empty_meta(BuildNftFields { token_address: transfer.common.token_address, @@ -1290,13 +1356,15 @@ async fn cache_nfts_from_moralis, ) -> MmResult, UpdateNftError> { - let nft_list = get_moralis_nft_list(wallet_address, wrapper).await?; + let nft_list = get_moralis_nft_list(wallet_address, wrapper).await.map_mm_err()?; let last_scanned_block = NftTransferHistoryStorageOps::get_last_block_number(storage, wrapper.chain) - .await? + .await + .map_mm_err()? .unwrap_or(0); storage .add_nfts_to_list(*wrapper.chain, nft_list.clone(), last_scanned_block) - .await?; + .await + .map_mm_err()?; Ok(nft_list) } @@ -1317,7 +1385,7 @@ where T: NftListStorageOps + NftTransferHistoryStorageOps, { let chain = wrapper.chain; - let token_addr_id = storage.get_transfers_with_empty_meta(*chain).await?; + let token_addr_id = storage.get_transfers_with_empty_meta(*chain).await.map_mm_err()?; for addr_id_pair in token_addr_id.into_iter() { let mut nft_meta = match get_moralis_metadata(addr_id_pair.token_address.clone(), addr_id_pair.token_id, wrapper).await { @@ -1325,10 +1393,12 @@ where Err(_) => { storage .update_nft_spam_by_token_address(chain, addr_id_pair.token_address.clone(), true) - .await?; + .await + .map_mm_err()?; storage .update_transfer_spam_by_token_address(chain, addr_id_pair.token_address, true) - .await?; + .await + .map_mm_err()?; continue; }, }; @@ -1506,9 +1576,9 @@ pub(crate) fn get_domain_from_url(url: Option<&str>) -> Option { pub async fn clear_nft_db(ctx: MmArc, req: ClearNftDbReq) -> MmResult<(), ClearNftDbError> { if req.clear_all { let nft_ctx = NftCtx::from_ctx(&ctx).map_to_mm(ClearNftDbError::Internal)?; - let storage = nft_ctx.lock_db().await?; - storage.clear_all_nft_data().await?; - storage.clear_all_history_data().await?; + let storage = nft_ctx.lock_db().await.map_mm_err()?; + storage.clear_all_nft_data().await.map_mm_err()?; + storage.clear_all_history_data().await.map_mm_err()?; return Ok(()); } @@ -1519,7 +1589,7 @@ pub async fn clear_nft_db(ctx: MmArc, req: ClearNftDbReq) -> MmResult<(), ClearN } let nft_ctx = NftCtx::from_ctx(&ctx).map_to_mm(ClearNftDbError::Internal)?; - let storage = nft_ctx.lock_db().await?; + let storage = nft_ctx.lock_db().await.map_mm_err()?; let mut errors = Vec::new(); for chain in req.chains.iter() { if let Err(e) = clear_data_for_chain(&storage, chain).await { @@ -1538,14 +1608,16 @@ where T: NftListStorageOps + NftTransferHistoryStorageOps, { let (is_nft_list_init, is_history_init) = ( - NftListStorageOps::is_initialized(storage, chain).await?, - NftTransferHistoryStorageOps::is_initialized(storage, chain).await?, + NftListStorageOps::is_initialized(storage, chain).await.map_mm_err()?, + NftTransferHistoryStorageOps::is_initialized(storage, chain) + .await + .map_mm_err()?, ); if is_nft_list_init { - storage.clear_nft_data(chain).await?; + storage.clear_nft_data(chain).await.map_mm_err()?; } if is_history_init { - storage.clear_history_data(chain).await?; + storage.clear_history_data(chain).await.map_mm_err()?; } Ok(()) } @@ -1574,6 +1646,6 @@ struct UrlSignWrapper<'a> { async fn build_and_send_request(uri: &str, proxy_sign: &Option) -> MmResult { let payload = proxy_sign.as_ref().map(|msg| serde_json::to_string(&msg)).transpose()?; - let response = send_request_to_uri(uri, payload.as_deref()).await?; + let response = send_request_to_uri(uri, payload.as_deref()).await.map_mm_err()?; Ok(response) } diff --git a/mm2src/coins/nft/storage/mod.rs b/mm2src/coins/nft/storage/mod.rs index 3eed941b5d..de61d04a40 100644 --- a/mm2src/coins/nft/storage/mod.rs +++ b/mm2src/coins/nft/storage/mod.rs @@ -4,7 +4,7 @@ use crate::nft::nft_structs::{Chain, Nft, NftList, NftListFilters, NftTokenAddrI use async_trait::async_trait; use ethereum_types::Address; use mm2_err_handle::mm_error::MmResult; -use mm2_err_handle::mm_error::{NotEqual, NotMmError}; +use mm2_err_handle::mm_error::NotMmError; use mm2_number::{BigDecimal, BigUint}; use serde::{Deserialize, Serialize}; use std::collections::HashSet; @@ -25,7 +25,7 @@ pub enum RemoveNftResult { } /// Defines the standard errors that can occur in NFT storage operations -pub trait NftStorageError: std::fmt::Debug + NotMmError + NotEqual + Send {} +pub trait NftStorageError: std::fmt::Debug + NotMmError + Send {} /// Provides asynchronous operations for handling and querying NFT listings. #[async_trait] diff --git a/mm2src/coins/nft/storage/sql_storage.rs b/mm2src/coins/nft/storage/sql_storage.rs index c3e575b321..1829f8d500 100644 --- a/mm2src/coins/nft/storage/sql_storage.rs +++ b/mm2src/coins/nft/storage/sql_storage.rs @@ -605,7 +605,7 @@ impl NftListStorageOps for AsyncMutexGuard<'_, AsyncConnection> { type Error = AsyncConnError; async fn init(&self, chain: &Chain) -> MmResult<(), Self::Error> { - let sql_nft_list = create_nft_list_table_sql(chain)?; + let sql_nft_list = create_nft_list_table_sql(chain).map_mm_err()?; self.call(move |conn| { conn.execute(&sql_nft_list, []).map(|_| ())?; conn.execute(&create_scanned_nft_blocks_sql()?, []).map(|_| ())?; @@ -843,7 +843,7 @@ impl NftListStorageOps for AsyncMutexGuard<'_, AsyncConnection> { } async fn get_last_scanned_block(&self, chain: &Chain) -> MmResult, Self::Error> { - let sql = select_last_scanned_block_sql()?; + let sql = select_last_scanned_block_sql().map_mm_err()?; let params = [chain.to_ticker()]; self.call(move |conn| { let block_number = query_single_row(conn, &sql, params, block_number_from_row)?; diff --git a/mm2src/coins/nft/storage/wasm/wasm_storage.rs b/mm2src/coins/nft/storage/wasm/wasm_storage.rs index 5ad0190179..47e16870e0 100644 --- a/mm2src/coins/nft/storage/wasm/wasm_storage.rs +++ b/mm2src/coins/nft/storage/wasm/wasm_storage.rs @@ -8,8 +8,7 @@ use crate::nft::storage::{get_offset_limit, NftListStorageOps, NftTokenAddrId, N use async_trait::async_trait; use ethereum_types::Address; use mm2_db::indexed_db::{BeBigUint, DbTable, DbUpgrader, MultiIndex, OnUpgradeError, OnUpgradeResult, TableSignature}; -use mm2_err_handle::map_to_mm::MapToMmResult; -use mm2_err_handle::prelude::{MmError, MmResult}; +use mm2_err_handle::prelude::*; use mm2_number::BigUint; use num_traits::ToPrimitive; use serde_json::{self as json, Value as Json}; @@ -144,13 +143,14 @@ impl NftListStorageOps for NftCacheIDBLocked<'_> { page_number: Option, filters: Option, ) -> MmResult { - let db_transaction = self.get_inner().transaction().await?; - let table = db_transaction.table::().await?; + let db_transaction = self.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; let mut nfts = Vec::new(); for chain in chains { let nft_tables = table .get_items("chain", chain.to_string()) - .await? + .await + .map_mm_err()? .into_iter() .map(|(_item_id, nft)| nft); let filtered = filter_nfts(nft_tables, filters)?; @@ -164,12 +164,12 @@ impl NftListStorageOps for NftCacheIDBLocked<'_> { I: IntoIterator + Send + 'static, I::IntoIter: Send, { - let db_transaction = self.get_inner().transaction().await?; - let nft_table = db_transaction.table::().await?; - let last_scanned_block_table = db_transaction.table::().await?; + let db_transaction = self.get_inner().transaction().await.map_mm_err()?; + let nft_table = db_transaction.table::().await.map_mm_err()?; + let last_scanned_block_table = db_transaction.table::().await.map_mm_err()?; for nft in nfts { let nft_item = NftListTable::from_nft(&nft)?; - nft_table.add_item(&nft_item).await?; + nft_table.add_item(&nft_item).await.map_mm_err()?; } let last_scanned_block = LastScannedBlockTable { chain: chain.to_string(), @@ -177,7 +177,8 @@ impl NftListStorageOps for NftCacheIDBLocked<'_> { }; last_scanned_block_table .replace_item_by_unique_index("chain", chain.to_string(), &last_scanned_block) - .await?; + .await + .map_mm_err()?; Ok(()) } @@ -187,14 +188,17 @@ impl NftListStorageOps for NftCacheIDBLocked<'_> { token_address: String, token_id: BigUint, ) -> MmResult, Self::Error> { - let db_transaction = self.get_inner().transaction().await?; - let table = db_transaction.table::().await?; + let db_transaction = self.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; let index_keys = MultiIndex::new(CHAIN_TOKEN_ADD_TOKEN_ID_INDEX) - .with_value(chain.to_string())? - .with_value(&token_address)? - .with_value(BeBigUint::from(token_id))?; - - if let Some((_item_id, item)) = table.get_item_by_unique_multi_index(index_keys).await? { + .with_value(chain.to_string()) + .map_mm_err()? + .with_value(&token_address) + .map_mm_err()? + .with_value(BeBigUint::from(token_id)) + .map_mm_err()?; + + if let Some((_item_id, item)) = table.get_item_by_unique_multi_index(index_keys).await.map_mm_err()? { Ok(Some(nft_details_from_item(item)?)) } else { Ok(None) @@ -208,24 +212,32 @@ impl NftListStorageOps for NftCacheIDBLocked<'_> { token_id: BigUint, scanned_block: u64, ) -> MmResult { - let db_transaction = self.get_inner().transaction().await?; - let nft_table = db_transaction.table::().await?; - let last_scanned_block_table = db_transaction.table::().await?; + let db_transaction = self.get_inner().transaction().await.map_mm_err()?; + let nft_table = db_transaction.table::().await.map_mm_err()?; + let last_scanned_block_table = db_transaction.table::().await.map_mm_err()?; let index_keys = MultiIndex::new(CHAIN_TOKEN_ADD_TOKEN_ID_INDEX) - .with_value(chain.to_string())? - .with_value(&token_address)? - .with_value(BeBigUint::from(token_id))?; + .with_value(chain.to_string()) + .map_mm_err()? + .with_value(&token_address) + .map_mm_err()? + .with_value(BeBigUint::from(token_id)) + .map_mm_err()?; let last_scanned_block = LastScannedBlockTable { chain: chain.to_string(), last_scanned_block: BeBigUint::from(scanned_block), }; - let nft_removed = nft_table.delete_item_by_unique_multi_index(index_keys).await?.is_some(); + let nft_removed = nft_table + .delete_item_by_unique_multi_index(index_keys) + .await + .map_mm_err()? + .is_some(); last_scanned_block_table .replace_item_by_unique_index("chain", chain.to_string(), &last_scanned_block) - .await?; + .await + .map_mm_err()?; if nft_removed { Ok(RemoveNftResult::NftRemoved) } else { @@ -239,14 +251,17 @@ impl NftListStorageOps for NftCacheIDBLocked<'_> { token_address: String, token_id: BigUint, ) -> MmResult, Self::Error> { - let db_transaction = self.get_inner().transaction().await?; - let table = db_transaction.table::().await?; + let db_transaction = self.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; let index_keys = MultiIndex::new(CHAIN_TOKEN_ADD_TOKEN_ID_INDEX) - .with_value(chain.to_string())? - .with_value(&token_address)? - .with_value(BeBigUint::from(token_id))?; - - if let Some((_item_id, item)) = table.get_item_by_unique_multi_index(index_keys).await? { + .with_value(chain.to_string()) + .map_mm_err()? + .with_value(&token_address) + .map_mm_err()? + .with_value(BeBigUint::from(token_id)) + .map_mm_err()?; + + if let Some((_item_id, item)) = table.get_item_by_unique_multi_index(index_keys).await.map_mm_err()? { Ok(Some(nft_details_from_item(item)?.common.amount.to_string())) } else { Ok(None) @@ -254,28 +269,38 @@ impl NftListStorageOps for NftCacheIDBLocked<'_> { } async fn refresh_nft_metadata(&self, chain: &Chain, nft: Nft) -> MmResult<(), Self::Error> { - let db_transaction = self.get_inner().transaction().await?; - let table = db_transaction.table::().await?; + let db_transaction = self.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; let index_keys = MultiIndex::new(CHAIN_TOKEN_ADD_TOKEN_ID_INDEX) - .with_value(chain.to_string())? - .with_value(nft.common.token_address.addr_to_string())? - .with_value(BeBigUint::from(nft.token_id.clone()))?; + .with_value(chain.to_string()) + .map_mm_err()? + .with_value(nft.common.token_address.addr_to_string()) + .map_mm_err()? + .with_value(BeBigUint::from(nft.token_id.clone())) + .map_mm_err()?; let nft_item = NftListTable::from_nft(&nft)?; - table.replace_item_by_unique_multi_index(index_keys, &nft_item).await?; + table + .replace_item_by_unique_multi_index(index_keys, &nft_item) + .await + .map_mm_err()?; Ok(()) } async fn get_last_block_number(&self, chain: &Chain) -> MmResult, Self::Error> { - let db_transaction = self.get_inner().transaction().await?; - let table = db_transaction.table::().await?; + let db_transaction = self.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; get_last_block_from_table(chain, table, CHAIN_BLOCK_NUMBER_INDEX).await } async fn get_last_scanned_block(&self, chain: &Chain) -> MmResult, Self::Error> { - let db_transaction = self.get_inner().transaction().await?; - let table = db_transaction.table::().await?; - if let Some((_item_id, item)) = table.get_item_by_unique_index("chain", chain.to_string()).await? { + let db_transaction = self.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; + if let Some((_item_id, item)) = table + .get_item_by_unique_index("chain", chain.to_string()) + .await + .map_mm_err()? + { let last_scanned_block = item .last_scanned_block .to_u64() @@ -287,64 +312,77 @@ impl NftListStorageOps for NftCacheIDBLocked<'_> { } async fn update_nft_amount(&self, chain: &Chain, nft: Nft, scanned_block: u64) -> MmResult<(), Self::Error> { - let db_transaction = self.get_inner().transaction().await?; - let nft_table = db_transaction.table::().await?; - let last_scanned_block_table = db_transaction.table::().await?; + let db_transaction = self.get_inner().transaction().await.map_mm_err()?; + let nft_table = db_transaction.table::().await.map_mm_err()?; + let last_scanned_block_table = db_transaction.table::().await.map_mm_err()?; let index_keys = MultiIndex::new(CHAIN_TOKEN_ADD_TOKEN_ID_INDEX) - .with_value(chain.to_string())? - .with_value(nft.common.token_address.addr_to_string())? - .with_value(BeBigUint::from(nft.token_id.clone()))?; + .with_value(chain.to_string()) + .map_mm_err()? + .with_value(nft.common.token_address.addr_to_string()) + .map_mm_err()? + .with_value(BeBigUint::from(nft.token_id.clone())) + .map_mm_err()?; let nft_item = NftListTable::from_nft(&nft)?; nft_table .replace_item_by_unique_multi_index(index_keys, &nft_item) - .await?; + .await + .map_mm_err()?; let last_scanned_block = LastScannedBlockTable { chain: chain.to_string(), last_scanned_block: BeBigUint::from(scanned_block), }; last_scanned_block_table .replace_item_by_unique_index("chain", chain.to_string(), &last_scanned_block) - .await?; + .await + .map_mm_err()?; Ok(()) } async fn update_nft_amount_and_block_number(&self, chain: &Chain, nft: Nft) -> MmResult<(), Self::Error> { - let db_transaction = self.get_inner().transaction().await?; - let nft_table = db_transaction.table::().await?; - let last_scanned_block_table = db_transaction.table::().await?; + let db_transaction = self.get_inner().transaction().await.map_mm_err()?; + let nft_table = db_transaction.table::().await.map_mm_err()?; + let last_scanned_block_table = db_transaction.table::().await.map_mm_err()?; let index_keys = MultiIndex::new(CHAIN_TOKEN_ADD_TOKEN_ID_INDEX) - .with_value(chain.to_string())? - .with_value(nft.common.token_address.addr_to_string())? - .with_value(BeBigUint::from(nft.token_id.clone()))?; + .with_value(chain.to_string()) + .map_mm_err()? + .with_value(nft.common.token_address.addr_to_string()) + .map_mm_err()? + .with_value(BeBigUint::from(nft.token_id.clone())) + .map_mm_err()?; let nft_item = NftListTable::from_nft(&nft)?; nft_table .replace_item_by_unique_multi_index(index_keys, &nft_item) - .await?; + .await + .map_mm_err()?; let last_scanned_block = LastScannedBlockTable { chain: chain.to_string(), last_scanned_block: BeBigUint::from(nft.block_number), }; last_scanned_block_table .replace_item_by_unique_index("chain", chain.to_string(), &last_scanned_block) - .await?; + .await + .map_mm_err()?; Ok(()) } async fn get_nfts_by_token_address(&self, chain: Chain, token_address: String) -> MmResult, Self::Error> { - let db_transaction = self.get_inner().transaction().await?; - let table = db_transaction.table::().await?; + let db_transaction = self.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; let index_keys = MultiIndex::new(CHAIN_TOKEN_ADD_INDEX) - .with_value(chain.to_string())? - .with_value(&token_address)?; + .with_value(chain.to_string()) + .map_mm_err()? + .with_value(&token_address) + .map_mm_err()?; table .get_items_by_multi_index(index_keys) - .await? + .await + .map_mm_err()? .into_iter() .map(|(_item_id, item)| nft_details_from_item(item)) .collect() @@ -356,17 +394,20 @@ impl NftListStorageOps for NftCacheIDBLocked<'_> { token_address: String, possible_spam: bool, ) -> MmResult<(), Self::Error> { - let db_transaction = self.get_inner().transaction().await?; - let table = db_transaction.table::().await?; + let db_transaction = self.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; let chain_str = chain.to_string(); let index_keys = MultiIndex::new(CHAIN_TOKEN_ADD_INDEX) - .with_value(&chain_str)? - .with_value(&token_address)?; + .with_value(&chain_str) + .map_mm_err()? + .with_value(&token_address) + .map_mm_err()?; let nfts: Result, _> = table .get_items_by_multi_index(index_keys) - .await? + .await + .map_mm_err()? .into_iter() .map(|(_item_id, item)| nft_details_from_item(item)) .collect(); @@ -377,22 +418,28 @@ impl NftListStorageOps for NftCacheIDBLocked<'_> { drop_mutability!(nft); let index_keys = MultiIndex::new(CHAIN_TOKEN_ADD_TOKEN_ID_INDEX) - .with_value(&chain_str)? - .with_value(nft.common.token_address.addr_to_string())? - .with_value(BeBigUint::from(nft.token_id.clone()))?; + .with_value(&chain_str) + .map_mm_err()? + .with_value(nft.common.token_address.addr_to_string()) + .map_mm_err()? + .with_value(BeBigUint::from(nft.token_id.clone())) + .map_mm_err()?; let item = NftListTable::from_nft(&nft)?; - table.replace_item_by_unique_multi_index(index_keys, &item).await?; + table + .replace_item_by_unique_multi_index(index_keys, &item) + .await + .map_mm_err()?; } Ok(()) } async fn get_animation_external_domains(&self, chain: &Chain) -> MmResult, Self::Error> { - let db_transaction = self.get_inner().transaction().await?; - let table = db_transaction.table::().await?; + let db_transaction = self.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; let mut domains = HashSet::new(); - let nft_tables = table.get_items("chain", chain.to_string()).await?; + let nft_tables = table.get_items("chain", chain.to_string()).await.map_mm_err()?; for (_item_id, nft) in nft_tables.into_iter() { if let Some(domain) = nft.animation_domain { domains.insert(domain); @@ -410,8 +457,8 @@ impl NftListStorageOps for NftCacheIDBLocked<'_> { domain: String, possible_phishing: bool, ) -> MmResult<(), Self::Error> { - let db_transaction = self.get_inner().transaction().await?; - let table = db_transaction.table::().await?; + let db_transaction = self.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; let chain_str = chain.to_string(); update_nft_phishing_for_index(&table, &chain_str, CHAIN_TOKEN_DOMAIN_INDEX, &domain, possible_phishing).await?; @@ -424,23 +471,27 @@ impl NftListStorageOps for NftCacheIDBLocked<'_> { } async fn clear_nft_data(&self, chain: &Chain) -> MmResult<(), Self::Error> { - let db_transaction = self.get_inner().transaction().await?; - let nft_table = db_transaction.table::().await?; - let last_scanned_block_table = db_transaction.table::().await?; + let db_transaction = self.get_inner().transaction().await.map_mm_err()?; + let nft_table = db_transaction.table::().await.map_mm_err()?; + let last_scanned_block_table = db_transaction.table::().await.map_mm_err()?; - nft_table.delete_items_by_index("chain", chain.to_string()).await?; + nft_table + .delete_items_by_index("chain", chain.to_string()) + .await + .map_mm_err()?; last_scanned_block_table .delete_item_by_unique_index("chain", chain.to_string()) - .await?; + .await + .map_mm_err()?; Ok(()) } async fn clear_all_nft_data(&self) -> MmResult<(), Self::Error> { - let db_transaction = self.get_inner().transaction().await?; - let nft_table = db_transaction.table::().await?; - let last_scanned_block_table = db_transaction.table::().await?; - nft_table.clear().await?; - last_scanned_block_table.clear().await?; + let db_transaction = self.get_inner().transaction().await.map_mm_err()?; + let nft_table = db_transaction.table::().await.map_mm_err()?; + let last_scanned_block_table = db_transaction.table::().await.map_mm_err()?; + nft_table.clear().await.map_mm_err()?; + last_scanned_block_table.clear().await.map_mm_err()?; Ok(()) } } @@ -461,13 +512,14 @@ impl NftTransferHistoryStorageOps for NftCacheIDBLocked<'_> { page_number: Option, filters: Option, ) -> MmResult { - let db_transaction = self.get_inner().transaction().await?; - let table = db_transaction.table::().await?; + let db_transaction = self.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; let mut transfers = Vec::new(); for chain in chains { let transfer_tables = table .get_items("chain", chain.to_string()) - .await? + .await + .map_mm_err()? .into_iter() .map(|(_item_id, transfer)| transfer); let filtered = filter_transfers(transfer_tables, filters)?; @@ -481,18 +533,18 @@ impl NftTransferHistoryStorageOps for NftCacheIDBLocked<'_> { I: IntoIterator + Send + 'static, I::IntoIter: Send, { - let db_transaction = self.get_inner().transaction().await?; - let table = db_transaction.table::().await?; + let db_transaction = self.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; for transfer in transfers { let transfer_item = NftTransferHistoryTable::from_transfer_history(&transfer)?; - table.add_item(&transfer_item).await?; + table.add_item(&transfer_item).await.map_mm_err()?; } Ok(()) } async fn get_last_block_number(&self, chain: &Chain) -> MmResult, Self::Error> { - let db_transaction = self.get_inner().transaction().await?; - let table = db_transaction.table::().await?; + let db_transaction = self.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; get_last_block_from_table(chain, table, CHAIN_BLOCK_NUMBER_INDEX).await } @@ -501,8 +553,8 @@ impl NftTransferHistoryStorageOps for NftCacheIDBLocked<'_> { chain: Chain, from_block: u64, ) -> MmResult, Self::Error> { - let db_transaction = self.get_inner().transaction().await?; - let table = db_transaction.table::().await?; + let db_transaction = self.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; let mut cursor_iter = table .cursor_builder() .only("chain", chain.to_string()) @@ -530,17 +582,21 @@ impl NftTransferHistoryStorageOps for NftCacheIDBLocked<'_> { token_address: String, token_id: BigUint, ) -> MmResult, Self::Error> { - let db_transaction = self.get_inner().transaction().await?; - let table = db_transaction.table::().await?; + let db_transaction = self.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; let index_keys = MultiIndex::new(CHAIN_TOKEN_ADD_TOKEN_ID_INDEX) - .with_value(chain.to_string())? - .with_value(&token_address)? - .with_value(BeBigUint::from(token_id))?; + .with_value(chain.to_string()) + .map_mm_err()? + .with_value(&token_address) + .map_mm_err()? + .with_value(BeBigUint::from(token_id)) + .map_mm_err()?; table .get_items_by_multi_index(index_keys) - .await? + .await + .map_mm_err()? .into_iter() .map(|(_item_id, item)| transfer_details_from_item(item)) .collect() @@ -553,15 +609,19 @@ impl NftTransferHistoryStorageOps for NftCacheIDBLocked<'_> { log_index: u32, token_id: BigUint, ) -> MmResult, Self::Error> { - let db_transaction = self.get_inner().transaction().await?; - let table = db_transaction.table::().await?; + let db_transaction = self.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; let index_keys = MultiIndex::new(NftTransferHistoryTable::CHAIN_TX_HASH_LOG_INDEX_TOKEN_ID_INDEX) - .with_value(chain.to_string())? - .with_value(&transaction_hash)? - .with_value(log_index)? - .with_value(BeBigUint::from(token_id))?; - - if let Some((_item_id, item)) = table.get_item_by_unique_multi_index(index_keys).await? { + .with_value(chain.to_string()) + .map_mm_err()? + .with_value(&transaction_hash) + .map_mm_err()? + .with_value(log_index) + .map_mm_err()? + .with_value(BeBigUint::from(token_id)) + .map_mm_err()?; + + if let Some((_item_id, item)) = table.get_item_by_unique_multi_index(index_keys).await.map_mm_err()? { Ok(Some(transfer_details_from_item(item)?)) } else { Ok(None) @@ -574,18 +634,22 @@ impl NftTransferHistoryStorageOps for NftCacheIDBLocked<'_> { transfer_meta: TransferMeta, set_spam: bool, ) -> MmResult<(), Self::Error> { - let db_transaction = self.get_inner().transaction().await?; - let table = db_transaction.table::().await?; + let db_transaction = self.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; let chain_str = chain.to_string(); let index_keys = MultiIndex::new(CHAIN_TOKEN_ADD_TOKEN_ID_INDEX) - .with_value(&chain_str)? - .with_value(&transfer_meta.token_address)? - .with_value(BeBigUint::from(transfer_meta.token_id))?; + .with_value(&chain_str) + .map_mm_err()? + .with_value(&transfer_meta.token_address) + .map_mm_err()? + .with_value(BeBigUint::from(transfer_meta.token_id)) + .map_mm_err()?; let transfers: Result, _> = table .get_items_by_multi_index(index_keys) - .await? + .await + .map_mm_err()? .into_iter() .map(|(_item_id, item)| transfer_details_from_item(item)) .collect(); @@ -604,20 +668,27 @@ impl NftTransferHistoryStorageOps for NftCacheIDBLocked<'_> { drop_mutability!(transfer); let index_keys = MultiIndex::new(NftTransferHistoryTable::CHAIN_TX_HASH_LOG_INDEX_TOKEN_ID_INDEX) - .with_value(&chain_str)? - .with_value(&transfer.common.transaction_hash)? - .with_value(transfer.common.log_index)? - .with_value(BeBigUint::from(transfer.token_id.clone()))?; + .with_value(&chain_str) + .map_mm_err()? + .with_value(&transfer.common.transaction_hash) + .map_mm_err()? + .with_value(transfer.common.log_index) + .map_mm_err()? + .with_value(BeBigUint::from(transfer.token_id.clone())) + .map_mm_err()?; let item = NftTransferHistoryTable::from_transfer_history(&transfer)?; - table.replace_item_by_unique_multi_index(index_keys, &item).await?; + table + .replace_item_by_unique_multi_index(index_keys, &item) + .await + .map_mm_err()?; } Ok(()) } async fn get_transfers_with_empty_meta(&self, chain: Chain) -> MmResult, Self::Error> { - let db_transaction = self.get_inner().transaction().await?; - let table = db_transaction.table::().await?; + let db_transaction = self.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; let mut cursor_iter = table .cursor_builder() .only("chain", chain.to_string()) @@ -652,16 +723,19 @@ impl NftTransferHistoryStorageOps for NftCacheIDBLocked<'_> { chain: Chain, token_address: String, ) -> MmResult, Self::Error> { - let db_transaction = self.get_inner().transaction().await?; - let table = db_transaction.table::().await?; + let db_transaction = self.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; let index_keys = MultiIndex::new(CHAIN_TOKEN_ADD_INDEX) - .with_value(chain.to_string())? - .with_value(&token_address)?; + .with_value(chain.to_string()) + .map_mm_err()? + .with_value(&token_address) + .map_mm_err()?; table .get_items_by_multi_index(index_keys) - .await? + .await + .map_mm_err()? .into_iter() .map(|(_item_id, item)| transfer_details_from_item(item)) .collect() @@ -673,17 +747,20 @@ impl NftTransferHistoryStorageOps for NftCacheIDBLocked<'_> { token_address: String, possible_spam: bool, ) -> MmResult<(), Self::Error> { - let db_transaction = self.get_inner().transaction().await?; - let table = db_transaction.table::().await?; + let db_transaction = self.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; let chain_str = chain.to_string(); let index_keys = MultiIndex::new(CHAIN_TOKEN_ADD_INDEX) - .with_value(&chain_str)? - .with_value(&token_address)?; + .with_value(&chain_str) + .map_mm_err()? + .with_value(&token_address) + .map_mm_err()?; let transfers: Result, _> = table .get_items_by_multi_index(index_keys) - .await? + .await + .map_mm_err()? .into_iter() .map(|(_item_id, item)| transfer_details_from_item(item)) .collect(); @@ -694,22 +771,29 @@ impl NftTransferHistoryStorageOps for NftCacheIDBLocked<'_> { drop_mutability!(transfer); let index_keys = MultiIndex::new(NftTransferHistoryTable::CHAIN_TX_HASH_LOG_INDEX_TOKEN_ID_INDEX) - .with_value(&chain_str)? - .with_value(&transfer.common.transaction_hash)? - .with_value(transfer.common.log_index)? - .with_value(BeBigUint::from(transfer.token_id.clone()))?; + .with_value(&chain_str) + .map_mm_err()? + .with_value(&transfer.common.transaction_hash) + .map_mm_err()? + .with_value(transfer.common.log_index) + .map_mm_err()? + .with_value(BeBigUint::from(transfer.token_id.clone())) + .map_mm_err()?; let item = NftTransferHistoryTable::from_transfer_history(&transfer)?; - table.replace_item_by_unique_multi_index(index_keys, &item).await?; + table + .replace_item_by_unique_multi_index(index_keys, &item) + .await + .map_mm_err()?; } Ok(()) } async fn get_token_addresses(&self, chain: Chain) -> MmResult, Self::Error> { - let db_transaction = self.get_inner().transaction().await?; - let table = db_transaction.table::().await?; + let db_transaction = self.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; - let items = table.get_items("chain", chain.to_string()).await?; + let items = table.get_items("chain", chain.to_string()).await.map_mm_err()?; let mut token_addresses = HashSet::with_capacity(items.len()); for (_item_id, item) in items.into_iter() { let transfer = transfer_details_from_item(item)?; @@ -719,11 +803,11 @@ impl NftTransferHistoryStorageOps for NftCacheIDBLocked<'_> { } async fn get_domains(&self, chain: &Chain) -> MmResult, Self::Error> { - let db_transaction = self.get_inner().transaction().await?; - let table = db_transaction.table::().await?; + let db_transaction = self.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; let mut domains = HashSet::new(); - let transfer_tables = table.get_items("chain", chain.to_string()).await?; + let transfer_tables = table.get_items("chain", chain.to_string()).await.map_mm_err()?; for (_item_id, transfer) in transfer_tables.into_iter() { if let Some(domain) = transfer.token_domain { domains.insert(domain); @@ -741,8 +825,8 @@ impl NftTransferHistoryStorageOps for NftCacheIDBLocked<'_> { domain: String, possible_phishing: bool, ) -> MmResult<(), Self::Error> { - let db_transaction = self.get_inner().transaction().await?; - let table = db_transaction.table::().await?; + let db_transaction = self.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; let chain_str = chain.to_string(); update_transfer_phishing_for_index(&table, &chain_str, CHAIN_TOKEN_DOMAIN_INDEX, &domain, possible_phishing) .await?; @@ -752,16 +836,19 @@ impl NftTransferHistoryStorageOps for NftCacheIDBLocked<'_> { } async fn clear_history_data(&self, chain: &Chain) -> MmResult<(), Self::Error> { - let db_transaction = self.get_inner().transaction().await?; - let table = db_transaction.table::().await?; - table.delete_items_by_index("chain", chain.to_string()).await?; + let db_transaction = self.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; + table + .delete_items_by_index("chain", chain.to_string()) + .await + .map_mm_err()?; Ok(()) } async fn clear_all_history_data(&self) -> MmResult<(), Self::Error> { - let db_transaction = self.get_inner().transaction().await?; - let table = db_transaction.table::().await?; - table.clear().await?; + let db_transaction = self.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; + table.clear().await.map_mm_err()?; Ok(()) } } @@ -773,21 +860,30 @@ async fn update_transfer_phishing_for_index( domain: &str, possible_phishing: bool, ) -> MmResult<(), WasmNftCacheError> { - let index_keys = MultiIndex::new(index).with_value(chain)?.with_value(domain)?; - let transfers_table = table.get_items_by_multi_index(index_keys).await?; + let index_keys = MultiIndex::new(index) + .with_value(chain) + .map_mm_err()? + .with_value(domain) + .map_mm_err()?; + let transfers_table = table.get_items_by_multi_index(index_keys).await.map_mm_err()?; for (_item_id, item) in transfers_table.into_iter() { let mut transfer = transfer_details_from_item(item)?; transfer.possible_phishing = possible_phishing; drop_mutability!(transfer); let transfer_item = NftTransferHistoryTable::from_transfer_history(&transfer)?; let index_keys = MultiIndex::new(NftTransferHistoryTable::CHAIN_TX_HASH_LOG_INDEX_TOKEN_ID_INDEX) - .with_value(chain)? - .with_value(&transfer.common.transaction_hash)? - .with_value(transfer.common.log_index)? - .with_value(BeBigUint::from(transfer.token_id))?; + .with_value(chain) + .map_mm_err()? + .with_value(&transfer.common.transaction_hash) + .map_mm_err()? + .with_value(transfer.common.log_index) + .map_mm_err()? + .with_value(BeBigUint::from(transfer.token_id)) + .map_mm_err()?; table .replace_item_by_unique_multi_index(index_keys, &transfer_item) - .await?; + .await + .map_mm_err()?; } Ok(()) } @@ -799,18 +895,28 @@ async fn update_nft_phishing_for_index( domain: &str, possible_phishing: bool, ) -> MmResult<(), WasmNftCacheError> { - let index_keys = MultiIndex::new(index).with_value(chain)?.with_value(domain)?; - let nfts_table = table.get_items_by_multi_index(index_keys).await?; + let index_keys = MultiIndex::new(index) + .with_value(chain) + .map_mm_err()? + .with_value(domain) + .map_mm_err()?; + let nfts_table = table.get_items_by_multi_index(index_keys).await.map_mm_err()?; for (_item_id, item) in nfts_table.into_iter() { let mut nft = nft_details_from_item(item)?; nft.possible_phishing = possible_phishing; drop_mutability!(nft); let nft_item = NftListTable::from_nft(&nft)?; let index_keys = MultiIndex::new(CHAIN_TOKEN_ADD_TOKEN_ID_INDEX) - .with_value(chain)? - .with_value(nft.common.token_address.addr_to_string())? - .with_value(BeBigUint::from(nft.token_id))?; - table.replace_item_by_unique_multi_index(index_keys, &nft_item).await?; + .with_value(chain) + .map_mm_err()? + .with_value(nft.common.token_address.addr_to_string()) + .map_mm_err()? + .with_value(BeBigUint::from(nft.token_id)) + .map_mm_err()?; + table + .replace_item_by_unique_multi_index(index_keys, &nft_item) + .await + .map_mm_err()?; } Ok(()) } diff --git a/mm2src/coins/qrc20.rs b/mm2src/coins/qrc20.rs index 3d6f8660b3..d070ccfed5 100644 --- a/mm2src/coins/qrc20.rs +++ b/mm2src/coins/qrc20.rs @@ -149,7 +149,7 @@ impl Qrc20ActivationParams { .map_to_mm(Qrc20FromLegacyReqErr::InvalidSwapContractAddr)?; let fallback_swap_contract = json::from_value(req["fallback_swap_contract"].clone()) .map_to_mm(Qrc20FromLegacyReqErr::InvalidFallbackSwapContract)?; - let utxo_params = UtxoActivationParams::from_legacy_req(req)?; + let utxo_params = UtxoActivationParams::from_legacy_req(req).map_mm_err()?; Ok(Qrc20ActivationParams { swap_contract_address, fallback_swap_contract, @@ -519,8 +519,8 @@ impl Qrc20Coin { &self, contract_outputs: Vec, ) -> Result> { - let my_address = self.utxo.derivation_method.single_addr_or_err().await?; - let (unspents, _) = self.get_unspent_ordered_list(&my_address).await?; + let my_address = self.utxo.derivation_method.single_addr_or_err().await.map_mm_err()?; + let (unspents, _) = self.get_unspent_ordered_list(&my_address).await.map_mm_err()?; let mut gas_fee = 0; let mut outputs = Vec::with_capacity(contract_outputs.len()); @@ -535,16 +535,18 @@ impl Qrc20Coin { .add_outputs(outputs) .with_gas_fee(gas_fee) .build() - .await?; + .await + .map_mm_err()?; - let key_pair = self.utxo.priv_key_policy.activated_key_or_err()?; + let key_pair = self.utxo.priv_key_policy.activated_key_or_err().map_mm_err()?; let signed = sign_tx( unsigned, key_pair, self.utxo.conf.signature_version, self.utxo.conf.fork_id, - )?; + ) + .map_mm_err()?; Ok(GenerateQrc20TxResult { signed, @@ -853,7 +855,8 @@ impl SwapOps for Qrc20Coin { let fee_addr = self .contract_address_from_raw_pubkey(self.dex_pubkey()) .map_to_mm(ValidatePaymentError::WrongPaymentTx)?; - let expected_value = wei_from_big_decimal(&validate_fee_args.dex_fee.fee_amount().into(), self.utxo.decimals)?; + let expected_value = + wei_from_big_decimal(&validate_fee_args.dex_fee.fee_amount().into(), self.utxo.decimals).map_mm_err()?; self.validate_fee_impl( fee_tx_hash, @@ -1065,9 +1068,10 @@ impl MarketCoinOps for Qrc20Coin { .rpc_client .rpc_contract_call(ViewContractCallType::BalanceOf, &contract_address, ¶ms) .compat() - .await?; + .await + .map_mm_err()?; let spendable = match tokens.first() { - Some(Token::Uint(bal)) => u256_to_big_decimal(*bal, decimals)?, + Some(Token::Uint(bal)) => u256_to_big_decimal(*bal, decimals).map_mm_err()?, _ => { let error = format!("Expected U256 as balanceOf result but got {:?}", tokens); return MmError::err(BalanceError::InvalidResponse(error)); @@ -1216,7 +1220,7 @@ impl MmCoin for Qrc20Coin { let my_balance = U256::max_value(); let value = match value { TradePreimageValue::Exact(value) | TradePreimageValue::UpperBound(value) => { - wei_from_big_decimal(&value, decimals)? + wei_from_big_decimal(&value, decimals).map_mm_err()? }, }; @@ -1231,15 +1235,17 @@ impl MmCoin for Qrc20Coin { receiver_addr, self.swap_contract_address, ) - .await?; + .await + .map_mm_err()?; self.preimage_trade_fee_required_to_send_outputs(erc20_payment_outputs, &stage) .await? }; // Optionally calculate refund fee. let sender_refund_fee = if include_refund_fee { - let sender_refund_output = - self.sender_refund_output(&self.swap_contract_address, swap_id, value, secret_hash, receiver_addr)?; + let sender_refund_output = self + .sender_refund_output(&self.swap_contract_address, swap_id, value, secret_hash, receiver_addr) + .map_mm_err()?; self.preimage_trade_fee_required_to_send_outputs(vec![sender_refund_output], &stage) .await? } else { @@ -1266,8 +1272,9 @@ impl MmCoin for Qrc20Coin { // get the max available value that we can pass into the contract call params // see `generate_contract_call_script_pubkey` let value = u64::MAX.into(); - let output = - selfi.receiver_spend_output(&selfi.swap_contract_address, swap_id, value, secret, sender_addr)?; + let output = selfi + .receiver_spend_output(&selfi.swap_contract_address, swap_id, value, secret, sender_addr) + .map_mm_err()?; let total_fee = selfi .preimage_trade_fee_required_to_send_outputs(vec![output], &stage) @@ -1286,12 +1293,13 @@ impl MmCoin for Qrc20Coin { dex_fee_amount: DexFee, stage: FeeApproxStage, ) -> TradePreimageResult { - let amount = wei_from_big_decimal(&dex_fee_amount.fee_amount().into(), self.utxo.decimals)?; + let amount = wei_from_big_decimal(&dex_fee_amount.fee_amount().into(), self.utxo.decimals).map_mm_err()?; // pass the dummy params let to_addr = H160::default(); - let transfer_output = - self.transfer_output(to_addr, amount, QRC20_GAS_LIMIT_DEFAULT, QRC20_GAS_PRICE_DEFAULT)?; + let transfer_output = self + .transfer_output(to_addr, amount, QRC20_GAS_LIMIT_DEFAULT, QRC20_GAS_PRICE_DEFAULT) + .map_mm_err()?; let total_fee = self .preimage_trade_fee_required_to_send_outputs(vec![transfer_output], &stage) @@ -1381,17 +1389,17 @@ async fn qrc20_withdraw(coin: Qrc20Coin, req: WithdrawRequest) -> WithdrawResult let _utxo_lock = UTXO_LOCK.lock().await; - let qrc20_balance = coin.my_spendable_balance().compat().await?; + let qrc20_balance = coin.my_spendable_balance().compat().await.map_mm_err()?; // the qrc20_amount_sat is used only within smart contract calls let (qrc20_amount_sat, qrc20_amount) = if req.max { - let amount = wei_from_big_decimal(&qrc20_balance, coin.utxo.decimals)?; + let amount = wei_from_big_decimal(&qrc20_balance, coin.utxo.decimals).map_mm_err()?; if amount.is_zero() { return MmError::err(WithdrawError::ZeroBalanceToWithdrawMax); } (amount, qrc20_balance.clone()) } else { - let amount_sat = wei_from_big_decimal(&req.amount, coin.utxo.decimals)?; + let amount_sat = wei_from_big_decimal(&req.amount, coin.utxo.decimals).map_mm_err()?; if req.amount > qrc20_balance { return MmError::err(WithdrawError::NotSufficientBalance { coin: coin.ticker().to_owned(), @@ -1412,8 +1420,10 @@ async fn qrc20_withdraw(coin: Qrc20Coin, req: WithdrawRequest) -> WithdrawResult }; // [`Qrc20Coin::transfer_output`] shouldn't fail if the arguments are correct - let contract_addr = qtum::contract_addr_from_utxo_addr(to_addr.clone())?; - let transfer_output = coin.transfer_output(contract_addr, qrc20_amount_sat, gas_limit, gas_price)?; + let contract_addr = qtum::contract_addr_from_utxo_addr(to_addr.clone()).map_mm_err()?; + let transfer_output = coin + .transfer_output(contract_addr, qrc20_amount_sat, gas_limit, gas_price) + .map_mm_err()?; let outputs = vec![transfer_output]; let GenerateQrc20TxResult { @@ -1425,7 +1435,7 @@ async fn qrc20_withdraw(coin: Qrc20Coin, req: WithdrawRequest) -> WithdrawResult .await .mm_err(|gen_tx_error| gen_tx_error.into_withdraw_error(coin.platform.clone(), coin.utxo.decimals))?; - let my_address = coin.utxo.derivation_method.single_addr_or_err().await?; + let my_address = coin.utxo.derivation_method.single_addr_or_err().await.map_mm_err()?; let received_by_me = if to_addr == my_address { qrc20_amount.clone() } else { @@ -1434,7 +1444,7 @@ async fn qrc20_withdraw(coin: Qrc20Coin, req: WithdrawRequest) -> WithdrawResult let my_balance_change = &received_by_me - &qrc20_amount; // [`MarketCoinOps::my_address`] and [`UtxoCommonOps::display_address`] shouldn't fail - let my_address_string = coin.my_address()?; + let my_address_string = coin.my_address().map_mm_err()?; let to_address = to_addr.display_address().map_to_mm(WithdrawError::InternalError)?; let fee_details = Qrc20FeeDetails { diff --git a/mm2src/coins/qrc20/swap.rs b/mm2src/coins/qrc20/swap.rs index 26dea25ab8..18e371bbdf 100644 --- a/mm2src/coins/qrc20/swap.rs +++ b/mm2src/coins/qrc20/swap.rs @@ -126,7 +126,8 @@ impl Qrc20Coin { let expected_swap_id = qrc20_swap_id(time_lock, &secret_hash); let status = self .payment_status(&expected_swap_contract_address, expected_swap_id.clone()) - .await?; + .await + .map_mm_err()?; if status != U256::from(PaymentState::Sent as u8) { return MmError::err(ValidatePaymentError::UnexpectedPaymentState(format!( "Payment state is not PAYMENT_STATE_SENT, got {}", @@ -135,8 +136,8 @@ impl Qrc20Coin { } let expected_call_bytes = { - let expected_value = wei_from_big_decimal(&amount, self.utxo.decimals)?; - let my_address = self.utxo.derivation_method.single_addr_or_err().await?; + let expected_value = wei_from_big_decimal(&amount, self.utxo.decimals).map_mm_err()?; + let my_address = self.utxo.derivation_method.single_addr_or_err().await.map_mm_err()?; let expected_receiver = qtum::contract_addr_from_utxo_addr(my_address) .mm_err(|err| ValidatePaymentError::InternalError(err.to_string()))?; self.erc20_payment_call_bytes( @@ -145,7 +146,8 @@ impl Qrc20Coin { time_lock, &secret_hash, expected_receiver, - )? + ) + .map_mm_err()? }; let erc20_payment = self .erc20_payment_details_from_tx(&payment_tx) @@ -454,21 +456,24 @@ impl Qrc20Coin { if allowance < value { if allowance > U256::zero() { // first reset the allowance to the 0 - outputs.push(self.approve_output(swap_contract_address, 0.into())?); + outputs.push(self.approve_output(swap_contract_address, 0.into()).map_mm_err()?); } // set the allowance from 0 to `my_balance` after the previous output is executed - outputs.push(self.approve_output(swap_contract_address, my_balance)?); + outputs.push(self.approve_output(swap_contract_address, my_balance).map_mm_err()?); } // when this output is executed, the allowance will be sufficient already - outputs.push(self.erc20_payment_output( - id, - value, - time_lock, - &secret_hash, - receiver_addr, - &swap_contract_address, - )?); + outputs.push( + self.erc20_payment_output( + id, + value, + time_lock, + &secret_hash, + receiver_addr, + &swap_contract_address, + ) + .map_mm_err()?, + ); Ok(outputs) } diff --git a/mm2src/coins/rpc_command/account_balance.rs b/mm2src/coins/rpc_command/account_balance.rs index 7e6587b788..f3f224ef73 100644 --- a/mm2src/coins/rpc_command/account_balance.rs +++ b/mm2src/coins/rpc_command/account_balance.rs @@ -62,7 +62,7 @@ pub async fn account_balance( ctx: MmArc, req: HDAccountBalanceRequest, ) -> MmResult { - match lp_coinfind_or_err(&ctx, &req.coin).await? { + match lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()? { MmCoinEnum::UtxoCoin(utxo) => Ok(HDAccountBalanceResponseEnum::Map( utxo.account_balance_rpc(req.params).await?, )), @@ -93,11 +93,12 @@ pub mod common_impl { let account_id = params.account_index; let hd_account = coin .derivation_method() - .hd_wallet_or_err()? + .hd_wallet_or_err() + .map_mm_err()? .get_account(account_id) .await .or_mm_err(|| HDAccountBalanceRpcError::UnknownAccount { account_id })?; - let total_addresses_number = hd_account.known_addresses_number(params.chain)?; + let total_addresses_number = hd_account.known_addresses_number(params.chain).map_mm_err()?; let from_address_id = match params.paging_options { PagingOptionsEnum::FromId(from_address_id) => from_address_id + 1, @@ -107,7 +108,8 @@ pub mod common_impl { let addresses = coin .known_addresses_balances_with_ids(&hd_account, params.chain, from_address_id..to_address_id) - .await?; + .await + .map_mm_err()?; let page_balance = addresses .iter() diff --git a/mm2src/coins/rpc_command/get_current_mtp.rs b/mm2src/coins/rpc_command/get_current_mtp.rs index 24b4f563b9..6db7b5b59a 100644 --- a/mm2src/coins/rpc_command/get_current_mtp.rs +++ b/mm2src/coins/rpc_command/get_current_mtp.rs @@ -1,7 +1,7 @@ use common::{HttpStatusCode, StatusCode}; use derive_more::Display; use mm2_core::mm_ctx::MmArc; -use mm2_err_handle::prelude::MmError; +use mm2_err_handle::prelude::*; use crate::{lp_coinfind_or_err, utxo::{rpc_clients::UtxoRpcError, UtxoCommonOps}, @@ -50,22 +50,22 @@ pub async fn get_current_mtp_rpc( ctx: MmArc, req: GetCurrentMtpRequest, ) -> GetCurrentMtpRpcResult { - match lp_coinfind_or_err(&ctx, &req.coin).await? { + match lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()? { MmCoinEnum::UtxoCoin(utxo) => Ok(GetCurrentMtpResponse { - mtp: utxo.get_current_mtp().await?, + mtp: utxo.get_current_mtp().await.map_mm_err()?, }), MmCoinEnum::QtumCoin(qtum) => Ok(GetCurrentMtpResponse { - mtp: qtum.get_current_mtp().await?, + mtp: qtum.get_current_mtp().await.map_mm_err()?, }), MmCoinEnum::Qrc20Coin(qrc) => Ok(GetCurrentMtpResponse { - mtp: qrc.get_current_mtp().await?, + mtp: qrc.get_current_mtp().await.map_mm_err()?, }), #[cfg(not(target_arch = "wasm32"))] MmCoinEnum::ZCoin(zcoin) => Ok(GetCurrentMtpResponse { - mtp: zcoin.get_current_mtp().await?, + mtp: zcoin.get_current_mtp().await.map_mm_err()?, }), MmCoinEnum::Bch(bch) => Ok(GetCurrentMtpResponse { - mtp: bch.get_current_mtp().await?, + mtp: bch.get_current_mtp().await.map_mm_err()?, }), _ => Err(MmError::new(GetCurrentMtpError::NotSupportedCoin(req.coin))), } diff --git a/mm2src/coins/rpc_command/get_new_address.rs b/mm2src/coins/rpc_command/get_new_address.rs index 1213905c74..a43225d864 100644 --- a/mm2src/coins/rpc_command/get_new_address.rs +++ b/mm2src/coins/rpc_command/get_new_address.rs @@ -315,7 +315,7 @@ impl RpcTask for InitGetNewAddressTask { on_ready: GetNewAddressInProgressStatus::RequestingAccountBalance, }; let confirm_address: RpcTaskConfirmAddress = - RpcTaskConfirmAddress::new(ctx, task_handle, hw_statuses, trezor_message_type)?; + RpcTaskConfirmAddress::new(ctx, task_handle, hw_statuses, trezor_message_type).map_mm_err()?; coin.get_new_address_rpc(params, &confirm_address).await } @@ -360,7 +360,7 @@ pub async fn get_new_address( ctx: MmArc, req: GetNewAddressRequest, ) -> MmResult { - let coin = lp_coinfind_or_err(&ctx, &req.coin).await?; + let coin = lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()?; match coin { MmCoinEnum::UtxoCoin(utxo) => Ok(GetNewAddressResponseEnum::Map( utxo.get_new_address_rpc_without_conf(req.params).await?, @@ -382,12 +382,13 @@ pub async fn init_get_new_address( req: RpcInitReq, ) -> MmResult { let (client_id, req) = (req.client_id, req.inner); - let coin = lp_coinfind_or_err(&ctx, &req.coin).await?; + let coin = lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()?; let coins_ctx = CoinsContext::from_ctx(&ctx).map_to_mm(GetNewAddressRpcError::Internal)?; let spawner = coin.spawner(); let task = InitGetNewAddressTask { ctx, coin, req }; let task_id = - GetNewAddressTaskManager::spawn_rpc_task(&coins_ctx.get_new_address_manager, &spawner, task, client_id)?; + GetNewAddressTaskManager::spawn_rpc_task(&coins_ctx.get_new_address_manager, &spawner, task, client_id) + .map_mm_err()?; Ok(InitRpcTaskResponse { task_id }) } @@ -414,7 +415,7 @@ pub async fn init_get_new_address_user_action( .get_new_address_manager .lock() .map_to_mm(|e| RpcTaskUserActionError::Internal(e.to_string()))?; - task_manager.on_user_action(req.task_id, req.user_action)?; + task_manager.on_user_action(req.task_id, req.user_action).map_mm_err()?; Ok(SuccessResponse::new()) } @@ -427,7 +428,7 @@ pub async fn cancel_get_new_address( .get_new_address_manager .lock() .map_to_mm(|e| CancelRpcTaskError::Internal(e.to_string()))?; - task_manager.cancel_task(req.task_id)?; + task_manager.cancel_task(req.task_id).map_mm_err()?; Ok(SuccessResponse::new()) } @@ -452,7 +453,7 @@ pub(crate) mod common_impl { Coin: HDWalletBalanceOps + CoinWithDerivationMethod + Sync + Send, HDCoinAddress: fmt::Display, { - let hd_wallet = coin.derivation_method().hd_wallet_or_err()?; + let hd_wallet = coin.derivation_method().hd_wallet_or_err().map_mm_err()?; let account_id = params.account_id; let mut hd_account = hd_wallet @@ -468,9 +469,10 @@ pub(crate) mod common_impl { let hd_address = coin .generate_new_address(hd_wallet, hd_account.deref_mut(), chain) - .await?; + .await + .map_mm_err()?; let address = hd_address.address(); - let balance = coin.known_address_balance(&address).await?; + let balance = coin.known_address_balance(&address).await.map_mm_err()?; Ok(GetNewAddressResponse { new_address: HDAddressBalance { @@ -492,7 +494,7 @@ pub(crate) mod common_impl { Coin: HDWalletBalanceOps + CoinWithDerivationMethod + Send + Sync, HDCoinAddress: Display + Eq + Hash, { - let hd_wallet = coin.derivation_method().hd_wallet_or_err()?; + let hd_wallet = coin.derivation_method().hd_wallet_or_err().map_mm_err()?; let account_id = params.account_id; let mut hd_account = hd_wallet @@ -508,9 +510,10 @@ pub(crate) mod common_impl { let hd_address = coin .generate_and_confirm_new_address(hd_wallet, &mut hd_account, chain, confirm_address) - .await?; + .await + .map_mm_err()?; let address = hd_address.address(); - let balance = coin.known_address_balance(&address).await?; + let balance = coin.known_address_balance(&address).await.map_mm_err()?; let formatted_address = address.display_address(); coin.prepare_addresses_for_balance_stream_if_enabled(HashSet::from([formatted_address.clone()])) @@ -537,7 +540,7 @@ pub(crate) mod common_impl { Coin: HDWalletBalanceOps + Sync, HDCoinAddress: fmt::Display, { - let known_addresses_number = hd_account.known_addresses_number(chain)?; + let known_addresses_number = hd_account.known_addresses_number(chain).map_mm_err()?; if known_addresses_number == 0 || gap_limit > known_addresses_number { return Ok(()); } @@ -547,15 +550,19 @@ pub(crate) mod common_impl { return MmError::err(GetNewAddressRpcError::AddressLimitReached { max_addresses_number }); } - let address_scanner = coin.produce_hd_address_scanner().await?; + let address_scanner = coin.produce_hd_address_scanner().await.map_mm_err()?; // Address IDs start from 0, so the `last_known_address_id = known_addresses_number - 1`. // At this point we are sure that `known_addresses_number > 0`. let last_address_id = known_addresses_number - 1; for address_id in (0..=last_address_id).rev() { - let address = coin.derive_address(hd_account, chain, address_id).await?.address(); - if address_scanner.is_address_used(&address).await? { + let address = coin + .derive_address(hd_account, chain, address_id) + .await + .map_mm_err()? + .address(); + if address_scanner.is_address_used(&address).await.map_mm_err()? { return Ok(()); } diff --git a/mm2src/coins/rpc_command/init_account_balance.rs b/mm2src/coins/rpc_command/init_account_balance.rs index b18e6bdbce..afec7e5761 100644 --- a/mm2src/coins/rpc_command/init_account_balance.rs +++ b/mm2src/coins/rpc_command/init_account_balance.rs @@ -93,12 +93,13 @@ pub async fn init_account_balance( req: RpcInitReq, ) -> MmResult { let (client_id, req) = (req.client_id, req.inner); - let coin = lp_coinfind_or_err(&ctx, &req.coin).await?; + let coin = lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()?; let spawner = coin.spawner(); let coins_ctx = CoinsContext::from_ctx(&ctx).map_to_mm(HDAccountBalanceRpcError::Internal)?; let task = InitAccountBalanceTask { coin, req }; let task_id = - AccountBalanceTaskManager::spawn_rpc_task(&coins_ctx.account_balance_task_manager, &spawner, task, client_id)?; + AccountBalanceTaskManager::spawn_rpc_task(&coins_ctx.account_balance_task_manager, &spawner, task, client_id) + .map_mm_err()?; Ok(InitRpcTaskResponse { task_id }) } @@ -125,7 +126,7 @@ pub async fn cancel_account_balance( .account_balance_task_manager .lock() .map_to_mm(|e| CancelRpcTaskError::Internal(e.to_string()))?; - task_manager.cancel_task(req.task_id)?; + task_manager.cancel_task(req.task_id).map_mm_err()?; Ok(SuccessResponse::new()) } @@ -148,12 +149,13 @@ pub mod common_impl { let account_id = params.account_index; let hd_account = coin .derivation_method() - .hd_wallet_or_err()? + .hd_wallet_or_err() + .map_mm_err()? .get_account(account_id) .await .or_mm_err(|| HDAccountBalanceRpcError::UnknownAccount { account_id })?; - let addresses = coin.all_known_addresses_balances(&hd_account).await?; + let addresses = coin.all_known_addresses_balances(&hd_account).await.map_mm_err()?; let total_balance = addresses .iter() diff --git a/mm2src/coins/rpc_command/init_create_account.rs b/mm2src/coins/rpc_command/init_create_account.rs index 774ab3bc77..4328e8f54a 100644 --- a/mm2src/coins/rpc_command/init_create_account.rs +++ b/mm2src/coins/rpc_command/init_create_account.rs @@ -273,12 +273,10 @@ impl RpcTask for InitCreateAccountTask { on_passphrase_request: CreateAccountAwaitingStatus::EnterTrezorPassphrase, on_ready: CreateAccountInProgressStatus::RequestingAccountBalance, }; - Some(CreateAccountXPubExtractor::new_trezor_extractor( - ctx, - task_handle, - hw_statuses, - coin_protocol, - )?) + Some( + CreateAccountXPubExtractor::new_trezor_extractor(ctx, task_handle, hw_statuses, coin_protocol) + .map_mm_err()?, + ) } else { None }; @@ -337,7 +335,7 @@ pub async fn init_create_new_account( req: RpcInitReq, ) -> MmResult { let (client_id, req) = (req.client_id, req.inner); - let coin = lp_coinfind_or_err(&ctx, &req.coin).await?; + let coin = lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()?; let coins_ctx = CoinsContext::from_ctx(&ctx).map_to_mm(CreateAccountRpcError::Internal)?; let spawner = coin.spawner(); let task = InitCreateAccountTask { @@ -347,7 +345,8 @@ pub async fn init_create_new_account( task_state: CreateAccountState::default(), }; let task_id = - CreateAccountTaskManager::spawn_rpc_task(&coins_ctx.create_account_manager, &spawner, task, client_id)?; + CreateAccountTaskManager::spawn_rpc_task(&coins_ctx.create_account_manager, &spawner, task, client_id) + .map_mm_err()?; Ok(InitRpcTaskResponse { task_id }) } @@ -374,7 +373,7 @@ pub async fn init_create_new_account_user_action( .create_account_manager .lock() .map_to_mm(|e| RpcTaskUserActionError::Internal(e.to_string()))?; - task_manager.on_user_action(req.task_id, req.user_action)?; + task_manager.on_user_action(req.task_id, req.user_action).map_mm_err()?; Ok(SuccessResponse::new()) } @@ -387,7 +386,7 @@ pub async fn cancel_create_new_account( .create_account_manager .lock() .map_to_mm(|e| CancelRpcTaskError::Internal(e.to_string()))?; - task_manager.cancel_task(req.task_id)?; + task_manager.cancel_task(req.task_id).map_mm_err()?; Ok(SuccessResponse::new()) } @@ -412,9 +411,11 @@ pub(crate) mod common_impl { XPubExtractor: HDXPubExtractor + Send, HDCoinHDAccount: HDAccountStorageOps, { - let hd_wallet = coin.derivation_method().hd_wallet_or_err()?; + let hd_wallet = coin.derivation_method().hd_wallet_or_err().map_mm_err()?; - let mut new_account = create_new_account(coin, hd_wallet, xpub_extractor, params.account_id).await?; + let mut new_account = create_new_account(coin, hd_wallet, xpub_extractor, params.account_id) + .await + .map_mm_err()?; let account_index = new_account.account_id(); let account_derivation_path = new_account.account_derivation_path(); @@ -423,9 +424,10 @@ pub(crate) mod common_impl { let addresses = if params.scan { let gap_limit = params.gap_limit.unwrap_or_else(|| hd_wallet.gap_limit()); - let address_scanner = coin.produce_hd_address_scanner().await?; + let address_scanner = coin.produce_hd_address_scanner().await.map_mm_err()?; coin.scan_for_new_addresses(hd_wallet, &mut new_account, &address_scanner, gap_limit) - .await? + .await + .map_mm_err()? } else { Vec::new() }; diff --git a/mm2src/coins/rpc_command/init_scan_for_new_addresses.rs b/mm2src/coins/rpc_command/init_scan_for_new_addresses.rs index d24c7229fe..7d1e7b1e09 100644 --- a/mm2src/coins/rpc_command/init_scan_for_new_addresses.rs +++ b/mm2src/coins/rpc_command/init_scan_for_new_addresses.rs @@ -112,12 +112,13 @@ pub async fn init_scan_for_new_addresses( req: RpcInitReq, ) -> MmResult { let (client_id, req) = (req.client_id, req.inner); - let coin = lp_coinfind_or_err(&ctx, &req.coin).await?; + let coin = lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()?; let spawner = coin.spawner(); let coins_ctx = CoinsContext::from_ctx(&ctx).map_to_mm(HDAccountBalanceRpcError::Internal)?; let task = InitScanAddressesTask { req, coin }; let task_id = - ScanAddressesTaskManager::spawn_rpc_task(&coins_ctx.scan_addresses_manager, &spawner, task, client_id)?; + ScanAddressesTaskManager::spawn_rpc_task(&coins_ctx.scan_addresses_manager, &spawner, task, client_id) + .map_mm_err()?; Ok(InitRpcTaskResponse { task_id }) } @@ -144,7 +145,7 @@ pub async fn cancel_scan_for_new_addresses( .scan_addresses_manager .lock() .map_to_mm(|e| CancelRpcTaskError::Internal(e.to_string()))?; - task_manager.cancel_task(req.task_id)?; + task_manager.cancel_task(req.task_id).map_mm_err()?; Ok(SuccessResponse::new()) } @@ -163,7 +164,7 @@ pub mod common_impl { where Coin: CoinWithDerivationMethod + HDWalletBalanceOps + Sync, { - let hd_wallet = coin.derivation_method().hd_wallet_or_err()?; + let hd_wallet = coin.derivation_method().hd_wallet_or_err().map_mm_err()?; let account_id = params.account_index; let mut hd_account = hd_wallet @@ -171,12 +172,13 @@ pub mod common_impl { .await .or_mm_err(|| HDAccountBalanceRpcError::CoinIsActivatedNotWithHDWallet)?; let account_derivation_path = hd_account.account_derivation_path(); - let address_scanner = coin.produce_hd_address_scanner().await?; + let address_scanner = coin.produce_hd_address_scanner().await.map_mm_err()?; let gap_limit = params.gap_limit.unwrap_or_else(|| hd_wallet.gap_limit()); let new_addresses = coin .scan_for_new_addresses(hd_wallet, hd_account.deref_mut(), &address_scanner, gap_limit) - .await?; + .await + .map_mm_err()?; let addresses: HashSet<_> = new_addresses .iter() diff --git a/mm2src/coins/rpc_command/init_withdraw.rs b/mm2src/coins/rpc_command/init_withdraw.rs index e82ccd4d63..1575f9b1ca 100644 --- a/mm2src/coins/rpc_command/init_withdraw.rs +++ b/mm2src/coins/rpc_command/init_withdraw.rs @@ -38,7 +38,7 @@ pub async fn init_withdraw( request: RpcInitReq, ) -> WithdrawInitResult { let (client_id, request) = (request.client_id, request.inner); - let coin = lp_coinfind_or_err(&ctx, &request.coin).await?; + let coin = lp_coinfind_or_err(&ctx, &request.coin).await.map_mm_err()?; let spawner = coin.spawner(); let task = WithdrawTask { ctx: ctx.clone(), @@ -46,7 +46,8 @@ pub async fn init_withdraw( request, }; let coins_ctx = CoinsContext::from_ctx(&ctx).map_to_mm(WithdrawError::InternalError)?; - let task_id = WithdrawTaskManager::spawn_rpc_task(&coins_ctx.withdraw_task_manager, &spawner, task, client_id)?; + let task_id = WithdrawTaskManager::spawn_rpc_task(&coins_ctx.withdraw_task_manager, &spawner, task, client_id) + .map_mm_err()?; Ok(InitWithdrawResponse { task_id }) } @@ -86,7 +87,7 @@ pub async fn withdraw_user_action( .withdraw_task_manager .lock() .map_to_mm(|e| WithdrawUserActionError::Internal(e.to_string()))?; - task_manager.on_user_action(req.task_id, req.user_action)?; + task_manager.on_user_action(req.task_id, req.user_action).map_mm_err()?; Ok(SuccessResponse::new()) } @@ -96,7 +97,7 @@ pub async fn cancel_withdraw(ctx: MmArc, req: CancelRpcTaskRequest) -> MmResult< .withdraw_task_manager .lock() .map_to_mm(|e| CancelRpcTaskError::Internal(e.to_string()))?; - task_manager.cancel_task(req.task_id)?; + task_manager.cancel_task(req.task_id).map_mm_err()?; Ok(SuccessResponse::new()) } diff --git a/mm2src/coins/rpc_command/lightning/close_channel.rs b/mm2src/coins/rpc_command/lightning/close_channel.rs index 716b7db969..cbcb237582 100644 --- a/mm2src/coins/rpc_command/lightning/close_channel.rs +++ b/mm2src/coins/rpc_command/lightning/close_channel.rs @@ -47,7 +47,7 @@ pub struct CloseChannelReq { } pub async fn close_channel(ctx: MmArc, req: CloseChannelReq) -> CloseChannelResult { - let ln_coin = match lp_coinfind_or_err(&ctx, &req.coin).await? { + let ln_coin = match lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()? { MmCoinEnum::LightningCoin(c) => c, e => return MmError::err(CloseChannelError::UnsupportedCoin(e.ticker().to_string())), }; diff --git a/mm2src/coins/rpc_command/lightning/connect_to_node.rs b/mm2src/coins/rpc_command/lightning/connect_to_node.rs index 79ba0f1889..ab776cb49e 100644 --- a/mm2src/coins/rpc_command/lightning/connect_to_node.rs +++ b/mm2src/coins/rpc_command/lightning/connect_to_node.rs @@ -68,7 +68,7 @@ pub struct ConnectToNodeRequest { /// Connect to a certain node on the lightning network. pub async fn connect_to_node(ctx: MmArc, req: ConnectToNodeRequest) -> ConnectToNodeResult { - let ln_coin = match lp_coinfind_or_err(&ctx, &req.coin).await? { + let ln_coin = match lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()? { MmCoinEnum::LightningCoin(c) => c, e => return MmError::err(ConnectToNodeError::UnsupportedCoin(e.ticker().to_string())), }; diff --git a/mm2src/coins/rpc_command/lightning/generate_invoice.rs b/mm2src/coins/rpc_command/lightning/generate_invoice.rs index 83d0fc41f6..051402b44c 100644 --- a/mm2src/coins/rpc_command/lightning/generate_invoice.rs +++ b/mm2src/coins/rpc_command/lightning/generate_invoice.rs @@ -75,7 +75,7 @@ pub async fn generate_invoice( ctx: MmArc, req: GenerateInvoiceRequest, ) -> GenerateInvoiceResult { - let ln_coin = match lp_coinfind_or_err(&ctx, &req.coin).await? { + let ln_coin = match lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()? { MmCoinEnum::LightningCoin(c) => c, e => return MmError::err(GenerateInvoiceError::UnsupportedCoin(e.ticker().to_string())), }; diff --git a/mm2src/coins/rpc_command/lightning/get_channel_details.rs b/mm2src/coins/rpc_command/lightning/get_channel_details.rs index c96cf06e57..f806c0e916 100644 --- a/mm2src/coins/rpc_command/lightning/get_channel_details.rs +++ b/mm2src/coins/rpc_command/lightning/get_channel_details.rs @@ -62,7 +62,7 @@ pub async fn get_channel_details( ctx: MmArc, req: GetChannelDetailsRequest, ) -> GetChannelDetailsResult { - let ln_coin = match lp_coinfind_or_err(&ctx, &req.coin).await? { + let ln_coin = match lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()? { MmCoinEnum::LightningCoin(c) => c, e => return MmError::err(GetChannelDetailsError::UnsupportedCoin(e.ticker().to_string())), }; diff --git a/mm2src/coins/rpc_command/lightning/get_claimable_balances.rs b/mm2src/coins/rpc_command/lightning/get_claimable_balances.rs index 5d1b84dad1..511892a1cd 100644 --- a/mm2src/coins/rpc_command/lightning/get_claimable_balances.rs +++ b/mm2src/coins/rpc_command/lightning/get_claimable_balances.rs @@ -44,7 +44,7 @@ pub async fn get_claimable_balances( ctx: MmArc, req: ClaimableBalancesReq, ) -> ClaimableBalancesResult> { - let ln_coin = match lp_coinfind_or_err(&ctx, &req.coin).await? { + let ln_coin = match lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()? { MmCoinEnum::LightningCoin(c) => c, e => return MmError::err(ClaimableBalancesError::UnsupportedCoin(e.ticker().to_string())), }; diff --git a/mm2src/coins/rpc_command/lightning/get_payment_details.rs b/mm2src/coins/rpc_command/lightning/get_payment_details.rs index 0e7a4868c2..7823e04b5f 100644 --- a/mm2src/coins/rpc_command/lightning/get_payment_details.rs +++ b/mm2src/coins/rpc_command/lightning/get_payment_details.rs @@ -61,7 +61,7 @@ pub async fn get_payment_details( ctx: MmArc, req: GetPaymentDetailsRequest, ) -> GetPaymentDetailsResult { - let ln_coin = match lp_coinfind_or_err(&ctx, &req.coin).await? { + let ln_coin = match lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()? { MmCoinEnum::LightningCoin(c) => c, e => return MmError::err(GetPaymentDetailsError::UnsupportedCoin(e.ticker().to_string())), }; diff --git a/mm2src/coins/rpc_command/lightning/list_channels.rs b/mm2src/coins/rpc_command/lightning/list_channels.rs index d3eb582633..3c857f2e0f 100644 --- a/mm2src/coins/rpc_command/lightning/list_channels.rs +++ b/mm2src/coins/rpc_command/lightning/list_channels.rs @@ -68,7 +68,7 @@ pub async fn list_open_channels_by_filter( ctx: MmArc, req: ListOpenChannelsRequest, ) -> ListChannelsResult { - let ln_coin = match lp_coinfind_or_err(&ctx, &req.coin).await? { + let ln_coin = match lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()? { MmCoinEnum::LightningCoin(c) => c, e => return MmError::err(ListChannelsError::UnsupportedCoin(e.ticker().to_string())), }; @@ -111,7 +111,7 @@ pub async fn list_closed_channels_by_filter( ctx: MmArc, req: ListClosedChannelsRequest, ) -> ListChannelsResult { - let ln_coin = match lp_coinfind_or_err(&ctx, &req.coin).await? { + let ln_coin = match lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()? { MmCoinEnum::LightningCoin(c) => c, e => return MmError::err(ListChannelsError::UnsupportedCoin(e.ticker().to_string())), }; diff --git a/mm2src/coins/rpc_command/lightning/list_payments_by_filter.rs b/mm2src/coins/rpc_command/lightning/list_payments_by_filter.rs index 0a6d0d3308..05f3a6a4f0 100644 --- a/mm2src/coins/rpc_command/lightning/list_payments_by_filter.rs +++ b/mm2src/coins/rpc_command/lightning/list_payments_by_filter.rs @@ -64,7 +64,7 @@ pub struct ListPaymentsResponse { } pub async fn list_payments_by_filter(ctx: MmArc, req: ListPaymentsReq) -> ListPaymentsResult { - let ln_coin = match lp_coinfind_or_err(&ctx, &req.coin).await? { + let ln_coin = match lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()? { MmCoinEnum::LightningCoin(c) => c, e => return MmError::err(ListPaymentsError::UnsupportedCoin(e.ticker().to_string())), }; diff --git a/mm2src/coins/rpc_command/lightning/open_channel.rs b/mm2src/coins/rpc_command/lightning/open_channel.rs index 095ee1c4ee..81622b5962 100644 --- a/mm2src/coins/rpc_command/lightning/open_channel.rs +++ b/mm2src/coins/rpc_command/lightning/open_channel.rs @@ -134,7 +134,7 @@ pub struct OpenChannelResponse { /// Opens a channel on the lightning network. pub async fn open_channel(ctx: MmArc, req: OpenChannelRequest) -> OpenChannelResult { - let ln_coin = match lp_coinfind_or_err(&ctx, &req.coin).await? { + let ln_coin = match lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()? { MmCoinEnum::LightningCoin(c) => c, e => return MmError::err(OpenChannelError::UnsupportedCoin(e.ticker().to_string())), }; @@ -146,15 +146,20 @@ pub async fn open_channel(ctx: MmArc, req: OpenChannelRequest) -> OpenChannelRes let platform_coin = ln_coin.platform_coin().clone(); let decimals = platform_coin.as_ref().decimals; - let my_address = platform_coin.as_ref().derivation_method.single_addr_or_err().await?; - let (unspents, _) = platform_coin.get_unspent_ordered_list(&my_address).await?; + let my_address = platform_coin + .as_ref() + .derivation_method + .single_addr_or_err() + .await + .map_mm_err()?; + let (unspents, _) = platform_coin.get_unspent_ordered_list(&my_address).await.map_mm_err()?; let (value, fee_policy) = match req.amount.clone() { ChannelOpenAmount::Max => ( unspents.iter().fold(0, |sum, unspent| sum + unspent.value), FeePolicy::DeductFromOutput(0), ), ChannelOpenAmount::Exact(v) => { - let value = sat_from_big_decimal(&v, decimals)?; + let value = sat_from_big_decimal(&v, decimals).map_mm_err()?; (value, FeePolicy::SendExact) }, }; @@ -179,7 +184,7 @@ pub async fn open_channel(ctx: MmArc, req: OpenChannelRequest) -> OpenChannelRes .map_err(|e| OpenChannelError::RpcError(e.to_string()))?; tx_builder = tx_builder.with_fee(fee); - let (unsigned, _) = tx_builder.build().await?; + let (unsigned, _) = tx_builder.build().await.map_mm_err()?; let amount_in_sat = unsigned.outputs[0].value; let push_msat = req.push_msat; diff --git a/mm2src/coins/rpc_command/lightning/send_payment.rs b/mm2src/coins/rpc_command/lightning/send_payment.rs index 3efde180d4..43f1e30ae5 100644 --- a/mm2src/coins/rpc_command/lightning/send_payment.rs +++ b/mm2src/coins/rpc_command/lightning/send_payment.rs @@ -85,7 +85,7 @@ pub struct SendPaymentResponse { } pub async fn send_payment(ctx: MmArc, req: SendPaymentReq) -> SendPaymentResult { - let ln_coin = match lp_coinfind_or_err(&ctx, &req.coin).await? { + let ln_coin = match lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()? { MmCoinEnum::LightningCoin(c) => c, e => return MmError::err(SendPaymentError::UnsupportedCoin(e.ticker().to_string())), }; @@ -99,12 +99,15 @@ pub async fn send_payment(ctx: MmArc, req: SendPaymentReq) -> SendPaymentResult< )); } let payment_info = match req.payment { - Payment::Invoice { invoice } => ln_coin.pay_invoice(invoice, None).await?, + Payment::Invoice { invoice } => ln_coin.pay_invoice(invoice, None).await.map_mm_err()?, Payment::Keysend { destination, amount_in_msat, expiry, - } => ln_coin.keysend(destination.into(), amount_in_msat, expiry).await?, + } => ln_coin + .keysend(destination.into(), amount_in_msat, expiry) + .await + .map_mm_err()?, }; Ok(SendPaymentResponse { diff --git a/mm2src/coins/rpc_command/lightning/trusted_nodes.rs b/mm2src/coins/rpc_command/lightning/trusted_nodes.rs index 6f0f2fd36e..5527215def 100644 --- a/mm2src/coins/rpc_command/lightning/trusted_nodes.rs +++ b/mm2src/coins/rpc_command/lightning/trusted_nodes.rs @@ -53,7 +53,7 @@ pub struct AddTrustedNodeResponse { } pub async fn add_trusted_node(ctx: MmArc, req: AddTrustedNodeReq) -> TrustedNodeResult { - let ln_coin = match lp_coinfind_or_err(&ctx, &req.coin).await? { + let ln_coin = match lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()? { MmCoinEnum::LightningCoin(c) => c, e => return MmError::err(TrustedNodeError::UnsupportedCoin(e.ticker().to_string())), }; @@ -82,7 +82,7 @@ pub async fn remove_trusted_node( ctx: MmArc, req: RemoveTrustedNodeReq, ) -> TrustedNodeResult { - let ln_coin = match lp_coinfind_or_err(&ctx, &req.coin).await? { + let ln_coin = match lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()? { MmCoinEnum::LightningCoin(c) => c, e => return MmError::err(TrustedNodeError::UnsupportedCoin(e.ticker().to_string())), }; @@ -107,7 +107,7 @@ pub struct ListTrustedNodesResponse { } pub async fn list_trusted_nodes(ctx: MmArc, req: ListTrustedNodesReq) -> TrustedNodeResult { - let ln_coin = match lp_coinfind_or_err(&ctx, &req.coin).await? { + let ln_coin = match lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()? { MmCoinEnum::LightningCoin(c) => c, e => return MmError::err(TrustedNodeError::UnsupportedCoin(e.ticker().to_string())), }; diff --git a/mm2src/coins/rpc_command/lightning/update_channel.rs b/mm2src/coins/rpc_command/lightning/update_channel.rs index ad7768831f..57b772764c 100644 --- a/mm2src/coins/rpc_command/lightning/update_channel.rs +++ b/mm2src/coins/rpc_command/lightning/update_channel.rs @@ -53,7 +53,7 @@ pub struct UpdateChannelResponse { /// Updates configuration for an open channel. pub async fn update_channel(ctx: MmArc, req: UpdateChannelReq) -> UpdateChannelResult { - let ln_coin = match lp_coinfind_or_err(&ctx, &req.coin).await? { + let ln_coin = match lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()? { MmCoinEnum::LightningCoin(c) => c, e => return MmError::err(UpdateChannelError::UnsupportedCoin(e.ticker().to_string())), }; diff --git a/mm2src/coins/rpc_command/tendermint/staking.rs b/mm2src/coins/rpc_command/tendermint/staking.rs index 519c18cc38..5ad332f5e3 100644 --- a/mm2src/coins/rpc_command/tendermint/staking.rs +++ b/mm2src/coins/rpc_command/tendermint/staking.rs @@ -1,6 +1,6 @@ use common::PagingOptions; use cosmrs::staking::{Commission, Description, Validator}; -use mm2_err_handle::prelude::MmError; +use mm2_err_handle::prelude::{MmError, MmResultExt}; use mm2_number::BigDecimal; use crate::{hd_wallet::HDAddressSelector, tendermint::TendermintCoinRpcError, MmCoinEnum, StakingInfoError, @@ -109,13 +109,15 @@ pub async fn validators_rpc( } let validators = match coin { - MmCoinEnum::Tendermint(coin) => coin.validators_list(req.filter_by_status, req.paging).await?, - MmCoinEnum::TendermintToken(token) => { - token - .platform_coin - .validators_list(req.filter_by_status, req.paging) - .await? - }, + MmCoinEnum::Tendermint(coin) => coin + .validators_list(req.filter_by_status, req.paging) + .await + .map_mm_err()?, + MmCoinEnum::TendermintToken(token) => token + .platform_coin + .validators_list(req.filter_by_status, req.paging) + .await + .map_mm_err()?, other => { return MmError::err(StakingInfoError::InvalidPayload { reason: format!("{} is not a Cosmos coin", other.ticker()), diff --git a/mm2src/coins/siacoin.rs b/mm2src/coins/siacoin.rs index c0b82f313b..628265b8c4 100644 --- a/mm2src/coins/siacoin.rs +++ b/mm2src/coins/siacoin.rs @@ -167,7 +167,7 @@ impl<'a> SiaCoinBuilder<'a> { fn ticker(&self) -> &str { self.ticker } async fn build(self) -> MmResult { - let conf = SiaConfBuilder::new(self.conf, self.ticker()).build()?; + let conf = SiaConfBuilder::new(self.conf, self.ticker()).build().map_mm_err()?; let sia_fields = SiaCoinFields { conf, http_client: SiaApiClient::new(self.params.http_conf.clone()) diff --git a/mm2src/coins/tendermint/tendermint_coin.rs b/mm2src/coins/tendermint/tendermint_coin.rs index b442f94ab2..1160d3b971 100644 --- a/mm2src/coins/tendermint/tendermint_coin.rs +++ b/mm2src/coins/tendermint/tendermint_coin.rs @@ -1990,7 +1990,7 @@ impl TendermintCoin { let sender = AccountId::new(&self.protocol_info.account_prefix, sender_pubkey_hash.as_slice()) .map_to_mm(|e| ValidatePaymentError::InvalidParameter(e.to_string()))?; - let amount = sat_from_big_decimal(&input.amount, decimals)?; + let amount = sat_from_big_decimal(&input.amount, decimals).map_mm_err()?; let amount = vec![Coin { denom, amount: amount.into(), @@ -2016,7 +2016,7 @@ impl TendermintCoin { } let hash = hex::encode_upper(sha256(&input.payment_tx).as_slice()); - let tx_from_rpc = self.request_tx(hash).await?; + let tx_from_rpc = self.request_tx(hash).await.map_mm_err()?; if input.payment_tx != tx_from_rpc.encode_to_vec() { return MmError::err(ValidatePaymentError::InvalidRpcResponse( "Tx from RPC doesn't match the input".into(), @@ -2025,7 +2025,7 @@ impl TendermintCoin { let htlc_id = self.calculate_htlc_id(&sender, &self.account_id, &amount, &input.secret_hash); - let htlc_response = self.query_htlc(htlc_id.clone()).await?; + let htlc_response = self.query_htlc(htlc_id.clone()).await.map_mm_err()?; let htlc_state = htlc_response .htlc_state() .or_mm_err(|| ValidatePaymentError::InvalidRpcResponse(format!("No HTLC data for {}", htlc_id)))?; @@ -2057,7 +2057,7 @@ impl TendermintCoin { let expected_dex_address = AccountId::new(&self.protocol_info.account_prefix, dex_pubkey_hash.as_slice()) .map_to_mm(|r| ValidatePaymentError::InvalidParameter(r.to_string()))?; - let fee_amount_as_u64 = dex_fee.fee_amount_as_u64(decimals)?; + let fee_amount_as_u64 = dex_fee.fee_amount_as_u64(decimals).map_mm_err()?; let expected_dex_amount = CoinProto { denom, amount: fee_amount_as_u64.to_string(), @@ -2113,12 +2113,12 @@ impl TendermintCoin { let expected_burn_address = AccountId::new(&self.protocol_info.account_prefix, burn_pubkey_hash.as_slice()) .map_to_mm(|r| ValidatePaymentError::InvalidParameter(r.to_string()))?; - let fee_amount_as_u64 = dex_fee.fee_amount_as_u64(decimals)?; + let fee_amount_as_u64 = dex_fee.fee_amount_as_u64(decimals).map_mm_err()?; let expected_dex_amount = CoinProto { denom: denom.clone(), amount: fee_amount_as_u64.to_string(), }; - let burn_amount_as_u64 = dex_fee.burn_amount_as_u64(decimals)?.unwrap_or_default(); + let burn_amount_as_u64 = dex_fee.burn_amount_as_u64(decimals).map_mm_err()?.unwrap_or_default(); let expected_burn_amount = CoinProto { denom, amount: burn_amount_as_u64.to_string(), @@ -2201,7 +2201,7 @@ impl TendermintCoin { let to_address = account_id_from_pubkey_hex(&self.protocol_info.account_prefix, DEX_FEE_ADDR_PUBKEY) .map_err(|e| MmError::new(TradePreimageError::InternalError(e.to_string())))?; - let amount = sat_from_big_decimal(&amount, decimals)?; + let amount = sat_from_big_decimal(&amount, decimals).map_mm_err()?; let create_htlc_tx = self .gen_create_htlc_tx(denom, &to_address, amount.into(), sha256(&sec).as_slice(), TIME_LOCK) @@ -2230,7 +2230,8 @@ impl TendermintCoin { TX_DEFAULT_MEMO, None, ) - .await?; + .await + .map_mm_err()?; let fee_amount = big_decimal_from_sat_unsigned(fee_uamount, self.protocol_info.decimals); @@ -2250,7 +2251,7 @@ impl TendermintCoin { ) -> TradePreimageResult { let to_address = account_id_from_pubkey_hex(&self.protocol_info.account_prefix, DEX_FEE_ADDR_PUBKEY) .map_err(|e| MmError::new(TradePreimageError::InternalError(e.to_string())))?; - let amount = sat_from_big_decimal(&dex_fee_amount.fee_amount().into(), decimals)?; + let amount = sat_from_big_decimal(&dex_fee_amount.fee_amount().into(), decimals).map_mm_err()?; let current_block = self.current_block().compat().await.map_err(|e| { MmError::new(TradePreimageError::InternalError(format!( @@ -2281,7 +2282,8 @@ impl TendermintCoin { TX_DEFAULT_MEMO, None, ) - .await?; + .await + .map_mm_err()?; let fee_amount = big_decimal_from_sat_unsigned(fee_uamount, decimals); Ok(TradeFee { @@ -2405,7 +2407,7 @@ impl TendermintCoin { let htlc = CreateHtlcMsg::try_from(htlc_proto)?; let htlc_id = self.calculate_htlc_id(htlc.sender(), htlc.to(), htlc.amount(), input.secret_hash); - let htlc_response = self.query_htlc(htlc_id.clone()).await?; + let htlc_response = self.query_htlc(htlc_id.clone()).await.map_mm_err()?; let htlc_state = match htlc_response.htlc_state() { Some(htlc_state) => htlc_state, @@ -2426,10 +2428,12 @@ impl TendermintCoin { let response = self .rpc_client() - .await? + .await + .map_mm_err()? .perform(request) .await - .map_to_mm(TendermintCoinRpcError::from)?; + .map_to_mm(TendermintCoinRpcError::from) + .map_mm_err()?; match response.txs.first() { Some(raw_tx) => { let tx = cosmrs::Tx::from_bytes(&raw_tx.tx)?; @@ -2593,7 +2597,8 @@ impl TendermintCoin { let (balance_u64, balance_dec) = self .get_balance_as_unsigned_and_decimal(&delegator_address, &self.protocol_info.denom, self.decimals()) - .await?; + .await + .map_mm_err()?; let amount_u64 = if req.max { balance_u64 @@ -2631,7 +2636,8 @@ impl TendermintCoin { &req.memo, req.fee, ) - .await?; + .await + .map_mm_err()?; let fee_amount_dec = big_decimal_from_sat_unsigned(fee_amount_u64, self.decimals()); @@ -2661,7 +2667,7 @@ impl TendermintCoin { ) .map_err(|e| DelegationError::InternalError(e.to_string()))?; - let account_info = self.account_info(&delegator_address).await?; + let account_info = self.account_info(&delegator_address).await.map_mm_err()?; let tx = self .any_to_transaction_data( @@ -2767,11 +2773,12 @@ impl TendermintCoin { &req.memo, req.fee, ) - .await?; + .await + .map_mm_err()?; let fee_amount_dec = big_decimal_from_sat_unsigned(fee_amount_u64, self.decimals()); - let my_balance = self.my_balance().compat().await?.spendable; + let my_balance = self.my_balance().compat().await.map_mm_err()?.spendable; if fee_amount_dec > my_balance { return MmError::err(DelegationError::NotSufficientBalance { @@ -2789,7 +2796,7 @@ impl TendermintCoin { gas_limit, ); - let account_info = self.account_info(&delegator_address).await?; + let account_info = self.account_info(&delegator_address).await.map_mm_err()?; let tx = self .any_to_transaction_data( @@ -2845,7 +2852,8 @@ impl TendermintCoin { let raw_response = self .rpc_client() - .await? + .await + .map_mm_err()? .abci_query( Some(ABCI_DELEGATION_PATH.to_owned()), request.encode_to_vec(), @@ -2892,7 +2900,8 @@ impl TendermintCoin { let raw_response = self .rpc_client() - .await? + .await + .map_mm_err()? .abci_query( Some(ABCI_DELEGATION_REWARDS_PATH.to_owned()), query_payload.encode_to_vec(), @@ -2964,11 +2973,12 @@ impl TendermintCoin { &req.memo, req.fee, ) - .await?; + .await + .map_mm_err()?; let fee_amount_dec = big_decimal_from_sat_unsigned(fee_amount_u64, self.decimals()); - let my_balance = self.my_balance().compat().await?.spendable; + let my_balance = self.my_balance().compat().await.map_mm_err()?.spendable; if fee_amount_dec > my_balance { return MmError::err(DelegationError::NotSufficientBalance { @@ -2993,7 +3003,7 @@ impl TendermintCoin { gas_limit, ); - let account_info = self.account_info(&delegator_address).await?; + let account_info = self.account_info(&delegator_address).await.map_mm_err()?; let tx = self .any_to_transaction_data(maybe_priv_key, msg, &account_info, fee, timeout_height, &req.memo) @@ -3237,7 +3247,8 @@ impl MmCoin for TendermintCoin { let (balance_denom, balance_dec) = coin .get_balance_as_unsigned_and_decimal(&account_id, &coin.protocol_info.denom, coin.decimals()) - .await?; + .await + .map_mm_err()?; let (amount_denom, amount_dec) = if req.max { let amount_denom = balance_denom; @@ -3246,7 +3257,10 @@ impl MmCoin for TendermintCoin { big_decimal_from_sat_unsigned(amount_denom, coin.decimals()), ) } else { - (sat_from_big_decimal(&req.amount, coin.decimals())?, req.amount.clone()) + ( + sat_from_big_decimal(&req.amount, coin.decimals()).map_mm_err()?, + req.amount.clone(), + ) }; if !coin.is_tx_amount_enough(coin.decimals(), &amount_dec) { @@ -3267,7 +3281,8 @@ impl MmCoin for TendermintCoin { Some(_) => req.ibc_source_channel, None => Some( coin.get_healthy_ibc_channel_for_address_prefix(to_address.prefix()) - .await?, + .await + .map_mm_err()?, ), } } else { @@ -3308,7 +3323,8 @@ impl MmCoin for TendermintCoin { &memo, req.fee, ) - .await?; + .await + .map_mm_err()?; let fee_amount_u64 = if coin.is_ledger_connection() { // When using `SIGN_MODE_LEGACY_AMINO_JSON`, Keplr ignores the fee we calculated @@ -3352,7 +3368,7 @@ impl MmCoin for TendermintCoin { }); } - (sat_from_big_decimal(&req.amount, coin.decimals())?, total) + (sat_from_big_decimal(&req.amount, coin.decimals()).map_mm_err()?, total) }; let msg_payload = create_withdraw_msg_as_any( @@ -3364,7 +3380,7 @@ impl MmCoin for TendermintCoin { ) .await?; - let account_info = coin.account_info(&account_id).await?; + let account_info = coin.account_info(&account_id).await.map_mm_err()?; let tx = coin .any_to_transaction_data(maybe_priv_key, msg_payload, &account_info, fee, timeout_height, &memo) @@ -3407,7 +3423,7 @@ impl MmCoin for TendermintCoin { let coin = self.clone(); let fut = async move { req.tx_hash.make_ascii_uppercase(); - let tx_from_rpc = coin.request_tx(req.tx_hash).await?; + let tx_from_rpc = coin.request_tx(req.tx_hash).await.map_mm_err()?; Ok(RawTransactionRes { tx_hex: tx_from_rpc.encode_to_vec().into(), }) @@ -3423,7 +3439,7 @@ impl MmCoin for TendermintCoin { RawTransactionError::InvalidHashError(format!("Invalid hash length: expected 32, got {}", len)) })?; let hash = hex::encode_upper(H256::from(hash)); - let tx_from_rpc = coin.request_tx(hash).await?; + let tx_from_rpc = coin.request_tx(hash).await.map_mm_err()?; Ok(RawTransactionRes { tx_hex: tx_from_rpc.encode_to_vec().into(), }) @@ -3672,7 +3688,7 @@ impl MarketCoinOps for TendermintCoin { } async fn get_public_key(&self) -> Result> { - let key = SigningKey::from_slice(self.activation_policy.activated_key_or_err()?.as_slice()) + let key = SigningKey::from_slice(self.activation_policy.activated_key_or_err().map_mm_err()?.as_slice()) .expect("privkey validity is checked on coin creation"); Ok(key.public_key().to_string()) } @@ -3697,7 +3713,8 @@ impl MarketCoinOps for TendermintCoin { let fut = async move { let balance_denom = coin .account_balance_for_denom(&coin.account_id, coin.protocol_info.denom.to_string()) - .await?; + .await + .map_mm_err()?; Ok(CoinBalance { spendable: big_decimal_from_sat_unsigned(balance_denom, coin.decimals()), unspendable: BigDecimal::default(), diff --git a/mm2src/coins/tendermint/tendermint_token.rs b/mm2src/coins/tendermint/tendermint_token.rs index 728541e9c3..c85fe08605 100644 --- a/mm2src/coins/tendermint/tendermint_token.rs +++ b/mm2src/coins/tendermint/tendermint_token.rs @@ -292,7 +292,8 @@ impl MarketCoinOps for TendermintToken { let balance_denom = coin .platform_coin .account_balance_for_denom(&coin.platform_coin.account_id, coin.denom.to_string()) - .await?; + .await + .map_mm_err()?; Ok(CoinBalance { spendable: big_decimal_from_sat_unsigned(balance_denom, coin.decimals), unspendable: BigDecimal::default(), @@ -383,11 +384,13 @@ impl MmCoin for TendermintToken { let (base_denom_balance, base_denom_balance_dec) = platform .get_balance_as_unsigned_and_decimal(&account_id, &platform.protocol_info.denom, token.decimals()) - .await?; + .await + .map_mm_err()?; let (balance_denom, balance_dec) = platform .get_balance_as_unsigned_and_decimal(&account_id, &token.denom, token.decimals()) - .await?; + .await + .map_mm_err()?; let (amount_denom, amount_dec, total_amount) = if req.max { ( @@ -405,7 +408,7 @@ impl MmCoin for TendermintToken { } ( - sat_from_big_decimal(&req.amount, token.decimals())?, + sat_from_big_decimal(&req.amount, token.decimals()).map_mm_err()?, req.amount.clone(), req.amount, ) @@ -430,7 +433,8 @@ impl MmCoin for TendermintToken { None => Some( platform .get_healthy_ibc_channel_for_address_prefix(to_address.prefix()) - .await?, + .await + .map_mm_err()?, ), } } else { @@ -470,7 +474,8 @@ impl MmCoin for TendermintToken { &memo, req.fee, ) - .await?; + .await + .map_mm_err()?; let fee_amount_dec = big_decimal_from_sat_unsigned(fee_amount_u64, platform.decimals()); @@ -489,7 +494,7 @@ impl MmCoin for TendermintToken { let fee = Fee::from_amount_and_gas(fee_amount, gas_limit); - let account_info = platform.account_info(&account_id).await?; + let account_info = platform.account_info(&account_id).await.map_mm_err()?; let tx = platform .any_to_transaction_data(maybe_priv_key, msg_payload, &account_info, fee, timeout_height, &memo) diff --git a/mm2src/coins/tx_history_storage/wasm/tx_history_storage_v1.rs b/mm2src/coins/tx_history_storage/wasm/tx_history_storage_v1.rs index c52fefd76d..77baedcb29 100644 --- a/mm2src/coins/tx_history_storage/wasm/tx_history_storage_v1.rs +++ b/mm2src/coins/tx_history_storage/wasm/tx_history_storage_v1.rs @@ -2,6 +2,7 @@ use crate::tx_history_storage::wasm::tx_history_db::TxHistoryDb; use crate::tx_history_storage::wasm::WasmTxHistoryResult; use crate::TransactionDetails; use mm2_db::indexed_db::{DbIdentifier, DbInstance, DbUpgrader, OnUpgradeResult, TableSignature}; +use mm2_err_handle::prelude::MmResultExt; pub async fn load_tx_history( db: &TxHistoryDb, @@ -10,12 +11,13 @@ pub async fn load_tx_history( ) -> WasmTxHistoryResult> { let history_id = HistoryId::new(ticker, wallet_address); - let transaction = db.get_inner().transaction().await?; - let table = transaction.table::().await?; + let transaction = db.get_inner().transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; let item_opt = table .get_item_by_unique_index("history_id", history_id.as_str()) - .await?; + .await + .map_mm_err()?; match item_opt { Some((_item_id, TxHistoryTableV1 { txs, .. })) => Ok(txs), None => Ok(Vec::new()), @@ -32,24 +34,26 @@ pub async fn save_tx_history( let history_id_value = history_id.to_string(); let tx_history_item = TxHistoryTableV1 { history_id, txs }; - let transaction = db.get_inner().transaction().await?; - let table = transaction.table::().await?; + let transaction = db.get_inner().transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; table .replace_item_by_unique_index("history_id", &history_id_value, &tx_history_item) - .await?; + .await + .map_mm_err()?; Ok(()) } pub async fn clear_tx_history(db: &TxHistoryDb, ticker: &str, wallet_address: &str) -> WasmTxHistoryResult<()> { let history_id = HistoryId::new(ticker, wallet_address); - let transaction = db.get_inner().transaction().await?; - let table = transaction.table::().await?; + let transaction = db.get_inner().transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; table .delete_item_by_unique_index("history_id", history_id.as_str()) - .await?; + .await + .map_mm_err()?; Ok(()) } diff --git a/mm2src/coins/tx_history_storage/wasm/tx_history_storage_v2.rs b/mm2src/coins/tx_history_storage/wasm/tx_history_storage_v2.rs index acc6d338e2..6b3f33ee2b 100644 --- a/mm2src/coins/tx_history_storage/wasm/tx_history_storage_v2.rs +++ b/mm2src/coins/tx_history_storage/wasm/tx_history_storage_v2.rs @@ -54,26 +54,29 @@ impl TxHistoryStorage for IndexedDbTxHistoryStorage { I::IntoIter: Send, { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let history_table = db_transaction.table::().await?; - let cache_table = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let history_table = db_transaction.table::().await.map_mm_err()?; + let cache_table = db_transaction.table::().await.map_mm_err()?; for tx in transactions { let Some(tx_hash) = tx.tx.tx_hash() else { continue }; let history_item = TxHistoryTableV2::from_tx_details(wallet_id.clone(), &tx)?; - history_table.add_item(&history_item).await?; + history_table.add_item(&history_item).await.map_mm_err()?; let cache_item = TxCacheTableV2::from_tx_details(wallet_id.clone(), &tx)?; let index_keys = MultiIndex::new(TxCacheTableV2::COIN_TX_HASH_INDEX) - .with_value(&wallet_id.ticker)? - .with_value(tx_hash)?; + .with_value(&wallet_id.ticker) + .map_mm_err()? + .with_value(tx_hash) + .map_mm_err()?; // `TxHistoryTableV2::tx_hash` is not a unique field, but `TxCacheTableV2::tx_hash` is unique. // So we use `DbTable::add_item_or_ignore_by_unique_multi_index` instead of `DbTable::add_item` // since `transactions` may contain txs with same `tx_hash` but different `internal_id`. cache_table .add_item_or_ignore_by_unique_multi_index(index_keys, &cache_item) - .await?; + .await + .map_mm_err()?; } Ok(()) } @@ -84,15 +87,23 @@ impl TxHistoryStorage for IndexedDbTxHistoryStorage { internal_id: &BytesJson, ) -> MmResult { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let table = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; let index_keys = MultiIndex::new(TxHistoryTableV2::WALLET_ID_INTERNAL_ID_INDEX) - .with_value(&wallet_id.ticker)? - .with_value(wallet_id.hd_wallet_rmd160_or_exclude())? - .with_value(internal_id)?; - - if table.delete_item_by_unique_multi_index(index_keys).await?.is_some() { + .with_value(&wallet_id.ticker) + .map_mm_err()? + .with_value(wallet_id.hd_wallet_rmd160_or_exclude()) + .map_mm_err()? + .with_value(internal_id) + .map_mm_err()?; + + if table + .delete_item_by_unique_multi_index(index_keys) + .await + .map_mm_err()? + .is_some() + { Ok(RemoveTxResult::TxRemoved) } else { Ok(RemoveTxResult::TxDidNotExist) @@ -105,15 +116,18 @@ impl TxHistoryStorage for IndexedDbTxHistoryStorage { internal_id: &BytesJson, ) -> MmResult, Self::Error> { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let table = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; let index_keys = MultiIndex::new(TxHistoryTableV2::WALLET_ID_INTERNAL_ID_INDEX) - .with_value(&wallet_id.ticker)? - .with_value(wallet_id.hd_wallet_rmd160_or_exclude())? - .with_value(internal_id)?; - - let details_json = match table.get_item_by_unique_multi_index(index_keys).await? { + .with_value(&wallet_id.ticker) + .map_mm_err()? + .with_value(wallet_id.hd_wallet_rmd160_or_exclude()) + .map_mm_err()? + .with_value(internal_id) + .map_mm_err()?; + + let details_json = match table.get_item_by_unique_multi_index(index_keys).await.map_mm_err()? { Some((_item_id, item)) => item.details_json, None => return Ok(None), }; @@ -133,7 +147,10 @@ impl TxHistoryStorage for IndexedDbTxHistoryStorage { wallet_id: &WalletId, for_addresses: FilteringAddresses, ) -> Result> { - let txs = self.get_unconfirmed_txes_from_history(wallet_id, for_addresses).await?; + let txs = self + .get_unconfirmed_txes_from_history(wallet_id, for_addresses) + .await + .map_mm_err()?; Ok(!txs.is_empty()) } @@ -144,17 +161,21 @@ impl TxHistoryStorage for IndexedDbTxHistoryStorage { for_addresses: FilteringAddresses, ) -> MmResult, Self::Error> { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let table = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; let index_keys = MultiIndex::new(TxHistoryTableV2::WALLET_ID_CONFIRMATION_STATUS_INDEX) - .with_value(&wallet_id.ticker)? - .with_value(wallet_id.hd_wallet_rmd160_or_exclude())? - .with_value(ConfirmationStatus::Unconfirmed)?; + .with_value(&wallet_id.ticker) + .map_mm_err()? + .with_value(wallet_id.hd_wallet_rmd160_or_exclude()) + .map_mm_err()? + .with_value(ConfirmationStatus::Unconfirmed) + .map_mm_err()?; let transactions = table .get_items_by_multi_index(index_keys) - .await? + .await + .map_mm_err()? .into_iter() .map(|(_item_id, item)| item); @@ -164,28 +185,37 @@ impl TxHistoryStorage for IndexedDbTxHistoryStorage { /// Updates transaction in the selected coin's history async fn update_tx_in_history(&self, wallet_id: &WalletId, tx: &TransactionDetails) -> MmResult<(), Self::Error> { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let table = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; let index_keys = MultiIndex::new(TxHistoryTableV2::WALLET_ID_INTERNAL_ID_INDEX) - .with_value(&wallet_id.ticker)? - .with_value(wallet_id.hd_wallet_rmd160_or_exclude())? - .with_value(&tx.internal_id)?; + .with_value(&wallet_id.ticker) + .map_mm_err()? + .with_value(wallet_id.hd_wallet_rmd160_or_exclude()) + .map_mm_err()? + .with_value(&tx.internal_id) + .map_mm_err()?; let item = TxHistoryTableV2::from_tx_details(wallet_id.clone(), tx)?; - table.replace_item_by_unique_multi_index(index_keys, &item).await?; + table + .replace_item_by_unique_multi_index(index_keys, &item) + .await + .map_mm_err()?; Ok(()) } async fn history_has_tx_hash(&self, wallet_id: &WalletId, tx_hash: &str) -> Result> { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let table = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; let index_keys = MultiIndex::new(TxHistoryTableV2::WALLET_ID_TX_HASH_INDEX) - .with_value(&wallet_id.ticker)? - .with_value(wallet_id.hd_wallet_rmd160_or_exclude())? - .with_value(tx_hash)?; - let count_txs = table.count_by_multi_index(index_keys).await?; + .with_value(&wallet_id.ticker) + .map_mm_err()? + .with_value(wallet_id.hd_wallet_rmd160_or_exclude()) + .map_mm_err()? + .with_value(tx_hash) + .map_mm_err()?; + let count_txs = table.count_by_multi_index(index_keys).await.map_mm_err()?; Ok(count_txs > 0) } @@ -196,18 +226,21 @@ impl TxHistoryStorage for IndexedDbTxHistoryStorage { for_addresses: FilteringAddresses, ) -> Result> { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let table = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; let index_keys = MultiIndex::new(TxHistoryTableV2::WALLET_ID_INDEX) - .with_value(&wallet_id.ticker)? - .with_value(wallet_id.hd_wallet_rmd160_or_exclude())?; + .with_value(&wallet_id.ticker) + .map_mm_err()? + .with_value(wallet_id.hd_wallet_rmd160_or_exclude()) + .map_mm_err()?; // `IndexedDb` doesn't provide an elegant way to count records applying custom filters to index properties like `tx_hash`, // so currently fetch all records with `coin,hd_wallet_rmd160=wallet_id` and apply the `unique_by(|tx| tx.tx_hash)` to them. let transactions = table .get_items_by_multi_index(index_keys) - .await? + .await + .map_mm_err()? .into_iter() .map(|(_item_id, tx)| tx) .unique_by(|tx| tx.tx_hash.clone()); @@ -223,8 +256,8 @@ impl TxHistoryStorage for IndexedDbTxHistoryStorage { tx_hex: &BytesJson, ) -> Result<(), MmError> { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let table = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; table .add_item(&TxCacheTableV2 { @@ -232,7 +265,8 @@ impl TxHistoryStorage for IndexedDbTxHistoryStorage { tx_hash: tx_hash.to_owned(), tx_hex: tx_hex.clone(), }) - .await?; + .await + .map_mm_err()?; Ok(()) } @@ -242,13 +276,15 @@ impl TxHistoryStorage for IndexedDbTxHistoryStorage { tx_hash: &str, ) -> MmResult, Self::Error> { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let table = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; let index_keys = MultiIndex::new(TxCacheTableV2::COIN_TX_HASH_INDEX) - .with_value(&wallet_id.ticker)? - .with_value(tx_hash)?; - match table.get_item_by_unique_multi_index(index_keys).await? { + .with_value(&wallet_id.ticker) + .map_mm_err()? + .with_value(tx_hash) + .map_mm_err()?; + match table.get_item_by_unique_multi_index(index_keys).await.map_mm_err()? { Some((_item_id, item)) => Ok(Some(item.tx_hex)), None => Ok(None), } @@ -283,17 +319,21 @@ impl TxHistoryStorage for IndexedDbTxHistoryStorage { } let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let table = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let table = db_transaction.table::().await.map_mm_err()?; let index_keys = MultiIndex::new(TxHistoryTableV2::WALLET_ID_TOKEN_ID_INDEX) - .with_value(&wallet_id.ticker)? - .with_value(wallet_id.hd_wallet_rmd160_or_exclude())? - .with_value(filters.token_id_or_exclude())?; + .with_value(&wallet_id.ticker) + .map_mm_err()? + .with_value(wallet_id.hd_wallet_rmd160_or_exclude()) + .map_mm_err()? + .with_value(filters.token_id_or_exclude()) + .map_mm_err()?; let transactions = table .get_items_by_multi_index(index_keys) - .await? + .await + .map_mm_err()? .into_iter() .map(|(_item_id, tx)| tx); diff --git a/mm2src/coins/utxo.rs b/mm2src/coins/utxo.rs index 53e9bc7cdb..b03e27f6c1 100644 --- a/mm2src/coins/utxo.rs +++ b/mm2src/coins/utxo.rs @@ -242,7 +242,7 @@ impl From for TxProviderError { #[async_trait] impl TxProvider for UtxoRpcClientEnum { async fn get_rpc_transaction(&self, tx_hash: &H256Json) -> Result> { - Ok(self.get_verbose_transaction(tx_hash).compat().await?) + Ok(self.get_verbose_transaction(tx_hash).compat().await.map_mm_err()?) } } diff --git a/mm2src/coins/utxo/bch.rs b/mm2src/coins/utxo/bch.rs index 8694710907..8e5aab5c5b 100644 --- a/mm2src/coins/utxo/bch.rs +++ b/mm2src/coins/utxo/bch.rs @@ -64,7 +64,7 @@ impl BchActivationRequest { pub fn from_legacy_req(req: &Json) -> Result> { let bchd_urls = json::from_value(req["bchd_urls"].clone()).map_to_mm(BchFromLegacyReqErr::InvalidBchdUrls)?; let allow_slp_unsafe_conf = req["allow_slp_unsafe_conf"].as_bool().unwrap_or_default(); - let utxo_params = UtxoActivationParams::from_legacy_req(req)?; + let utxo_params = UtxoActivationParams::from_legacy_req(req).map_mm_err()?; Ok(BchActivationRequest { allow_slp_unsafe_conf, @@ -493,7 +493,7 @@ impl BchCoin { ) -> MmResult { let token_genesis_tx = self.tx_from_storage_or_rpc(&token_id.into(), storage).await?; let maybe_genesis_script: Script = token_genesis_tx.outputs[0].script_pubkey.clone().into(); - let slp_details = parse_slp_script(&maybe_genesis_script)?; + let slp_details = parse_slp_script(&maybe_genesis_script).map_mm_err()?; match slp_details.transaction { SlpTransaction::Genesis(params) => Ok(params), _ => { @@ -1160,8 +1160,13 @@ impl MarketCoinOps for BchCoin { fn my_balance(&self) -> BalanceFut { let coin = self.clone(); let fut = async move { - let my_address = coin.as_ref().derivation_method.single_addr_or_err().await?; - let bch_unspents = coin.bch_unspents_for_display(&my_address).await?; + let my_address = coin + .as_ref() + .derivation_method + .single_addr_or_err() + .await + .map_mm_err()?; + let bch_unspents = coin.bch_unspents_for_display(&my_address).await.map_mm_err()?; Ok(bch_unspents.platform_balance(coin.as_ref().decimals)) }; Box::new(fut.boxed().compat()) @@ -1474,7 +1479,7 @@ impl CoinWithTxHistoryV2 for BchCoin { return MmError::err(MyTxHistoryErrorV2::InvalidTarget(error)); }, } - let my_address = self.my_address()?; + let my_address = self.my_address().map_mm_err()?; Ok(GetTxHistoryFilters::for_address(my_address)) } } @@ -1482,7 +1487,7 @@ impl CoinWithTxHistoryV2 for BchCoin { #[async_trait] impl UtxoTxHistoryOps for BchCoin { async fn my_addresses(&self) -> MmResult, UtxoMyAddressesHistoryError> { - let addresses = self.all_addresses().await?; + let addresses = self.all_addresses().await.map_mm_err()?; Ok(addresses) } diff --git a/mm2src/coins/utxo/bchd_grpc.rs b/mm2src/coins/utxo/bchd_grpc.rs index c7c01d073b..56c4bc3849 100644 --- a/mm2src/coins/utxo/bchd_grpc.rs +++ b/mm2src/coins/utxo/bchd_grpc.rs @@ -130,7 +130,8 @@ pub async fn validate_slp_utxos( .iter() .map(|url| url.as_ref().to_owned() + "/pb.bchrpc/GetSlpTrustedValidation") .collect(); - let responses: Vec<(_, GetSlpTrustedValidationResponse)> = grpc_web_multi_url_request(&urls, &request).await?; + let responses: Vec<(_, GetSlpTrustedValidationResponse)> = + grpc_web_multi_url_request(&urls, &request).await.map_mm_err()?; for (url, response) in responses { for validation_result in response.results { let actual_token_id = { @@ -253,7 +254,8 @@ pub async fn check_slp_transaction( .map(|url| url.as_ref().to_owned() + "/pb.bchrpc/CheckSlpTransaction") .collect(); - let responses: Vec<(_, CheckSlpTransactionResponse)> = grpc_web_multi_url_request(&urls, &request).await?; + let responses: Vec<(_, CheckSlpTransactionResponse)> = + grpc_web_multi_url_request(&urls, &request).await.map_mm_err()?; for (url, response) in responses { if !response.is_valid { return MmError::err(CheckSlpTransactionErr { diff --git a/mm2src/coins/utxo/qtum.rs b/mm2src/coins/utxo/qtum.rs index a45b4a9491..472baedcfa 100644 --- a/mm2src/coins/utxo/qtum.rs +++ b/mm2src/coins/utxo/qtum.rs @@ -156,7 +156,12 @@ pub trait QtumBasedCoin: UtxoCommonOps + MarketCoinOps { } async fn my_addr_as_contract_addr(&self) -> MmResult { - let my_address = self.as_ref().derivation_method.single_addr_or_err().await?; + let my_address = self + .as_ref() + .derivation_method + .single_addr_or_err() + .await + .map_mm_err()?; contract_addr_from_utxo_addr(my_address).mm_err(Qrc20AddressError::from) } @@ -1200,7 +1205,7 @@ impl CoinWithTxHistoryV2 for QtumCoin { #[async_trait] impl UtxoTxHistoryOps for QtumCoin { async fn my_addresses(&self) -> MmResult, UtxoMyAddressesHistoryError> { - let addresses = self.all_addresses().await?; + let addresses = self.all_addresses().await.map_mm_err()?; Ok(addresses) } diff --git a/mm2src/coins/utxo/qtum_delegation.rs b/mm2src/coins/utxo/qtum_delegation.rs index 3723109720..a37eba4cdf 100644 --- a/mm2src/coins/utxo/qtum_delegation.rs +++ b/mm2src/coins/utxo/qtum_delegation.rs @@ -105,11 +105,12 @@ impl QtumDelegationOps for QtumCoin { let mut buffer = b"\x15Qtum Signed Message:\n\x28".to_vec(); buffer.append(&mut addr_hash.to_string().into_bytes()); let hashed = dhash256(&buffer); - let key_pair = self.as_ref().priv_key_policy.activated_key_or_err()?; + let key_pair = self.as_ref().priv_key_policy.activated_key_or_err().map_mm_err()?; let signature = key_pair .private() .sign_compact(&hashed) - .map_to_mm(|e| QtumStakingAbiError::PodSigningError(e.to_string()))?; + .map_to_mm(|e| QtumStakingAbiError::PodSigningError(e.to_string())) + .map_mm_err()?; Ok(signature) } } @@ -121,9 +122,11 @@ impl QtumCoin { reason: "Qtum doesn't support delegation for segwit".to_string(), }); } - let delegation_output = self.remove_delegation_output(QRC20_GAS_LIMIT_DEFAULT, QRC20_GAS_PRICE_DEFAULT)?; + let delegation_output = self + .remove_delegation_output(QRC20_GAS_LIMIT_DEFAULT, QRC20_GAS_PRICE_DEFAULT) + .map_mm_err()?; let outputs = vec![delegation_output]; - let my_address = self.my_address()?; + let my_address = self.my_address().map_mm_err()?; self.generate_delegation_transaction( outputs, my_address, @@ -142,7 +145,7 @@ impl QtumCoin { }, UtxoRpcClientEnum::Electrum(electrum) => electrum, }; - let address = self.my_addr_as_contract_addr().await?; + let address = self.my_addr_as_contract_addr().await.map_mm_err()?; let address_rpc = contract_addr_into_rpc_format(&address); let add_delegation_history = client .blockchain_contract_event_get_history(&address_rpc, &contract_address, QTUM_ADD_DELEGATION_TOPIC) @@ -198,10 +201,10 @@ impl QtumCoin { async fn get_delegation_infos_impl(&self) -> StakingInfosResult { let coin = self.as_ref(); - let my_address = coin.derivation_method.single_addr_or_err().await?; + let my_address = coin.derivation_method.single_addr_or_err().await.map_mm_err()?; let staker = self.am_i_currently_staking().await?; - let (unspents, _) = self.get_unspent_ordered_list(&my_address).await?; + let (unspents, _) = self.get_unspent_ordered_list(&my_address).await.map_mm_err()?; let lower_bound = QTUM_LOWER_BOUND_DELEGATION_AMOUNT .try_into() .expect("Conversion should succeed"); @@ -232,7 +235,7 @@ impl QtumCoin { reason: "Qtum doesn't support delegation for segwit".to_string(), }); } - if let Some(staking_addr) = self.am_i_currently_staking().await? { + if let Some(staking_addr) = self.am_i_currently_staking().await.map_mm_err()? { return MmError::err(DelegationError::AlreadyDelegating(staking_addr)); } let to_addr = @@ -240,7 +243,7 @@ impl QtumCoin { .map_to_mm(DelegationError::AddressError)?; let fee = request.fee.unwrap_or(QTUM_DELEGATION_STANDARD_FEE); let _utxo_lock = UTXO_LOCK.lock(); - let staker_address_hex = qtum::contract_addr_from_utxo_addr(to_addr.clone())?; + let staker_address_hex = qtum::contract_addr_from_utxo_addr(to_addr.clone()).map_mm_err()?; let delegation_output = self.add_delegation_output( staker_address_hex, to_addr.hash().clone(), @@ -250,7 +253,7 @@ impl QtumCoin { )?; let outputs = vec![delegation_output]; - let my_address = self.my_address()?; + let my_address = self.my_address().map_mm_err()?; self.generate_delegation_transaction( outputs, my_address, @@ -269,10 +272,10 @@ impl QtumCoin { ) -> DelegationResult { let utxo = self.as_ref(); - let key_pair = utxo.priv_key_policy.activated_key_or_err()?; - let my_address = utxo.derivation_method.single_addr_or_err().await?; + let key_pair = utxo.priv_key_policy.activated_key_or_err().map_mm_err()?; + let my_address = utxo.derivation_method.single_addr_or_err().await.map_mm_err()?; - let (unspents, _) = self.get_unspent_ordered_list(&my_address).await?; + let (unspents, _) = self.get_unspent_ordered_list(&my_address).await.map_mm_err()?; let mut gas_fee = 0; let mut outputs = Vec::with_capacity(contract_outputs.len()); for output in contract_outputs { @@ -292,7 +295,7 @@ impl QtumCoin { DelegationError::from_generate_tx_error(gen_tx_error, self.ticker().to_string(), utxo.decimals) })?; - let signed = sign_tx(unsigned, key_pair, utxo.conf.signature_version, utxo.conf.fork_id)?; + let signed = sign_tx(unsigned, key_pair, utxo.conf.signature_version, utxo.conf.fork_id).map_mm_err()?; let generated_tx = GenerateQrc20TxResult { signed, @@ -308,7 +311,7 @@ impl QtumCoin { gas_price: QRC20_GAS_PRICE_DEFAULT, total_gas_fee: utxo_common::big_decimal_from_sat(generated_tx.gas_fee as i64, utxo.decimals), }; - let my_address_string = self.my_address()?; + let my_address_string = self.my_address().map_mm_err()?; let spent_by_me = utxo_common::big_decimal_from_sat(data.spent_by_me as i64, utxo.decimals); let qtum_amount = spent_by_me.clone(); @@ -345,7 +348,8 @@ impl QtumCoin { gas_limit, gas_price, QTUM_DELEGATE_CONTRACT_ADDRESS.as_bytes(), - )? + ) + .map_mm_err()? .to_bytes(); Ok(ContractCallOutput { value: OUTPUT_QTUM_AMOUNT, @@ -377,7 +381,8 @@ impl QtumCoin { gas_limit, gas_price, QTUM_DELEGATE_CONTRACT_ADDRESS.as_bytes(), - )? + ) + .map_mm_err()? .to_bytes(); Ok(ContractCallOutput { value: OUTPUT_QTUM_AMOUNT, diff --git a/mm2src/coins/utxo/rpc_clients.rs b/mm2src/coins/utxo/rpc_clients.rs index fce6afa82a..f09d7ddf67 100644 --- a/mm2src/coins/utxo/rpc_clients.rs +++ b/mm2src/coins/utxo/rpc_clients.rs @@ -785,7 +785,7 @@ impl UtxoRpcClientOps for NativeClient { .and_then(move |unspents| { unspents .into_iter() - .map(|unspent| Ok(UnspentInfo::from_native(unspent, decimals, None)?)) + .map(|unspent| UnspentInfo::from_native(unspent, decimals, None).map_mm_err()) .collect::>() }); Box::new(fut) @@ -814,7 +814,7 @@ impl UtxoRpcClientOps for NativeClient { UtxoRpcError::InvalidResponse(format!("Unexpected address '{}'", unspent.address)) })? .clone(); - let unspent_info = UnspentInfo::from_native(unspent, decimals, None)?; + let unspent_info = UnspentInfo::from_native(unspent, decimals, None).map_mm_err()?; Ok((orig_address, unspent_info)) }) // Collect `(Address, UnspentInfo)` items into `HashMap>` grouped by the addresses. @@ -991,7 +991,7 @@ impl UtxoRpcClientOps for NativeClient { } async fn get_block_timestamp(&self, height: u64) -> Result> { - let block = self.get_block_by_height(height).await?; + let block = self.get_block_by_height(height).await.map_mm_err()?; Ok(block.time as u64) } } diff --git a/mm2src/coins/utxo/rpc_clients/electrum_rpc/client.rs b/mm2src/coins/utxo/rpc_clients/electrum_rpc/client.rs index 3cf3996f09..dec5920659 100644 --- a/mm2src/coins/utxo/rpc_clients/electrum_rpc/client.rs +++ b/mm2src/coins/utxo/rpc_clients/electrum_rpc/client.rs @@ -610,7 +610,12 @@ impl ElectrumClient { // This method should always be used if the block headers are saved to the DB async fn get_tx_height_from_storage(&self, tx: &UtxoTx) -> Result> { let tx_hash = tx.hash().reversed(); - let blockhash = self.get_verbose_transaction(&tx_hash.into()).compat().await?.blockhash; + let blockhash = self + .get_verbose_transaction(&tx_hash.into()) + .compat() + .await + .map_mm_err()? + .blockhash; Ok(self .block_headers_storage() .get_block_height_by_hash(blockhash.into()) @@ -688,7 +693,7 @@ impl ElectrumClient { &self, tx: &UtxoTx, ) -> Result<(TxMerkleBranch, BlockHeader, u64), MmError> { - let height = self.get_tx_height_from_storage(tx).await?; + let height = self.get_tx_height_from_storage(tx).await.map_mm_err()?; let merkle_branch = self .blockchain_transaction_get_merkle(tx.hash().reversed().into(), height) @@ -699,7 +704,7 @@ impl ElectrumClient { err: err.to_string(), })?; - let header = self.block_header_from_storage(height).await?; + let header = self.block_header_from_storage(height).await.map_mm_err()?; Ok((merkle_branch, header, height)) } diff --git a/mm2src/coins/utxo/slp.rs b/mm2src/coins/utxo/slp.rs index 5a537e42dc..13ac99cbe0 100644 --- a/mm2src/coins/utxo/slp.rs +++ b/mm2src/coins/utxo/slp.rs @@ -348,7 +348,7 @@ impl SlpToken { if slp_outputs.len() > 18 { return MmError::err(GenSlpSpendErr::TooManyOutputs); } - let (slp_unspents, bch_unspents, recently_spent) = self.slp_unspents_for_spend().await?; + let (slp_unspents, bch_unspents, recently_spent) = self.slp_unspents_for_spend().await.map_mm_err()?; let total_slp_output = slp_outputs.iter().fold(0, |cur, slp_out| cur + slp_out.amount); let mut total_slp_input = 0; @@ -385,7 +385,7 @@ impl SlpToken { })); if change > 0 { - let my_public_key = self.platform_coin.my_public_key()?; + let my_public_key = self.platform_coin.my_public_key().map_mm_err()?; let slp_change_out = TransactionOutput { value: self.platform_dust(), script_pubkey: ScriptBuilder::build_p2pkh(&my_public_key.address_hash().into()).to_bytes(), @@ -393,7 +393,9 @@ impl SlpToken { outputs.push(slp_change_out); } - validate_slp_utxos(self.platform_coin.bchd_urls(), &inputs, self.token_id()).await?; + validate_slp_utxos(self.platform_coin.bchd_urls(), &inputs, self.token_id()) + .await + .map_mm_err()?; let preimage = SlpTxPreimage { slp_inputs: inputs, available_bch_inputs: bch_unspents, @@ -447,7 +449,7 @@ impl SlpToken { )); } - let slp_satoshis = sat_from_big_decimal(&input.amount, self.decimals())?; + let slp_satoshis = sat_from_big_decimal(&input.amount, self.decimals()).map_mm_err()?; let slp_unspent = SlpUnspent { bch_unspent: UnspentInfo { @@ -461,9 +463,11 @@ impl SlpToken { }, slp_amount: slp_satoshis, }; - validate_slp_utxos(self.platform_coin.bchd_urls(), &[slp_unspent], self.token_id()).await?; + validate_slp_utxos(self.platform_coin.bchd_urls(), &[slp_unspent], self.token_id()) + .await + .map_mm_err()?; - let slp_tx: SlpTxDetails = parse_slp_script(tx.outputs[0].script_pubkey.as_slice())?; + let slp_tx: SlpTxDetails = parse_slp_script(tx.outputs[0].script_pubkey.as_slice()).map_mm_err()?; match slp_tx.transaction { SlpTransaction::Send { token_id, amounts } => { @@ -533,10 +537,10 @@ impl SlpToken { return MmError::err(SpendHtlcError::TxLackOfOutputs); } - let slp_tx: SlpTxDetails = parse_slp_script(tx.outputs[0].script_pubkey.as_slice())?; + let slp_tx: SlpTxDetails = parse_slp_script(tx.outputs[0].script_pubkey.as_slice()).map_mm_err()?; let other_pub = Public::from_slice(other_pub)?; - let my_public_key = self.platform_coin.my_public_key()?; + let my_public_key = self.platform_coin.my_public_key().map_mm_err()?; let redeem_script = payment_script(time_lock, secret_hash, my_public_key, &other_pub); let slp_amount = match slp_tx.transaction { @@ -561,7 +565,7 @@ impl SlpToken { slp_amount, }; - let tx_locktime = self.platform_coin.p2sh_tx_locktime(time_lock).await?; + let tx_locktime = self.platform_coin.p2sh_tx_locktime(time_lock).await.map_mm_err()?; let script_data = ScriptBuilder::default().push_opcode(Opcode::OP_1).into_script(); let tx = self .spend_p2sh( @@ -572,7 +576,8 @@ impl SlpToken { redeem_script, htlc_keypair, ) - .await?; + .await + .map_mm_err()?; Ok(tx) } @@ -613,14 +618,15 @@ impl SlpToken { slp_amount, }; - let tx_locktime = self.platform_coin.p2sh_tx_locktime(time_lock).await?; + let tx_locktime = self.platform_coin.p2sh_tx_locktime(time_lock).await.map_mm_err()?; let script_data = ScriptBuilder::default() .push_data(secret) .push_opcode(Opcode::OP_0) .into_script(); let tx = self .spend_p2sh(slp_utxo, tx_locktime, SEQUENCE_FINAL, script_data, redeem, keypair) - .await?; + .await + .map_mm_err()?; Ok(tx) } @@ -637,7 +643,7 @@ impl SlpToken { let mut outputs = Vec::with_capacity(3); outputs.push(op_return_out_mm); - let my_public_key = self.platform_coin.my_public_key()?; + let my_public_key = self.platform_coin.my_public_key().map_mm_err()?; let my_script_pubkey = ScriptBuilder::build_p2pkh(&my_public_key.address_hash().into()); let slp_output = TransactionOutput { value: self.platform_dust(), @@ -645,19 +651,25 @@ impl SlpToken { }; outputs.push(slp_output); - let (_, bch_inputs, _recently_spent) = self.slp_unspents_for_spend().await?; + let (_, bch_inputs, _recently_spent) = self.slp_unspents_for_spend().await.map_mm_err()?; let (mut unsigned, _) = UtxoTxBuilder::new(&self.platform_coin) .await .add_required_inputs(std::iter::once(p2sh_utxo.bch_unspent)) .add_available_inputs(bch_inputs) .add_outputs(outputs) .build() - .await?; + .await + .map_mm_err()?; unsigned.lock_time = tx_locktime; unsigned.inputs[0].sequence = input_sequence; - let my_key_pair = self.platform_coin.as_ref().priv_key_policy.activated_key_or_err()?; + let my_key_pair = self + .platform_coin + .as_ref() + .priv_key_policy + .activated_key_or_err() + .map_mm_err()?; let signed_p2sh_input = p2sh_spend( &unsigned, 0, @@ -666,7 +678,8 @@ impl SlpToken { redeem_script, self.platform_coin.as_ref().conf.signature_version, self.platform_coin.as_ref().conf.fork_id, - )?; + ) + .map_mm_err()?; let signed_inputs: Result, _> = unsigned .inputs @@ -684,7 +697,7 @@ impl SlpToken { }) .collect(); - let mut signed_inputs = signed_inputs?; + let mut signed_inputs = signed_inputs.map_mm_err()?; signed_inputs.insert(0, signed_p2sh_input); @@ -715,7 +728,8 @@ impl SlpToken { .rpc() .send_raw_transaction(serialize(&signed).into()) .compat() - .await?; + .await + .map_mm_err()?; Ok(signed) } @@ -730,7 +744,7 @@ impl SlpToken { return MmError::err(ValidateDexFeeError::TxLackOfOutputs); } - let slp_tx: SlpTxDetails = parse_slp_script(tx.outputs[0].script_pubkey.as_slice())?; + let slp_tx: SlpTxDetails = parse_slp_script(tx.outputs[0].script_pubkey.as_slice()).map_mm_err()?; match slp_tx.transaction { SlpTransaction::Send { token_id, amounts } => { @@ -742,7 +756,7 @@ impl SlpToken { return MmError::err(ValidateDexFeeError::InvalidSlpDetails); } - let expected = sat_from_big_decimal(&amount, self.decimals())?; + let expected = sat_from_big_decimal(&amount, self.decimals()).map_mm_err()?; if amounts[0] != expected { return MmError::err(ValidateDexFeeError::InvalidSlpDetails); @@ -1066,7 +1080,12 @@ impl UtxoTxBroadcastOps for SlpToken { .await .mm_err(|e| BroadcastTxErr::Other(e.to_string()))?; - let hash = self.rpc().send_raw_transaction(tx_bytes.into()).compat().await?; + let hash = self + .rpc() + .send_raw_transaction(tx_bytes.into()) + .compat() + .await + .map_mm_err()?; Ok(hash) } @@ -1140,7 +1159,7 @@ impl MarketCoinOps for SlpToken { fn my_balance(&self) -> BalanceFut { let coin = self.clone(); - let fut = async move { Ok(coin.my_coin_balance().await?) }; + let fut = async move { coin.my_coin_balance().await.map_mm_err() }; Box::new(fut.boxed().compat()) } @@ -1493,7 +1512,12 @@ impl MmCoin for SlpToken { )); } - let key_pair = coin.platform_coin.as_ref().priv_key_policy.activated_key_or_err()?; + let key_pair = coin + .platform_coin + .as_ref() + .priv_key_policy + .activated_key_or_err() + .map_mm_err()?; let address = CashAddress::decode(&req.to).map_to_mm(WithdrawError::InvalidAddress)?; if address.prefix != *coin.slp_prefix() { @@ -1504,9 +1528,9 @@ impl MmCoin for SlpToken { ))); }; let amount = if req.max { - coin.my_balance_sat().await? + coin.my_balance_sat().await.map_mm_err()? } else { - sat_from_big_decimal(&req.amount, coin.decimals())? + sat_from_big_decimal(&req.amount, coin.decimals()).map_mm_err()? }; let address_hash = address.hash.clone(); @@ -1530,7 +1554,7 @@ impl MmCoin for SlpToken { }, }; let slp_output = SlpOutput { amount, script_pubkey }; - let (slp_preimage, _) = coin.generate_slp_tx_preimage(vec![slp_output]).await?; + let (slp_preimage, _) = coin.generate_slp_tx_preimage(vec![slp_output]).await.map_mm_err()?; let mut tx_builder = UtxoTxBuilder::new(&coin.platform_coin) .await .add_required_inputs(slp_preimage.slp_inputs.into_iter().map(|slp| slp.bch_unspent)) @@ -1540,11 +1564,11 @@ impl MmCoin for SlpToken { let platform_decimals = coin.platform_decimals(); match req.fee { Some(WithdrawFee::UtxoFixed { amount }) => { - let fixed = sat_from_big_decimal(&amount, platform_decimals)?; + let fixed = sat_from_big_decimal(&amount, platform_decimals).map_mm_err()?; tx_builder = tx_builder.with_fee(ActualFeeRate::FixedPerKb(fixed)) }, Some(WithdrawFee::UtxoPerKbyte { amount }) => { - let dynamic = sat_from_big_decimal(&amount, platform_decimals)?; + let dynamic = sat_from_big_decimal(&amount, platform_decimals).map_mm_err()?; tx_builder = tx_builder.with_fee(ActualFeeRate::Dynamic(dynamic)); }, Some(fee_policy) => { @@ -1566,12 +1590,13 @@ impl MmCoin for SlpToken { key_pair, coin.platform_conf().signature_version, coin.platform_conf().fork_id, - )?; + ) + .map_mm_err()?; let fee_details = SlpFeeDetails { amount: big_decimal_from_sat_unsigned(tx_data.fee_amount, coin.platform_decimals()), coin: coin.platform_coin.ticker().into(), }; - let my_address_string = coin.my_address()?; + let my_address_string = coin.my_address().map_mm_err()?; let to_address = address.encode().map_to_mm(WithdrawError::InternalError)?; let total_amount = big_decimal_from_sat_unsigned(amount, coin.decimals()); @@ -1660,7 +1685,7 @@ impl MmCoin for SlpToken { ) -> TradePreimageResult { let slp_amount = match value { TradePreimageValue::Exact(decimal) | TradePreimageValue::UpperBound(decimal) => { - sat_from_big_decimal(&decimal, self.decimals())? + sat_from_big_decimal(&decimal, self.decimals()).map_mm_err()? }, }; // can use dummy P2SH script_pubkey here @@ -1669,7 +1694,7 @@ impl MmCoin for SlpToken { amount: slp_amount, script_pubkey, }; - let (preimage, _) = self.generate_slp_tx_preimage(vec![slp_out]).await?; + let (preimage, _) = self.generate_slp_tx_preimage(vec![slp_out]).await.map_mm_err()?; let fee = utxo_common::preimage_trade_fee_required_to_send_outputs( &self.platform_coin, self.platform_ticker(), @@ -1693,7 +1718,8 @@ impl MmCoin for SlpToken { let htlc_fee = coin .platform_coin .get_htlc_spend_fee(SLP_HTLC_SPEND_SIZE, &FeeApproxStage::WithoutApprox) - .await?; + .await + .map_mm_err()?; let amount = (big_decimal_from_sat_unsigned(htlc_fee, coin.platform_decimals()) + coin.platform_dust_dec()).into(); Ok(TradeFee { @@ -1711,14 +1737,14 @@ impl MmCoin for SlpToken { dex_fee_amount: DexFee, stage: FeeApproxStage, ) -> TradePreimageResult { - let slp_amount = sat_from_big_decimal(&dex_fee_amount.fee_amount().into(), self.decimals())?; + let slp_amount = sat_from_big_decimal(&dex_fee_amount.fee_amount().into(), self.decimals()).map_mm_err()?; // can use dummy P2PKH script_pubkey here let script_pubkey = ScriptBuilder::build_p2pkh(&H160::default().into()).into(); let slp_out = SlpOutput { amount: slp_amount, script_pubkey, }; - let (preimage, _) = self.generate_slp_tx_preimage(vec![slp_out]).await?; + let (preimage, _) = self.generate_slp_tx_preimage(vec![slp_out]).await.map_mm_err()?; let fee = utxo_common::preimage_trade_fee_required_to_send_outputs( &self.platform_coin, self.platform_ticker(), @@ -1787,7 +1813,7 @@ impl CoinWithTxHistoryV2 for SlpToken { MyTxHistoryTarget::Iguana => (), target => return MmError::err(MyTxHistoryErrorV2::with_expected_target(target, "Iguana")), } - let my_address = self.my_address()?; + let my_address = self.my_address().map_mm_err()?; Ok(GetTxHistoryFilters::for_address(my_address).with_token_id(self.token_id().to_string())) } } diff --git a/mm2src/coins/utxo/utxo_builder/utxo_coin_builder.rs b/mm2src/coins/utxo/utxo_builder/utxo_coin_builder.rs index 03ccd6fd8b..3c26f99c7d 100644 --- a/mm2src/coins/utxo/utxo_builder/utxo_coin_builder.rs +++ b/mm2src/coins/utxo/utxo_builder/utxo_coin_builder.rs @@ -141,7 +141,9 @@ pub trait UtxoFieldsWithIguanaSecretBuilder: UtxoCoinBuilderCommonOps { &self, priv_key: IguanaPrivKey, ) -> UtxoCoinBuildResult { - let conf = UtxoConfBuilder::new(self.conf(), self.activation_params(), self.ticker()).build()?; + let conf = UtxoConfBuilder::new(self.conf(), self.activation_params(), self.ticker()) + .build() + .map_mm_err()?; let private = Private { prefix: conf.wif_prefix, secret: priv_key, @@ -171,13 +173,16 @@ pub trait UtxoFieldsWithGlobalHDBuilder: UtxoCoinBuilderCommonOps { &self, global_hd_ctx: GlobalHDAccountArc, ) -> UtxoCoinBuildResult { - let conf = UtxoConfBuilder::new(self.conf(), self.activation_params(), self.ticker()).build()?; + let conf = UtxoConfBuilder::new(self.conf(), self.activation_params(), self.ticker()) + .build() + .map_mm_err()?; let path_to_address = self.activation_params().path_to_address; let path_to_coin = conf .derivation_path .as_ref() - .or_mm_err(|| UtxoConfError::DerivationPathIsNotSet)?; + .or_mm_err(|| UtxoConfError::DerivationPathIsNotSet) + .map_mm_err()?; let secret = global_hd_ctx .derive_secp256k1_secret( &path_to_address @@ -202,7 +207,9 @@ pub trait UtxoFieldsWithGlobalHDBuilder: UtxoCoinBuilderCommonOps { let address_format = self.address_format()?; let hd_wallet_rmd160 = *self.ctx().rmd160(); let hd_wallet_storage = - HDWalletCoinStorage::init_with_rmd160(self.ctx(), self.ticker().to_owned(), hd_wallet_rmd160).await?; + HDWalletCoinStorage::init_with_rmd160(self.ctx(), self.ticker().to_owned(), hd_wallet_rmd160) + .await + .map_mm_err()?; let accounts = load_hd_accounts_from_storage(&hd_wallet_storage, path_to_coin) .await .mm_err(UtxoCoinBuildError::from)?; @@ -234,7 +241,7 @@ async fn build_utxo_coin_fields_with_conf_and_policy( where Builder: UtxoCoinBuilderCommonOps + Sync + ?Sized, { - let key_pair = priv_key_policy.activated_key_or_err()?; + let key_pair = priv_key_policy.activated_key_or_err().map_mm_err()?; let addr_format = builder.address_format()?; let my_address = AddressBuilder::new( addr_format, @@ -290,7 +297,9 @@ where pub trait UtxoFieldsWithHardwareWalletBuilder: UtxoCoinBuilderCommonOps { async fn build_utxo_fields_with_trezor(&self) -> UtxoCoinBuildResult { let ticker = self.ticker().to_owned(); - let conf = UtxoConfBuilder::new(self.conf(), self.activation_params(), &ticker).build()?; + let conf = UtxoConfBuilder::new(self.conf(), self.activation_params(), &ticker) + .build() + .map_mm_err()?; if !self.supports_trezor(&conf) { return MmError::err(UtxoCoinBuildError::CoinDoesntSupportTrezor); @@ -301,9 +310,10 @@ pub trait UtxoFieldsWithHardwareWalletBuilder: UtxoCoinBuilderCommonOps { let path_to_coin = conf .derivation_path .clone() - .or_mm_err(|| UtxoConfError::DerivationPathIsNotSet)?; + .or_mm_err(|| UtxoConfError::DerivationPathIsNotSet) + .map_mm_err()?; - let hd_wallet_storage = HDWalletCoinStorage::init(self.ctx(), ticker).await?; + let hd_wallet_storage = HDWalletCoinStorage::init(self.ctx(), ticker).await.map_mm_err()?; let accounts = load_hd_accounts_from_storage(&hd_wallet_storage, &path_to_coin) .await @@ -370,7 +380,7 @@ pub trait UtxoFieldsWithHardwareWalletBuilder: UtxoCoinBuilderCommonOps { fn supports_trezor(&self, conf: &UtxoCoinConf) -> bool { conf.trezor_coin.is_some() } fn trezor_wallet_rmd160(&self) -> UtxoCoinBuildResult { - let crypto_ctx = CryptoCtx::from_ctx(self.ctx())?; + let crypto_ctx = CryptoCtx::from_ctx(self.ctx()).map_mm_err()?; let hw_ctx = crypto_ctx .hw_ctx() .or_mm_err(|| UtxoCoinBuildError::HwContextNotInitialized)?; @@ -380,7 +390,7 @@ pub trait UtxoFieldsWithHardwareWalletBuilder: UtxoCoinBuilderCommonOps { } fn check_if_trezor_is_initialized(&self) -> UtxoCoinBuildResult<()> { - let crypto_ctx = CryptoCtx::from_ctx(self.ctx())?; + let crypto_ctx = CryptoCtx::from_ctx(self.ctx()).map_mm_err()?; let hw_ctx = crypto_ctx .hw_ctx() .or_mm_err(|| UtxoCoinBuildError::HwContextNotInitialized)?; @@ -403,7 +413,8 @@ pub trait UtxoCoinBuilderCommonOps { fn address_format(&self) -> UtxoCoinBuildResult { let format_from_req = self.activation_params().address_format.clone(); let format_from_conf = json::from_value::>(self.conf()["address_format"].clone()) - .map_to_mm(|e| UtxoConfError::InvalidAddressFormat(e.to_string()))? + .map_to_mm(|e| UtxoConfError::InvalidAddressFormat(e.to_string())) + .map_mm_err()? .unwrap_or(UtxoAddressFormat::Standard); let mut address_format = match format_from_req { @@ -625,7 +636,8 @@ pub trait UtxoCoinBuilderCommonOps { None => { let name = conf["name"] .as_str() - .or_mm_err(|| UtxoConfError::CurrencyNameIsNotSet)?; + .or_mm_err(|| UtxoConfError::CurrencyNameIsNotSet) + .map_mm_err()?; (name, false) }, } diff --git a/mm2src/coins/utxo/utxo_common.rs b/mm2src/coins/utxo/utxo_common.rs index 73f7043784..701cf58db0 100644 --- a/mm2src/coins/utxo/utxo_common.rs +++ b/mm2src/coins/utxo/utxo_common.rs @@ -142,7 +142,9 @@ pub async fn produce_hd_address_scanner(coin: &T) -> BalanceResult, { - Ok(UtxoAddressScanner::init(coin.as_ref().rpc_client.clone()).await?) + UtxoAddressScanner::init(coin.as_ref().rpc_client.clone()) + .await + .map_mm_err() } pub async fn scan_for_new_addresses( @@ -214,7 +216,7 @@ where T: UtxoCommonOps + GetUtxoListOps + MarketCoinOps, { if coin.as_ref().check_utxo_maturity { - let (unspents, _) = coin.get_mature_unspent_ordered_list(address).await?; + let (unspents, _) = coin.get_mature_unspent_ordered_list(address).await.map_mm_err()?; return Ok(unspents.to_coin_balance(coin.as_ref().decimals)); } @@ -238,7 +240,10 @@ where T: UtxoCommonOps + GetUtxoMapOps + MarketCoinOps, { if coin.as_ref().check_utxo_maturity { - let (unspents_map, _) = coin.get_mature_unspent_ordered_map(addresses.clone()).await?; + let (unspents_map, _) = coin + .get_mature_unspent_ordered_map(addresses.clone()) + .await + .map_mm_err()?; addresses .into_iter() .map(|address| { @@ -256,7 +261,8 @@ where .rpc_client .display_balances(addresses.clone(), coin.as_ref().decimals) .compat() - .await? + .await + .map_mm_err()? .into_iter() .map(|(address, spendable)| { let unspendable = BigDecimal::from(0); @@ -283,7 +289,8 @@ pub async fn get_htlc_spend_fee( }, ActualFeeRate::FixedPerKb(_) => fee_rate, }; - let min_relay_fee_rate = get_min_relay_rate(coin).await?; + + let min_relay_fee_rate = get_min_relay_rate(coin).await.map_mm_err()?; Ok(get_tx_fee_with_relay_fee(&fee_rate, tx_size, min_relay_fee_rate)) } @@ -376,7 +383,7 @@ pub fn my_public_key(coin: &UtxoCoinFields) -> Result<&Public, MmError(coin: &T, address: &str) -> MmResult { let addr = address_from_str_unchecked(coin.as_ref(), address)?; - check_withdraw_address_supported(coin, &addr)?; + check_withdraw_address_supported(coin, &addr).map_mm_err()?; Ok(addr) } @@ -699,7 +706,7 @@ impl<'a, T: AsRef + UtxoTxGenerationOps> UtxoTxBuilder<'a, T> { let actual_fee_rate = match self.fee { Some(fee) => fee, - None => coin.get_fee_rate().await?, + None => coin.get_fee_rate().await.map_mm_err()?, }; return_err_if!(self.outputs.is_empty(), GenerateTxError::EmptyOutputs); @@ -713,14 +720,14 @@ impl<'a, T: AsRef + UtxoTxGenerationOps> UtxoTxBuilder<'a, T> { } ); - self.min_relay_fee_rate = get_min_relay_rate(coin).await?; + self.min_relay_fee_rate = get_min_relay_rate(coin).await.map_mm_err()?; let mut one_time_fee_update = false; loop { let required_amount_0 = self.required_amount(); self.sum_inputs = self.add_tx_inputs(required_amount_0); self.sum_outputs = self.add_tx_outputs(); - self.interest = coin.calc_interest_if_required(&mut self.tx).await?; + self.interest = coin.calc_interest_if_required(&mut self.tx).await.map_mm_err()?; // try once tx_fee without the change output (if maybe txfee fits between total inputs and outputs) if !one_time_fee_update { @@ -842,7 +849,7 @@ pub fn is_kmd(coin: &T) -> bool { &coin.as_ref().conf.ticker = async fn get_min_relay_rate + UtxoTxGenerationOps>(coin: &T) -> UtxoRpcResult> { if coin.as_ref().conf.force_min_relay_fee { let fee_dec = coin.as_ref().rpc_client.get_relay_fee().compat().await?; - let min_relay_fee_rate = sat_from_big_decimal(&fee_dec, coin.as_ref().decimals)?; + let min_relay_fee_rate = sat_from_big_decimal(&fee_dec, coin.as_ref().decimals).map_mm_err()?; Ok(Some(min_relay_fee_rate)) } else { Ok(None) @@ -1016,10 +1023,10 @@ async fn gen_taker_funding_spend_preimage( .value; let fee = match fee { - FundingSpendFeeSetting::GetFromCoin => { - coin.get_htlc_spend_fee(DEFAULT_SWAP_TX_SPEND_SIZE, &FeeApproxStage::WithoutApprox) - .await? - }, + FundingSpendFeeSetting::GetFromCoin => coin + .get_htlc_spend_fee(DEFAULT_SWAP_TX_SPEND_SIZE, &FeeApproxStage::WithoutApprox) + .await + .map_mm_err()?, FundingSpendFeeSetting::UseExact(f) => f, }; @@ -1075,7 +1082,8 @@ pub async fn gen_and_sign_taker_funding_spend_preimage( coin.as_ref().conf.signature_version, SIGHASH_ALL, coin.as_ref().conf.fork_id, - )?; + ) + .map_mm_err()?; Ok(TxPreimageWithSig { preimage: preimage.into(), signature: signature.take().into(), @@ -1110,7 +1118,8 @@ pub async fn validate_taker_funding_spend_preimage( let expected_fee = coin .get_htlc_spend_fee(DEFAULT_SWAP_TX_SPEND_SIZE, &FeeApproxStage::WithoutApprox) - .await?; + .await + .map_mm_err()?; let actual_fee = funding_amount - payment_amount; @@ -1129,7 +1138,8 @@ pub async fn validate_taker_funding_spend_preimage( NTimeSetting::UseValue(preimage.preimage.n_time), FundingSpendFeeSetting::UseExact(actual_fee), ) - .await?; + .await + .map_mm_err()?; let funding_time_lock = gen_args .funding_time_lock @@ -1148,7 +1158,8 @@ pub async fn validate_taker_funding_spend_preimage( coin.as_ref().conf.signature_version, SIGHASH_ALL, coin.as_ref().conf.fork_id, - )?; + ) + .map_mm_err()?; if !gen_args .maker_pub @@ -1263,7 +1274,8 @@ async fn gen_taker_payment_spend_preimage( })?; let tx_fee = coin .get_htlc_spend_fee(DEFAULT_SWAP_TX_SPEND_SIZE, &FeeApproxStage::WithoutApprox) - .await?; + .await + .map_mm_err()?; let dex_fee_value = if matches!(args.dex_fee, &DexFee::WithBurn { .. }) { outputs[0].value + outputs[1].value } else { @@ -1359,7 +1371,8 @@ pub async fn gen_and_sign_taker_payment_spend_preimage( // Here, we have to use the exact lock time from the preimage because maker // can get different values (e.g. if MTP advances during preimage exchange/fee rate changes) let expected_preimage = - gen_taker_payment_spend_preimage(coin, gen_args, NTimeSetting::UseValue(preimage.preimage.n_time)).await?; + gen_taker_payment_spend_preimage(coin, gen_args, NTimeSetting::UseValue(preimage.preimage.n_time)) + .await + .map_mm_err()?; let time_lock = gen_args .time_lock @@ -1401,7 +1416,8 @@ pub async fn validate_taker_payment_spend_preimage( coin.as_ref().conf.signature_version, sig_hash_type, coin.as_ref().conf.fork_id, - )?; + ) + .map_mm_err()?; if !gen_args .taker_pub @@ -2335,7 +2351,7 @@ fn validate_dex_output( dex_address: &Address, fee_amount: &MmNumber, ) -> MmResult<(), ValidatePaymentError> { - let fee_amount_u64 = sat_from_big_decimal(&fee_amount.to_decimal(), coin.as_ref().decimals)?; + let fee_amount_u64 = sat_from_big_decimal(&fee_amount.to_decimal(), coin.as_ref().decimals).map_mm_err()?; match tx.outputs.get(output_index) { Some(out) => { let expected_script_pubkey = Builder::build_p2pkh(dex_address.hash()).to_bytes(); @@ -2370,7 +2386,7 @@ fn validate_burn_output( burn_script_pubkey: &Script, burn_amount: &MmNumber, ) -> MmResult<(), ValidatePaymentError> { - let burn_amount_u64 = sat_from_big_decimal(&burn_amount.to_decimal(), coin.as_ref().decimals)?; + let burn_amount_u64 = sat_from_big_decimal(&burn_amount.to_decimal(), coin.as_ref().decimals).map_mm_err()?; match tx.outputs.get(output_index) { Some(out) => { if out.script_pubkey != burn_script_pubkey.to_bytes() { @@ -2426,7 +2442,8 @@ pub fn validate_fee( .rpc_client .get_verbose_transaction(&tx.hash().reversed().into()) .compat() - .await?; + .await + .map_mm_err()?; let tx_confirmed_before_block = is_tx_confirmed_before_block(&coin, &tx_from_rpc, min_block_number) .await @@ -2625,7 +2642,12 @@ pub fn validate_payment_spend_or_refund( let coin = coin.clone(); let fut = async move { - let my_address = coin.as_ref().derivation_method.single_addr_or_err().await?; + let my_address = coin + .as_ref() + .derivation_method + .single_addr_or_err() + .await + .map_mm_err()?; let expected_script_pubkey = output_script(&my_address).map(|script| script.to_bytes())?; let output = payment_spend_tx .outputs @@ -2896,13 +2918,15 @@ pub fn sign_message( let message_hash = sign_message_hash(coin, message).ok_or(SignatureError::PrefixNotFound)?; let private = if let Some(account) = account { - let path_to_coin = coin.priv_key_policy.path_to_coin_or_err()?; + let path_to_coin = coin.priv_key_policy.path_to_coin_or_err().map_mm_err()?; let derivation_path = account .valid_derivation_path(path_to_coin) - .mm_err(|err| SignatureError::InvalidRequest(err.to_string()))?; + .mm_err(|err| SignatureError::InvalidRequest(err.to_string())) + .map_mm_err()?; let privkey = coin .priv_key_policy - .hd_wallet_derived_priv_key_or_err(&derivation_path)?; + .hd_wallet_derived_priv_key_or_err(&derivation_path) + .map_mm_err()?; Private { prefix: coin.conf.wif_prefix, secret: privkey, @@ -2910,10 +2934,10 @@ pub fn sign_message( checksum_type: coin.conf.checksum_type, } } else { - *coin.priv_key_policy.activated_key_or_err()?.private() + *coin.priv_key_policy.activated_key_or_err().map_mm_err()?.private() }; - let signature = private.sign_compact(&H256::from(message_hash))?; + Ok(STANDARD.encode(&*signature)) } @@ -2927,7 +2951,7 @@ pub fn verify_message( let signature = CompactSignature::try_from(STANDARD.decode(signature_base64)?) .map_to_mm(|err| VerificationError::SignatureDecodingError(err.to_string()))?; let recovered_pubkey = Public::recover_compact(&H256::from(message_hash), &signature)?; - let received_address = checked_address_from_str(coin, address)?; + let received_address = checked_address_from_str(coin, address).map_mm_err()?; Ok(AddressHashEnum::from(recovered_pubkey.address_hash()) == *received_address.hash()) } @@ -4038,7 +4062,7 @@ where } // Todo: https://github.com/KomodoPlatform/komodo-defi-framework/issues/1625 - let my_address = &coin.my_address()?; + let my_address = &coin.my_address().map_mm_err()?; let claimed_by_me = tx_details.from.iter().all(|from| from == my_address) && tx_details.to.contains(my_address); tx_details.kmd_rewards = Some(KmdRewardsDetails { @@ -4126,10 +4150,15 @@ where T: UtxoCommonOps + GetUtxoListOps, { let decimals = coin.as_ref().decimals; - let fee_rate = coin.get_fee_rate().await?; + let fee_rate = coin.get_fee_rate().await.map_mm_err()?; // [`FeePolicy::DeductFromOutput`] is used if the value is [`TradePreimageValue::UpperBound`] only let is_amount_upper_bound = matches!(fee_policy, FeePolicy::DeductFromOutput(_)); - let my_address = coin.as_ref().derivation_method.single_addr_or_err().await?; + let my_address = coin + .as_ref() + .derivation_method + .single_addr_or_err() + .await + .map_mm_err()?; match fee_rate { // if it's a dynamic fee, we should generate a swap transaction to get an actual trade fee @@ -4138,7 +4167,7 @@ where let dynamic_fee_rate = coin.increase_dynamic_fee_by_stage(fee_rate, stage); let outputs_count = outputs.len(); - let (unspents, _recently_sent_txs) = coin.get_unspent_ordered_list(&my_address).await?; + let (unspents, _recently_sent_txs) = coin.get_unspent_ordered_list(&my_address).await.map_mm_err()?; let actual_fee_rate = ActualFeeRate::Dynamic(dynamic_fee_rate); let mut tx_builder = UtxoTxBuilder::new(coin) @@ -4167,7 +4196,7 @@ where }, ActualFeeRate::FixedPerKb(_fee) => { let outputs_count = outputs.len(); - let (unspents, _recently_sent_txs) = coin.get_unspent_ordered_list(&my_address).await?; + let (unspents, _recently_sent_txs) = coin.get_unspent_ordered_list(&my_address).await.map_mm_err()?; let mut tx_builder = UtxoTxBuilder::new(coin) .await .add_available_inputs(unspents) @@ -4246,7 +4275,9 @@ where /// The fee to spend (receive) other payment is deducted from the trading amount so we should display it pub fn get_receiver_trade_fee(coin: T) -> TradePreimageFut { let fut = async move { - let amount_sat = get_htlc_spend_fee(&coin, DEFAULT_SWAP_TX_SPEND_SIZE, &FeeApproxStage::WithoutApprox).await?; + let amount_sat = get_htlc_spend_fee(&coin, DEFAULT_SWAP_TX_SPEND_SIZE, &FeeApproxStage::WithoutApprox) + .await + .map_mm_err()?; let amount = big_decimal_from_sat_unsigned(amount_sat, coin.as_ref().decimals).into(); Ok(TradeFee { coin: coin.as_ref().conf.ticker.clone(), @@ -4560,7 +4591,7 @@ pub async fn validate_payment<'a, T: UtxoCommonOps>( try_spv_proof_until: u64, confirmations: u64, ) -> ValidatePaymentResult<()> { - let amount = sat_from_big_decimal(&amount, coin.as_ref().decimals)?; + let amount = sat_from_big_decimal(&amount, coin.as_ref().decimals).map_mm_err()?; let expected_redeem = tx_type_with_secret_hash.redeem_script(time_lock, first_pub0, second_pub0); let tx_hash = tx.tx_hash_as_bytes(); @@ -4606,7 +4637,7 @@ pub async fn validate_payment<'a, T: UtxoCommonOps>( } if let Some(watcher_reward) = watcher_reward { - let expected_reward = sat_from_big_decimal(&watcher_reward.amount, coin.as_ref().decimals)?; + let expected_reward = sat_from_big_decimal(&watcher_reward.amount, coin.as_ref().decimals).map_mm_err()?; let actual_reward = actual_output.value - amount; validate_watcher_reward(expected_reward, actual_reward, false)?; } else if actual_output.value != amount { @@ -5174,7 +5205,7 @@ where let total_expected_amount = &args.dex_fee.total_spend_amount().to_decimal() + &args.premium_amount + &args.trading_amount; - let expected_amount_sat = sat_from_big_decimal(&total_expected_amount, coin.as_ref().decimals)?; + let expected_amount_sat = sat_from_big_decimal(&total_expected_amount, coin.as_ref().decimals).map_mm_err()?; let time_lock = args .funding_time_lock @@ -5205,7 +5236,8 @@ where .rpc_client .get_transaction_bytes(&args.funding_tx.hash().reversed().into()) .compat() - .await?; + .await + .map_mm_err()?; let actual_tx_bytes = serialize(args.funding_tx).take(); if tx_bytes_from_rpc.0 != actual_tx_bytes { return MmError::err(ValidateSwapV2TxError::TxBytesMismatch { diff --git a/mm2src/coins/utxo/utxo_common/utxo_tx_history_v2_common.rs b/mm2src/coins/utxo/utxo_common/utxo_tx_history_v2_common.rs index 01f9750b03..c677e5f513 100644 --- a/mm2src/coins/utxo/utxo_common/utxo_tx_history_v2_common.rs +++ b/mm2src/coins/utxo/utxo_common/utxo_tx_history_v2_common.rs @@ -39,7 +39,7 @@ where { match (coin.derivation_method(), target) { (DerivationMethod::SingleAddress(_), MyTxHistoryTarget::Iguana) => { - let my_address = coin.my_address()?; + let my_address = coin.my_address().map_mm_err()?; Ok(GetTxHistoryFilters::for_address(my_address)) }, (DerivationMethod::SingleAddress(_), target) => { @@ -73,8 +73,14 @@ where .await .or_mm_err(|| MyTxHistoryErrorV2::InvalidTarget(format!("No such account_id={account_id}")))?; - let external_addresses = coin.derive_known_addresses(&hd_account, Bip44Chain::External).await?; - let internal_addresses = coin.derive_known_addresses(&hd_account, Bip44Chain::Internal).await?; + let external_addresses = coin + .derive_known_addresses(&hd_account, Bip44Chain::External) + .await + .map_mm_err()?; + let internal_addresses = coin + .derive_known_addresses(&hd_account, Bip44Chain::Internal) + .await + .map_mm_err()?; let addresses_iter = external_addresses .into_iter() @@ -98,7 +104,9 @@ where .await .or_mm_err(|| MyTxHistoryErrorV2::InvalidTarget(format!("No such account_id={}", hd_address_id.account_id)))?; - let is_address_activated = hd_account.is_address_activated(hd_address_id.chain, hd_address_id.address_id)?; + let is_address_activated = hd_account + .is_address_activated(hd_address_id.chain, hd_address_id.address_id) + .map_mm_err()?; if !is_address_activated { let error = format!( "'{:?}:{}' address is not activated", @@ -109,7 +117,8 @@ where let hd_address = coin .derive_address(&hd_account, hd_address_id.chain, hd_address_id.address_id) - .await?; + .await + .map_mm_err()?; Ok(GetTxHistoryFilters::for_address(hd_address.address().display_address())) } @@ -130,7 +139,8 @@ where .rpc_client .get_verbose_transaction(params.hash) .compat() - .await?; + .await + .map_mm_err()?; let tx: UtxoTx = deserialize(verbose_tx.hex.as_slice())?; let mut tx_builder = TxDetailsBuilder::new( @@ -227,11 +237,24 @@ where { let tx_hash_str = format!("{:02x}", tx_hash); let wallet_id = coin.history_wallet_id(); - let tx_bytes = match storage.tx_bytes_from_cache(&wallet_id, &tx_hash_str).await? { + let tx_bytes = match storage + .tx_bytes_from_cache(&wallet_id, &tx_hash_str) + .await + .map_mm_err()? + { Some(tx_bytes) => tx_bytes, None => { - let tx_bytes = coin.as_ref().rpc_client.get_transaction_bytes(tx_hash).compat().await?; - storage.add_tx_to_cache(&wallet_id, &tx_hash_str, &tx_bytes).await?; + let tx_bytes = coin + .as_ref() + .rpc_client + .get_transaction_bytes(tx_hash) + .compat() + .await + .map_mm_err()?; + storage + .add_tx_to_cache(&wallet_id, &tx_hash_str, &tx_bytes) + .await + .map_mm_err()?; tx_bytes }, }; diff --git a/mm2src/coins/utxo/utxo_standard.rs b/mm2src/coins/utxo/utxo_standard.rs index 49e4ea9d60..6297509289 100644 --- a/mm2src/coins/utxo/utxo_standard.rs +++ b/mm2src/coins/utxo/utxo_standard.rs @@ -813,7 +813,8 @@ impl TakerCoinSwapOpsV2 for UtxoStandardCoin { wait_until, 10., ) - .await?; + .await + .map_mm_err()?; Ok(res) } @@ -1287,7 +1288,7 @@ impl CoinWithTxHistoryV2 for UtxoStandardCoin { #[async_trait] impl UtxoTxHistoryOps for UtxoStandardCoin { async fn my_addresses(&self) -> MmResult, UtxoMyAddressesHistoryError> { - let addresses = self.all_addresses().await?; + let addresses = self.all_addresses().await.map_mm_err()?; Ok(addresses) } diff --git a/mm2src/coins/utxo/utxo_withdraw.rs b/mm2src/coins/utxo/utxo_withdraw.rs index 8dd491babe..9c8953cf3d 100644 --- a/mm2src/coins/utxo/utxo_withdraw.rs +++ b/mm2src/coins/utxo/utxo_withdraw.rs @@ -101,7 +101,8 @@ where let secret = coin .as_ref() .priv_key_policy - .hd_wallet_derived_priv_key_or_err(derivation_path)?; + .hd_wallet_derived_priv_key_or_err(derivation_path) + .map_mm_err()?; let private = Private { prefix: coin.as_ref().conf.wif_prefix, @@ -150,7 +151,7 @@ where let decimals = coin.as_ref().decimals; let req = self.request(); - let to = coin.address_from_str(&req.to)?; + let to = coin.address_from_str(&req.to).map_mm_err()?; // Generate unsigned transaction. self.on_generating_transaction()?; @@ -158,14 +159,17 @@ where let script_pubkey = output_script(&to).map(|script| script.to_bytes())?; let _utxo_lock = UTXO_LOCK.lock().await; - let (unspents, _) = coin.get_unspent_ordered_list(&self.sender_address()).await?; + let (unspents, _) = coin + .get_unspent_ordered_list(&self.sender_address()) + .await + .map_mm_err()?; let (value, fee_policy) = if req.max { ( unspents.iter().fold(0, |sum, unspent| sum + unspent.value), FeePolicy::DeductFromOutput(0), ) } else { - let value = sat_from_big_decimal(&req.amount, decimals)?; + let value = sat_from_big_decimal(&req.amount, decimals).map_mm_err()?; (value, FeePolicy::SendExact) }; let outputs = vec![TransactionOutput { value, script_pubkey }]; @@ -179,11 +183,11 @@ where match req.fee { Some(WithdrawFee::UtxoFixed { ref amount }) => { - let fixed = sat_from_big_decimal(amount, decimals)?; + let fixed = sat_from_big_decimal(amount, decimals).map_mm_err()?; tx_builder = tx_builder.with_fee(ActualFeeRate::FixedPerKb(fixed)); }, Some(WithdrawFee::UtxoPerKbyte { ref amount }) => { - let dynamic_fee_rate = sat_from_big_decimal(amount, decimals)?; + let dynamic_fee_rate = sat_from_big_decimal(amount, decimals).map_mm_err()?; tx_builder = tx_builder.with_fee(ActualFeeRate::Dynamic(dynamic_fee_rate)); }, Some(ref fee_policy) => { @@ -274,20 +278,21 @@ where amount_display, self.req.coin, self.from_address_string, self.req.to, ); - Ok(self - .task_handle - .update_in_progress_status(WithdrawInProgressStatus::GeneratingTransaction)?) + self.task_handle + .update_in_progress_status(WithdrawInProgressStatus::GeneratingTransaction) + .map_mm_err() } fn on_finishing(&self) -> Result<(), MmError> { - Ok(self - .task_handle - .update_in_progress_status(WithdrawInProgressStatus::Finishing)?) + self.task_handle + .update_in_progress_status(WithdrawInProgressStatus::Finishing) + .map_mm_err() } async fn sign_tx(&self, unsigned_tx: TransactionInputSigner) -> Result> { self.task_handle - .update_in_progress_status(WithdrawInProgressStatus::SigningTransaction)?; + .update_in_progress_status(WithdrawInProgressStatus::SigningTransaction) + .map_mm_err()?; let mut sign_params = UtxoSignTxParamsBuilder::new(); @@ -331,19 +336,20 @@ where sign_params .with_signature_version(self.signature_version()) .with_unsigned_tx(unsigned_tx); - let sign_params = sign_params.build()?; + let sign_params = sign_params.build().map_mm_err()?; let signed = match self.coin.as_ref().priv_key_policy { - PrivKeyPolicy::Iguana(ref key_pair) => { - self.coin - .sign_tx(sign_params, SignPolicy::WithKeyPair(key_pair)) - .await? - }, + PrivKeyPolicy::Iguana(ref key_pair) => self + .coin + .sign_tx(sign_params, SignPolicy::WithKeyPair(key_pair)) + .await + .map_mm_err()?, PrivKeyPolicy::HDWallet { .. } => { - let from_key_pair = derive_hd_key_pair(self.coin(), &self.from_derivation_path)?; + let from_key_pair = derive_hd_key_pair(self.coin(), &self.from_derivation_path).map_mm_err()?; self.coin() .sign_tx(sign_params, SignPolicy::WithKeyPair(&from_key_pair)) - .await? + .await + .map_mm_err()? }, PrivKeyPolicy::Trezor => { let trezor_statuses = TrezorRequestStatuses { @@ -354,16 +360,18 @@ where }; let sign_processor = TrezorRpcTaskProcessor::new(self.task_handle.clone(), trezor_statuses); let sign_processor = Arc::new(sign_processor); - let crypto_ctx = CryptoCtx::from_ctx(&self.ctx)?; + let crypto_ctx = CryptoCtx::from_ctx(&self.ctx).map_mm_err()?; let hw_ctx = crypto_ctx .hw_ctx() .or_mm_err(|| WithdrawError::HwError(HwRpcError::NoTrezorDeviceAvailable))?; - let trezor_session = hw_ctx.trezor(sign_processor).await?; + let trezor_session = hw_ctx.trezor(sign_processor).await.map_mm_err()?; self.task_handle - .update_in_progress_status(WithdrawInProgressStatus::WaitingForUserToConfirmSigning)?; + .update_in_progress_status(WithdrawInProgressStatus::WaitingForUserToConfirmSigning) + .map_mm_err()?; self.coin .sign_tx(sign_params, SignPolicy::WithTrezor(trezor_session)) - .await? + .await + .map_mm_err()? }, #[cfg(target_arch = "wasm32")] PrivKeyPolicy::Metamask(_) => { @@ -450,7 +458,8 @@ where &self.key_pair, self.signature_version(), self.coin.as_ref().conf.fork_id, - )?) + ) + .map_mm_err()?) } } @@ -467,13 +476,13 @@ where let from_address_string = from.address.display_address().map_to_mm(WithdrawError::InternalError)?; let key_pair = match from.derivation_path { - Some(der_path) => derive_hd_key_pair(&coin, &der_path)?, + Some(der_path) => derive_hd_key_pair(&coin, &der_path).map_mm_err()?, // [`WithdrawSenderAddress::derivation_path`] is not set, but the coin is initialized with an HD wallet derivation method. None if coin.has_hd_wallet_derivation_method() => { let error = "Cannot determine 'from' address derivation path".to_owned(); return MmError::err(WithdrawError::UnexpectedFromAddress(error)); }, - None => *coin.as_ref().priv_key_policy.activated_key_or_err()?, + None => *coin.as_ref().priv_key_policy.activated_key_or_err().map_mm_err()?, }; Ok(StandardUtxoWithdraw { diff --git a/mm2src/coins/utxo_signer/src/lib.rs b/mm2src/coins/utxo_signer/src/lib.rs index 8032e9acf7..3f9ee23095 100644 --- a/mm2src/coins/utxo_signer/src/lib.rs +++ b/mm2src/coins/utxo_signer/src/lib.rs @@ -138,7 +138,7 @@ pub trait UtxoSignerOps { let signer = with_trezor::TrezorTxSigner { trezor, tx_provider: self.tx_provider(), - trezor_coin: self.trezor_coin()?, + trezor_coin: self.trezor_coin().map_mm_err()?, params, fork_id: self.fork_id(), branch_id: self.branch_id(), @@ -147,7 +147,8 @@ pub trait UtxoSignerOps { }, SignPolicy::WithKeyPair(key_pair) => { let signed = - with_key_pair::sign_tx(params.unsigned_tx, key_pair, params.signature_version, self.fork_id())?; + with_key_pair::sign_tx(params.unsigned_tx, key_pair, params.signature_version, self.fork_id()) + .map_mm_err()?; Ok(signed) }, } diff --git a/mm2src/coins/utxo_signer/src/with_trezor.rs b/mm2src/coins/utxo_signer/src/with_trezor.rs index 8da3b972bb..75d882fa49 100644 --- a/mm2src/coins/utxo_signer/src/with_trezor.rs +++ b/mm2src/coins/utxo_signer/src/with_trezor.rs @@ -23,12 +23,12 @@ pub struct TrezorTxSigner<'a, TxP> { impl<'a, TxP: TxProvider + Send + Sync> TrezorTxSigner<'a, TxP> { pub async fn sign_tx(mut self) -> UtxoSignTxResult { - let trezor_unsigned_tx = self.get_trezor_unsigned_tx().await?; + let trezor_unsigned_tx = self.get_trezor_unsigned_tx().await.map_mm_err()?; let TxSignResult { signatures, serialized_tx, - } = self.trezor.sign_utxo_tx(trezor_unsigned_tx).await?; + } = self.trezor.sign_utxo_tx(trezor_unsigned_tx).await.map_mm_err()?; debug!("Transaction signed by Trezor: {}", hex::encode(serialized_tx)); if signatures.len() != self.params.inputs_count() { return MmError::err(UtxoSignTxError::InvalidSignaturesNumber { @@ -56,7 +56,10 @@ impl<'a, TxP: TxProvider + Send + Sync> TrezorTxSigner<'a, TxP> { async fn get_trezor_unsigned_tx(&self) -> UtxoSignTxResult { let mut inputs = Vec::with_capacity(self.params.unsigned_tx.inputs.len()); for (unsigned_input, input_info) in self.params.inputs() { - let unsigned_input = self.get_trezor_unsigned_input(unsigned_input, input_info).await?; + let unsigned_input = self + .get_trezor_unsigned_input(unsigned_input, input_info) + .await + .map_mm_err()?; inputs.push(unsigned_input); } @@ -99,7 +102,7 @@ impl<'a, TxP: TxProvider + Send + Sync> TrezorTxSigner<'a, TxP> { input_info: &SpendingInputInfo, ) -> UtxoSignTxResult { let prev_tx_hash_json = H256Json::from(unsigned_input.previous_output.hash.reversed()); - let prev_tx = self.get_trezor_prev_tx(&prev_tx_hash_json).await?; + let prev_tx = self.get_trezor_prev_tx(&prev_tx_hash_json).await.map_mm_err()?; let (address_derivation_path, input_script_type) = match input_info { SpendingInputInfo::P2PKH { @@ -130,9 +133,10 @@ impl<'a, TxP: TxProvider + Send + Sync> TrezorTxSigner<'a, TxP> { } async fn get_trezor_prev_tx(&self, prev_tx_hash: &H256Json) -> UtxoSignTxResult { - let prev_verbose = self.tx_provider.get_rpc_transaction(prev_tx_hash).await?; - let prev_utxo: UtxoTx = - deserialize(prev_verbose.hex.as_slice()).map_to_mm(|e| UtxoSignTxError::Transport(e.to_string()))?; + let prev_verbose = self.tx_provider.get_rpc_transaction(prev_tx_hash).await.map_mm_err()?; + let prev_utxo: UtxoTx = deserialize(prev_verbose.hex.as_slice()) + .map_to_mm(|e| UtxoSignTxError::Transport(e.to_string())) + .map_mm_err()?; let prev_tx_inputs = prev_utxo .inputs diff --git a/mm2src/coins/z_coin.rs b/mm2src/coins/z_coin.rs index 2d4d3bde42..4a0e92056e 100644 --- a/mm2src/coins/z_coin.rs +++ b/mm2src/coins/z_coin.rs @@ -380,9 +380,9 @@ impl ZCoin { ) -> Result, MmError> { // Wait for chain to sync before selecting spendable notes or waiting for locked_notes to become // available. - let sync_guard = self.wait_for_gen_tx_blockchain_sync().await?; + let sync_guard = self.wait_for_gen_tx_blockchain_sync().await.map_mm_err()?; drop(sync_guard); - let tx_fee = self.get_one_kbyte_tx_fee().await?; + let tx_fee = self.get_one_kbyte_tx_fee().await.map_mm_err()?; let t_output_sat: u64 = t_outputs.iter().fold(0, |cur, out| cur + u64::from(out.value)); let z_output_sat: u64 = z_outputs.iter().fold(0, |cur, out| cur + u64::from(out.amount)); let total_output_sat = t_output_sat + z_output_sat; @@ -391,7 +391,7 @@ impl ZCoin { let spendable_notes = wait_for_spendable_balance_spawner(self, &total_required).await?; // Recreate sync_guard - let sync_guard = self.wait_for_gen_tx_blockchain_sync().await?; + let sync_guard = self.wait_for_gen_tx_blockchain_sync().await.map_mm_err()?; let mut total_input_amount = BigDecimal::from(0); let mut change = BigDecimal::from(0); @@ -442,7 +442,7 @@ impl ZCoin { } // add change to tx output - let change_sat = sat_from_big_decimal(&change, self.utxo_arc.decimals)?; + let change_sat = sat_from_big_decimal(&change, self.utxo_arc.decimals).map_mm_err()?; if change > BigDecimal::from(0u8) { received_by_me += change_sat; let change_amount = Amount::from_u64(change_sat).map_to_mm(|_| { @@ -474,13 +474,15 @@ impl ZCoin { #[cfg(target_arch = "wasm32")] let (tx, _) = TxBuilderSpawner::request_tx_result(tx_builder, BranchId::Sapling, self.z_fields.z_tx_prover.clone()) - .await? - .tx_result?; + .await + .map_mm_err()? + .tx_result + .map_mm_err()?; let data = AdditionalTxData { received_by_me, - spent_by_me: sat_from_big_decimal(&total_input_amount, self.decimals())?, - fee_amount: sat_from_big_decimal(&tx_fee, self.decimals())?, + spent_by_me: sat_from_big_decimal(&total_input_amount, self.decimals()).map_mm_err()?, + fee_amount: sat_from_big_decimal(&tx_fee, self.decimals()).map_mm_err()?, kmd_rewards: None, }; @@ -502,14 +504,15 @@ impl ZCoin { data, rseeds, mut sync_guard, - } = self.gen_tx(t_outputs, z_outputs).await?; + } = self.gen_tx(t_outputs, z_outputs).await.map_mm_err()?; let mut tx_bytes = Vec::with_capacity(1024); tx.write(&mut tx_bytes).expect("Write should not fail"); self.utxo_rpc_client() .send_raw_transaction(tx_bytes.into()) .compat() - .await?; + .await + .map_mm_err()?; // TODO: Execute updates to `locked_notes_db` and `wallet_db` in a single transaction. // This will be possible with a newer librustzcash that supports both spent notes and unconfirmed change tracking. @@ -648,15 +651,20 @@ impl ZCoin { &self, request: MyTxHistoryRequestV2, ) -> Result, MmError> { - let current_block = self.utxo_rpc_client().get_block_count().compat().await?; - let req_result = fetch_tx_history_from_db(self, request.limit, request.paging_options.clone()).await?; + let current_block = self.utxo_rpc_client().get_block_count().compat().await.map_mm_err()?; + let req_result = fetch_tx_history_from_db(self, request.limit, request.paging_options.clone()) + .await + .map_mm_err()?; let hashes_for_verbose = req_result .transactions .iter() .map(|item| H256Json::from(item.tx_hash)) .collect(); - let transactions = self.z_transactions_from_cache_or_rpc(hashes_for_verbose).await?; + let transactions = self + .z_transactions_from_cache_or_rpc(hashes_for_verbose) + .await + .map_mm_err()?; let prev_tx_hashes: HashSet<_> = transactions .iter() @@ -668,13 +676,17 @@ impl ZCoin { }) }) .collect(); - let prev_transactions = self.z_transactions_from_cache_or_rpc(prev_tx_hashes).await?; + let prev_transactions = self + .z_transactions_from_cache_or_rpc(prev_tx_hashes) + .await + .map_mm_err()?; let transactions = req_result .transactions .into_iter() .map(|sql_item| self.tx_details_from_db_item(sql_item, &transactions, &prev_transactions, current_block)) - .collect::>()?; + .collect::>() + .map_mm_err()?; Ok(MyTxHistoryResponseV2 { coin: self.ticker().into(), @@ -930,7 +942,7 @@ impl<'a> UtxoCoinBuilder for ZCoinBuilder<'a> { fn priv_key_policy(&self) -> PrivKeyBuildPolicy { self.priv_key_policy.clone() } async fn build(self) -> MmResult { - let utxo = self.build_utxo_fields().await?; + let utxo = self.build_utxo_fields().await.map_mm_err()?; let utxo_arc = UtxoArc::new(utxo); let dex_fee_addr = decode_payment_address( @@ -948,30 +960,36 @@ impl<'a> UtxoCoinBuilder for ZCoinBuilder<'a> { .expect("DEX_BURN_Z_ADDR is a valid z-address"); let z_tx_prover = self.z_tx_prover().await?; - let blocks_db = self.init_blocks_db().await?; - let locked_notes_db = LockedNotesStorage::new(self.ctx, self.my_z_addr_encoded.clone()).await?; + let blocks_db = self.init_blocks_db().await.map_mm_err()?; + let locked_notes_db = LockedNotesStorage::new(self.ctx, self.my_z_addr_encoded.clone()) + .await + .map_mm_err()?; let (sync_state_connector, light_wallet_db) = match &self.z_coin_params.mode { #[cfg(not(target_arch = "wasm32"))] - ZcoinRpcMode::Native => { - init_native_client(&self, self.native_client()?, blocks_db, locked_notes_db.clone()).await? - }, + ZcoinRpcMode::Native => init_native_client( + &self, + self.native_client().map_mm_err()?, + blocks_db, + locked_notes_db.clone(), + ) + .await + .map_mm_err()?, ZcoinRpcMode::Light { light_wallet_d_servers, sync_params, skip_sync_params, .. - } => { - init_light_client( - &self, - light_wallet_d_servers.clone(), - blocks_db, - sync_params, - skip_sync_params.unwrap_or_default(), - locked_notes_db.clone(), - ) - .await? - }, + } => init_light_client( + &self, + light_wallet_d_servers.clone(), + blocks_db, + sync_params, + skip_sync_params.unwrap_or_default(), + locked_notes_db.clone(), + ) + .await + .map_mm_err()?, #[cfg(test)] ZcoinRpcMode::UnitTests => z_unit_tests::create_test_sync_connector(&self).await, }; @@ -1506,8 +1524,14 @@ impl SwapOps for ZCoin { ))) }, }; - let fee_amount_sat = validate_fee_args.dex_fee.fee_amount_as_u64(self.utxo_arc.decimals)?; - let burn_amount_sat = validate_fee_args.dex_fee.burn_amount_as_u64(self.utxo_arc.decimals)?; + let fee_amount_sat = validate_fee_args + .dex_fee + .fee_amount_as_u64(self.utxo_arc.decimals) + .map_mm_err()?; + let burn_amount_sat = validate_fee_args + .dex_fee + .burn_amount_as_u64(self.utxo_arc.decimals) + .map_mm_err()?; let expected_memo = MemoBytes::from_bytes(validate_fee_args.uuid).expect("Uuid length < 512"); let tx_hash = H256::from(z_tx.txid().0).reversed(); @@ -1750,7 +1774,7 @@ impl MmCoin for ZCoin { ) -> TradePreimageResult { Ok(TradeFee { coin: self.ticker().to_owned(), - amount: self.get_one_kbyte_tx_fee().await?.into(), + amount: self.get_one_kbyte_tx_fee().await.map_mm_err()?.into(), paid_from_trading_vol: false, }) } @@ -1766,7 +1790,7 @@ impl MmCoin for ZCoin { ) -> TradePreimageResult { Ok(TradeFee { coin: self.ticker().to_owned(), - amount: self.get_one_kbyte_tx_fee().await?.into(), + amount: self.get_one_kbyte_tx_fee().await.map_mm_err()?.into(), paid_from_trading_vol: false, }) } @@ -1985,27 +2009,30 @@ impl InitWithdrawCoin for ZCoin { .map_to_mm(|e| WithdrawError::InvalidAddress(format!("{}", e)))? .or_mm_err(|| WithdrawError::InvalidAddress(format!("Address {} decoded to None", req.to)))?; let amount = if req.max { - let fee = self.get_one_kbyte_tx_fee().await?; - let balance = self.my_balance().compat().await?; + let fee = self.get_one_kbyte_tx_fee().await.map_mm_err()?; + let balance = self.my_balance().compat().await.map_mm_err()?; balance.spendable - fee } else { req.amount }; - task_handle.update_in_progress_status(WithdrawInProgressStatus::GeneratingTransaction)?; - let satoshi = sat_from_big_decimal(&amount, self.decimals())?; + task_handle + .update_in_progress_status(WithdrawInProgressStatus::GeneratingTransaction) + .map_mm_err()?; + let satoshi = sat_from_big_decimal(&amount, self.decimals()).map_mm_err()?; let memo = req.memo.as_deref().map(interpret_memo_string).transpose()?; let z_output = ZOutput { to_addr, amount: Amount::from_u64(satoshi) - .map_to_mm(|_| NumConversError(format!("Failed to get ZCash amount from {}", amount)))?, + .map_to_mm(|_| NumConversError(format!("Failed to get ZCash amount from {}", amount))) + .map_mm_err()?, // TODO add optional viewing_key and memo fields to the WithdrawRequest viewing_key: Some(self.z_fields.evk.fvk.ovk), memo, }; - let GenTxData { tx, data, .. } = self.gen_tx(vec![], vec![z_output]).await?; + let GenTxData { tx, data, .. } = self.gen_tx(vec![], vec![z_output]).await.map_mm_err()?; let mut tx_bytes = Vec::with_capacity(1024); tx.write(&mut tx_bytes) .map_to_mm(|e| WithdrawError::InternalError(e.to_string()))?; @@ -2060,7 +2087,7 @@ async fn wait_for_spendable_balance_impl( .map_err(|e| GenTxError::SpendableNotesError(e.to_string()))?; let wallet_notes_len = wallet_notes.len(); - let locked_notes = selfi.z_fields.locked_notes_db.load_all_notes().await?; + let locked_notes = selfi.z_fields.locked_notes_db.load_all_notes().await.map_mm_err()?; let unlocked_notes: Vec = if locked_notes.is_empty() { wallet_notes diff --git a/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs b/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs index b95af8c4cd..4a74c621fe 100644 --- a/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs +++ b/mm2src/coins/z_coin/storage/blockdb/blockdb_idb_storage.rs @@ -85,18 +85,21 @@ impl BlockDbImpl { pub async fn get_latest_block(&self) -> ZcoinStorageRes { let ticker = self.ticker.clone(); let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let block_db = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let block_db = db_transaction.table::().await.map_mm_err()?; let maybe_height = block_db .cursor_builder() - .only("ticker", &ticker)? + .only("ticker", &ticker) + .map_mm_err()? .bound("height", 0u32, u32::MAX) .reverse() .where_first() .open_cursor(BlockDbTable::TICKER_HEIGHT_INDEX) - .await? + .await + .map_mm_err()? .next() - .await?; + .await + .map_mm_err()?; Ok(maybe_height.map(|(_, item)| item.height).unwrap_or_else(|| 0)) } @@ -105,12 +108,14 @@ impl BlockDbImpl { pub async fn insert_block(&self, height: u32, cb_bytes: Vec) -> ZcoinStorageRes { let ticker = self.ticker.clone(); let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let block_db = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let block_db = db_transaction.table::().await.map_mm_err()?; let indexes = MultiIndex::new(BlockDbTable::TICKER_HEIGHT_INDEX) - .with_value(&ticker)? - .with_value(BeBigUint::from(height))?; + .with_value(&ticker) + .map_mm_err()? + .with_value(BeBigUint::from(height)) + .map_mm_err()?; let block = BlockDbTable { height, data: cb_bytes, @@ -119,7 +124,8 @@ impl BlockDbImpl { Ok(block_db .add_item_or_ignore_by_unique_multi_index(indexes, &block) - .await? + .await + .map_mm_err()? .get_id() as usize) } @@ -127,28 +133,34 @@ impl BlockDbImpl { /// removing data beyond the specified height from the storage. pub async fn rewind_to_height(&self, height: BlockHeight) -> ZcoinStorageRes { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let block_db = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let block_db = db_transaction.table::().await.map_mm_err()?; let blocks = block_db .cursor_builder() - .only("ticker", &self.ticker)? + .only("ticker", &self.ticker) + .map_mm_err()? .bound("height", 0u32, u32::MAX) .reverse() .open_cursor(BlockDbTable::TICKER_HEIGHT_INDEX) - .await? + .await + .map_mm_err()? .collect() - .await?; + .await + .map_mm_err()?; for (_, block) in &blocks { if block.height > u32::from(height) { block_db .delete_item_by_unique_multi_index( MultiIndex::new(BlockDbTable::TICKER_HEIGHT_INDEX) - .with_value(&self.ticker)? - .with_value(block.height)?, + .with_value(&self.ticker) + .map_mm_err()? + .with_value(block.height) + .map_mm_err()?, ) - .await?; + .await + .map_mm_err()?; } } @@ -158,17 +170,20 @@ impl BlockDbImpl { #[allow(unused)] pub(crate) async fn get_earliest_block(&self) -> ZcoinStorageRes { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let block_db = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let block_db = db_transaction.table::().await.map_mm_err()?; let maybe_min_block = block_db .cursor_builder() - .only("ticker", &self.ticker)? + .only("ticker", &self.ticker) + .map_mm_err()? .bound("height", 0u32, u32::MAX) .where_first() .open_cursor(BlockDbTable::TICKER_HEIGHT_INDEX) - .await? + .await + .map_mm_err()? .next() - .await?; + .await + .map_mm_err()?; Ok(maybe_min_block.map(|(_, b)| b.height).unwrap_or(0)) } @@ -181,20 +196,22 @@ impl BlockDbImpl { limit: Option, ) -> ZcoinStorageRes> { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let block_db = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let block_db = db_transaction.table::().await.map_mm_err()?; // Fetch CompactBlocks block_db are needed for scanning. let min = u32::from(from_height + 1); let mut maybe_blocks = block_db .cursor_builder() - .only("ticker", &self.ticker)? + .only("ticker", &self.ticker) + .map_mm_err()? .bound("height", min, u32::MAX) .open_cursor(BlockDbTable::TICKER_HEIGHT_INDEX) - .await?; + .await + .map_mm_err()?; let mut blocks_to_scan = vec![]; - while let Some((_, block)) = maybe_blocks.next().await? { + while let Some((_, block)) = maybe_blocks.next().await.map_mm_err()? { if let Some(limit) = limit { if blocks_to_scan.len() > limit as usize { break; diff --git a/mm2src/coins/z_coin/storage/walletdb/wasm/storage.rs b/mm2src/coins/z_coin/storage/walletdb/wasm/storage.rs index 78d8a6fbaa..f4e08c3ef2 100644 --- a/mm2src/coins/z_coin/storage/walletdb/wasm/storage.rs +++ b/mm2src/coins/z_coin/storage/walletdb/wasm/storage.rs @@ -154,13 +154,15 @@ impl<'a> WalletIndexedDb { pub async fn is_tx_imported(&self, tx_id: TxId) -> ZcoinStorageRes { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; - let tx_table = db_transaction.table::().await?; + let tx_table = db_transaction.table::().await.map_mm_err()?; let index_keys = MultiIndex::new(WalletDbTransactionsTable::TICKER_TXID_INDEX) - .with_value(&self.ticker)? - .with_value(tx_id.0.to_vec())?; - let maybe_tx = tx_table.get_items_by_multi_index(index_keys).await?; + .with_value(&self.ticker) + .map_mm_err()? + .with_value(tx_id.0.to_vec()) + .map_mm_err()?; + let maybe_tx = tx_table.get_items_by_multi_index(index_keys).await.map_mm_err()?; if !maybe_tx.is_empty() { Ok(true) @@ -175,19 +177,22 @@ impl<'a> WalletIndexedDb { pub(crate) async fn init_accounts_table(&self, extfvks: &[ExtendedFullViewingKey]) -> ZcoinStorageRes<()> { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let walletdb_account_table = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let walletdb_account_table = db_transaction.table::().await.map_mm_err()?; // check if account exists let maybe_min_account = walletdb_account_table .cursor_builder() - .only("ticker", &self.ticker)? + .only("ticker", &self.ticker) + .map_mm_err()? .bound("height", 0u32, u32::MAX) .where_first() .open_cursor(WalletDbAccountsTable::TICKER_ACCOUNT_INDEX) - .await? + .await + .map_mm_err()? .next() - .await?; + .await + .map_mm_err()?; if maybe_min_account.is_some() { return MmError::err(ZcoinStorageError::TableNotEmpty( "Account table is not empty".to_string(), @@ -209,12 +214,15 @@ impl<'a> WalletIndexedDb { }; let index_keys = MultiIndex::new(WalletDbAccountsTable::TICKER_ACCOUNT_INDEX) - .with_value(&self.ticker)? - .with_value(account_int)?; + .with_value(&self.ticker) + .map_mm_err()? + .with_value(account_int) + .map_mm_err()?; walletdb_account_table .replace_item_by_unique_multi_index(index_keys, &account) - .await?; + .await + .map_mm_err()?; } Ok(()) @@ -228,19 +236,22 @@ impl<'a> WalletIndexedDb { sapling_tree: &[u8], ) -> ZcoinStorageRes<()> { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let walletdb_account_table = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let walletdb_account_table = db_transaction.table::().await.map_mm_err()?; // check if account exists let maybe_min_account = walletdb_account_table .cursor_builder() - .only("ticker", &self.ticker)? + .only("ticker", &self.ticker) + .map_mm_err()? .bound("height", 0u32, u32::MAX) .where_first() .open_cursor(WalletDbBlocksTable::TICKER_HEIGHT_INDEX) - .await? + .await + .map_mm_err()? .next() - .await?; + .await + .map_mm_err()?; if maybe_min_account.is_some() { return MmError::err(ZcoinStorageError::TableNotEmpty( "Account table is not empty".to_string(), @@ -254,14 +265,18 @@ impl<'a> WalletIndexedDb { sapling_tree: sapling_tree.to_vec(), ticker: self.ticker.clone(), }; - let walletdb_blocks_table = db_transaction.table::().await?; + let walletdb_blocks_table = db_transaction.table::().await.map_mm_err()?; let height = u32::from(height); let index_keys = MultiIndex::new(WalletDbBlocksTable::TICKER_HEIGHT_INDEX) - .with_value(&self.ticker)? - .with_value(num_to_bigint!(height)?)?; + .with_value(&self.ticker) + .map_mm_err()? + .with_value(num_to_bigint!(height)?) + .map_mm_err()?; + walletdb_blocks_table .replace_item_by_unique_multi_index(index_keys, &block) - .await?; + .await + .map_mm_err()?; Ok(()) } @@ -276,8 +291,8 @@ impl WalletIndexedDb { commitment_tree: &CommitmentTree, ) -> ZcoinStorageRes<()> { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let walletdb_blocks_table = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let walletdb_blocks_table = db_transaction.table::().await.map_mm_err()?; let mut encoded_tree = Vec::new(); commitment_tree.write(&mut encoded_tree).unwrap(); @@ -292,27 +307,35 @@ impl WalletIndexedDb { }; let index_keys = MultiIndex::new(WalletDbBlocksTable::TICKER_HEIGHT_INDEX) - .with_value(&self.ticker)? - .with_value(u32::from(block_height))?; + .with_value(&self.ticker) + .map_mm_err()? + .with_value(u32::from(block_height)) + .map_mm_err()?; - Ok(walletdb_blocks_table + walletdb_blocks_table .replace_item_by_unique_multi_index(index_keys, &block) .await - .map(|_| ())?) + .map(|_| ()) + .map_mm_err() } pub async fn get_balance(&self, account: AccountId) -> ZcoinStorageRes { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let rec_note_table = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let rec_note_table = db_transaction + .table::() + .await + .map_mm_err()?; let index_keys = MultiIndex::new(WalletDbReceivedNotesTable::TICKER_ACCOUNT_INDEX) - .with_value(&self.ticker)? - .with_value(account.0.to_bigint().unwrap())?; - let maybe_notes = rec_note_table.get_items_by_multi_index(index_keys).await?; + .with_value(&self.ticker) + .map_mm_err()? + .with_value(account.0.to_bigint().unwrap()) + .map_mm_err()?; + let maybe_notes = rec_note_table.get_items_by_multi_index(index_keys).await.map_mm_err()?; - let tx_table = db_transaction.table::().await?; - let txs = tx_table.get_items("ticker", &self.ticker).await?; + let tx_table = db_transaction.table::().await.map_mm_err()?; + let txs = tx_table.get_items("ticker", &self.ticker).await.map_mm_err()?; let balance: i64 = maybe_notes .iter() @@ -339,17 +362,19 @@ impl WalletIndexedDb { pub async fn put_tx_data(&self, tx: &Transaction, created_at: Option) -> ZcoinStorageRes { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let tx_table = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let tx_table = db_transaction.table::().await.map_mm_err()?; let mut raw_tx = vec![]; tx.write(&mut raw_tx).unwrap(); let txid = tx.txid().0.to_vec(); let index_keys = MultiIndex::new(WalletDbTransactionsTable::TICKER_TXID_INDEX) - .with_value(&self.ticker)? - .with_value(&txid)?; - let single_tx = tx_table.get_item_by_unique_multi_index(index_keys).await?; + .with_value(&self.ticker) + .map_mm_err()? + .with_value(&txid) + .map_mm_err()?; + let single_tx = tx_table.get_item_by_unique_multi_index(index_keys).await.map_mm_err()?; if let Some((id_tx, some_tx)) = single_tx { let updated_tx = WalletDbTransactionsTable { txid: txid.clone(), @@ -360,7 +385,7 @@ impl WalletIndexedDb { raw: Some(raw_tx), ticker: self.ticker.clone(), }; - tx_table.replace_item(id_tx, &updated_tx).await?; + tx_table.replace_item(id_tx, &updated_tx).await.map_mm_err()?; return Ok(id_tx as i64); }; @@ -375,25 +400,30 @@ impl WalletIndexedDb { ticker: self.ticker.clone(), }; let index_keys = MultiIndex::new(WalletDbTransactionsTable::TICKER_TXID_INDEX) - .with_value(&self.ticker)? - .with_value(txid)?; + .with_value(&self.ticker) + .map_mm_err()? + .with_value(txid) + .map_mm_err()?; Ok(tx_table .replace_item_by_unique_multi_index(index_keys, &new_tx) - .await? + .await + .map_mm_err()? .into()) } pub async fn put_tx_meta(&self, tx: &WalletTx, height: BlockHeight) -> ZcoinStorageRes { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let tx_table = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let tx_table = db_transaction.table::().await.map_mm_err()?; let txid = tx.txid.0.to_vec(); let index_keys = MultiIndex::new(WalletDbTransactionsTable::TICKER_TXID_INDEX) - .with_value(&self.ticker)? - .with_value(&txid)?; - let single_tx = tx_table.get_item_by_unique_multi_index(index_keys).await?; + .with_value(&self.ticker) + .map_mm_err()? + .with_value(&txid) + .map_mm_err()?; + let single_tx = tx_table.get_item_by_unique_multi_index(index_keys).await.map_mm_err()?; if let Some((id_tx, some_tx)) = single_tx { let updated_tx = WalletDbTransactionsTable { @@ -405,7 +435,7 @@ impl WalletIndexedDb { raw: some_tx.raw, ticker: self.ticker.clone(), }; - tx_table.replace_item(id_tx, &updated_tx).await?; + tx_table.replace_item(id_tx, &updated_tx).await.map_mm_err()?; return Ok(id_tx as i64); }; @@ -420,25 +450,36 @@ impl WalletIndexedDb { ticker: self.ticker.clone(), }; let index_keys = MultiIndex::new(WalletDbTransactionsTable::TICKER_TXID_INDEX) - .with_value(&self.ticker)? - .with_value(txid)?; + .with_value(&self.ticker) + .map_mm_err()? + .with_value(txid) + .map_mm_err()?; Ok(tx_table .replace_item_by_unique_multi_index(index_keys, &new_tx) - .await? + .await + .map_mm_err()? .into()) } pub async fn mark_spent(&self, tx_ref: i64, nf: &Nullifier) -> ZcoinStorageRes<()> { let ticker = self.ticker.clone(); let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let received_notes_table = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let received_notes_table = db_transaction + .table::() + .await + .map_mm_err()?; let index_keys = MultiIndex::new(WalletDbReceivedNotesTable::TICKER_NF_INDEX) - .with_value(&ticker)? - .with_value(nf.0.to_vec())?; - let maybe_note = received_notes_table.get_item_by_unique_multi_index(index_keys).await?; + .with_value(&ticker) + .map_mm_err()? + .with_value(nf.0.to_vec()) + .map_mm_err()?; + let maybe_note = received_notes_table + .get_item_by_unique_multi_index(index_keys) + .await + .map_mm_err()?; if let Some((id, note)) = maybe_note { let new_received_note = WalletDbReceivedNotesTable { @@ -454,7 +495,10 @@ impl WalletIndexedDb { spent: Some(num_to_bigint!(tx_ref)?), ticker, }; - received_notes_table.replace_item(id, &new_received_note).await?; + received_notes_table + .replace_item(id, &new_received_note) + .await + .map_mm_err()?; return Ok(()); } @@ -464,7 +508,7 @@ impl WalletIndexedDb { pub async fn put_received_note(&self, output: &T, tx_ref: i64) -> ZcoinStorageRes { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; let rcm = output.note().rcm().to_repr(); let account = BigInt::from(output.account().0); @@ -477,12 +521,21 @@ impl WalletIndexedDb { let output_index = output.index() as u32; let nf_bytes = output.nullifier().map(|nf| nf.0.to_vec()); - let received_note_table = db_transaction.table::().await?; + let received_note_table = db_transaction + .table::() + .await + .map_mm_err()?; let index_keys = MultiIndex::new(WalletDbReceivedNotesTable::TICKER_TX_OUTPUT_INDEX) - .with_value(&self.ticker)? - .with_value(tx)? - .with_value(output_index)?; - let current_note = received_note_table.get_item_by_unique_multi_index(index_keys).await?; + .with_value(&self.ticker) + .map_mm_err()? + .with_value(tx) + .map_mm_err()? + .with_value(output_index) + .map_mm_err()?; + let current_note = received_note_table + .get_item_by_unique_multi_index(index_keys) + .await + .map_mm_err()?; let id = if let Some((id, note)) = current_note { let temp_note = WalletDbReceivedNotesTable { @@ -498,7 +551,7 @@ impl WalletIndexedDb { spent: note.spent, ticker: self.ticker.clone(), }; - received_note_table.replace_item(id, &temp_note).await? + received_note_table.replace_item(id, &temp_note).await.map_mm_err()? } else { let new_note = WalletDbReceivedNotesTable { tx, @@ -515,12 +568,16 @@ impl WalletIndexedDb { }; let index_keys = MultiIndex::new(WalletDbReceivedNotesTable::TICKER_TX_OUTPUT_INDEX) - .with_value(&self.ticker)? - .with_value(tx)? - .with_value(num_to_bigint!(output_index)?)?; + .with_value(&self.ticker) + .map_mm_err()? + .with_value(tx) + .map_mm_err()? + .with_value(num_to_bigint!(output_index)?) + .map_mm_err()?; received_note_table .replace_item_by_unique_multi_index(index_keys, &new_note) - .await? + .await + .map_mm_err()? }; Ok(NoteId::ReceivedNoteId(id.into())) @@ -533,8 +590,11 @@ impl WalletIndexedDb { height: BlockHeight, ) -> ZcoinStorageRes<()> { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let witness_table = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let witness_table = db_transaction + .table::() + .await + .map_mm_err()?; let mut encoded = Vec::new(); witness.write(&mut encoded).unwrap(); @@ -547,23 +607,28 @@ impl WalletIndexedDb { ticker: self.ticker.clone(), }; - Ok(witness_table.add_item(&witness).await.map(|_| ())?) + witness_table.add_item(&witness).await.map(|_| ()).map_mm_err() } pub async fn prune_witnesses(&self, below_height: BlockHeight) -> ZcoinStorageRes<()> { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let witness_table = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let witness_table = db_transaction + .table::() + .await + .map_mm_err()?; let mut maybe_witness = witness_table .cursor_builder() - .only("ticker", &self.ticker)? + .only("ticker", &self.ticker) + .map_mm_err()? .bound("block", 0u32, (below_height - 1).into()) .open_cursor(WalletDbSaplingWitnessesTable::TICKER_BLOCK_INDEX) - .await?; + .await + .map_mm_err()?; - while let Some((id, _)) = maybe_witness.next().await? { - witness_table.delete_item(id).await?; + while let Some((id, _)) = maybe_witness.next().await.map_mm_err()? { + witness_table.delete_item(id).await.map_mm_err()?; } Ok(()) @@ -571,22 +636,30 @@ impl WalletIndexedDb { pub async fn update_expired_notes(&self, height: BlockHeight) -> ZcoinStorageRes<()> { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; // fetch received_notes. - let received_notes_table = db_transaction.table::().await?; - let maybe_notes = received_notes_table.get_items("ticker", &self.ticker).await?; + let received_notes_table = db_transaction + .table::() + .await + .map_mm_err()?; + let maybe_notes = received_notes_table + .get_items("ticker", &self.ticker) + .await + .map_mm_err()?; // fetch transactions with block < height . - let txs_table = db_transaction.table::().await?; + let txs_table = db_transaction.table::().await.map_mm_err()?; let mut maybe_txs = txs_table .cursor_builder() - .only("ticker", &self.ticker)? + .only("ticker", &self.ticker) + .map_mm_err()? .bound("expiry_height", 0u32, u32::from(height - 1)) .reverse() .open_cursor(WalletDbTransactionsTable::TICKER_EXP_HEIGHT_INDEX) - .await?; + .await + .map_mm_err()?; - while let Some((id, note)) = maybe_txs.next().await? { + while let Some((id, note)) = maybe_txs.next().await.map_mm_err()? { if note.block.is_none() { if let Some(curr) = maybe_notes.iter().find(|(_, n)| n.spent == id.to_bigint()) { let temp_note = WalletDbReceivedNotesTable { @@ -603,7 +676,10 @@ impl WalletIndexedDb { ticker: self.ticker.clone(), }; - received_notes_table.replace_item(curr.0, &temp_note).await?; + received_notes_table + .replace_item(curr.0, &temp_note) + .await + .map_mm_err()?; } }; } @@ -613,7 +689,7 @@ impl WalletIndexedDb { pub async fn put_sent_note(&self, output: &DecryptedOutput, tx_ref: i64) -> ZcoinStorageRes<()> { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; let tx_ref = num_to_bigint!(tx_ref)?; let output_index = output.index; @@ -624,12 +700,18 @@ impl WalletIndexedDb { let value = num_to_bigint!(value)?; let address = encode_payment_address(self.params.hrp_sapling_payment_address(), &output.to); - let sent_note_table = db_transaction.table::().await?; + let sent_note_table = db_transaction.table::().await.map_mm_err()?; let index_keys = MultiIndex::new(WalletDbSentNotesTable::TICKER_TX_OUTPUT_INDEX) - .with_value(&self.ticker)? - .with_value(&tx_ref)? - .with_value(&output_index)?; - let maybe_note = sent_note_table.get_item_by_unique_multi_index(index_keys).await?; + .with_value(&self.ticker) + .map_mm_err()? + .with_value(&tx_ref) + .map_mm_err()? + .with_value(&output_index) + .map_mm_err()?; + let maybe_note = sent_note_table + .get_item_by_unique_multi_index(index_keys) + .await + .map_mm_err()?; let update_note = WalletDbSentNotesTable { tx: tx_ref.clone(), @@ -641,15 +723,19 @@ impl WalletIndexedDb { ticker: self.ticker.clone(), }; if let Some((id, _)) = maybe_note { - sent_note_table.replace_item(id, &update_note).await?; + sent_note_table.replace_item(id, &update_note).await.map_mm_err()?; } else { let index_keys = MultiIndex::new(WalletDbReceivedNotesTable::TICKER_TX_OUTPUT_INDEX) - .with_value(&self.ticker)? - .with_value(tx_ref)? - .with_value(output_index)?; + .with_value(&self.ticker) + .map_mm_err()? + .with_value(tx_ref) + .map_mm_err()? + .with_value(output_index) + .map_mm_err()?; sent_note_table .replace_item_by_unique_multi_index(index_keys, &update_note) - .await?; + .await + .map_mm_err()?; } Ok(()) @@ -665,8 +751,8 @@ impl WalletIndexedDb { memo: Option<&MemoBytes>, ) -> ZcoinStorageRes<()> { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let sent_note_table = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let sent_note_table = db_transaction.table::().await.map_mm_err()?; let tx_ref = num_to_bigint!(tx_ref)?; let output_index = num_to_bigint!(output_index)?; @@ -685,36 +771,43 @@ impl WalletIndexedDb { ticker: self.ticker.clone(), }; let index_keys = MultiIndex::new(WalletDbReceivedNotesTable::TICKER_TX_OUTPUT_INDEX) - .with_value(&self.ticker)? - .with_value(tx_ref)? - .with_value(output_index)?; - - Ok(sent_note_table + .with_value(&self.ticker) + .map_mm_err()? + .with_value(tx_ref) + .map_mm_err()? + .with_value(output_index) + .map_mm_err()?; + + sent_note_table .replace_item_by_unique_multi_index(index_keys, &new_note) .await - .map(|_| ())?) + .map(|_| ()) + .map_mm_err() } /// Asynchronously rewinds the storage to a specified block height, effectively /// removing data beyond the specified height from the storage. pub async fn rewind_to_height(&self, block_height: BlockHeight) -> ZcoinStorageRes<()> { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; let block_height = u32::from(block_height); // Recall where we synced up to previously. - let blocks_table = db_transaction.table::().await?; + let blocks_table = db_transaction.table::().await.map_mm_err()?; let maybe_height = blocks_table .cursor_builder() - .only("ticker", &self.ticker)? + .only("ticker", &self.ticker) + .map_mm_err()? .bound("height", 0u32, u32::MAX) .reverse() .where_first() .open_cursor(WalletDbBlocksTable::TICKER_HEIGHT_INDEX) - .await? + .await + .map_mm_err()? .next() - .await? + .await + .map_mm_err()? .map(|(_, item)| { item.height .to_u32() @@ -732,31 +825,39 @@ impl WalletIndexedDb { }; // Decrement witnesses. - let db_transaction = locked_db.get_inner().transaction().await?; - let witnesses_table = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let witnesses_table = db_transaction + .table::() + .await + .map_mm_err()?; let maybe_witnesses_cursor = witnesses_table .cursor_builder() - .only("ticker", &self.ticker)? + .only("ticker", &self.ticker) + .map_mm_err()? .bound("block", block_height + 1, u32::MAX) .open_cursor(WalletDbSaplingWitnessesTable::TICKER_BLOCK_INDEX) - .await? + .await + .map_mm_err()? .collect() - .await?; + .await + .map_mm_err()?; for (id, _witness) in maybe_witnesses_cursor { - witnesses_table.delete_item(id).await?; + witnesses_table.delete_item(id).await.map_mm_err()?; } // Un-mine transactions. - let db_transaction = locked_db.get_inner().transaction().await?; - let transactions_table = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let transactions_table = db_transaction.table::().await.map_mm_err()?; let mut maybe_txs_cursor = transactions_table .cursor_builder() - .only("ticker", &self.ticker)? + .only("ticker", &self.ticker) + .map_mm_err()? .bound("block", block_height + 1, u32::MAX) .open_cursor(WalletDbTransactionsTable::TICKER_BLOCK_INDEX) - .await?; - while let Some((_, tx)) = maybe_txs_cursor.next().await? { + .await + .map_mm_err()?; + while let Some((_, tx)) = maybe_txs_cursor.next().await.map_mm_err()? { let modified_tx = WalletDbTransactionsTable { txid: tx.txid.clone(), created: tx.created.clone(), @@ -767,30 +868,41 @@ impl WalletIndexedDb { ticker: self.ticker.clone(), }; let index_keys = MultiIndex::new(WalletDbTransactionsTable::TICKER_TXID_INDEX) - .with_value(&self.ticker)? - .with_value(tx.txid)?; + .with_value(&self.ticker) + .map_mm_err()? + .with_value(tx.txid) + .map_mm_err()?; transactions_table .replace_item_by_unique_multi_index(index_keys, &modified_tx) - .await?; + .await + .map_mm_err()?; } // Now that they aren't depended on, delete scanned blocks. - let db_transaction = locked_db.get_inner().transaction().await?; - let blocks_table = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let blocks_table = db_transaction.table::().await.map_mm_err()?; let maybe_blocks = blocks_table .cursor_builder() - .only("ticker", &self.ticker)? + .only("ticker", &self.ticker) + .map_mm_err()? .bound("height", block_height + 1, u32::MAX) .open_cursor(WalletDbBlocksTable::TICKER_HEIGHT_INDEX) - .await? + .await + .map_mm_err()? .collect() - .await?; + .await + .map_mm_err()?; for (_, block) in maybe_blocks { let index_keys = MultiIndex::new(WalletDbBlocksTable::TICKER_HEIGHT_INDEX) - .with_value(&self.ticker)? - .with_value(block.height)?; - blocks_table.delete_item_by_unique_multi_index(index_keys).await?; + .with_value(&self.ticker) + .map_mm_err()? + .with_value(block.height) + .map_mm_err()?; + blocks_table + .delete_item_by_unique_multi_index(index_keys) + .await + .map_mm_err()?; } Ok(()) @@ -805,29 +917,35 @@ impl WalletRead for WalletIndexedDb { async fn block_height_extrema(&self) -> Result, Self::Error> { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let block_headers_db = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let block_headers_db = db_transaction.table::().await.map_mm_err()?; let earliest_block = block_headers_db .cursor_builder() - .only("ticker", &self.ticker)? + .only("ticker", &self.ticker) + .map_mm_err()? .bound("height", 0u32, u32::MAX) .where_first() .open_cursor(WalletDbBlocksTable::TICKER_HEIGHT_INDEX) - .await? + .await + .map_mm_err()? .next() - .await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let block_headers_db = db_transaction.table::().await?; + .await + .map_mm_err()?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let block_headers_db = db_transaction.table::().await.map_mm_err()?; let latest_block = block_headers_db .cursor_builder() - .only("ticker", &self.ticker)? + .only("ticker", &self.ticker) + .map_mm_err()? .bound("height", 0u32, u32::MAX) .reverse() .where_first() .open_cursor(WalletDbBlocksTable::TICKER_HEIGHT_INDEX) - .await? + .await + .map_mm_err()? .next() - .await?; + .await + .map_mm_err()?; if let (Some(min), Some(max)) = (earliest_block, latest_block) { Ok(Some((BlockHeight::from(min.1.height), BlockHeight::from(max.1.height)))) @@ -838,44 +956,53 @@ impl WalletRead for WalletIndexedDb { async fn get_block_hash(&self, block_height: BlockHeight) -> Result, Self::Error> { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let block_headers_db = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let block_headers_db = db_transaction.table::().await.map_mm_err()?; let index_keys = MultiIndex::new(WalletDbBlocksTable::TICKER_HEIGHT_INDEX) - .with_value(&self.ticker)? - .with_value(u32::from(block_height))?; + .with_value(&self.ticker) + .map_mm_err()? + .with_value(u32::from(block_height)) + .map_mm_err()?; Ok(block_headers_db .get_item_by_unique_multi_index(index_keys) - .await? + .await + .map_mm_err()? .map(|(_, block)| BlockHash::from_slice(&block.hash[..]))) } async fn get_tx_height(&self, txid: TxId) -> Result, Self::Error> { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let block_headers_db = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let block_headers_db = db_transaction.table::().await.map_mm_err()?; let index_keys = MultiIndex::new(WalletDbTransactionsTable::TICKER_TXID_INDEX) - .with_value(&self.ticker)? - .with_value(txid.0.to_vec())?; + .with_value(&self.ticker) + .map_mm_err()? + .with_value(txid.0.to_vec()) + .map_mm_err()?; Ok(block_headers_db .get_item_by_unique_multi_index(index_keys) - .await? + .await + .map_mm_err()? .and_then(|(_, tx)| tx.block.map(BlockHeight::from))) } async fn get_address(&self, account: AccountId) -> Result, Self::Error> { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let block_headers_db = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let block_headers_db = db_transaction.table::().await.map_mm_err()?; let account_num = account.0; let index_keys = MultiIndex::new(WalletDbAccountsTable::TICKER_ACCOUNT_INDEX) - .with_value(&self.ticker)? - .with_value(num_to_bigint!(account_num)?)?; + .with_value(&self.ticker) + .map_mm_err()? + .with_value(num_to_bigint!(account_num)?) + .map_mm_err()?; let address = block_headers_db .get_item_by_unique_multi_index(index_keys) - .await? + .await + .map_mm_err()? .map(|(_, account)| account.address) .ok_or_else(|| ZcoinStorageError::GetFromStorageError("Invalid account/not found".to_string()))?; @@ -889,9 +1016,9 @@ impl WalletRead for WalletIndexedDb { async fn get_extended_full_viewing_keys(&self) -> Result, Self::Error> { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let accounts_table = db_transaction.table::().await?; - let maybe_accounts = accounts_table.get_items("ticker", &self.ticker).await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let accounts_table = db_transaction.table::().await.map_mm_err()?; + let maybe_accounts = accounts_table.get_items("ticker", &self.ticker).await.map_mm_err()?; let mut res_accounts: HashMap = HashMap::with_capacity(maybe_accounts.len()); for (_, account) in maybe_accounts { @@ -916,13 +1043,18 @@ impl WalletRead for WalletIndexedDb { extfvk: &ExtendedFullViewingKey, ) -> Result { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let accounts_table = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let accounts_table = db_transaction.table::().await.map_mm_err()?; let index_keys = MultiIndex::new(WalletDbAccountsTable::TICKER_ACCOUNT_INDEX) - .with_value(&self.ticker)? - .with_value(account.0.to_bigint())?; + .with_value(&self.ticker) + .map_mm_err()? + .with_value(account.0.to_bigint()) + .map_mm_err()?; - let account = accounts_table.get_item_by_unique_multi_index(index_keys).await?; + let account = accounts_table + .get_item_by_unique_multi_index(index_keys) + .await + .map_mm_err()?; if let Some((_, account)) = account { let expected = @@ -938,28 +1070,39 @@ impl WalletRead for WalletIndexedDb { async fn get_balance_at(&self, account: AccountId, anchor_height: BlockHeight) -> Result { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; - let tx_table = db_transaction.table::().await?; + let tx_table = db_transaction.table::().await.map_mm_err()?; // Retrieves a list of transaction IDs (txid) from the transactions table // that match the provided account ID. let txids = tx_table .cursor_builder() - .only("ticker", &self.ticker)? + .only("ticker", &self.ticker) + .map_mm_err()? .bound("block", 0u32, u32::from(anchor_height)) .open_cursor(WalletDbTransactionsTable::TICKER_BLOCK_INDEX) - .await? + .await + .map_mm_err()? .collect() - .await? + .await + .map_mm_err()? .into_iter() .map(|(id, _)| id) .collect::>(); - let received_notes_table = db_transaction.table::().await?; + let received_notes_table = db_transaction + .table::() + .await + .map_mm_err()?; let index_keys = MultiIndex::new(WalletDbReceivedNotesTable::TICKER_ACCOUNT_INDEX) - .with_value(&self.ticker)? - .with_value(account.0.to_bigint().unwrap())?; - let maybe_notes = received_notes_table.get_items_by_multi_index(index_keys).await?; + .with_value(&self.ticker) + .map_mm_err()? + .with_value(account.0.to_bigint().unwrap()) + .map_mm_err()?; + let maybe_notes = received_notes_table + .get_items_by_multi_index(index_keys) + .await + .map_mm_err()?; let mut value: i64 = 0; for (_, note) in maybe_notes { @@ -980,20 +1123,23 @@ impl WalletRead for WalletIndexedDb { async fn get_memo(&self, id_note: Self::NoteRef) -> Result { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; let memo = match id_note { NoteId::SentNoteId(id_note) => { - let sent_notes_table = db_transaction.table::().await?; - let notes = sent_notes_table.get_items("ticker", &self.ticker).await?; + let sent_notes_table = db_transaction.table::().await.map_mm_err()?; + let notes = sent_notes_table.get_items("ticker", &self.ticker).await.map_mm_err()?; notes .into_iter() .find(|(id, _)| *id as i64 == id_note) .map(|(_, n)| n.memo) }, NoteId::ReceivedNoteId(id_note) => { - let received_notes_table = db_transaction.table::().await?; - let notes = received_notes_table.get_items("ticker", &self.ticker).await?; + let received_notes_table = db_transaction.table::().await.map_mm_err()?; + let notes = received_notes_table + .get_items("ticker", &self.ticker) + .await + .map_mm_err()?; notes .into_iter() .find(|(id, _)| *id as i64 == id_note) @@ -1015,15 +1161,18 @@ impl WalletRead for WalletIndexedDb { block_height: BlockHeight, ) -> Result>, Self::Error> { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let blocks_table = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let blocks_table = db_transaction.table::().await.map_mm_err()?; let index_keys = MultiIndex::new(WalletDbBlocksTable::TICKER_HEIGHT_INDEX) - .with_value(&self.ticker)? - .with_value(u32::from(block_height))?; + .with_value(&self.ticker) + .map_mm_err()? + .with_value(u32::from(block_height)) + .map_mm_err()?; let block = blocks_table .get_item_by_unique_multi_index(index_keys) - .await? + .await + .map_mm_err()? .map(|(_, account)| account); if let Some(block) = block { @@ -1041,14 +1190,22 @@ impl WalletRead for WalletIndexedDb { block_height: BlockHeight, ) -> Result)>, Self::Error> { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; - let sapling_witness_table = db_transaction.table::().await?; + let sapling_witness_table = db_transaction + .table::() + .await + .map_mm_err()?; let index_keys = MultiIndex::new(WalletDbSaplingWitnessesTable::TICKER_BLOCK_INDEX) - .with_value(&self.ticker)? - .with_value(u32::from(block_height))?; - let maybe_witnesses = sapling_witness_table.get_items_by_multi_index(index_keys).await?; + .with_value(&self.ticker) + .map_mm_err()? + .with_value(u32::from(block_height)) + .map_mm_err()?; + let maybe_witnesses = sapling_witness_table + .get_items_by_multi_index(index_keys) + .await + .map_mm_err()?; // Retrieves a list of transaction IDs (id_tx) from the transactions table // that match the provided account ID and have not been spent (spent IS NULL). @@ -1067,15 +1224,21 @@ impl WalletRead for WalletIndexedDb { async fn get_nullifiers(&self) -> Result, Self::Error> { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; // Received notes - let received_notes_table = db_transaction.table::().await?; - let maybe_notes = received_notes_table.get_items("ticker", &self.ticker).await?; + let received_notes_table = db_transaction + .table::() + .await + .map_mm_err()?; + let maybe_notes = received_notes_table + .get_items("ticker", &self.ticker) + .await + .map_mm_err()?; // Transactions - let txs_table = db_transaction.table::().await?; - let maybe_txs = txs_table.get_items("ticker", &self.ticker).await?; + let txs_table = db_transaction.table::().await.map_mm_err()?; + let maybe_txs = txs_table.get_items("ticker", &self.ticker).await.map_mm_err()?; let mut nullifiers = vec![]; for (_, note) in maybe_notes { @@ -1107,38 +1270,55 @@ impl WalletRead for WalletIndexedDb { anchor_height: BlockHeight, ) -> Result, Self::Error> { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; // Received notes - let received_notes_table = db_transaction.table::().await?; + let received_notes_table = db_transaction + .table::() + .await + .map_mm_err()?; let index_keys = MultiIndex::new(WalletDbReceivedNotesTable::TICKER_ACCOUNT_INDEX) - .with_value(&self.ticker)? - .with_value(account.0.to_bigint())?; - let maybe_notes = received_notes_table.get_items_by_multi_index(index_keys).await?; + .with_value(&self.ticker) + .map_mm_err()? + .with_value(account.0.to_bigint()) + .map_mm_err()?; + let maybe_notes = received_notes_table + .get_items_by_multi_index(index_keys) + .await + .map_mm_err()?; // Transactions - let txs_table = db_transaction.table::().await?; + let txs_table = db_transaction.table::().await.map_mm_err()?; let txs = txs_table .cursor_builder() - .only("ticker", &self.ticker)? + .only("ticker", &self.ticker) + .map_mm_err()? .bound("block", 0u32, u32::from(anchor_height + 1)) .open_cursor(WalletDbTransactionsTable::TICKER_BLOCK_INDEX) - .await? + .await + .map_mm_err()? .collect() - .await? + .await + .map_mm_err()? .into_iter() .map(|(i, item)| (i, item)) .collect::>(); // Witnesses - let witnesses_table = db_transaction.table::().await?; + let witnesses_table = db_transaction + .table::() + .await + .map_mm_err()?; let witnesses = witnesses_table .cursor_builder() - .only("ticker", &self.ticker)? + .only("ticker", &self.ticker) + .map_mm_err()? .bound("block", 0u32, u32::from(anchor_height + 1)) .open_cursor(WalletDbSaplingWitnessesTable::TICKER_BLOCK_INDEX) - .await? + .await + .map_mm_err()? .collect() - .await? + .await + .map_mm_err()? .into_iter() .map(|(_, item)| item) .collect::>(); @@ -1190,34 +1370,50 @@ impl WalletRead for WalletIndexedDb { // // 4) Match the selected notes against the witnesses at the desired height. let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; // Received notes - let received_notes_table = db_transaction.table::().await?; + let received_notes_table = db_transaction + .table::() + .await + .map_mm_err()?; let index_keys = MultiIndex::new(WalletDbReceivedNotesTable::TICKER_ACCOUNT_INDEX) - .with_value(&self.ticker)? - .with_value(account.0.to_bigint().unwrap())?; - let maybe_notes = received_notes_table.get_items_by_multi_index(index_keys).await?; + .with_value(&self.ticker) + .map_mm_err()? + .with_value(account.0.to_bigint().unwrap()) + .map_mm_err()?; + let maybe_notes = received_notes_table + .get_items_by_multi_index(index_keys) + .await + .map_mm_err()?; // Transactions - let db_transaction = locked_db.get_inner().transaction().await?; - let txs_table = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let txs_table = db_transaction.table::().await.map_mm_err()?; let txs = txs_table .cursor_builder() - .only("ticker", &self.ticker)? + .only("ticker", &self.ticker) + .map_mm_err()? .bound("block", 0u32, u32::from(anchor_height)) .open_cursor(WalletDbTransactionsTable::TICKER_BLOCK_INDEX) - .await? + .await + .map_mm_err()? .collect() - .await?; + .await + .map_mm_err()?; // Sapling Witness - let db_transaction = locked_db.get_inner().transaction().await?; - let witness_table = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let witness_table = db_transaction + .table::() + .await + .map_mm_err()?; let index_keys = MultiIndex::new(WalletDbSaplingWitnessesTable::TICKER_BLOCK_INDEX) - .with_value(&self.ticker)? - .with_value(u32::from(anchor_height))?; - let witnesses = witness_table.get_items_by_multi_index(index_keys).await?; + .with_value(&self.ticker) + .map_mm_err()? + .with_value(u32::from(anchor_height)) + .map_mm_err()?; + let witnesses = witness_table.get_items_by_multi_index(index_keys).await.map_mm_err()?; let mut running_sum = 0; let mut notes = vec![]; diff --git a/mm2src/coins/z_coin/storage/z_locked_notes/wasm.rs b/mm2src/coins/z_coin/storage/z_locked_notes/wasm.rs index dc72ca9d4e..1713ca3ea9 100644 --- a/mm2src/coins/z_coin/storage/z_locked_notes/wasm.rs +++ b/mm2src/coins/z_coin/storage/z_locked_notes/wasm.rs @@ -70,12 +70,12 @@ impl LockedNoteDbInner { impl LockedNotesStorage { async fn lockdb(&self) -> MmResult { - Ok(self.db.get_or_initialize().await?) + self.db.get_or_initialize().await.map_mm_err() } } impl LockedNotesStorage { - pub(crate) async fn new(ctx: &MmArc, address: String) -> Result { + pub(crate) async fn new(ctx: &MmArc, address: String) -> MmResult { let db = ConstructibleDb::new(ctx).into_shared(); Ok(Self { address, db }) } @@ -87,8 +87,8 @@ impl LockedNotesStorage { ) -> MmResult<(), LockedNotesStorageError> { let db = self.lockdb().await?; let address = self.address.clone(); - let transaction = db.get_inner().transaction().await?; - let change_note_table = transaction.table::().await?; + let transaction = db.get_inner().transaction().await.map_mm_err()?; + let change_note_table = transaction.table::().await.map_mm_err()?; let change_note = LockedNoteTable { address, @@ -97,10 +97,10 @@ impl LockedNotesStorage { rseed: Some(rseed), value: None, }; - Ok(change_note_table + change_note_table .add_item(&change_note) .await - .map(|_| ())?) + .map(|_| ()).map_mm_err() } pub(crate) async fn insert_change_note( @@ -110,8 +110,8 @@ impl LockedNotesStorage { ) -> MmResult<(), LockedNotesStorageError> { let db = self.lockdb().await?; let address = self.address.clone(); - let transaction = db.get_inner().transaction().await?; - let change_note_table = transaction.table::().await?; + let transaction = db.get_inner().transaction().await.map_mm_err()?; + let change_note_table = transaction.table::().await.map_mm_err()?; let change_note = LockedNoteTable { address, @@ -120,26 +120,26 @@ impl LockedNotesStorage { rseed: None, value: Some(value), }; - Ok(change_note_table + change_note_table .add_item(&change_note) .await - .map(|_| ())?) + .map(|_| ()).map_mm_err() } pub(crate) async fn remove_notes_for_txid(&self, txid: String) -> MmResult<(), LockedNotesStorageError> { let db = self.lockdb().await?; - let transaction = db.get_inner().transaction().await?; - let change_note_table = transaction.table::().await?; - change_note_table.delete_items_by_index("txid", &txid).await?; + let transaction = db.get_inner().transaction().await.map_mm_err()?; + let change_note_table = transaction.table::().await.map_mm_err()?; + change_note_table.delete_items_by_index("txid", &txid).await.map_mm_err()?; Ok(()) } pub(crate) async fn load_all_notes(&self) -> MmResult, LockedNotesStorageError> { let db = self.lockdb().await?; - let transaction = db.get_inner().transaction().await?; - let change_note_table = transaction.table::().await?; - let records = change_note_table.get_items("address", &self.address).await?; + let transaction = db.get_inner().transaction().await.map_mm_err()?; + let change_note_table = transaction.table::().await.map_mm_err()?; + let records = change_note_table.get_items("address", &self.address).await.map_mm_err()?; Ok(records .into_iter() .filter_map(|(_, n)| { diff --git a/mm2src/coins/z_coin/storage/z_params/indexeddb.rs b/mm2src/coins/z_coin/storage/z_params/indexeddb.rs index 91a2ec51b4..6822c89c5b 100644 --- a/mm2src/coins/z_coin/storage/z_params/indexeddb.rs +++ b/mm2src/coins/z_coin/storage/z_params/indexeddb.rs @@ -88,8 +88,8 @@ impl ZcashParamsWasmImpl { sapling_output: &[u8], ) -> MmResult<(), ZcoinStorageError> { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let params_db = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let params_db = db_transaction.table::().await.map_mm_err()?; let params = ZcashParamsWasmTable { sapling_spend_id, sapling_spend: sapling_spend.to_vec(), @@ -97,20 +97,21 @@ impl ZcashParamsWasmImpl { ticker: CHAIN.to_string(), }; - Ok(params_db + params_db .replace_item_by_unique_index("sapling_spend_id", sapling_spend_id as u32, ¶ms) .await - .map(|_| ())?) + .map(|_| ()) + .map_mm_err() } /// Check if z_params is previously stored. pub(crate) async fn check_params(&self) -> MmResult { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let params_db = db_transaction.table::().await?; - let count = params_db.count_all().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let params_db = db_transaction.table::().await.map_mm_err()?; + let count = params_db.count_all().await.map_mm_err()?; if count != TARGET_SPEND_CHUNKS { - params_db.delete_items_by_index("ticker", CHAIN).await?; + params_db.delete_items_by_index("ticker", CHAIN).await.map_mm_err()?; } Ok(count == TARGET_SPEND_CHUNKS) @@ -119,18 +120,20 @@ impl ZcashParamsWasmImpl { /// Get z_params from storage. pub(crate) async fn get_params(&self) -> MmResult<(Vec, Vec), ZcoinStorageError> { let locked_db = self.lock_db().await?; - let db_transaction = locked_db.get_inner().transaction().await?; - let params_db = db_transaction.table::().await?; + let db_transaction = locked_db.get_inner().transaction().await.map_mm_err()?; + let params_db = db_transaction.table::().await.map_mm_err()?; let mut maybe_params = params_db .cursor_builder() - .only("ticker", CHAIN)? + .only("ticker", CHAIN) + .map_mm_err()? .open_cursor("ticker") - .await?; + .await + .map_mm_err()?; let mut sapling_spend = vec![]; let mut sapling_output = vec![]; - while let Some((_, params)) = maybe_params.next().await? { + while let Some((_, params)) = maybe_params.next().await.map_mm_err()? { sapling_spend.extend_from_slice(¶ms.sapling_spend); if params.sapling_spend_id == 0 { sapling_output = params.sapling_output diff --git a/mm2src/coins/z_coin/z_coin_errors.rs b/mm2src/coins/z_coin/z_coin_errors.rs index 23b1664a5b..df293b89ff 100644 --- a/mm2src/coins/z_coin/z_coin_errors.rs +++ b/mm2src/coins/z_coin/z_coin_errors.rs @@ -256,11 +256,6 @@ pub enum ZCoinBuildError { FailedSpawningBalanceEvents(String), } -#[cfg(not(target_arch = "wasm32"))] -impl From for ZCoinBuildError { - fn from(err: SqliteError) -> ZCoinBuildError { ZCoinBuildError::ZcashDBError(err.to_string()) } -} - impl From for ZCoinBuildError { fn from(err: UtxoRpcError) -> ZCoinBuildError { ZCoinBuildError::Rpc(err) } } diff --git a/mm2src/coins/z_coin/z_htlc.rs b/mm2src/coins/z_coin/z_htlc.rs index ffda1aba42..0d68f7258e 100644 --- a/mm2src/coins/z_coin/z_htlc.rs +++ b/mm2src/coins/z_coin/z_htlc.rs @@ -56,7 +56,7 @@ pub async fn z_send_htlc( .build() .map_to_mm(SendOutputsErr::InternalError)?; - let amount_sat = sat_from_big_decimal(&amount, coin.utxo_arc.decimals)?; + let amount_sat = sat_from_big_decimal(&amount, coin.utxo_arc.decimals).map_mm_err()?; let address = htlc_address.to_string(); if let UtxoRpcClientEnum::Native(native) = coin.utxo_rpc_client() { native.import_address(&address, &address, false).compat().await.unwrap(); @@ -91,7 +91,8 @@ pub async fn z_send_dex_fee( if matches!(dex_fee, DexFee::NoFee) { return MmError::err(SendOutputsErr::InternalError("unexpected DexFee::NoFee".to_string())); } - let dex_fee_amount_sat = sat_from_big_decimal(&dex_fee.fee_amount().to_decimal(), coin.utxo_arc.decimals)?; + let dex_fee_amount_sat = + sat_from_big_decimal(&dex_fee.fee_amount().to_decimal(), coin.utxo_arc.decimals).map_mm_err()?; // add dex fee output let dex_fee_out = ZOutput { to_addr: coin.z_fields.dex_fee_addr.clone(), @@ -102,7 +103,8 @@ pub async fn z_send_dex_fee( }; let mut outputs = vec![dex_fee_out]; if let Some(dex_burn_amount) = dex_fee.burn_amount() { - let dex_burn_amount_sat = sat_from_big_decimal(&dex_burn_amount.to_decimal(), coin.utxo_arc.decimals)?; + let dex_burn_amount_sat = + sat_from_big_decimal(&dex_burn_amount.to_decimal(), coin.utxo_arc.decimals).map_mm_err()?; // add output to the dex burn address: let dex_burn_out = ZOutput { to_addr: coin.z_fields.dex_burn_addr.clone(), @@ -166,7 +168,7 @@ pub async fn z_p2sh_spend( script_data: Script, htlc_keypair: &KeyPair, ) -> Result> { - let current_block = coin.utxo_arc.rpc_client.get_block_count().compat().await? as u32; + let current_block = coin.utxo_arc.rpc_client.get_block_count().compat().await.map_mm_err()? as u32; let mut tx_builder = ZTxBuilder::new(coin.consensus_params(), current_block.into()); tx_builder.set_lock_time(tx_locktime); diff --git a/mm2src/coins/z_coin/z_rpc.rs b/mm2src/coins/z_coin/z_rpc.rs index 9b35081f7c..4971c6bc5a 100644 --- a/mm2src/coins/z_coin/z_rpc.rs +++ b/mm2src/coins/z_coin/z_rpc.rs @@ -380,7 +380,7 @@ impl ZRpcOps for LightRpcClient { #[async_trait] impl ZRpcOps for NativeClient { async fn get_block_height(&self) -> Result> { - Ok(self.get_block_count().compat().await?) + Ok(self.get_block_count().compat().await.map_mm_err()?) } async fn get_tree_state(&self, _height: u64) -> Result> { todo!() } @@ -393,13 +393,13 @@ impl ZRpcOps for NativeClient { handler: &mut SaplingSyncLoopHandle, ) -> Result<(), MmError> { for height in start_block..=last_block { - let block = self.get_block_by_height(height).await?; + let block = self.get_block_by_height(height).await.map_mm_err()?; debug!("Got block {:?}", block); let mut compact_txs = Vec::with_capacity(block.tx.len()); // By default, CompactBlocks only contain CompactTxs for transactions that contain Sapling spends or outputs. // Create and push compact_tx during iteration. for (tx_id, hash_tx) in block.tx.iter().enumerate() { - let tx_bytes = self.get_transaction_bytes(hash_tx).compat().await?; + let tx_bytes = self.get_transaction_bytes(hash_tx).compat().await.map_mm_err()?; let tx = ZTransaction::read(tx_bytes.as_slice()).unwrap(); let mut spends = Vec::new(); let mut outputs = Vec::new(); @@ -514,7 +514,7 @@ pub(super) async fn init_light_client<'a>( let light_rpc_clients = LightRpcClient::new(lightwalletd_urls).await?; - let min_height = blocks_db.get_earliest_block().await? as u64; + let min_height = blocks_db.get_earliest_block().await.map_mm_err()? as u64; let current_block_height = light_rpc_clients .get_block_height() .await @@ -534,19 +534,24 @@ pub(super) async fn init_light_client<'a>( }; let maybe_checkpoint_block = light_rpc_clients .checkpoint_block_from_height(sync_height.max(sapling_activation_height), &coin) - .await?; + .await + .map_mm_err()?; // check if no sync_params was provided and continue syncing from last height in db if it's > 0 or skip_sync_params is true. let continue_from_prev_sync = (min_height > 0 && sync_params.is_none()) || (skip_sync_params && min_height < sapling_activation_height); - let wallet_db = WalletDbShared::new(builder, maybe_checkpoint_block, continue_from_prev_sync).await?; + + let wallet_db = WalletDbShared::new(builder, maybe_checkpoint_block, continue_from_prev_sync) + .await + .map_mm_err()?; + // Check min_height in blocks_db and rewind blocks_db to 0 if sync_height != min_height if !continue_from_prev_sync && (sync_height != min_height) { // let user know we're clearing cache and re-syncing from new provided height. if min_height > 0 { info!("Older/Newer sync height detected!, rewinding blocks_db to new height: {sync_height:?}"); } - blocks_db.rewind_to_height(u32::MIN.into()).await?; + blocks_db.rewind_to_height(u32::MIN.into()).await.map_mm_err()?; }; let first_sync_block = FirstSyncBlock { @@ -771,9 +776,13 @@ impl SaplingSyncLoopHandle { async fn update_blocks_cache(&mut self, rpc: &dyn ZRpcOps) -> Result<(), MmError> { let current_block = rpc.get_block_height().await?; let block_db = self.blocks_db.clone(); - let current_block_in_db = &self.blocks_db.get_latest_block().await?; + let current_block_in_db = &self.blocks_db.get_latest_block().await.map_mm_err()?; let wallet_db = self.wallet_db.clone(); - let extrema = wallet_db.db.block_height_extrema().await?; + let extrema = wallet_db + .db + .block_height_extrema() + .await + .map_err(|err| MmError::new(UpdateBlocksCacheErr::ZcashDBError(err.to_string())))?; let mut from_block = self .consensus_params .sapling_activation_height @@ -784,7 +793,9 @@ impl SaplingSyncLoopHandle { } if current_block >= from_block { - rpc.scan_blocks(from_block, current_block, &block_db, self).await?; + rpc.scan_blocks(from_block, current_block, &block_db, self) + .await + .map_mm_err()?; } self.current_block = BlockHeight::from_u32(current_block as u32); diff --git a/mm2src/coins/z_coin/z_tx_history.rs b/mm2src/coins/z_coin/z_tx_history.rs index 7c442cc676..7061fbca6b 100644 --- a/mm2src/coins/z_coin/z_tx_history.rs +++ b/mm2src/coins/z_coin/z_tx_history.rs @@ -2,7 +2,7 @@ use std::collections::HashSet; use crate::z_coin::{ZCoin, ZTxHistoryError}; use common::PagingOptionsEnum; -use mm2_err_handle::prelude::MmError; +use mm2_err_handle::prelude::*; use primitives::hash::H256; use std::convert::TryInto; use zcash_primitives::transaction::TxId; @@ -12,7 +12,6 @@ cfg_wasm32!( use crate::MarketCoinOps; use mm2_number::BigInt; use mm2_db::indexed_db::cursor_prelude::CursorError; - use mm2_err_handle::prelude::MapToMmResult; use num_traits::ToPrimitive; ); @@ -53,9 +52,9 @@ pub(crate) async fn fetch_tx_history_from_db( ) -> Result> { let wallet_db = z.z_fields.light_wallet_db.clone(); let wallet_db = wallet_db.db.lock_db().await.unwrap(); - let db_transaction = wallet_db.get_inner().transaction().await?; - let tx_table = db_transaction.table::().await?; - let total_tx_count = tx_table.count_all().await? as u32; + let db_transaction = wallet_db.get_inner().transaction().await.map_mm_err()?; + let tx_table = db_transaction.table::().await.map_mm_err()?; + let total_tx_count = tx_table.count_all().await.map_mm_err()? as u32; let offset = match paging_options { PagingOptionsEnum::PageNumber(page_number) => ((page_number.get() - 1) * limit) as i64, PagingOptionsEnum::FromId(tx_id) => { @@ -69,34 +68,46 @@ pub(crate) async fn fetch_tx_history_from_db( // Fetch transactions let txs = tx_table .cursor_builder() - .only("ticker", z.ticker())? + .only("ticker", z.ticker()) + .map_mm_err()? .offset(offset as u32) .limit(limit) .reverse() .open_cursor("ticker") - .await? + .await + .map_mm_err()? .collect() - .await?; + .await + .map_mm_err()?; // Fetch received notes - let rn_table = db_transaction.table::().await?; + let rn_table = db_transaction + .table::() + .await + .map_mm_err()?; let received_notes = rn_table .cursor_builder() - .only("ticker", z.ticker())? + .only("ticker", z.ticker()) + .map_mm_err()? .open_cursor("ticker") - .await? + .await + .map_mm_err()? .collect() - .await?; + .await + .map_mm_err()?; // Fetch blocks - let blocks_table = db_transaction.table::().await?; + let blocks_table = db_transaction.table::().await.map_mm_err()?; let blocks = blocks_table .cursor_builder() - .only("ticker", z.ticker())? + .only("ticker", z.ticker()) + .map_mm_err()? .open_cursor("ticker") - .await? + .await + .map_mm_err()? .collect() - .await?; + .await + .map_mm_err()?; // Process transactions and construct tx_details let mut tx_details = Vec::new(); @@ -250,8 +261,8 @@ pub(crate) async fn fetch_txs_from_db( ) -> Result, MmError> { let wallet_db = z.z_fields.light_wallet_db.clone(); let wallet_db = wallet_db.db.lock_db().await.unwrap(); - let db_transaction = wallet_db.get_inner().transaction().await?; - let tx_table = db_transaction.table::().await?; + let db_transaction = wallet_db.get_inner().transaction().await.map_mm_err()?; + let tx_table = db_transaction.table::().await.map_mm_err()?; let limit = tx_hashes.len(); let condition = { @@ -267,36 +278,48 @@ pub(crate) async fn fetch_txs_from_db( // Fetch transactions let txs = tx_table .cursor_builder() - .only("ticker", z.ticker())? + .only("ticker", z.ticker()) + .map_mm_err()? // We need to explicitly set a limit since `where_` implicitly sets a limit of 1 if no limit is set. // TODO: Remove when `where_` doesn't exhibit this behavior. .limit(limit) .where_(condition) .reverse() .open_cursor("ticker") - .await? + .await + .map_mm_err()? .collect() - .await?; + .await + .map_mm_err()?; // Fetch received notes - let rn_table = db_transaction.table::().await?; + let rn_table = db_transaction + .table::() + .await + .map_mm_err()?; let received_notes = rn_table .cursor_builder() - .only("ticker", z.ticker())? + .only("ticker", z.ticker()) + .map_mm_err()? .open_cursor("ticker") - .await? + .await + .map_mm_err()? .collect() - .await?; + .await + .map_mm_err()?; // Fetch blocks - let blocks_table = db_transaction.table::().await?; + let blocks_table = db_transaction.table::().await.map_mm_err()?; let blocks = blocks_table .cursor_builder() - .only("ticker", z.ticker())? + .only("ticker", z.ticker()) + .map_mm_err()? .open_cursor("ticker") - .await? + .await + .map_mm_err()? .collect() - .await?; + .await + .map_mm_err()?; // Process transactions and construct tx_details let mut transactions = Vec::new(); diff --git a/mm2src/coins_activation/src/bch_with_tokens_activation.rs b/mm2src/coins_activation/src/bch_with_tokens_activation.rs index b38c1bee36..289c0785a6 100644 --- a/mm2src/coins_activation/src/bch_with_tokens_activation.rs +++ b/mm2src/coins_activation/src/bch_with_tokens_activation.rs @@ -226,7 +226,7 @@ impl PlatformCoinWithTokensActivationOps for BchCoin { activation_request: Self::ActivationRequest, protocol_conf: Self::PlatformProtocolInfo, ) -> Result> { - let priv_key_policy = PrivKeyBuildPolicy::detect_priv_key_policy(&ctx)?; + let priv_key_policy = PrivKeyBuildPolicy::detect_priv_key_policy(&ctx).map_mm_err::()?; let slp_prefix = CashAddrPrefix::from_str(&protocol_conf.slp_prefix).map_to_mm(|error| { BchWithTokensActivationError::InvalidSlpPrefix { @@ -245,7 +245,9 @@ impl PlatformCoinWithTokensActivationOps for BchCoin { priv_key_policy, ) .await - .map_to_mm(|error| BchWithTokensActivationError::PlatformCoinCreationError { ticker, error })?; + .map_to_mm(|error| BchWithTokensActivationError::PlatformCoinCreationError { ticker, error }) + .map_mm_err::()?; + Ok(platform_coin) } @@ -280,26 +282,53 @@ impl PlatformCoinWithTokensActivationOps for BchCoin { activation_request: &Self::ActivationRequest, _nft_global: &Option, ) -> Result> { - let current_block = self.as_ref().rpc_client.get_block_count().compat().await?; + let current_block = self + .as_ref() + .rpc_client + .get_block_count() + .compat() + .await + .map_mm_err::()?; - let my_address = self.as_ref().derivation_method.single_addr_or_err().await?; + let my_address = self + .as_ref() + .derivation_method + .single_addr_or_err() + .await + .map_mm_err::()?; let my_slp_address = self .get_my_slp_address() .await - .map_to_mm(BchWithTokensActivationError::Internal)? + .map_to_mm(BchWithTokensActivationError::Internal) + .map_mm_err::()? .encode() - .map_to_mm(BchWithTokensActivationError::Internal)?; - let pubkey = self.my_public_key()?.to_string(); + .map_to_mm(BchWithTokensActivationError::Internal) + .map_mm_err::()?; + + let pubkey = self + .my_public_key() + .map_mm_err::()? + .to_string(); let mut bch_address_info = CoinAddressInfo { - derivation_method: self.as_ref().derivation_method.to_response().await?, + derivation_method: self + .as_ref() + .derivation_method + .to_response() + .await + .map_mm_err::()?, pubkey: pubkey.clone(), balances: None, tickers: None, }; let mut slp_address_info = CoinAddressInfo { - derivation_method: self.as_ref().derivation_method.to_response().await?, + derivation_method: self + .as_ref() + .derivation_method + .to_response() + .await + .map_mm_err::()?, pubkey: pubkey.clone(), balances: None, tickers: None, @@ -318,7 +347,10 @@ impl PlatformCoinWithTokensActivationOps for BchCoin { }); } - let bch_unspents = self.bch_unspents_for_display(&my_address).await?; + let bch_unspents = self + .bch_unspents_for_display(&my_address) + .await + .map_mm_err::()?; bch_address_info.balances = Some(bch_unspents.platform_balance(self.decimals())); drop_mutability!(bch_address_info); diff --git a/mm2src/coins_activation/src/erc20_token_activation.rs b/mm2src/coins_activation/src/erc20_token_activation.rs index c73672d9e8..aa9d66ddeb 100644 --- a/mm2src/coins_activation/src/erc20_token_activation.rs +++ b/mm2src/coins_activation/src/erc20_token_activation.rs @@ -150,9 +150,15 @@ impl TokenActivationOps for EthCoin { erc20_protocol, is_custom, ) - .await?; + .await + .map_mm_err::()?; - let address = token.derivation_method().single_addr_or_err().await?.display_address(); + let address = token + .derivation_method() + .single_addr_or_err() + .await + .map_mm_err::()? + .display_address(); let token_contract_address = token.erc20_token_address().ok_or_else(|| { EthTokenActivationError::InternalError("Token contract address is missing".to_string()) })?; @@ -186,9 +192,10 @@ impl TokenActivationOps for EthCoin { )); } let nft_global = match &nft_init_params.provider { - NftProviderEnum::Moralis { url, komodo_proxy } => { - platform_coin.initialize_global_nft(url, *komodo_proxy).await? - }, + NftProviderEnum::Moralis { url, komodo_proxy } => platform_coin + .initialize_global_nft(url, *komodo_proxy) + .await + .map_mm_err::()?, }; let nfts = nft_global.nfts_infos.lock().await.clone(); let init_result = EthTokenInitResult::Nft(NftInitResult { diff --git a/mm2src/coins_activation/src/eth_with_token_activation.rs b/mm2src/coins_activation/src/eth_with_token_activation.rs index 95b74f71a4..b1fdf3a782 100644 --- a/mm2src/coins_activation/src/eth_with_token_activation.rs +++ b/mm2src/coins_activation/src/eth_with_token_activation.rs @@ -311,7 +311,10 @@ impl PlatformCoinWithTokensActivationOps for EthCoin { }, None => return Ok(None), }; - let nft_global = self.initialize_global_nft(url, proxy_auth).await?; + let nft_global = self + .initialize_global_nft(url, proxy_auth) + .await + .map_mm_err::()?; Ok(Some(MmCoinEnum::EthCoin(nft_global))) } @@ -353,15 +356,15 @@ impl PlatformCoinWithTokensActivationOps for EthCoin { match self.derivation_method() { DerivationMethod::SingleAddress(my_address) => { - let pubkey = self.get_public_key().await?; + let pubkey = self.get_public_key().await.map_mm_err()?; let mut eth_address_info = CoinAddressInfo { - derivation_method: self.derivation_method().to_response().await?, + derivation_method: self.derivation_method().to_response().await.map_mm_err()?, pubkey: pubkey.clone(), balances: None, tickers: None, }; let mut erc20_address_info = CoinAddressInfo { - derivation_method: self.derivation_method().to_response().await?, + derivation_method: self.derivation_method().to_response().await.map_mm_err()?, pubkey, balances: None, tickers: None, @@ -441,7 +444,8 @@ impl PlatformCoinWithTokensActivationOps for EthCoin { activation_request.platform_request.enable_params.clone(), &activation_request.platform_request.path_to_address, ) - .await?; + .await + .map_mm_err()?; Ok(EthWithTokensActivationResult::HD(HDEthWithTokensActivationResult { current_block, @@ -474,10 +478,13 @@ async fn eth_priv_key_build_policy( protocol: &ChainSpec, ) -> MmResult { match activation_policy { - EthPrivKeyActivationPolicy::ContextPrivKey => Ok(EthPrivKeyBuildPolicy::detect_priv_key_policy(ctx)?), + EthPrivKeyActivationPolicy::ContextPrivKey => { + Ok(EthPrivKeyBuildPolicy::detect_priv_key_policy(ctx).map_mm_err::()?) + }, #[cfg(target_arch = "wasm32")] EthPrivKeyActivationPolicy::Metamask => { - let metamask_ctx = crypto::CryptoCtx::from_ctx(ctx)? + let metamask_ctx = crypto::CryptoCtx::from_ctx(ctx) + .map_mm_err()? .metamask_ctx() .or_mm_err(|| EthActivationV2Error::MetamaskError(MetamaskRpcError::MetamaskCtxNotInitialized))?; Ok(EthPrivKeyBuildPolicy::Metamask(metamask_ctx)) diff --git a/mm2src/coins_activation/src/init_erc20_token_activation.rs b/mm2src/coins_activation/src/init_erc20_token_activation.rs index f162cb1754..491947e8bf 100644 --- a/mm2src/coins_activation/src/init_erc20_token_activation.rs +++ b/mm2src/coins_activation/src/init_erc20_token_activation.rs @@ -138,7 +138,8 @@ impl InitTokenActivationOps for EthCoin { protocol_conf, is_custom, ) - .await?; + .await + .map_mm_err()?; Ok(token) } @@ -156,7 +157,8 @@ impl InitTokenActivationOps for EthCoin { .current_block() .compat() .await - .map_to_mm(EthTokenActivationError::Transport)?; + .map_to_mm(EthTokenActivationError::Transport) + .map_mm_err()?; let xpub_extractor = if self.is_trezor() { Some( @@ -172,15 +174,20 @@ impl InitTokenActivationOps for EthCoin { None }; - task_handle.update_in_progress_status(InitTokenInProgressStatus::RequestingWalletBalance)?; + task_handle + .update_in_progress_status(InitTokenInProgressStatus::RequestingWalletBalance) + .map_mm_err()?; let wallet_balance = self .enable_coin_balance( xpub_extractor, activation_request.enable_params.clone(), &activation_request.path_to_address, ) - .await?; - task_handle.update_in_progress_status(InitTokenInProgressStatus::ActivatingCoin)?; + .await + .map_mm_err()?; + task_handle + .update_in_progress_status(InitTokenInProgressStatus::ActivatingCoin) + .map_mm_err()?; let token_contract_address = self .erc20_token_address() diff --git a/mm2src/coins_activation/src/init_token.rs b/mm2src/coins_activation/src/init_token.rs index 6b32f83622..2ed7b7b80d 100644 --- a/mm2src/coins_activation/src/init_token.rs +++ b/mm2src/coins_activation/src/init_token.rs @@ -12,7 +12,7 @@ use crypto::hw_rpc_task::{HwConnectStatuses, HwRpcTaskAwaitingStatus, HwRpcTaskU use crypto::HwRpcError; use derive_more::Display; use mm2_core::mm_ctx::MmArc; -use mm2_err_handle::mm_error::{MmError, MmResult, NotEqual, NotMmError}; +use mm2_err_handle::mm_error::{MmError, MmResult, NotMmError}; use mm2_err_handle::prelude::*; use rpc_task::rpc_common::{CancelRpcTaskError, CancelRpcTaskRequest, InitRpcTaskResponse, RpcTaskStatusError, RpcTaskStatusRequest, RpcTaskUserActionError, RpcTaskUserActionRequest}; @@ -49,13 +49,7 @@ pub trait InitTokenActivationOps: Into + TokenOf + Clone + Send + Sy type ActivationRequest: Clone + Send + Sync; type ProtocolInfo: TokenProtocolParams + TryFromCoinProtocol + Clone + Send + Sync; type ActivationResult: CurrentBlock + serde::Serialize + Clone + Send + Sync; - type ActivationError: From - + Into - + NotEqual - + SerMmErrorType - + Clone - + Send - + Sync; + type ActivationError: From + Into + SerMmErrorType + Clone + Send + Sync; type InProgressStatus: InitTokenInitialStatus + serde::Serialize + Clone + Send + Sync; type AwaitingStatus: serde::Serialize + Clone + Send + Sync; type UserAction: NotMmError + Send + Sync; @@ -93,7 +87,6 @@ where Token: InitTokenActivationOps + Send + Sync + 'static, Token::InProgressStatus: InitTokenInitialStatus, InitTokenError: From, - (Token::ActivationError, InitTokenError): NotEqual, { let (client_id, request) = (request.client_id, request.inner); if let Ok(Some(_)) = lp_coinfind(&ctx, &request.ticker).await { @@ -101,7 +94,7 @@ where } let (token_conf, token_protocol): (_, Token::ProtocolInfo) = - coin_conf_with_protocol(&ctx, &request.ticker, request.protocol.clone())?; + coin_conf_with_protocol(&ctx, &request.ticker, request.protocol.clone()).map_mm_err::()?; let platform_coin = lp_coinfind_or_err(&ctx, token_protocol.platform_coin_ticker()) .await @@ -113,7 +106,9 @@ where token_ticker: request.ticker.clone(), })?; - let coins_act_ctx = CoinsActivationContext::from_ctx(&ctx).map_to_mm(InitTokenError::Internal)?; + let coins_act_ctx = CoinsActivationContext::from_ctx(&ctx) + .map_to_mm(InitTokenError::Internal) + .map_mm_err::()?; let spawner = ctx.spawner(); let task = InitTokenTask:: { ctx, @@ -160,7 +155,9 @@ pub async fn init_token_user_action( let mut task_manager = Token::rpc_task_manager(&coins_act_ctx) .lock() .map_to_mm(|poison| InitTokenUserActionError::Internal(poison.to_string()))?; - task_manager.on_user_action(req.task_id, req.user_action)?; + task_manager + .on_user_action(req.task_id, req.user_action) + .map_mm_err::()?; Ok(SuccessResponse::new()) } @@ -173,7 +170,9 @@ pub async fn cancel_init_token( let mut task_manager = Standalone::rpc_task_manager(&coins_act_ctx) .lock() .map_to_mm(|poison| CancelInitTokenError::Internal(poison.to_string()))?; - task_manager.cancel_task(req.task_id)?; + task_manager + .cancel_task(req.task_id) + .map_mm_err::()?; Ok(SuccessResponse::new()) } @@ -237,7 +236,10 @@ where log::info!("{} current block {}", ticker, activation_result.current_block()); let coins_ctx = CoinsContext::from_ctx(&self.ctx).unwrap(); - coins_ctx.add_token(token.clone().into()).await?; + coins_ctx + .add_token(token.clone().into()) + .await + .map_mm_err::()?; self.platform_coin.register_token_info(&token); diff --git a/mm2src/coins_activation/src/l2/init_l2.rs b/mm2src/coins_activation/src/l2/init_l2.rs index 3dd3276ec6..5271cd36f2 100644 --- a/mm2src/coins_activation/src/l2/init_l2.rs +++ b/mm2src/coins_activation/src/l2/init_l2.rs @@ -39,7 +39,7 @@ pub trait InitL2ActivationOps: Into + Send + Sync + 'static { type ValidatedParams: Clone + Send + Sync; type CoinConf: Clone + Send + Sync; type ActivationResult: serde::Serialize + Clone + Send + Sync; - type ActivationError: From + NotEqual + SerMmErrorType + Clone + Send + Sync; + type ActivationError: From + SerMmErrorType + Clone + Send + Sync; type InProgressStatus: InitL2InitialStatus + serde::Serialize + Clone + Send + Sync; type AwaitingStatus: serde::Serialize + Clone + Send + Sync; type UserAction: NotMmError + Send + Sync; @@ -73,7 +73,6 @@ pub async fn init_l2( where L2: InitL2ActivationOps, InitL2Error: From, - (L2::ActivationError, InitL2Error): NotEqual, { let (client_id, req) = (req.client_id, req.inner); let ticker = req.ticker.clone(); @@ -81,8 +80,9 @@ where return MmError::err(InitL2Error::L2IsAlreadyActivated(ticker)); } - let (coin_conf_json, protocol_conf): (Json, L2::ProtocolInfo) = coin_conf_with_protocol(&ctx, &ticker, None)?; - let coin_conf = L2::coin_conf_from_json(coin_conf_json)?; + let (coin_conf_json, protocol_conf): (Json, L2::ProtocolInfo) = + coin_conf_with_protocol(&ctx, &ticker, None).map_mm_err::()?; + let coin_conf = L2::coin_conf_from_json(coin_conf_json).map_mm_err::()?; let platform_coin = lp_coinfind_or_err(&ctx, protocol_conf.platform_coin_ticker()) .await @@ -94,11 +94,13 @@ where l2_ticker: ticker.clone(), })?; - L2::validate_platform_configuration(&platform_coin)?; + L2::validate_platform_configuration(&platform_coin).map_mm_err::()?; - let validated_params = L2::validate_activation_params(req.activation_params.clone())?; + let validated_params = L2::validate_activation_params(req.activation_params.clone()).map_mm_err::()?; - let coins_act_ctx = CoinsActivationContext::from_ctx(&ctx).map_to_mm(InitL2Error::Internal)?; + let coins_act_ctx = CoinsActivationContext::from_ctx(&ctx) + .map_to_mm(InitL2Error::Internal) + .map_mm_err::()?; let spawner = ctx.spawner(); let task = InitL2Task:: { ctx, @@ -126,7 +128,9 @@ pub async fn init_l2_status( where InitL2Error: From, { - let coins_act_ctx = CoinsActivationContext::from_ctx(&ctx).map_to_mm(InitL2StatusError::Internal)?; + let coins_act_ctx = CoinsActivationContext::from_ctx(&ctx) + .map_to_mm(InitL2StatusError::Internal) + .map_mm_err::()?; let mut task_manager = L2::rpc_task_manager(&coins_act_ctx) .lock() .map_to_mm(|poison| InitL2StatusError::Internal(poison.to_string()))?; @@ -140,11 +144,15 @@ pub async fn init_l2_user_action( ctx: MmArc, req: InitL2UserActionRequest, ) -> MmResult { - let coins_act_ctx = CoinsActivationContext::from_ctx(&ctx).map_to_mm(InitL2UserActionError::Internal)?; + let coins_act_ctx = CoinsActivationContext::from_ctx(&ctx) + .map_to_mm(InitL2UserActionError::Internal) + .map_mm_err::()?; let mut task_manager = L2::rpc_task_manager(&coins_act_ctx) .lock() .map_to_mm(|poison| InitL2UserActionError::Internal(poison.to_string()))?; - task_manager.on_user_action(req.task_id, req.user_action)?; + task_manager + .on_user_action(req.task_id, req.user_action) + .map_mm_err::()?; Ok(SuccessResponse::new()) } @@ -152,11 +160,14 @@ pub async fn cancel_init_l2( ctx: MmArc, req: CancelRpcTaskRequest, ) -> MmResult { - let coins_act_ctx = CoinsActivationContext::from_ctx(&ctx).map_to_mm(CancelInitL2Error::Internal)?; + let coins_act_ctx = CoinsActivationContext::from_ctx(&ctx) + .map_to_mm(CancelInitL2Error::Internal) + .map_mm_err::()?; let mut task_manager = L2::rpc_task_manager(&coins_act_ctx) .lock() - .map_to_mm(|poison| CancelInitL2Error::Internal(poison.to_string()))?; - task_manager.cancel_task(req.task_id)?; + .map_to_mm(|poison| CancelInitL2Error::Internal(poison.to_string())) + .map_mm_err::()?; + task_manager.cancel_task(req.task_id).map_mm_err()?; Ok(SuccessResponse::new()) } @@ -205,8 +216,10 @@ where ) .await?; - let c_ctx = CoinsContext::from_ctx(&self.ctx).map_to_mm(RegisterCoinError::Internal)?; - c_ctx.add_l2(coin.into()).await?; + let c_ctx = CoinsContext::from_ctx(&self.ctx) + .map_to_mm(RegisterCoinError::Internal) + .map_mm_err()?; + c_ctx.add_l2(coin.into()).await.map_mm_err()?; Ok(result) } diff --git a/mm2src/coins_activation/src/lightning_activation.rs b/mm2src/coins_activation/src/lightning_activation.rs index 105fb2c422..e4a1a080ad 100644 --- a/mm2src/coins_activation/src/lightning_activation.rs +++ b/mm2src/coins_activation/src/lightning_activation.rs @@ -277,7 +277,8 @@ impl InitL2ActivationOps for LightningCoin { activation_params.color.unwrap_or_else(|| "000000".into()), &mut node_color as &mut [u8], ) - .map_to_mm(|_| LightningValidationErr::InvalidRequest("Invalid Hex Color".into()))?; + .map_to_mm(|_| LightningValidationErr::InvalidRequest("Invalid Hex Color".into())) + .map_mm_err()?; let listening_port = activation_params.listening_port.unwrap_or(DEFAULT_LISTENING_PORT); @@ -306,10 +307,11 @@ impl InitL2ActivationOps for LightningCoin { validated_params, task_handle, ) - .await?; + .await + .map_mm_err()?; Timer::sleep(10.).await; - let address = lightning_coin.my_address()?; + let address = lightning_coin.my_address().map_mm_err()?; let balance = lightning_coin .my_balance() .compat() @@ -345,8 +347,10 @@ async fn start_lightning( protocol_conf.network.clone(), protocol_conf.confirmation_targets, )?); - task_handle.update_in_progress_status(LightningInProgressStatus::GettingFeesFromRPC)?; - platform.set_latest_fees().await?; + task_handle + .update_in_progress_status(LightningInProgressStatus::GettingFeesFromRPC) + .map_mm_err()?; + platform.set_latest_fees().await.map_mm_err()?; // Initialize the Logger let logger = ctx.log.0.clone(); @@ -363,7 +367,9 @@ async fn start_lightning( let persister = init_persister(ctx, &node_id, conf.ticker.clone(), params.backup_path).await?; // Initialize the P2PGossipSync. This is used for providing routes to send payments over - task_handle.update_in_progress_status(LightningInProgressStatus::ReadingNetworkGraphFromFile)?; + task_handle + .update_in_progress_status(LightningInProgressStatus::ReadingNetworkGraphFromFile) + .map_mm_err()?; let network_graph = Arc::new( persister .get_network_graph(protocol_conf.network.into(), logger.clone()) @@ -380,7 +386,9 @@ async fn start_lightning( let db = init_db(ctx, &node_id, conf.ticker.clone()).await?; // Initialize the ChannelManager - task_handle.update_in_progress_status(LightningInProgressStatus::InitializingChannelManager)?; + task_handle + .update_in_progress_status(LightningInProgressStatus::InitializingChannelManager) + .map_mm_err()?; let (chain_monitor, channel_manager) = init_channel_manager( platform.clone(), logger.clone(), @@ -392,7 +400,9 @@ async fn start_lightning( .await?; // Initialize the PeerManager - task_handle.update_in_progress_status(LightningInProgressStatus::InitializingPeerManager)?; + task_handle + .update_in_progress_status(LightningInProgressStatus::InitializingPeerManager) + .map_mm_err()?; let peer_manager = init_peer_manager( ctx.clone(), &platform, @@ -418,7 +428,9 @@ async fn start_lightning( )); // Initialize routing Scorer - task_handle.update_in_progress_status(LightningInProgressStatus::ReadingScorerFromFile)?; + task_handle + .update_in_progress_status(LightningInProgressStatus::ReadingScorerFromFile) + .map_mm_err()?; // status_notifier // .try_send(LightningInProgressStatus::ReadingScorerFromFile) // .debug_log_with_msg("No one seems interested in LightningInProgressStatus"); @@ -451,7 +463,9 @@ async fn start_lightning( // InvoicePayer will act as our event handler as it handles some of the payments related events before // delegating it to LightningEventHandler. // note: background_processor stops automatically when dropped since BackgroundProcessor implements the Drop trait. - task_handle.update_in_progress_status(LightningInProgressStatus::InitializingBackgroundProcessor)?; + task_handle + .update_in_progress_status(LightningInProgressStatus::InitializingBackgroundProcessor) + .map_mm_err()?; let background_processor = Arc::new(BackgroundProcessor::start( persister.clone(), invoice_payer.clone(), @@ -464,7 +478,9 @@ async fn start_lightning( )); // If channel_nodes_data file exists, read channels nodes data from disk and reconnect to channel nodes/peers if possible. - task_handle.update_in_progress_status(LightningInProgressStatus::ReadingChannelsAddressesFromFile)?; + task_handle + .update_in_progress_status(LightningInProgressStatus::ReadingChannelsAddressesFromFile) + .map_mm_err()?; let open_channels_nodes = Arc::new(PaMutex::new( get_open_channels_nodes_addresses(persister.clone(), channel_manager.clone()).await?, )); diff --git a/mm2src/coins_activation/src/platform_coin_with_tokens.rs b/mm2src/coins_activation/src/platform_coin_with_tokens.rs index 24a1aca710..a53223f1ff 100644 --- a/mm2src/coins_activation/src/platform_coin_with_tokens.rs +++ b/mm2src/coins_activation/src/platform_coin_with_tokens.rs @@ -127,7 +127,6 @@ impl TokenAsMmCoinInitializer for T where T: TokenInitializer + Send + Sync, InitTokensAsMmCoinsError: From, - (T::InitTokensError, InitTokensAsMmCoinsError): NotEqual, { type PlatformCoin = ::PlatformCoin; type ActivationRequest = ::ActivationRequest; @@ -150,9 +149,13 @@ where is_custom: req.protocol.is_some(), }) }) - .collect::, _>>()?; + .collect::, _>>() + .map_mm_err::()?; - let tokens = self.enable_tokens(token_params).await?; + let tokens = self + .enable_tokens(token_params) + .await + .map_mm_err::()?; for token in tokens.iter() { self.platform_coin().register_token_info(token); } @@ -169,13 +172,7 @@ pub trait PlatformCoinWithTokensActivationOps: Into + Clone + Send + type ActivationRequest: Clone + Send + Sync + TxHistory + ActivationRequestInfo; type PlatformProtocolInfo: TryFromCoinProtocol + Send; type ActivationResult: GetPlatformBalance + CurrentBlock + serde::Serialize + Send + Clone + Sync + 'static; - type ActivationError: NotMmError - + std::fmt::Debug - + NotEqual - + Into - + Clone - + Send - + Sync; + type ActivationError: NotMmError + std::fmt::Debug + Into + Clone + Send + Sync; type InProgressStatus: InitPlatformCoinWithTokensInitialStatus + serde::Serialize + Clone + Send + Sync; type AwaitingStatus: serde::Serialize + Clone + Send + Sync; @@ -391,19 +388,25 @@ pub async fn re_enable_passive_platform_coin_with_tokens( where Platform: PlatformCoinWithTokensActivationOps + Clone, EnablePlatformCoinWithTokensError: From, - (Platform::ActivationError, EnablePlatformCoinWithTokensError): NotEqual, { let mut mm_tokens = Vec::new(); for initializer in platform_coin.token_initializers() { - let tokens = initializer.enable_tokens_as_mm_coins(&ctx, &req.request).await?; + let tokens = initializer + .enable_tokens_as_mm_coins(&ctx, &req.request) + .await + .map_mm_err()?; mm_tokens.extend(tokens); } - let nft_global = platform_coin.enable_global_nft(&req.request).await?; + let nft_global = platform_coin + .enable_global_nft(&req.request) + .await + .map_mm_err::()?; let activation_result = platform_coin .get_activation_result(task_handle, &req.request, &nft_global) - .await?; + .await + .map_mm_err::()?; log::info!("{} current block {}", req.ticker, activation_result.current_block()); let coins_ctx = CoinsContext::from_ctx(&ctx).unwrap(); @@ -422,7 +425,6 @@ pub async fn enable_platform_coin_with_tokens( where Platform: PlatformCoinWithTokensActivationOps, EnablePlatformCoinWithTokensError: From, - (Platform::ActivationError, EnablePlatformCoinWithTokensError): NotEqual, { if req.request.is_hw_policy() { return MmError::err(EnablePlatformCoinWithTokensError::UnexpectedDeviceActivationPolicy); @@ -438,7 +440,6 @@ pub async fn enable_platform_coin_with_tokens_impl( where Platform: PlatformCoinWithTokensActivationOps + Clone, EnablePlatformCoinWithTokensError: From, - (Platform::ActivationError, EnablePlatformCoinWithTokensError): NotEqual, { if let Ok(Some(coin)) = lp_coinfind_any(&ctx, &req.ticker).await { if !coin.is_available() { @@ -452,7 +453,8 @@ where )); } - let (platform_conf, platform_protocol) = coin_conf_with_protocol(&ctx, &req.ticker, None)?; + let (platform_conf, platform_protocol) = + coin_conf_with_protocol(&ctx, &req.ticker, None).map_mm_err::()?; let platform_coin = Platform::enable_platform_coin( ctx.clone(), @@ -461,25 +463,35 @@ where req.request.clone(), platform_protocol, ) - .await?; + .await + .map_mm_err::()?; let mut mm_tokens = Vec::new(); for initializer in platform_coin.token_initializers() { - let tokens = initializer.enable_tokens_as_mm_coins(&ctx, &req.request).await?; + let tokens = initializer + .enable_tokens_as_mm_coins(&ctx, &req.request) + .await + .map_mm_err()?; mm_tokens.extend(tokens); } - let nft_global = platform_coin.enable_global_nft(&req.request).await?; + let nft_global = platform_coin + .enable_global_nft(&req.request) + .await + .map_mm_err::()?; let activation_result = platform_coin .get_activation_result(task_handle, &req.request, &nft_global) - .await?; + .await + .map_mm_err::()?; log::info!("{} current block {}", req.ticker, activation_result.current_block()); if req.request.tx_history() { platform_coin.start_history_background_fetching( ctx.clone(), - TxHistoryStorageBuilder::new(&ctx).build()?, + TxHistoryStorageBuilder::new(&ctx) + .build() + .map_mm_err::()?, activation_result.get_platform_balance(), ); } @@ -562,7 +574,6 @@ where Platform: PlatformCoinWithTokensActivationOps + Send + Sync + 'static + Clone, Platform::InProgressStatus: InitPlatformCoinWithTokensInitialStatus, EnablePlatformCoinWithTokensError: From, - (Platform::ActivationError, EnablePlatformCoinWithTokensError): NotEqual, { let (client_id, request) = (request.client_id, request.inner); if let Ok(Some(_)) = lp_coinfind(&ctx, &request.ticker).await { @@ -618,12 +629,16 @@ pub async fn init_platform_coin_with_tokens_user_action, { - let coins_act_ctx = - CoinsActivationContext::from_ctx(&ctx).map_to_mm(InitPlatformCoinWithTokensUserActionError::Internal)?; + let coins_act_ctx = CoinsActivationContext::from_ctx(&ctx) + .map_to_mm(InitPlatformCoinWithTokensUserActionError::Internal) + .map_mm_err::()?; let mut task_manager = Platform::rpc_task_manager(&coins_act_ctx) .lock() - .map_to_mm(|poison| InitPlatformCoinWithTokensUserActionError::Internal(poison.to_string()))?; - task_manager.on_user_action(req.task_id, req.user_action)?; + .map_to_mm(|poison| InitPlatformCoinWithTokensUserActionError::Internal(poison.to_string())) + .map_mm_err::()?; + task_manager + .on_user_action(req.task_id, req.user_action) + .map_mm_err::()?; Ok(SuccessResponse::new()) } @@ -635,12 +650,16 @@ pub async fn cancel_init_platform_coin_with_tokens, { - let coins_act_ctx = - CoinsActivationContext::from_ctx(&ctx).map_to_mm(CancelInitPlatformCoinWithTokensError::Internal)?; + let coins_act_ctx = CoinsActivationContext::from_ctx(&ctx) + .map_to_mm(CancelInitPlatformCoinWithTokensError::Internal) + .map_mm_err::()?; let mut task_manager = Platform::rpc_task_manager(&coins_act_ctx) .lock() - .map_to_mm(|poison| CancelInitPlatformCoinWithTokensError::Internal(poison.to_string()))?; - task_manager.cancel_task(req.task_id)?; + .map_to_mm(|poison| CancelInitPlatformCoinWithTokensError::Internal(poison.to_string())) + .map_mm_err::()?; + task_manager + .cancel_task(req.task_id) + .map_mm_err::()?; Ok(SuccessResponse::new()) } @@ -665,7 +684,7 @@ pub mod for_tests { use super::{init_platform_coin_with_tokens, init_platform_coin_with_tokens_status, EnablePlatformCoinWithTokensError, EnablePlatformCoinWithTokensReq, - EnablePlatformCoinWithTokensStatusRequest, InitPlatformCoinWithTokensInitialStatus, NotEqual, + EnablePlatformCoinWithTokensStatusRequest, InitPlatformCoinWithTokensInitialStatus, PlatformCoinWithTokensActivationOps}; /// test helper to activate platform coin with waiting for the result @@ -677,7 +696,6 @@ pub mod for_tests { Platform: PlatformCoinWithTokensActivationOps + Clone + Send + Sync + 'static, Platform::InProgressStatus: InitPlatformCoinWithTokensInitialStatus, EnablePlatformCoinWithTokensError: From, - (Platform::ActivationError, EnablePlatformCoinWithTokensError): NotEqual, { let request = RpcInitReq { client_id: 0, diff --git a/mm2src/coins_activation/src/sia_coin_activation.rs b/mm2src/coins_activation/src/sia_coin_activation.rs index 110f8bbb7b..e2cd92ddbc 100644 --- a/mm2src/coins_activation/src/sia_coin_activation.rs +++ b/mm2src/coins_activation/src/sia_coin_activation.rs @@ -202,7 +202,7 @@ impl InitStandaloneCoinActivationOps for SiaCoin { _protocol_info: SiaCoinProtocolInfo, _task_handle: SiaCoinRpcTaskHandleShared, ) -> MmResult { - let priv_key_policy = PrivKeyBuildPolicy::detect_priv_key_policy(&ctx)?; + let priv_key_policy = PrivKeyBuildPolicy::detect_priv_key_policy(&ctx).map_mm_err()?; let coin = sia_coin_from_conf_and_params(&ctx, &ticker, &coin_conf, activation_request, priv_key_policy) .await @@ -217,15 +217,18 @@ impl InitStandaloneCoinActivationOps for SiaCoin { task_handle: SiaCoinRpcTaskHandleShared, _activation_request: &Self::ActivationRequest, ) -> MmResult { - task_handle.update_in_progress_status(SiaCoinInProgressStatus::RequestingWalletBalance)?; + task_handle + .update_in_progress_status(SiaCoinInProgressStatus::RequestingWalletBalance) + .map_mm_err()?; let current_block = self .current_block() .compat() .await - .map_to_mm(SiaCoinInitError::CouldNotGetBlockCount)?; + .map_to_mm(SiaCoinInitError::CouldNotGetBlockCount) + .map_mm_err()?; - let balance = self.my_balance().compat().await?; - let address = self.my_address()?; + let balance = self.my_balance().compat().await.map_mm_err()?; + let address = self.my_address().map_mm_err()?; Ok(SiaCoinActivationResult { ticker: self.ticker().into(), diff --git a/mm2src/coins_activation/src/slp_token_activation.rs b/mm2src/coins_activation/src/slp_token_activation.rs index 91dbf95ea7..66ea8d18a4 100644 --- a/mm2src/coins_activation/src/slp_token_activation.rs +++ b/mm2src/coins_activation/src/slp_token_activation.rs @@ -102,7 +102,7 @@ impl TokenActivationOps for SlpToken { required_confirmations, )?; let balance = token.my_coin_balance().await.mm_err(EnableSlpError::GetBalanceError)?; - let my_address = token.my_address()?; + let my_address = token.my_address().map_mm_err()?; let balances = HashMap::from([(my_address, balance)]); let init_result = SlpInitResult { balances, diff --git a/mm2src/coins_activation/src/standalone_coin/init_standalone_coin.rs b/mm2src/coins_activation/src/standalone_coin/init_standalone_coin.rs index 002d87c872..12a5af5d29 100644 --- a/mm2src/coins_activation/src/standalone_coin/init_standalone_coin.rs +++ b/mm2src/coins_activation/src/standalone_coin/init_standalone_coin.rs @@ -42,7 +42,6 @@ pub trait InitStandaloneCoinActivationOps: Into + Send + Sync + 'sta + From + Into + SerMmErrorType - + NotEqual + Clone + Send + Sync @@ -87,16 +86,19 @@ where Standalone: InitStandaloneCoinActivationOps + Send + Sync + 'static, Standalone::InProgressStatus: InitStandaloneCoinInitialStatus, InitStandaloneCoinError: From, - (Standalone::ActivationError, InitStandaloneCoinError): NotEqual, { let (client_id, request) = (request.client_id, request.inner); if let Ok(Some(_)) = lp_coinfind(&ctx, &request.ticker).await { return MmError::err(InitStandaloneCoinError::CoinIsAlreadyActivated { ticker: request.ticker }); } - let (coin_conf, protocol_info) = coin_conf_with_protocol(&ctx, &request.ticker, None)?; + let (coin_conf, protocol_info) = + coin_conf_with_protocol(&ctx, &request.ticker, None).map_mm_err::()?; + + let coins_act_ctx = CoinsActivationContext::from_ctx(&ctx) + .map_to_mm(InitStandaloneCoinError::Internal) + .map_mm_err::()?; - let coins_act_ctx = CoinsActivationContext::from_ctx(&ctx).map_to_mm(InitStandaloneCoinError::Internal)?; let spawner = ctx.spawner(); let task = InitStandaloneCoinTask:: { ctx, @@ -141,12 +143,16 @@ pub async fn init_standalone_coin_user_action, ) -> MmResult { - let coins_act_ctx = - CoinsActivationContext::from_ctx(&ctx).map_to_mm(InitStandaloneCoinUserActionError::Internal)?; + let coins_act_ctx = CoinsActivationContext::from_ctx(&ctx) + .map_to_mm(InitStandaloneCoinUserActionError::Internal) + .map_mm_err::()?; let mut task_manager = Standalone::rpc_task_manager(&coins_act_ctx) .lock() - .map_to_mm(|poison| InitStandaloneCoinUserActionError::Internal(poison.to_string()))?; - task_manager.on_user_action(req.task_id, req.user_action)?; + .map_to_mm(|poison| InitStandaloneCoinUserActionError::Internal(poison.to_string())) + .map_mm_err::()?; + task_manager + .on_user_action(req.task_id, req.user_action) + .map_mm_err::()?; Ok(SuccessResponse::new()) } @@ -157,8 +163,11 @@ pub async fn cancel_init_standalone_coin()?; + task_manager + .cancel_task(req.task_id) + .map_mm_err::()?; Ok(SuccessResponse::new()) } @@ -206,11 +215,13 @@ where self.protocol_info.clone(), task_handle.clone(), ) - .await?; + .await + .map_mm_err::()?; let result = coin .get_activation_result(self.ctx.clone(), task_handle, &self.request.activation_params) - .await?; + .await + .map_mm_err::()?; log::info!("{} current block {}", ticker, result.current_block()); let tx_history = self.request.activation_params.tx_history(); @@ -218,13 +229,17 @@ where let current_balances = result.get_addresses_balances(); coin.start_history_background_fetching( self.ctx.metrics.clone(), - TxHistoryStorageBuilder::new(&self.ctx).build()?, + TxHistoryStorageBuilder::new(&self.ctx) + .build() + .map_mm_err::()?, self.ctx.event_stream_manager.clone(), current_balances, ); } - lp_register_coin(&self.ctx, coin.into(), RegisterCoinParams { ticker }).await?; + lp_register_coin(&self.ctx, coin.into(), RegisterCoinParams { ticker }) + .await + .map_mm_err::()?; Ok(result) } diff --git a/mm2src/coins_activation/src/tendermint_token_activation.rs b/mm2src/coins_activation/src/tendermint_token_activation.rs index 8f31ef75b2..e930b740b2 100644 --- a/mm2src/coins_activation/src/tendermint_token_activation.rs +++ b/mm2src/coins_activation/src/tendermint_token_activation.rs @@ -5,7 +5,8 @@ use coins::{tendermint::{TendermintCoin, TendermintToken, TendermintTokenActivat TendermintTokenProtocolInfo}, CoinBalance, MarketCoinOps, MmCoinEnum}; use common::Future01CompatExt; -use mm2_err_handle::prelude::{MapMmError, MmError}; +use mm2_err_handle::{map_mm_error::MmResultExt, + prelude::{MapMmError, MmError}}; use serde::Serialize; use serde_json::Value as Json; use std::collections::HashMap; @@ -66,7 +67,7 @@ impl TokenActivationOps for TendermintToken { .await .mm_err(|e| TendermintTokenInitError::CouldNotFetchBalance(e.to_string()))?; - let my_address = token.my_address()?; + let my_address = token.my_address().map_mm_err()?; let balances = HashMap::from([(my_address, balance)]); let init_result = TendermintTokenInitResult { diff --git a/mm2src/coins_activation/src/token.rs b/mm2src/coins_activation/src/token.rs index 5001a0f3de..46fb9b1a58 100644 --- a/mm2src/coins_activation/src/token.rs +++ b/mm2src/coins_activation/src/token.rs @@ -122,14 +122,13 @@ pub async fn enable_token( where Token: TokenActivationOps + Clone, EnableTokenError: From, - (Token::ActivationError, EnableTokenError): NotEqual, { if let Ok(Some(_)) = lp_coinfind(&ctx, &req.ticker).await { return MmError::err(EnableTokenError::TokenIsAlreadyActivated(req.ticker)); } let (token_conf, token_protocol): (_, Token::ProtocolInfo) = - coin_conf_with_protocol(&ctx, &req.ticker, req.protocol.clone())?; + coin_conf_with_protocol(&ctx, &req.ticker, req.protocol.clone()).map_mm_err::()?; let platform_coin = lp_coinfind_or_err(&ctx, token_protocol.platform_coin_ticker()) .await @@ -150,10 +149,14 @@ where token_protocol, req.protocol.is_some(), ) - .await?; + .await + .map_mm_err::()?; let coins_ctx = CoinsContext::from_ctx(&ctx).unwrap(); - coins_ctx.add_token(token.clone().into()).await?; + coins_ctx + .add_token(token.clone().into()) + .await + .map_mm_err::()?; platform_coin.register_token_info(&token); diff --git a/mm2src/coins_activation/src/utxo_activation/common_impl.rs b/mm2src/coins_activation/src/utxo_activation/common_impl.rs index eba196c370..589efa5b08 100644 --- a/mm2src/coins_activation/src/utxo_activation/common_impl.rs +++ b/mm2src/coins_activation/src/utxo_activation/common_impl.rs @@ -55,7 +55,9 @@ where } else { None }; - task_handle.update_in_progress_status(UtxoStandardInProgressStatus::RequestingWalletBalance)?; + task_handle + .update_in_progress_status(UtxoStandardInProgressStatus::RequestingWalletBalance) + .map_mm_err()?; let wallet_balance = coin .enable_coin_balance( xpub_extractor, @@ -64,7 +66,9 @@ where ) .await .mm_err(|enable_err| InitUtxoStandardError::from_enable_coin_balance_err(enable_err, ticker.clone()))?; - task_handle.update_in_progress_status(UtxoStandardInProgressStatus::ActivatingCoin)?; + task_handle + .update_in_progress_status(UtxoStandardInProgressStatus::ActivatingCoin) + .map_mm_err()?; let result = UtxoStandardActivationResult { ticker, diff --git a/mm2src/coins_activation/src/utxo_activation/init_bch_activation.rs b/mm2src/coins_activation/src/utxo_activation/init_bch_activation.rs index 8c27226959..35c1a32cc5 100644 --- a/mm2src/coins_activation/src/utxo_activation/init_bch_activation.rs +++ b/mm2src/coins_activation/src/utxo_activation/init_bch_activation.rs @@ -77,7 +77,8 @@ impl InitStandaloneCoinActivationOps for BchCoin { error: format!("Couldn't parse cash address prefix: {e:?}"), } })?; - let priv_key_policy = priv_key_build_policy(&ctx, activation_request.utxo_params.priv_key_policy)?; + let priv_key_policy = + priv_key_build_policy(&ctx, activation_request.utxo_params.priv_key_policy).map_mm_err()?; let bchd_urls = activation_request.bchd_urls.clone(); let constructor = { move |utxo_arc| BchCoin::new(utxo_arc, prefix.clone(), bchd_urls.clone()) }; diff --git a/mm2src/coins_activation/src/utxo_activation/init_qtum_activation.rs b/mm2src/coins_activation/src/utxo_activation/init_qtum_activation.rs index a6644f3275..3dd9010709 100644 --- a/mm2src/coins_activation/src/utxo_activation/init_qtum_activation.rs +++ b/mm2src/coins_activation/src/utxo_activation/init_qtum_activation.rs @@ -62,7 +62,7 @@ impl InitStandaloneCoinActivationOps for QtumCoin { _protocol_info: Self::StandaloneProtocol, _task_handle: QtumRpcTaskHandleShared, ) -> Result> { - let priv_key_policy = priv_key_build_policy(&ctx, activation_request.priv_key_policy)?; + let priv_key_policy = priv_key_build_policy(&ctx, activation_request.priv_key_policy).map_mm_err()?; let coin = QtumCoinBuilder::new(&ctx, &ticker, &coin_conf, activation_request, priv_key_policy) .build() diff --git a/mm2src/coins_activation/src/utxo_activation/init_utxo_standard_activation.rs b/mm2src/coins_activation/src/utxo_activation/init_utxo_standard_activation.rs index 10715e2f0e..f975d49fd7 100644 --- a/mm2src/coins_activation/src/utxo_activation/init_utxo_standard_activation.rs +++ b/mm2src/coins_activation/src/utxo_activation/init_utxo_standard_activation.rs @@ -63,7 +63,7 @@ impl InitStandaloneCoinActivationOps for UtxoStandardCoin { _protocol_info: Self::StandaloneProtocol, task_handle: UtxoStandardRpcTaskHandleShared, ) -> MmResult { - let priv_key_policy = priv_key_build_policy(&ctx, activation_request.priv_key_policy)?; + let priv_key_policy = priv_key_build_policy(&ctx, activation_request.priv_key_policy).map_mm_err()?; let coin = UtxoArcBuilder::new( &ctx, @@ -105,7 +105,7 @@ impl InitStandaloneCoinActivationOps for UtxoStandardCoin { }, UtxoSyncStatus::Finished { .. } => break, }; - task_handle.update_in_progress_status(in_progress_status)?; + task_handle.update_in_progress_status(in_progress_status).map_mm_err()?; } } diff --git a/mm2src/coins_activation/src/utxo_activation/mod.rs b/mm2src/coins_activation/src/utxo_activation/mod.rs index 42764e5c93..1dc64c620c 100644 --- a/mm2src/coins_activation/src/utxo_activation/mod.rs +++ b/mm2src/coins_activation/src/utxo_activation/mod.rs @@ -15,7 +15,7 @@ pub use init_utxo_standard_activation::UtxoStandardTaskManagerShared; pub mod for_tests { use common::{executor::Timer, now_ms, wait_until_ms}; use mm2_core::mm_ctx::MmArc; - use mm2_err_handle::prelude::{MmResult, NotEqual}; + use mm2_err_handle::prelude::MmResult; use rpc_task::{RpcInitReq, RpcTaskStatus}; use crate::{init_standalone_coin, init_standalone_coin_status, @@ -32,7 +32,6 @@ pub mod for_tests { Standalone: InitStandaloneCoinActivationOps + Send + Sync + 'static, Standalone::InProgressStatus: InitStandaloneCoinInitialStatus, InitStandaloneCoinError: From, - (Standalone::ActivationError, InitStandaloneCoinError): NotEqual, { let request = RpcInitReq { client_id: 0, diff --git a/mm2src/coins_activation/src/z_coin_activation.rs b/mm2src/coins_activation/src/z_coin_activation.rs index 2332710218..ff9df16119 100644 --- a/mm2src/coins_activation/src/z_coin_activation.rs +++ b/mm2src/coins_activation/src/z_coin_activation.rs @@ -234,7 +234,7 @@ impl InitStandaloneCoinActivationOps for ZCoin { ) -> MmResult { // When `ZCoin` supports Trezor, we'll need to check [`ZcoinActivationParams::priv_key_policy`] // instead of using [`PrivKeyBuildPolicy::detect_priv_key_policy`]. - let priv_key_policy = PrivKeyBuildPolicy::detect_priv_key_policy(&ctx)?; + let priv_key_policy = PrivKeyBuildPolicy::detect_priv_key_policy(&ctx).map_mm_err()?; let coin = z_coin_from_conf_and_params( &ctx, @@ -248,7 +248,7 @@ impl InitStandaloneCoinActivationOps for ZCoin { .mm_err(|e| ZcoinInitError::from_build_err(e, ticker))?; loop { - let in_progress_status = match coin.sync_status().await? { + let in_progress_status = match coin.sync_status().await.map_mm_err()? { SyncStatus::UpdatingBlocksCache { current_scanned_block, latest_block, @@ -266,7 +266,7 @@ impl InitStandaloneCoinActivationOps for ZCoin { SyncStatus::TemporaryError(e) => ZcoinInProgressStatus::TemporaryError(e), SyncStatus::Finished { .. } => break, }; - task_handle.update_in_progress_status(in_progress_status)?; + task_handle.update_in_progress_status(in_progress_status).map_mm_err()?; } Ok(coin) @@ -278,15 +278,17 @@ impl InitStandaloneCoinActivationOps for ZCoin { task_handle: ZcoinRpcTaskHandleShared, _activation_request: &Self::ActivationRequest, ) -> MmResult { - task_handle.update_in_progress_status(ZcoinInProgressStatus::RequestingWalletBalance)?; + task_handle + .update_in_progress_status(ZcoinInProgressStatus::RequestingWalletBalance) + .map_mm_err()?; let current_block = self .current_block() .compat() .await .map_to_mm(ZcoinInitError::CouldNotGetBlockCount)?; - let balance = self.my_balance().compat().await?; - let first_sync_block = self.first_sync_block().await?; + let balance = self.my_balance().compat().await.map_mm_err()?; + let first_sync_block = self.first_sync_block().await.map_mm_err()?; Ok(ZcoinActivationResult { ticker: self.ticker().into(), diff --git a/mm2src/crypto/src/crypto_ctx.rs b/mm2src/crypto/src/crypto_ctx.rs index ffc83603a6..e591ac37b4 100644 --- a/mm2src/crypto/src/crypto_ctx.rs +++ b/mm2src/crypto/src/crypto_ctx.rs @@ -76,9 +76,6 @@ impl From> for HwCtxInitError< } } -/// This is required for converting `MmError>` into `MmError>`. -impl NotEqual for HwCtxInitError {} - #[cfg(target_arch = "wasm32")] #[derive(Debug)] pub enum MetamaskCtxInitError { @@ -265,7 +262,7 @@ impl CryptoCtx { *state = InitializationState::Initializing; } - let metamask_ctx = MetamaskCtx::init(project_name).await?; + let metamask_ctx = MetamaskCtx::init(project_name).await.map_mm_err()?; let metamask_arc = MetamaskArc::new(metamask_ctx); *self.metamask_ctx.write() = InitializationState::Ready(metamask_arc.clone()); @@ -302,7 +299,7 @@ impl CryptoCtx { let (secp256k1_key_pair, key_pair_policy) = policy_builder.build(passphrase)?; let rmd160 = secp256k1_key_pair.public().address_hash(); - let shared_db_id = shared_db_id_from_seed(passphrase)?; + let shared_db_id = shared_db_id_from_seed(passphrase).map_mm_err()?; let crypto_ctx = CryptoCtx { secp256k1_key_pair, @@ -339,11 +336,11 @@ impl KeyPairPolicyBuilder { fn build(self, passphrase: &str) -> CryptoInitResult<(KeyPair, KeyPairPolicy)> { match self { KeyPairPolicyBuilder::Iguana => { - let secp256k1_key_pair = key_pair_from_seed(passphrase)?; + let secp256k1_key_pair = key_pair_from_seed(passphrase).map_mm_err()?; Ok((secp256k1_key_pair, KeyPairPolicy::Iguana)) }, KeyPairPolicyBuilder::GlobalHDAccount => { - let (mm2_internal_key_pair, global_hd_ctx) = GlobalHDAccountCtx::new(passphrase)?; + let (mm2_internal_key_pair, global_hd_ctx) = GlobalHDAccountCtx::new(passphrase).map_mm_err()?; let key_pair_policy = KeyPairPolicy::GlobalHDAccount(global_hd_ctx.into_arc()); Ok((mm2_internal_key_pair, key_pair_policy)) }, @@ -361,7 +358,7 @@ async fn init_check_hw_ctx_with_trezor( processor: Arc>, expected_pubkey: Option, ) -> MmResult<(HwDeviceInfo, HardwareWalletArc), HwCtxInitError> { - let (hw_device_info, hw_ctx) = HardwareWalletCtx::init_with_trezor(processor).await?; + let (hw_device_info, hw_ctx) = HardwareWalletCtx::init_with_trezor(processor).await.map_mm_err()?; let expected_pubkey = match expected_pubkey { Some(expected) => expected, None => return Ok((hw_device_info, hw_ctx)), diff --git a/mm2src/crypto/src/global_hd_ctx.rs b/mm2src/crypto/src/global_hd_ctx.rs index ad7c2bc63b..a2a3bb159a 100644 --- a/mm2src/crypto/src/global_hd_ctx.rs +++ b/mm2src/crypto/src/global_hd_ctx.rs @@ -29,9 +29,10 @@ pub struct GlobalHDAccountCtx { impl GlobalHDAccountCtx { pub fn new(passphrase: &str) -> CryptoInitResult<(Mm2InternalKeyPair, GlobalHDAccountCtx)> { - let bip39_seed = bip39_seed_from_passphrase(passphrase)?; - let bip39_secp_priv_key: ExtendedPrivateKey = - ExtendedPrivateKey::new(bip39_seed.0).map_to_mm(|e| PrivKeyError::InvalidPrivKey(e.to_string()))?; + let bip39_seed = bip39_seed_from_passphrase(passphrase).map_mm_err()?; + let bip39_secp_priv_key: ExtendedPrivateKey = ExtendedPrivateKey::new(bip39_seed.0) + .map_to_mm(|e| PrivKeyError::InvalidPrivKey(e.to_string())) + .map_mm_err()?; let derivation_path = mm2_internal_der_path(); @@ -39,10 +40,11 @@ impl GlobalHDAccountCtx { for child in derivation_path { internal_priv_key = internal_priv_key .derive_child(child) - .map_to_mm(|e| CryptoInitError::InvalidPassphrase(PrivKeyError::InvalidPrivKey(e.to_string())))?; + .map_to_mm(|e| CryptoInitError::InvalidPassphrase(PrivKeyError::InvalidPrivKey(e.to_string()))) + .map_mm_err()?; } - let mm2_internal_key_pair = key_pair_from_secret(internal_priv_key.private_key().as_ref())?; + let mm2_internal_key_pair = key_pair_from_secret(internal_priv_key.private_key().as_ref()).map_mm_err()?; let global_hd_ctx = GlobalHDAccountCtx { bip39_seed, diff --git a/mm2src/crypto/src/hw_client.rs b/mm2src/crypto/src/hw_client.rs index 4cb78b05b5..d9c6679e26 100644 --- a/mm2src/crypto/src/hw_client.rs +++ b/mm2src/crypto/src/hw_client.rs @@ -41,9 +41,6 @@ impl From> for HwProcessingError { } } -/// This is required for converting `MmError` into `MmError>`. -impl NotEqual for HwProcessingError {} - #[derive(Clone, Copy, Deserialize)] pub enum HwWalletType { Trezor, @@ -95,7 +92,7 @@ impl HwClient { pub(crate) async fn trezor( processor: Arc>, ) -> MmResult> { - let timeout = processor.on_connect().await?; + let timeout = processor.on_connect().await.map_mm_err()?; let fut = async move { // `find_devices` in a browser leads to a popup that asks the user which device he wants to connect. @@ -104,21 +101,23 @@ impl HwClient { .boxed() .timeout(timeout) .await - .map_to_mm(|_| HwError::ConnectionTimedOut { timeout })??; + .map_to_mm(|_| HwError::ConnectionTimedOut { timeout }) + .map_mm_err()? + .map_mm_err()?; if devices.available.is_empty() { return MmError::err(HwProcessingError::HwError(HwError::NoTrezorDeviceAvailable)); } let device = devices.available.remove(0); - Ok(device.connect().await?) + device.connect().await.map_mm_err() }; match fut.await { Ok(transport) => { - processor.on_connected().await?; + processor.on_connected().await.map_mm_err()?; Ok(TrezorClient::from_transport(transport)) }, Err(e) => { - processor.on_connection_failed().await?; + processor.on_connection_failed().await.map_mm_err()?; Err(e) }, } @@ -136,7 +135,7 @@ impl HwClient { where C: ConnectableDeviceWrapper + 'static, { - let mut devices = C::find_devices().await?; + let mut devices = C::find_devices().await.map_mm_err()?; if devices.is_empty() { return Ok(None); } @@ -144,7 +143,7 @@ impl HwClient { return MmError::err(HwError::CannotChooseDevice { count: devices.len() }); } let device = devices.remove(0); - let transport = device.connect().await?; + let transport = device.connect().await.map_mm_err()?; let trezor = TrezorClient::from_transport(transport); Ok(Some(trezor)) } @@ -165,19 +164,19 @@ impl HwClient { } }; - let timeout = processor.on_connect().await?; + let timeout = processor.on_connect().await.map_mm_err()?; let result: Result, TimeoutError> = fut.boxed().timeout(timeout).await; match result { Ok(Ok(trezor)) => { - processor.on_connected().await?; + processor.on_connected().await.map_mm_err()?; Ok(trezor) }, Ok(Err(hw_err)) => { - processor.on_connection_failed().await?; + processor.on_connection_failed().await.map_mm_err()?; Err(hw_err.map(HwProcessingError::from)) }, Err(_timed_out) => { - processor.on_connection_failed().await?; + processor.on_connection_failed().await.map_mm_err()?; MmError::err(HwProcessingError::HwError(HwError::ConnectionTimedOut { timeout })) }, } diff --git a/mm2src/crypto/src/hw_ctx.rs b/mm2src/crypto/src/hw_ctx.rs index 8d2c84a8f9..cda40a1159 100644 --- a/mm2src/crypto/src/hw_ctx.rs +++ b/mm2src/crypto/src/hw_ctx.rs @@ -55,8 +55,10 @@ impl HardwareWalletCtx { let (hw_device_info, hw_internal_pubkey) = { let processor = processor.as_base_shared(); - let (device_info, mut session) = trezor.init_new_session(processor).await?; - let hw_internal_pubkey = HardwareWalletCtx::trezor_mm_internal_pubkey(&mut session).await?; + let (device_info, mut session) = trezor.init_new_session(processor).await.map_mm_err()?; + let hw_internal_pubkey = HardwareWalletCtx::trezor_mm_internal_pubkey(&mut session) + .await + .map_mm_err()?; (HwDeviceInfo::Trezor(device_info), hw_internal_pubkey) }; @@ -131,10 +133,14 @@ impl HardwareWalletCtx { SHOW_PUBKEY_ON_DISPLAY, IGNORE_XPUB_MAGIC, ) - .await? + .await + .map_mm_err()? .process(processor) - .await?; - let extended_pubkey = Secp256k1ExtendedPublicKey::from_str(&mm2_internal_xpub).map_to_mm(HwError::from)?; + .await + .map_mm_err()?; + let extended_pubkey = Secp256k1ExtendedPublicKey::from_str(&mm2_internal_xpub) + .map_to_mm(HwError::from) + .map_mm_err()?; Ok(H264::from(extended_pubkey.public_key().serialize())) } diff --git a/mm2src/crypto/src/hw_rpc_task.rs b/mm2src/crypto/src/hw_rpc_task.rs index 96b0c73c03..140bcfba81 100644 --- a/mm2src/crypto/src/hw_rpc_task.rs +++ b/mm2src/crypto/src/hw_rpc_task.rs @@ -125,20 +125,23 @@ where { async fn on_connect(&self) -> MmResult> { self.request_processor - .update_in_progress_status(self.on_connect.clone())?; + .update_in_progress_status(self.on_connect.clone()) + .map_mm_err()?; Ok(self.connect_timeout) } async fn on_connected(&self) -> MmResult<(), HwProcessingError> { Ok(self .request_processor - .update_in_progress_status(self.on_connected.clone())?) + .update_in_progress_status(self.on_connected.clone()) + .map_mm_err()?) } async fn on_connection_failed(&self) -> MmResult<(), HwProcessingError> { Ok(self .request_processor - .update_in_progress_status(self.on_connection_failed.clone())?) + .update_in_progress_status(self.on_connection_failed.clone()) + .map_mm_err()?) } fn as_base_shared(&self) -> Arc> { diff --git a/mm2src/crypto/src/mnemonic.rs b/mm2src/crypto/src/mnemonic.rs index 9d89b25fce..793609bef0 100644 --- a/mm2src/crypto/src/mnemonic.rs +++ b/mm2src/crypto/src/mnemonic.rs @@ -80,7 +80,7 @@ pub fn encrypt_mnemonic(mnemonic: &str, password: &str) -> MmResult MmResult MmResult { // Re-create the keys from the password and salts - let (key_aes, key_hmac) = derive_keys_for_mnemonic(password, &encrypted_data.key_derivation_details)?; + let (key_aes, key_hmac) = + derive_keys_for_mnemonic(password, &encrypted_data.key_derivation_details).map_mm_err()?; // Decrypt the ciphertext let decrypted_data = decrypt_data(encrypted_data, &key_aes, &key_hmac).mm_err(|e| MnemonicError::DecryptionError(e.to_string()))?; // Convert decrypted data back to a string - let mnemonic_str = String::from_utf8(decrypted_data).map_to_mm(|e| MnemonicError::DecodeError(e.to_string()))?; + let mnemonic_str = String::from_utf8(decrypted_data) + .map_to_mm(|e| MnemonicError::DecodeError(e.to_string())) + .map_mm_err()?; Ok(mnemonic_str) } diff --git a/mm2src/crypto/src/privkey.rs b/mm2src/crypto/src/privkey.rs index 4d296d72a8..506d52b11a 100644 --- a/mm2src/crypto/src/privkey.rs +++ b/mm2src/crypto/src/privkey.rs @@ -94,7 +94,7 @@ pub fn secp_privkey_from_hash(mut hash: Secp256k1Secret) -> Secp256k1Secret { } pub fn key_pair_from_seed(seed: &str) -> PrivKeyResult { - let private = private_from_seed(seed)?; + let private = private_from_seed(seed).map_mm_err()?; if !private.compressed { return MmError::err(PrivKeyError::ExpectedCompressedKeys); } diff --git a/mm2src/crypto/src/slip21.rs b/mm2src/crypto/src/slip21.rs index bc2bb976d5..131202f4c9 100644 --- a/mm2src/crypto/src/slip21.rs +++ b/mm2src/crypto/src/slip21.rs @@ -40,7 +40,7 @@ pub fn encrypt_with_slip21( // Derive encryption and authentication keys using SLIP-0021 let (key_aes, key_hmac) = - derive_encryption_authentication_keys(master_secret, &encryption_path, &authentication_path)?; + derive_encryption_authentication_keys(master_secret, &encryption_path, &authentication_path).map_mm_err()?; let key_derivation_details = KeyDerivationDetails::SLIP0021 { encryption_path, @@ -71,7 +71,7 @@ pub fn decrypt_with_slip21(encrypted_data: &EncryptedData, master_secret: &[u8; // Derive encryption and authentication keys using SLIP-0021 let (key_aes, key_hmac) = - derive_encryption_authentication_keys(master_secret, encryption_path, authentication_path)?; + derive_encryption_authentication_keys(master_secret, encryption_path, authentication_path).map_mm_err()?; decrypt_data(encrypted_data, &key_aes, &key_hmac).mm_err(|e| SLIP21Error::DecryptionFailed(e.to_string())) } diff --git a/mm2src/crypto/src/xpub.rs b/mm2src/crypto/src/xpub.rs index 3d97168975..aba5adccf9 100644 --- a/mm2src/crypto/src/xpub.rs +++ b/mm2src/crypto/src/xpub.rs @@ -31,7 +31,7 @@ impl XPubConverter { /// The input string must start with the standard `xpub` prefix and contain a valid checksum. pub fn is_standard_xpub(xpub: &str) -> MmResult<(), XpubError> { let bytes = bs58::decode(&xpub).with_check(None).into_vec()?; - if has_xpub_prefix(&bytes)? { + if has_xpub_prefix(&bytes).map_mm_err()? { Ok(()) } else { MmError::err(XpubError::UnknownPrefix) @@ -43,7 +43,7 @@ impl XPubConverter { pub fn replace_magic_prefix(xpub: XPub) -> MmResult { let mut bytes = bs58::decode(&xpub).with_check(None).into_vec()?; - if has_xpub_prefix(&bytes)? { + if has_xpub_prefix(&bytes).map_mm_err()? { return Ok(xpub); } diff --git a/mm2src/kdf_walletconnect/src/storage/indexed_db.rs b/mm2src/kdf_walletconnect/src/storage/indexed_db.rs index ac9205600f..978123ede4 100644 --- a/mm2src/kdf_walletconnect/src/storage/indexed_db.rs +++ b/mm2src/kdf_walletconnect/src/storage/indexed_db.rs @@ -77,11 +77,12 @@ impl WalletConnectStorageOps for IDBSessionStorage { async fn save_session(&self, session: &Session) -> MmResult<(), Self::Error> { debug!("[{}] Saving WalletConnect session to storage", session.topic); let lock_db = self.lock_db().await?; - let transaction = lock_db.get_inner().transaction().await?; - let session_table = transaction.table::().await?; + let transaction = lock_db.get_inner().transaction().await.map_mm_err()?; + let session_table = transaction.table::().await.map_mm_err()?; session_table .replace_item_by_unique_index("topic", session.topic.clone(), session) - .await?; + .await + .map_mm_err()?; Ok(()) } @@ -89,24 +90,26 @@ impl WalletConnectStorageOps for IDBSessionStorage { async fn get_session(&self, topic: &Topic) -> MmResult, Self::Error> { debug!("[{topic}] Retrieving WalletConnect session from storage"); let lock_db = self.lock_db().await?; - let transaction = lock_db.get_inner().transaction().await?; - let session_table = transaction.table::().await?; + let transaction = lock_db.get_inner().transaction().await.map_mm_err()?; + let session_table = transaction.table::().await.map_mm_err()?; Ok(session_table .get_item_by_unique_index("topic", topic) - .await? + .await + .map_mm_err()? .map(|s| s.1)) } async fn get_all_sessions(&self) -> MmResult, Self::Error> { debug!("Loading WalletConnect sessions from storage"); let lock_db = self.lock_db().await?; - let transaction = lock_db.get_inner().transaction().await?; - let session_table = transaction.table::().await?; + let transaction = lock_db.get_inner().transaction().await.map_mm_err()?; + let session_table = transaction.table::().await.map_mm_err()?; Ok(session_table .get_all_items() - .await? + .await + .map_mm_err()? .into_iter() .map(|s| s.1) .collect::>()) @@ -115,10 +118,13 @@ impl WalletConnectStorageOps for IDBSessionStorage { async fn delete_session(&self, topic: &Topic) -> MmResult<(), Self::Error> { debug!("[{topic}] Deleting WalletConnect session from storage"); let lock_db = self.lock_db().await?; - let transaction = lock_db.get_inner().transaction().await?; - let session_table = transaction.table::().await?; + let transaction = lock_db.get_inner().transaction().await.map_mm_err()?; + let session_table = transaction.table::().await.map_mm_err()?; - session_table.delete_item_by_unique_index("topic", topic).await?; + session_table + .delete_item_by_unique_index("topic", topic) + .await + .map_mm_err()?; Ok(()) } diff --git a/mm2src/kdf_walletconnect/src/storage/mod.rs b/mm2src/kdf_walletconnect/src/storage/mod.rs index 088e052e2f..7fee54c535 100644 --- a/mm2src/kdf_walletconnect/src/storage/mod.rs +++ b/mm2src/kdf_walletconnect/src/storage/mod.rs @@ -13,7 +13,7 @@ use crate::{error::WalletConnectError, session::Session}; #[async_trait] pub(crate) trait WalletConnectStorageOps { - type Error: std::fmt::Debug + NotMmError + NotEqual + Send; + type Error: std::fmt::Debug + NotMmError + Send; async fn init(&self) -> MmResult<(), Self::Error>; async fn is_initialized(&self) -> MmResult; diff --git a/mm2src/mm2_err_handle/src/lib.rs b/mm2src/mm2_err_handle/src/lib.rs index 93b5030af3..b128b93b31 100644 --- a/mm2src/mm2_err_handle/src/lib.rs +++ b/mm2src/mm2_err_handle/src/lib.rs @@ -15,10 +15,10 @@ pub mod split_mm; pub mod prelude { pub use crate::common_errors::{WithInternal, WithTimeout}; pub use crate::discard_mm_trace::DiscardMmTrace; - pub use crate::map_mm_error::MapMmError; + pub use crate::map_mm_error::{MapMmError, MmResultExt}; pub use crate::map_to_mm::MapToMmResult; pub use crate::map_to_mm_fut::MapToMmFutureExt; - pub use crate::mm_error::{MmError, MmResult, NotEqual, NotMmError, SerMmErrorType}; + pub use crate::mm_error::{MmError, MmResult, NotMmError, SerMmErrorType}; pub use crate::mm_json_error::MmJsonError; pub use crate::or_mm_error::OrMmError; pub use crate::split_mm::SplitMmResult; diff --git a/mm2src/mm2_err_handle/src/map_mm_error.rs b/mm2src/mm2_err_handle/src/map_mm_error.rs index 3f1e3718ec..0f3c597ace 100644 --- a/mm2src/mm2_err_handle/src/map_mm_error.rs +++ b/mm2src/mm2_err_handle/src/map_mm_error.rs @@ -37,3 +37,28 @@ where } } } + +pub trait MmResultExt { + /// Convert `Result>` into `Result>` + /// by applying `E2::from` to the inner `E1`. + #[track_caller] + fn map_mm_err(self) -> Result> + where + E2: From + NotMmError; +} + +impl MmResultExt for Result> +where + E1: NotMmError, +{ + #[track_caller] + fn map_mm_err(self) -> Result> + where + E2: From + NotMmError, + { + match self { + Ok(v) => Ok(v), + Err(err_e1) => Err(err_e1.map(E2::from)), + } + } +} diff --git a/mm2src/mm2_err_handle/src/map_to_mm.rs b/mm2src/mm2_err_handle/src/map_to_mm.rs index 568df94ab1..9e88551631 100644 --- a/mm2src/mm2_err_handle/src/map_to_mm.rs +++ b/mm2src/mm2_err_handle/src/map_to_mm.rs @@ -35,7 +35,7 @@ where { match self { Ok(x) => Ok(x), - Err(e1) => MmError::err(f(e1)), + Err(e1) => Err(MmError::new(f(e1))), } } } diff --git a/mm2src/mm2_err_handle/src/mm_error.rs b/mm2src/mm2_err_handle/src/mm_error.rs index 1ea7bf1555..2264ca9ff8 100644 --- a/mm2src/mm2_err_handle/src/mm_error.rs +++ b/mm2src/mm2_err_handle/src/mm_error.rs @@ -17,7 +17,7 @@ //! //! fn is_static_library(path: &str) -> Result<(), MmError> { //! let filename = filename(path)?; -//! let extension = get_file_extension(filename)?; +//! let extension = get_file_extension(filename).map_mm_err()?; //! if extension == "a" || extension == "lib" { //! Ok(()) //! } else { @@ -42,7 +42,7 @@ //! fn get_file_extension(filename: &str) -> Result<&str, MmError> { MmError::err(E1::new()) } //! //! fn is_static_library(path: &str) -> Result<(), MmError> { -//! let filename = filename(path).map_to_mm(|e1| E2::from_e1(e1))?; +//! let filename = filename(path).map_to_mm(|e1| E2::from_e1(e1)).map_mm_err()??; //! let extension = get_file_extension(filename).mm_err(|e1| E2::from_e1(e1))?; //! if extension == "a" || extension == "lib" { //! Ok(()) @@ -115,11 +115,6 @@ pub trait SerMmErrorType: SerializeErrorType + fmt::Display + NotMmError {} impl SerMmErrorType for E where E: SerializeErrorType + fmt::Display + NotMmError {} -pub auto trait NotEqual {} -impl !NotEqual for (X, X) {} -impl NotEqual for Box {} -impl NotEqual for Arc {} - /// The unified error representation tracing an error path. #[derive(Clone, Eq, PartialEq)] pub struct MmError { @@ -145,17 +140,6 @@ where impl StdError for MmError {} -/// Track the location whenever `MmError::from(MmError)` is called. -impl From> for MmError -where - E1: NotMmError, - E2: From + NotMmError, - (E1, E2): NotEqual, -{ - #[track_caller] - fn from(orig: MmError) -> Self { orig.map(E2::from) } -} - /// Track the location whenever `MmError::from(E1)` is called. impl From for MmError where @@ -367,7 +351,7 @@ mod tests { const FORWARDED_LINE: u32 = line!() + 2; fn forward_error(actual: u64, required: u64) -> Result<(), MmError> { - generate_error(actual, required)?; + generate_error(actual, required).map_mm_err()?; unreachable!("'generate_error' must return an error") } @@ -462,7 +446,7 @@ mod tests { const FORWARDED_LINE: u32 = line!() + 2; fn forward_error_for_box(actual: u64, required: u64) -> Result<(), MmError> { - generate_error_for_box(actual, required)?; + generate_error_for_box(actual, required).map_mm_err()?; unreachable!("'generate_error' must return an error") } diff --git a/mm2src/mm2_gui_storage/src/account/storage/wasm_storage.rs b/mm2src/mm2_gui_storage/src/account/storage/wasm_storage.rs index 1f05370c29..bd051b3dc3 100644 --- a/mm2src/mm2_gui_storage/src/account/storage/wasm_storage.rs +++ b/mm2src/mm2_gui_storage/src/account/storage/wasm_storage.rs @@ -79,10 +79,11 @@ impl WasmAccountStorage { async fn load_accounts( db_transaction: &DbTransaction<'_>, ) -> AccountStorageResult> { - let table = db_transaction.table::().await?; + let table = db_transaction.table::().await.map_mm_err()?; table .get_all_items() - .await? + .await + .map_mm_err()? .into_iter() .map(|(_item_id, account)| { let account_info = AccountInfo::try_from(account)?; @@ -96,8 +97,8 @@ impl WasmAccountStorage { async fn load_enabled_account_id( db_transaction: &DbTransaction<'_>, ) -> AccountStorageResult> { - let enabled_table = db_transaction.table::().await?; - let enabled_accounts = enabled_table.get_all_items().await?; + let enabled_table = db_transaction.table::().await.map_mm_err()?; + let enabled_accounts = enabled_table.get_all_items().await.map_mm_err()?; if enabled_accounts.len() > 1 { let error = format!("Expected only one enabled account, found {}", enabled_accounts.len()); return MmError::err(AccountStorageError::Internal(error)); @@ -125,12 +126,13 @@ impl WasmAccountStorage { db_transaction: &DbTransaction<'_>, account_id: &AccountId, ) -> AccountStorageResult> { - let table = db_transaction.table::().await?; + let table = db_transaction.table::().await.map_mm_err()?; let index_keys = AccountTable::account_id_to_index(account_id)?; table .get_item_by_unique_multi_index(index_keys) - .await? + .await + .map_mm_err()? .map(|(_item_id, account)| AccountWithCoins::try_from(account)) .transpose() } @@ -138,10 +140,10 @@ impl WasmAccountStorage { /// Checks whether an account with the given `account_id` exists. /// This method takes `db_transaction` to ensure data coherence. async fn account_exists(db_transaction: &DbTransaction<'_>, account_id: &AccountId) -> AccountStorageResult { - let table = db_transaction.table::().await?; + let table = db_transaction.table::().await.map_mm_err()?; let index_keys = AccountTable::account_id_to_index(account_id)?; - let count = table.count_by_multi_index(index_keys).await?; + let count = table.count_by_multi_index(index_keys).await.map_mm_err()?; Ok(count > 0) } @@ -157,9 +159,9 @@ impl WasmAccountStorage { _ => return Ok(()), } - let table = db_transaction.table::().await?; + let table = db_transaction.table::().await.map_mm_err()?; // Remove the account by clearing the table. - table.clear().await?; + table.clear().await.map_mm_err()?; Ok(()) } @@ -170,16 +172,17 @@ impl WasmAccountStorage { F: FnOnce(&mut AccountTable), { let locked_db = self.lock_db_mutex().await?; - let transaction = locked_db.inner.transaction().await?; - let table = transaction.table::().await?; + let transaction = locked_db.inner.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; let index_keys = AccountTable::account_id_to_index(&account_id)?; let (item_id, mut account) = table .get_item_by_unique_multi_index(index_keys) - .await? + .await + .map_mm_err()? .or_mm_err(|| AccountStorageError::NoSuchAccount(account_id))?; f(&mut account); - table.replace_item(item_id, &account).await?; + table.replace_item(item_id, &account).await.map_mm_err()?; Ok(()) } } @@ -191,7 +194,7 @@ impl AccountStorage for WasmAccountStorage { async fn load_account_coins(&self, account_id: AccountId) -> AccountStorageResult> { let locked_db = self.lock_db_mutex().await?; - let transaction = locked_db.inner.transaction().await?; + let transaction = locked_db.inner.transaction().await.map_mm_err()?; let account = Self::load_account_with_coins(&transaction, &account_id) .await? @@ -201,7 +204,7 @@ impl AccountStorage for WasmAccountStorage { async fn load_accounts(&self) -> AccountStorageResult> { let locked_db = self.lock_db_mutex().await?; - let transaction = locked_db.inner.transaction().await?; + let transaction = locked_db.inner.transaction().await.map_mm_err()?; Self::load_accounts(&transaction).await } @@ -210,7 +213,7 @@ impl AccountStorage for WasmAccountStorage { &self, ) -> AccountStorageResult> { let locked_db = self.lock_db_mutex().await?; - let transaction = locked_db.inner.transaction().await?; + let transaction = locked_db.inner.transaction().await.map_mm_err()?; let enabled_account_id = AccountId::from(Self::load_enabled_account_id_or_err(&transaction).await?); @@ -237,13 +240,13 @@ impl AccountStorage for WasmAccountStorage { async fn load_enabled_account_id(&self) -> AccountStorageResult { let locked_db = self.lock_db_mutex().await?; - let transaction = locked_db.inner.transaction().await?; + let transaction = locked_db.inner.transaction().await.map_mm_err()?; Self::load_enabled_account_id_or_err(&transaction).await } async fn load_enabled_account_with_coins(&self) -> AccountStorageResult { let locked_db = self.lock_db_mutex().await?; - let transaction = locked_db.inner.transaction().await?; + let transaction = locked_db.inner.transaction().await.map_mm_err()?; let account_id = AccountId::from(Self::load_enabled_account_id_or_err(&transaction).await?); @@ -254,7 +257,7 @@ impl AccountStorage for WasmAccountStorage { async fn enable_account(&self, enabled_account_id: EnabledAccountId) -> AccountStorageResult<()> { let locked_db = self.lock_db_mutex().await?; - let transaction = locked_db.inner.transaction().await?; + let transaction = locked_db.inner.transaction().await.map_mm_err()?; let account_id = AccountId::from(enabled_account_id); @@ -263,31 +266,34 @@ impl AccountStorage for WasmAccountStorage { return MmError::err(AccountStorageError::NoSuchAccount(account_id)); } - let table = transaction.table::().await?; + let table = transaction.table::().await.map_mm_err()?; // Remove the previous enabled account by clearing the table. - table.clear().await?; + table.clear().await.map_mm_err()?; - table.add_item(&EnabledAccountTable::from(enabled_account_id)).await?; + table + .add_item(&EnabledAccountTable::from(enabled_account_id)) + .await + .map_mm_err()?; Ok(()) } async fn upload_account(&self, account_info: AccountInfo) -> AccountStorageResult<()> { let locked_db = self.lock_db_mutex().await?; - let transaction = locked_db.inner.transaction().await?; + let transaction = locked_db.inner.transaction().await.map_mm_err()?; // First, check if the account doesn't exist. if Self::account_exists(&transaction, &account_info.account_id).await? { return MmError::err(AccountStorageError::AccountExistsAlready(account_info.account_id)); } - let table = transaction.table::().await?; - table.add_item(&AccountTable::from(account_info)).await?; + let table = transaction.table::().await.map_mm_err()?; + table.add_item(&AccountTable::from(account_info)).await.map_mm_err()?; Ok(()) } async fn delete_account(&self, account_id: AccountId) -> AccountStorageResult<()> { let locked_db = self.lock_db_mutex().await?; - let transaction = locked_db.inner.transaction().await?; + let transaction = locked_db.inner.transaction().await.map_mm_err()?; // First, check if the account exists already. if !Self::account_exists(&transaction, &account_id).await? { @@ -300,9 +306,9 @@ impl AccountStorage for WasmAccountStorage { } // Remove the account info. - let table = transaction.table::().await?; + let table = transaction.table::().await.map_mm_err()?; let index_keys = AccountTable::account_id_to_index(&account_id)?; - table.delete_item_by_unique_multi_index(index_keys).await?; + table.delete_item_by_unique_multi_index(index_keys).await.map_mm_err()?; Ok(()) } @@ -378,9 +384,12 @@ impl AccountTable { let (account_type, account_idx, device_pubkey) = account_id.to_tuple(); let multi_index = MultiIndex::new(AccountTable::ACCOUNT_ID_INDEX) - .with_value(account_type)? - .with_value(account_idx)? - .with_value(device_pubkey)?; + .with_value(account_type) + .map_mm_err()? + .with_value(account_idx) + .map_mm_err()? + .with_value(device_pubkey) + .map_mm_err()?; Ok(multi_index) } } diff --git a/mm2src/mm2_gui_storage/src/rpc_commands.rs b/mm2src/mm2_gui_storage/src/rpc_commands.rs index 2c3363443c..87f658a836 100644 --- a/mm2src/mm2_gui_storage/src/rpc_commands.rs +++ b/mm2src/mm2_gui_storage/src/rpc_commands.rs @@ -172,20 +172,30 @@ pub struct SetBalanceRequest { /// /// This RPC affects the storage **only**. It doesn't affect MarketMaker. pub async fn enable_account(ctx: MmArc, req: EnableAccountRequest) -> MmResult { - let account_ctx = AccountContext::from_ctx(&ctx).map_to_mm(AccountRpcError::Internal)?; + let account_ctx = AccountContext::from_ctx(&ctx) + .map_to_mm(AccountRpcError::Internal) + .map_mm_err()?; let account_id = match req.policy { EnableAccountPolicy::Existing(account_id) => account_id, EnableAccountPolicy::New(new_account) => { let account_id = new_account.account_id; account_ctx .storage() - .await? + .await + .map_mm_err()? .upload_account(AccountInfo::from(new_account)) - .await?; + .await + .map_mm_err()?; account_id }, }; - account_ctx.storage().await?.enable_account(account_id).await?; + account_ctx + .storage() + .await + .map_mm_err()? + .enable_account(account_id) + .await + .map_mm_err()?; Ok(SuccessResponse::new()) } @@ -197,12 +207,16 @@ pub async fn enable_account(ctx: MmArc, req: EnableAccountRequest) -> MmResult MmResult { validate_new_account(&req.account)?; - let account_ctx = AccountContext::from_ctx(&ctx).map_to_mm(AccountRpcError::Internal)?; + let account_ctx = AccountContext::from_ctx(&ctx) + .map_to_mm(AccountRpcError::Internal) + .map_mm_err()?; account_ctx .storage() - .await? + .await + .map_mm_err()? .upload_account(AccountInfo::from(req.account)) - .await?; + .await + .map_mm_err()?; Ok(SuccessResponse::new()) } @@ -214,7 +228,13 @@ pub async fn add_account(ctx: MmArc, req: AddAccountRequest) -> MmResult MmResult { let account_ctx = AccountContext::from_ctx(&ctx).map_to_mm(AccountRpcError::Internal)?; - account_ctx.storage().await?.delete_account(req.account_id).await?; + account_ctx + .storage() + .await + .map_mm_err()? + .delete_account(req.account_id) + .await + .map_mm_err()?; Ok(SuccessResponse::new()) } @@ -228,12 +248,16 @@ pub async fn get_accounts( ctx: MmArc, _req: GetAccountsRequest, ) -> MmResult, AccountRpcError> { - let account_ctx = AccountContext::from_ctx(&ctx).map_to_mm(AccountRpcError::Internal)?; + let account_ctx = AccountContext::from_ctx(&ctx) + .map_to_mm(AccountRpcError::Internal) + .map_mm_err()?; let accounts = account_ctx .storage() - .await? + .await + .map_mm_err()? .load_accounts_with_enabled_flag() - .await? + .await + .map_mm_err()? // The given `BTreeMap` accounts are sorted by `AccountId`. .into_values() .collect(); @@ -249,12 +273,16 @@ pub async fn get_account_coins( ctx: MmArc, req: GetAccountCoinsRequest, ) -> MmResult { - let account_ctx = AccountContext::from_ctx(&ctx).map_to_mm(AccountRpcError::Internal)?; + let account_ctx = AccountContext::from_ctx(&ctx) + .map_to_mm(AccountRpcError::Internal) + .map_mm_err()?; let coins = account_ctx .storage() - .await? + .await + .map_mm_err()? .load_account_coins(req.account_id.clone()) - .await?; + .await + .map_mm_err()?; Ok(GetAccountCoinsResponse { account_id: req.account_id, coins, @@ -271,16 +299,32 @@ pub async fn get_enabled_account( ctx: MmArc, _req: GetEnabledAccountRequest, ) -> MmResult { - let account_ctx = AccountContext::from_ctx(&ctx).map_to_mm(AccountRpcError::Internal)?; - let account = account_ctx.storage().await?.load_enabled_account_with_coins().await?; + let account_ctx = AccountContext::from_ctx(&ctx) + .map_to_mm(AccountRpcError::Internal) + .map_mm_err()?; + let account = account_ctx + .storage() + .await + .map_mm_err()? + .load_enabled_account_with_coins() + .await + .map_mm_err()?; Ok(account) } /// Sets the account name. pub async fn set_account_name(ctx: MmArc, req: SetAccountNameRequest) -> MmResult { - validate_account_name(&req.name)?; - let account_ctx = AccountContext::from_ctx(&ctx).map_to_mm(AccountRpcError::Internal)?; - account_ctx.storage().await?.set_name(req.account_id, req.name).await?; + validate_account_name(&req.name).map_mm_err()?; + let account_ctx = AccountContext::from_ctx(&ctx) + .map_to_mm(AccountRpcError::Internal) + .map_mm_err()?; + account_ctx + .storage() + .await + .map_mm_err()? + .set_name(req.account_id, req.name) + .await + .map_mm_err()?; Ok(SuccessResponse::new()) } @@ -290,12 +334,16 @@ pub async fn set_account_description( req: SetAccountDescriptionRequest, ) -> MmResult { validate_account_desc(&req.description)?; - let account_ctx = AccountContext::from_ctx(&ctx).map_to_mm(AccountRpcError::Internal)?; + let account_ctx = AccountContext::from_ctx(&ctx) + .map_to_mm(AccountRpcError::Internal) + .map_mm_err()?; account_ctx .storage() - .await? + .await + .map_mm_err()? .set_description(req.account_id, req.description) - .await?; + .await + .map_mm_err()?; Ok(SuccessResponse::new()) } @@ -305,12 +353,16 @@ pub async fn set_account_description( /// /// This RPC affects the storage **only**. It doesn't affect MarketMaker. pub async fn set_account_balance(ctx: MmArc, req: SetBalanceRequest) -> MmResult { - let account_ctx = AccountContext::from_ctx(&ctx).map_to_mm(AccountRpcError::Internal)?; + let account_ctx = AccountContext::from_ctx(&ctx) + .map_to_mm(AccountRpcError::Internal) + .map_mm_err()?; account_ctx .storage() - .await? + .await + .map_mm_err()? .set_balance(req.account_id, req.balance_usd) - .await?; + .await + .map_mm_err()?; Ok(SuccessResponse::new()) } @@ -321,12 +373,16 @@ pub async fn set_account_balance(ctx: MmArc, req: SetBalanceRequest) -> MmResult /// This RPC affects the storage **only**. It doesn't affect MarketMaker. pub async fn activate_coins(ctx: MmArc, req: CoinRequest) -> MmResult { validate_tickers(&req.tickers)?; - let account_ctx = AccountContext::from_ctx(&ctx).map_to_mm(AccountRpcError::Internal)?; + let account_ctx = AccountContext::from_ctx(&ctx) + .map_to_mm(AccountRpcError::Internal) + .map_mm_err()?; account_ctx .storage() - .await? + .await + .map_mm_err()? .activate_coins(req.account_id, req.tickers) - .await?; + .await + .map_mm_err()?; Ok(SuccessResponse::new()) } @@ -336,18 +392,22 @@ pub async fn activate_coins(ctx: MmArc, req: CoinRequest) -> MmResult MmResult { - let account_ctx = AccountContext::from_ctx(&ctx).map_to_mm(AccountRpcError::Internal)?; + let account_ctx = AccountContext::from_ctx(&ctx) + .map_to_mm(AccountRpcError::Internal) + .map_mm_err()?; account_ctx .storage() - .await? + .await + .map_mm_err()? .deactivate_coins(req.account_id, req.tickers) - .await?; + .await + .map_mm_err()?; Ok(SuccessResponse::new()) } fn validate_new_account(account: &NewAccount) -> MmResult<(), AccountRpcError> { - validate_account_name(&account.name)?; - validate_account_desc(&account.description) + validate_account_name(&account.name).map_mm_err()?; + validate_account_desc(&account.description).map_mm_err() } fn validate_account_name(name: &str) -> MmResult<(), AccountRpcError> { diff --git a/mm2src/mm2_main/src/lp_init/init_hw.rs b/mm2src/mm2_main/src/lp_init/init_hw.rs index 6148a44f53..77375928d9 100644 --- a/mm2src/mm2_main/src/lp_init/init_hw.rs +++ b/mm2src/mm2_main/src/lp_init/init_hw.rs @@ -136,7 +136,7 @@ impl RpcTask for InitHwTask { } async fn run(&mut self, task_handle: InitHwTaskHandleShared) -> Result> { - let crypto_ctx = CryptoCtx::from_ctx(&self.ctx)?; + let crypto_ctx = CryptoCtx::from_ctx(&self.ctx).map_mm_err()?; match self.hw_wallet_type { HwWalletType::Trezor => { @@ -154,7 +154,8 @@ impl RpcTask for InitHwTask { let trezor_connect_processor = Arc::new(trezor_connect_processor); let (device_info, hw_ctx) = crypto_ctx .init_hw_ctx_with_trezor(trezor_connect_processor, self.req.device_pubkey) - .await?; + .await + .map_mm_err()?; let device_pubkey = hw_ctx.hw_pubkey(); Ok(InitHwResponse { device_info, @@ -174,7 +175,8 @@ pub async fn init_trezor(ctx: MmArc, req: RpcInitReq) -> MmResult hw_wallet_type: HwWalletType::Trezor, req, }; - let task_id = RpcTaskManager::spawn_rpc_task(&init_ctx.init_hw_task_manager, &spawner, task, client_id)?; + let task_id = + RpcTaskManager::spawn_rpc_task(&init_ctx.init_hw_task_manager, &spawner, task, client_id).map_mm_err()?; Ok(InitRpcTaskResponse { task_id }) } @@ -198,7 +200,7 @@ pub async fn init_trezor_user_action( .init_hw_task_manager .lock() .map_to_mm(|e| RpcTaskUserActionError::Internal(e.to_string()))?; - task_manager.on_user_action(req.task_id, req.user_action)?; + task_manager.on_user_action(req.task_id, req.user_action).map_mm_err()?; Ok(SuccessResponse::new()) } @@ -211,6 +213,6 @@ pub async fn cancel_init_trezor( .init_hw_task_manager .lock() .map_to_mm(|e| CancelRpcTaskError::Internal(e.to_string()))?; - task_manager.cancel_task(req.task_id)?; + task_manager.cancel_task(req.task_id).map_mm_err()?; Ok(SuccessResponse::new()) } diff --git a/mm2src/mm2_main/src/lp_init/init_metamask.rs b/mm2src/mm2_main/src/lp_init/init_metamask.rs index 66b8524624..602c95bc58 100644 --- a/mm2src/mm2_main/src/lp_init/init_metamask.rs +++ b/mm2src/mm2_main/src/lp_init/init_metamask.rs @@ -122,9 +122,9 @@ impl RpcTask for InitMetamaskTask { } async fn run(&mut self, _task_handle: InitMetamaskTaskHandleShared) -> Result> { - let crypto_ctx = CryptoCtx::from_ctx(&self.ctx)?; + let crypto_ctx = CryptoCtx::from_ctx(&self.ctx).map_mm_err()?; - let metamask = crypto_ctx.init_metamask_ctx(self.req.project.clone()).await?; + let metamask = crypto_ctx.init_metamask_ctx(self.req.project.clone()).await.map_mm_err()?; Ok(InitMetamaskResponse { eth_address: metamask.eth_account_str().to_string(), }) @@ -139,7 +139,7 @@ pub async fn connect_metamask( let init_ctx = MmInitContext::from_ctx(&ctx).map_to_mm(InitMetamaskError::Internal)?; let spawner = ctx.spawner(); let task = InitMetamaskTask { ctx, req }; - let task_id = RpcTaskManager::spawn_rpc_task(&init_ctx.init_metamask_manager, &spawner, task, client_id)?; + let task_id = RpcTaskManager::spawn_rpc_task(&init_ctx.init_metamask_manager, &spawner, task, client_id).map_mm_err()?; Ok(InitRpcTaskResponse { task_id }) } @@ -166,6 +166,6 @@ pub async fn cancel_connect_metamask( .init_metamask_manager .lock() .map_to_mm(|e| CancelRpcTaskError::Internal(e.to_string()))?; - task_manager.cancel_task(req.task_id)?; + task_manager.cancel_task(req.task_id).map_mm_err()?; Ok(SuccessResponse::new()) } diff --git a/mm2src/mm2_main/src/lp_native_dex.rs b/mm2src/mm2_main/src/lp_native_dex.rs index 4877ef8de8..7ae20cad70 100644 --- a/mm2src/mm2_main/src/lp_native_dex.rs +++ b/mm2src/mm2_main/src/lp_native_dex.rs @@ -362,10 +362,10 @@ fn init_wasm_event_streaming(ctx: &MmArc) { } pub async fn lp_init_continue(ctx: MmArc) -> MmInitResult<()> { - init_ordermatch_context(&ctx)?; - init_p2p(ctx.clone()).await?; + init_ordermatch_context(&ctx).map_mm_err()?; + init_p2p(ctx.clone()).await.map_mm_err()?; - if !CryptoCtx::is_init(&ctx)? { + if !CryptoCtx::is_init(&ctx).map_mm_err()? { return Ok(()); } @@ -397,7 +397,7 @@ pub async fn lp_init_continue(ctx: MmArc) -> MmInitResult<()> { } } - init_message_service(&ctx).await?; + init_message_service(&ctx).await.map_mm_err()?; let balance_update_ordermatch_handler = BalanceUpdateOrdermatchHandler::new(ctx.clone()); register_balance_update_handler(ctx.clone(), Box::new(balance_update_ordermatch_handler)).await; @@ -437,7 +437,7 @@ pub async fn lp_init(ctx: MmArc, version: String, datetime: String) -> MmInitRes } // This either initializes the cryptographic context or sets up the context for "no login mode". - initialize_wallet_passphrase(&ctx).await?; + initialize_wallet_passphrase(&ctx).await.map_mm_err()?; lp_init_continue(ctx.clone()).await?; @@ -646,7 +646,7 @@ async fn relay_node_type(ctx: &MmArc) -> P2PResult { let ip = myipaddr(ctx.clone()) .await .map_to_mm(P2PInitError::ErrorGettingMyIpAddr)?; - let network_ports = lp_network_ports(netid)?; + let network_ports = lp_network_ports(netid).map_mm_err()?; let wss_certs = wss_certs(ctx)?; if wss_certs.is_none() { const WARN_MSG: &str = r#"Please note TLS private key and certificate are not specified. @@ -677,7 +677,7 @@ fn light_node_type(ctx: &MmArc) -> P2PResult { } let netid = ctx.netid(); - let network_ports = lp_network_ports(netid)?; + let network_ports = lp_network_ports(netid).map_mm_err()?; Ok(NodeType::Light { network_ports }) } diff --git a/mm2src/mm2_main/src/lp_ordermatch.rs b/mm2src/mm2_main/src/lp_ordermatch.rs index 9f57101d42..5fd6b8c8c7 100644 --- a/mm2src/mm2_main/src/lp_ordermatch.rs +++ b/mm2src/mm2_main/src/lp_ordermatch.rs @@ -321,7 +321,8 @@ async fn process_orders_keep_alive( P2PRequest::Ordermatch(req), propagated_from_peer.clone(), ) - .await? + .await + .map_mm_err()? .ok_or_else(|| { MmError::new(OrderbookP2PHandlerError::P2PRequestError(format!( "No response was received from peer {} for SyncPubkeyOrderbookState request!", diff --git a/mm2src/mm2_main/src/lp_ordermatch/my_orders_storage.rs b/mm2src/mm2_main/src/lp_ordermatch/my_orders_storage.rs index 9faa4f4722..11eccbb232 100644 --- a/mm2src/mm2_main/src/lp_ordermatch/my_orders_storage.rs +++ b/mm2src/mm2_main/src/lp_ordermatch/my_orders_storage.rs @@ -239,30 +239,31 @@ mod native_impl { impl MyActiveOrders for MyOrdersStorage { async fn load_active_maker_orders(&self) -> MyOrdersResult> { let dir_path = my_maker_orders_dir(&self.ctx); - Ok(read_dir_json(&dir_path).await?) + Ok(read_dir_json(&dir_path).await.map_mm_err()?) } async fn load_active_maker_order(&self, uuid: Uuid) -> MyOrdersResult { let path = my_maker_order_file_path(&self.ctx, &uuid); read_json(&path) - .await? + .await + .map_mm_err()? .or_mm_err(|| MyOrdersError::NoSuchOrder { uuid }) } async fn load_active_taker_orders(&self) -> MyOrdersResult> { let dir_path = my_taker_orders_dir(&self.ctx); - Ok(read_dir_json(&dir_path).await?) + Ok(read_dir_json(&dir_path).await.map_mm_err()?) } async fn save_new_active_maker_order(&self, order: &MakerOrder) -> MyOrdersResult<()> { let path = my_maker_order_file_path(&self.ctx, &order.uuid); - write_json(order, &path, USE_TMP_FILE).await?; + write_json(order, &path, USE_TMP_FILE).await.map_mm_err()?; Ok(()) } async fn save_new_active_taker_order(&self, order: &TakerOrder) -> MyOrdersResult<()> { let path = my_taker_order_file_path(&self.ctx, &order.request.uuid); - write_json(order, &path, USE_TMP_FILE).await?; + write_json(order, &path, USE_TMP_FILE).await.map_mm_err()?; Ok(()) } @@ -295,14 +296,15 @@ mod native_impl { impl MyOrdersHistory for MyOrdersStorage { async fn save_order_in_history(&self, order: &Order) -> MyOrdersResult<()> { let path = my_order_history_file_path(&self.ctx, &order.uuid()); - write_json(order, &path, USE_TMP_FILE).await?; + write_json(order, &path, USE_TMP_FILE).await.map_mm_err()?; Ok(()) } async fn load_order_from_history(&self, uuid: Uuid) -> MyOrdersResult { let path = my_order_history_file_path(&self.ctx, &uuid); read_json(&path) - .await? + .await + .map_mm_err()? .or_mm_err(|| MyOrdersError::NoSuchOrder { uuid }) } } @@ -402,10 +404,10 @@ mod wasm_impl { #[async_trait] impl MyActiveOrders for MyOrdersStorage { async fn load_active_maker_orders(&self) -> MyOrdersResult> { - let db = self.ctx.ordermatch_db().await?; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; - let maker_orders = table.get_all_items().await?; + let db = self.ctx.ordermatch_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; + let maker_orders = table.get_all_items().await.map_mm_err()?; Ok(maker_orders .into_iter() .map(|(_item_id, MyActiveMakerOrdersTable { order_payload, .. })| order_payload) @@ -413,22 +415,23 @@ mod wasm_impl { } async fn load_active_maker_order(&self, uuid: Uuid) -> MyOrdersResult { - let db = self.ctx.ordermatch_db().await?; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; + let db = self.ctx.ordermatch_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; table .get_item_by_unique_index("uuid", uuid) - .await? + .await + .map_mm_err()? .map(|(_item_id, MyActiveMakerOrdersTable { order_payload, .. })| order_payload) .or_mm_err(|| MyOrdersError::NoSuchOrder { uuid }) } async fn load_active_taker_orders(&self) -> MyOrdersResult> { - let db = self.ctx.ordermatch_db().await?; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; - let maker_orders = table.get_all_items().await?; + let db = self.ctx.ordermatch_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; + let maker_orders = table.get_all_items().await.map_mm_err()?; Ok(maker_orders .into_iter() .map(|(_item_id, MyActiveTakerOrdersTable { order_payload, .. })| order_payload) @@ -436,64 +439,67 @@ mod wasm_impl { } async fn save_new_active_maker_order(&self, order: &MakerOrder) -> MyOrdersResult<()> { - let db = self.ctx.ordermatch_db().await?; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; + let db = self.ctx.ordermatch_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; let item = MyActiveMakerOrdersTable { uuid: order.uuid, order_payload: order.clone(), }; - table.add_item(&item).await?; + table.add_item(&item).await.map_mm_err()?; Ok(()) } async fn save_new_active_taker_order(&self, order: &TakerOrder) -> MyOrdersResult<()> { - let db = self.ctx.ordermatch_db().await?; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; + let db = self.ctx.ordermatch_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; let item = MyActiveTakerOrdersTable { uuid: order.request.uuid, order_payload: order.clone(), }; - table.add_item(&item).await?; + table.add_item(&item).await.map_mm_err()?; Ok(()) } async fn delete_active_maker_order(&self, uuid: Uuid) -> MyOrdersResult<()> { - let db = self.ctx.ordermatch_db().await?; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; - table.delete_item_by_unique_index("uuid", uuid).await?; + let db = self.ctx.ordermatch_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; + table.delete_item_by_unique_index("uuid", uuid).await.map_mm_err()?; Ok(()) } async fn delete_active_taker_order(&self, uuid: Uuid) -> MyOrdersResult<()> { - let db = self.ctx.ordermatch_db().await?; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; - table.delete_item_by_unique_index("uuid", uuid).await?; + let db = self.ctx.ordermatch_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; + table.delete_item_by_unique_index("uuid", uuid).await.map_mm_err()?; Ok(()) } async fn update_active_maker_order(&self, order: &MakerOrder) -> MyOrdersResult<()> { - let db = self.ctx.ordermatch_db().await?; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; + let db = self.ctx.ordermatch_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; let item = MyActiveMakerOrdersTable { uuid: order.uuid, order_payload: order.clone(), }; - table.replace_item_by_unique_index("uuid", order.uuid, &item).await?; + table + .replace_item_by_unique_index("uuid", order.uuid, &item) + .await + .map_mm_err()?; Ok(()) } async fn update_active_taker_order(&self, order: &TakerOrder) -> MyOrdersResult<()> { - let db = self.ctx.ordermatch_db().await?; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; + let db = self.ctx.ordermatch_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; let item = MyActiveTakerOrdersTable { uuid: order.request.uuid, @@ -501,7 +507,8 @@ mod wasm_impl { }; table .replace_item_by_unique_index("uuid", order.request.uuid, &item) - .await?; + .await + .map_mm_err()?; Ok(()) } } @@ -509,26 +516,27 @@ mod wasm_impl { #[async_trait] impl MyOrdersHistory for MyOrdersStorage { async fn save_order_in_history(&self, order: &Order) -> MyOrdersResult<()> { - let db = self.ctx.ordermatch_db().await?; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; + let db = self.ctx.ordermatch_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; let item = MyHistoryOrdersTable { uuid: order.uuid(), order_payload: order.clone(), }; - table.add_item(&item).await?; + table.add_item(&item).await.map_mm_err()?; Ok(()) } async fn load_order_from_history(&self, uuid: Uuid) -> MyOrdersResult { - let db = self.ctx.ordermatch_db().await?; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; + let db = self.ctx.ordermatch_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; table .get_item_by_unique_index("uuid", uuid) - .await? + .await + .map_mm_err()? .map(|(_item_id, MyHistoryOrdersTable { order_payload, .. })| order_payload) .or_mm_err(|| MyOrdersError::NoSuchOrder { uuid }) } @@ -548,13 +556,17 @@ mod wasm_impl { } async fn select_order_status(&self, uuid: Uuid) -> MyOrdersResult { - let db = self.ctx.ordermatch_db().await?; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; + let db = self.ctx.ordermatch_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction + .table::() + .await + .map_mm_err()?; table .get_item_by_unique_index("uuid", uuid) - .await? + .await + .map_mm_err()? .map(|(_item_id, MyFilteringHistoryOrdersTable { status, .. })| status) .or_mm_err(|| MyOrdersError::NoSuchOrder { uuid }) } @@ -562,65 +574,83 @@ mod wasm_impl { async fn save_maker_order_in_filtering_history(&self, order: &MakerOrder) -> MyOrdersResult<()> { let item = maker_order_to_filtering_history_item(order, "Created".to_owned(), false)?; - let db = self.ctx.ordermatch_db().await?; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; - table.add_item(&item).await?; + let db = self.ctx.ordermatch_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction + .table::() + .await + .map_mm_err()?; + table.add_item(&item).await.map_mm_err()?; Ok(()) } async fn save_taker_order_in_filtering_history(&self, order: &TakerOrder) -> MyOrdersResult<()> { let item = taker_order_to_filtering_history_item(order, "Created".to_owned())?; - let db = self.ctx.ordermatch_db().await?; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; - table.add_item(&item).await?; + let db = self.ctx.ordermatch_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction + .table::() + .await + .map_mm_err()?; + table.add_item(&item).await.map_mm_err()?; Ok(()) } async fn update_maker_order_in_filtering_history(&self, order: &MakerOrder) -> MyOrdersResult<()> { - let db = self.ctx.ordermatch_db().await?; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; + let db = self.ctx.ordermatch_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction + .table::() + .await + .map_mm_err()?; // get the previous item to see if the order was taker let (item_id, prev_item) = table .get_item_by_unique_index("uuid", order.uuid) - .await? + .await + .map_mm_err()? .or_mm_err(|| MyOrdersError::NoSuchOrder { uuid: order.uuid })?; let item = maker_order_to_filtering_history_item(order, "Updated".to_owned(), prev_item.was_taker)?; - table.replace_item(item_id, &item).await?; + table.replace_item(item_id, &item).await.map_mm_err()?; Ok(()) } async fn update_order_status_in_filtering_history(&self, uuid: Uuid, status: String) -> MyOrdersResult<()> { - let db = self.ctx.ordermatch_db().await?; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; + let db = self.ctx.ordermatch_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction + .table::() + .await + .map_mm_err()?; let (item_id, mut item) = table .get_item_by_unique_index("uuid", uuid) - .await? + .await + .map_mm_err()? .or_mm_err(|| MyOrdersError::NoSuchOrder { uuid })?; item.status = status; - table.replace_item(item_id, &item).await?; + table.replace_item(item_id, &item).await.map_mm_err()?; Ok(()) } async fn update_was_taker_in_filtering_history(&self, uuid: Uuid) -> MyOrdersResult<()> { - let db = self.ctx.ordermatch_db().await?; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; + let db = self.ctx.ordermatch_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction + .table::() + .await + .map_mm_err()?; let (item_id, mut item) = table .get_item_by_unique_index("uuid", uuid) - .await? + .await + .map_mm_err()? .or_mm_err(|| MyOrdersError::NoSuchOrder { uuid })?; item.was_taker = true; - table.replace_item(item_id, &item).await?; + table.replace_item(item_id, &item).await.map_mm_err()?; Ok(()) } } diff --git a/mm2src/mm2_main/src/lp_ordermatch/orderbook_rpc.rs b/mm2src/mm2_main/src/lp_ordermatch/orderbook_rpc.rs index d76af5dfba..66d24d1daf 100644 --- a/mm2src/mm2_main/src/lp_ordermatch/orderbook_rpc.rs +++ b/mm2src/mm2_main/src/lp_ordermatch/orderbook_rpc.rs @@ -239,9 +239,9 @@ pub async fn orderbook_rpc_v2( if req.base == req.rel { return MmError::err(OrderbookRpcError::BaseRelSame); } - let base_coin_conf = get_tradeable_coin_conf(&ctx, &req.base)?; + let base_coin_conf = get_tradeable_coin_conf(&ctx, &req.base).map_mm_err()?; - let rel_coin_conf = get_tradeable_coin_conf(&ctx, &req.rel)?; + let rel_coin_conf = get_tradeable_coin_conf(&ctx, &req.rel).map_mm_err()?; let ordermatch_ctx = OrdermatchContext::from_ctx(&ctx).expect("ctx is available"); let base_ticker = ordermatch_ctx.orderbook_ticker_bypass(&req.base); diff --git a/mm2src/mm2_main/src/lp_ordermatch/simple_market_maker.rs b/mm2src/mm2_main/src/lp_ordermatch/simple_market_maker.rs index 14551167d6..78aca5278d 100644 --- a/mm2src/mm2_main/src/lp_ordermatch/simple_market_maker.rs +++ b/mm2src/mm2_main/src/lp_ordermatch/simple_market_maker.rs @@ -356,8 +356,12 @@ async fn vwap_calculator( ctx: &MmArc, cfg: &SimpleCoinMarketMakerCfg, ) -> VwapProcessingResult { - let base_swaps = latest_swaps_for_pair(ctx.clone(), cfg.base.clone(), cfg.rel.clone(), LATEST_SWAPS_LIMIT).await?; - let rel_swaps = latest_swaps_for_pair(ctx.clone(), cfg.rel.clone(), cfg.base.clone(), LATEST_SWAPS_LIMIT).await?; + let base_swaps = latest_swaps_for_pair(ctx.clone(), cfg.base.clone(), cfg.rel.clone(), LATEST_SWAPS_LIMIT) + .await + .map_mm_err()?; + let rel_swaps = latest_swaps_for_pair(ctx.clone(), cfg.rel.clone(), cfg.base.clone(), LATEST_SWAPS_LIMIT) + .await + .map_mm_err()?; Ok(vwap(base_swaps, rel_swaps, calculated_price, cfg).await) } @@ -466,7 +470,7 @@ async fn prepare_order( let base_coin = lp_coinfind(ctx, cfg.base.as_str()) .await? .ok_or_else(|| MmError::new(OrderProcessingError::AssetNotEnabled))?; - let base_balance = base_coin.get_non_zero_balance().compat().await?; + let base_balance = base_coin.get_non_zero_balance().compat().await.map_mm_err()?; lp_coinfind(ctx, cfg.rel.as_str()) .await? .ok_or_else(|| MmError::new(OrderProcessingError::AssetNotEnabled))?; diff --git a/mm2src/mm2_main/src/lp_stats.rs b/mm2src/mm2_main/src/lp_stats.rs index b4d908e65a..0cef1b38aa 100644 --- a/mm2src/mm2_main/src/lp_stats.rs +++ b/mm2src/mm2_main/src/lp_stats.rs @@ -135,7 +135,7 @@ pub async fn add_node_to_version_stat(ctx: MmArc, req: Json) -> NodeVersionResul .parse::() .map_to_mm(|e| NodeVersionError::PeerIdParseError(node_info.peer_id.clone(), e.to_string()))?; - let ipv4_addr = mm2_net::ip_addr::addr_to_ipv4_string(&node_info.address)?; + let ipv4_addr = mm2_net::ip_addr::addr_to_ipv4_string(&node_info.address).map_mm_err()?; let node_info_with_ipv4_addr = NodeInfo { name: node_info.name, address: ipv4_addr, @@ -241,7 +241,7 @@ pub async fn start_version_stat_collection(ctx: MmArc, req: Json) -> NodeVersion let network_info = if ctx.p2p_in_memory() { NetworkInfo::InMemory } else { - let network_ports = lp_network_ports(netid)?; + let network_ports = lp_network_ports(netid).map_mm_err()?; NetworkInfo::Distributed { network_ports } }; diff --git a/mm2src/mm2_main/src/lp_swap.rs b/mm2src/mm2_main/src/lp_swap.rs index 7744b555d8..28dacbffe2 100644 --- a/mm2src/mm2_main/src/lp_swap.rs +++ b/mm2src/mm2_main/src/lp_swap.rs @@ -615,7 +615,7 @@ pub async fn get_locked_amount_rpc( ctx: MmArc, req: GetLockedAmountReq, ) -> Result> { - lp_coinfind_or_err(&ctx, &req.coin).await?; + lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()?; let locked_amount = get_locked_amount(&ctx, &req.coin); Ok(GetLockedAmountResp { diff --git a/mm2src/mm2_main/src/lp_swap/check_balance.rs b/mm2src/mm2_main/src/lp_swap/check_balance.rs index 178a3433fe..bae4a4d14a 100644 --- a/mm2src/mm2_main/src/lp_swap/check_balance.rs +++ b/mm2src/mm2_main/src/lp_swap/check_balance.rs @@ -24,7 +24,7 @@ pub async fn check_my_coin_balance_for_swap( ) -> CheckBalanceResult { let ticker = coin.ticker(); debug!("Check my_coin '{}' balance for swap", ticker); - let balance: MmNumber = coin.my_spendable_balance().compat().await?.into(); + let balance: MmNumber = coin.my_spendable_balance().compat().await.map_mm_err()?.into(); let locked = match swap_uuid { Some(u) => get_locked_amount_by_other_swaps(ctx, u, ticker), @@ -53,8 +53,10 @@ pub async fn check_my_coin_balance_for_swap( let total_trade_fee = if ticker == trade_fee.coin { trade_fee.amount } else { - let base_coin_balance: MmNumber = coin.base_coin_balance().compat().await?.into(); - check_base_coin_balance_for_swap(ctx, &base_coin_balance, trade_fee, swap_uuid).await?; + let base_coin_balance: MmNumber = coin.base_coin_balance().compat().await.map_mm_err()?.into(); + check_base_coin_balance_for_swap(ctx, &base_coin_balance, trade_fee, swap_uuid) + .await + .map_mm_err()?; MmNumber::from(0) }; @@ -94,7 +96,7 @@ pub async fn check_other_coin_balance_for_swap( } let ticker = coin.ticker(); debug!("Check other_coin '{}' balance for swap", ticker); - let balance: MmNumber = coin.my_spendable_balance().compat().await?.into(); + let balance: MmNumber = coin.my_spendable_balance().compat().await.map_mm_err()?.into(); let locked = match swap_uuid { Some(u) => get_locked_amount_by_other_swaps(ctx, u, ticker), @@ -120,8 +122,10 @@ pub async fn check_other_coin_balance_for_swap( }); } } else { - let base_coin_balance: MmNumber = coin.base_coin_balance().compat().await?.into(); - check_base_coin_balance_for_swap(ctx, &base_coin_balance, trade_fee, swap_uuid).await?; + let base_coin_balance: MmNumber = coin.base_coin_balance().compat().await.map_mm_err()?.into(); + check_base_coin_balance_for_swap(ctx, &base_coin_balance, trade_fee, swap_uuid) + .await + .map_mm_err()?; } Ok(()) diff --git a/mm2src/mm2_main/src/lp_swap/maker_swap.rs b/mm2src/mm2_main/src/lp_swap/maker_swap.rs index b74953f42b..af3b1bb767 100644 --- a/mm2src/mm2_main/src/lp_swap/maker_swap.rs +++ b/mm2src/mm2_main/src/lp_swap/maker_swap.rs @@ -2301,9 +2301,10 @@ pub async fn maker_swap_trade_preimage( let base_coin_ticker = base_coin.ticker(); let rel_coin_ticker = rel_coin.ticker(); let volume = if req.max { - let balance = base_coin.my_spendable_balance().compat().await?; + let balance = base_coin.my_spendable_balance().compat().await.map_mm_err()?; calc_max_maker_vol(ctx, &base_coin, &balance, FeeApproxStage::TradePreimage) - .await? + .await + .map_mm_err()? .volume } else { let threshold = base_coin.min_trading_vol().to_decimal(); @@ -2331,7 +2332,9 @@ pub async fn maker_swap_trade_preimage( if req.max { // Note the `calc_max_maker_vol` returns [`CheckBalanceError::NotSufficientBalance`] error if the balance of `base_coin` is not sufficient. // So we have to check the balance of the other coin only. - check_other_coin_balance_for_swap(ctx, rel_coin.deref(), None, rel_coin_fee.clone()).await? + check_other_coin_balance_for_swap(ctx, rel_coin.deref(), None, rel_coin_fee.clone()) + .await + .map_mm_err()? } else { let prepared_params = MakerSwapPreparedParams { maker_payment_trade_fee: base_coin_fee.clone(), @@ -2346,7 +2349,8 @@ pub async fn maker_swap_trade_preimage( Some(prepared_params), FeeApproxStage::TradePreimage, ) - .await?; + .await + .map_mm_err()?; } let conf_settings = OrderConfirmationsSettings { @@ -2382,7 +2386,7 @@ pub struct CoinVolumeInfo { /// Requests the `coin` balance and calculates max Maker volume. /// Returns [`CheckBalanceError::NotSufficientBalance`] if the balance is insufficient. pub async fn get_max_maker_vol(ctx: &MmArc, my_coin: &MmCoinEnum) -> CheckBalanceResult { - let my_balance = my_coin.my_spendable_balance().compat().await?; + let my_balance = my_coin.my_spendable_balance().compat().await.map_mm_err()?; calc_max_maker_vol(ctx, my_coin, &my_balance, FeeApproxStage::OrderIssue).await } @@ -2412,7 +2416,7 @@ pub async fn calc_max_maker_vol( volume = &volume - &trade_fee.amount; required_to_pay_fee = trade_fee.amount; } else { - let base_coin_balance = coin.base_coin_balance().compat().await?; + let base_coin_balance = coin.base_coin_balance().compat().await.map_mm_err()?; check_base_coin_balance_for_swap(ctx, &MmNumber::from(base_coin_balance), trade_fee.clone(), None).await?; } let min_tx_amount = MmNumber::from(coin.min_tx_amount()); diff --git a/mm2src/mm2_main/src/lp_swap/maker_swap_v2.rs b/mm2src/mm2_main/src/lp_swap/maker_swap_v2.rs index 3783e43950..ac10601737 100644 --- a/mm2src/mm2_main/src/lp_swap/maker_swap_v2.rs +++ b/mm2src/mm2_main/src/lp_swap/maker_swap_v2.rs @@ -194,10 +194,10 @@ impl StateMachineStorage for MakerSwapStorage { #[cfg(target_arch = "wasm32")] async fn store_repr(&mut self, uuid: Self::MachineId, repr: Self::DbRepr) -> Result<(), Self::Error> { let swaps_ctx = SwapsContext::from_ctx(&self.ctx).expect("SwapsContext::from_ctx should not fail"); - let db = swaps_ctx.swap_db().await?; - let transaction = db.transaction().await?; + let db = swaps_ctx.swap_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; - let filters_table = transaction.table::().await?; + let filters_table = transaction.table::().await.map_mm_err()?; let item = MySwapsFiltersTable { uuid, @@ -207,14 +207,14 @@ impl StateMachineStorage for MakerSwapStorage { is_finished: false.into(), swap_type: MAKER_SWAP_V2_TYPE, }; - filters_table.add_item(&item).await?; + filters_table.add_item(&item).await.map_mm_err()?; - let table = transaction.table::().await?; + let table = transaction.table::().await.map_mm_err()?; let item = SavedSwapTable { uuid, saved_swap: serde_json::to_value(repr)?, }; - table.add_item(&item).await?; + table.add_item(&item).await.map_mm_err()?; Ok(()) } diff --git a/mm2src/mm2_main/src/lp_swap/max_maker_vol_rpc.rs b/mm2src/mm2_main/src/lp_swap/max_maker_vol_rpc.rs index 625fad2947..18829252b5 100644 --- a/mm2src/mm2_main/src/lp_swap/max_maker_vol_rpc.rs +++ b/mm2src/mm2_main/src/lp_swap/max_maker_vol_rpc.rs @@ -134,12 +134,12 @@ pub struct MaxMakerVolResponse { } pub async fn max_maker_vol(ctx: MmArc, req: MaxMakerVolRequest) -> MmResult { - let coin = lp_coinfind_or_err(&ctx, &req.coin).await?; + let coin = lp_coinfind_or_err(&ctx, &req.coin).await.map_mm_err()?; let CoinVolumeInfo { volume, balance, locked_by_swaps, - } = get_max_maker_vol(&ctx, &coin).await?; + } = get_max_maker_vol(&ctx, &coin).await.map_mm_err()?; Ok(MaxMakerVolResponse { coin: req.coin, diff --git a/mm2src/mm2_main/src/lp_swap/my_swaps_storage.rs b/mm2src/mm2_main/src/lp_swap/my_swaps_storage.rs index f725dce5dc..150e8b9489 100644 --- a/mm2src/mm2_main/src/lp_swap/my_swaps_storage.rs +++ b/mm2src/mm2_main/src/lp_swap/my_swaps_storage.rs @@ -177,9 +177,9 @@ mod wasm_impl { swap_type: u8, ) -> MySwapsResult<()> { let swap_ctx = SwapsContext::from_ctx(&self.ctx).map_to_mm(MySwapsError::InternalError)?; - let db = swap_ctx.swap_db().await?; - let transaction = db.transaction().await?; - let my_swaps_table = transaction.table::().await?; + let db = swap_ctx.swap_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let my_swaps_table = transaction.table::().await.map_mm_err()?; let item = MySwapsFiltersTable { uuid, @@ -189,7 +189,7 @@ mod wasm_impl { is_finished: false.into(), swap_type, }; - my_swaps_table.add_item(&item).await?; + my_swaps_table.add_item(&item).await.map_mm_err()?; Ok(()) } @@ -199,9 +199,9 @@ mod wasm_impl { paging_options: Option<&PagingOptions>, ) -> MySwapsResult { let swap_ctx = SwapsContext::from_ctx(&self.ctx).map_to_mm(MySwapsError::InternalError)?; - let db = swap_ctx.swap_db().await?; - let transaction = db.transaction().await?; - let my_swaps_table = transaction.table::().await?; + let db = swap_ctx.swap_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let my_swaps_table = transaction.table::().await.map_mm_err()?; let from_timestamp = filter.from_timestamp.map(|t| t as u32).unwrap_or_default(); let to_timestamp = filter.to_timestamp.map(|t| t as u32).unwrap_or(u32::MAX); @@ -210,46 +210,50 @@ mod wasm_impl { } let items = match (&filter.my_coin, &filter.other_coin) { - (Some(my_coin), Some(other_coin)) => { - my_swaps_table - .cursor_builder() - .only("my_coin", my_coin)? - .only("other_coin", other_coin)? - .bound("started_at", from_timestamp, to_timestamp) - .open_cursor("with_my_other_coins") - .await? - .collect() - .await? - }, - (Some(my_coin), None) => { - my_swaps_table - .cursor_builder() - .only("my_coin", my_coin)? - .bound("started_at", from_timestamp, to_timestamp) - .open_cursor("with_my_coin") - .await? - .collect() - .await? - }, - (None, Some(other_coin)) => { - my_swaps_table - .cursor_builder() - .only("other_coin", other_coin)? - .bound("started_at", from_timestamp, to_timestamp) - .open_cursor("with_other_coin") - .await? - .collect() - .await? - }, - (None, None) => { - my_swaps_table - .cursor_builder() - .bound("started_at", from_timestamp, to_timestamp) - .open_cursor("started_at") - .await? - .collect() - .await? - }, + (Some(my_coin), Some(other_coin)) => my_swaps_table + .cursor_builder() + .only("my_coin", my_coin) + .map_mm_err()? + .only("other_coin", other_coin) + .map_mm_err()? + .bound("started_at", from_timestamp, to_timestamp) + .open_cursor("with_my_other_coins") + .await + .map_mm_err()? + .collect() + .await + .map_mm_err()?, + (Some(my_coin), None) => my_swaps_table + .cursor_builder() + .only("my_coin", my_coin) + .map_mm_err()? + .bound("started_at", from_timestamp, to_timestamp) + .open_cursor("with_my_coin") + .await + .map_mm_err()? + .collect() + .await + .map_mm_err()?, + (None, Some(other_coin)) => my_swaps_table + .cursor_builder() + .only("other_coin", other_coin) + .map_mm_err()? + .bound("started_at", from_timestamp, to_timestamp) + .open_cursor("with_other_coin") + .await + .map_mm_err()? + .collect() + .await + .map_mm_err()?, + (None, None) => my_swaps_table + .cursor_builder() + .bound("started_at", from_timestamp, to_timestamp) + .open_cursor("started_at") + .await + .map_mm_err()? + .collect() + .await + .map_mm_err()?, }; let uuids: BTreeSet = items diff --git a/mm2src/mm2_main/src/lp_swap/saved_swap.rs b/mm2src/mm2_main/src/lp_swap/saved_swap.rs index 158843dadb..93c6eabf29 100644 --- a/mm2src/mm2_main/src/lp_swap/saved_swap.rs +++ b/mm2src/mm2_main/src/lp_swap/saved_swap.rs @@ -231,7 +231,7 @@ mod native_impl { #[cfg(not(feature = "new-db-arch"))] let address_dir = address_dir.unwrap_or("no address directory for old DB architecture (has no effect)"); let path = my_swap_file_path(ctx, address_dir, &uuid); - Ok(read_json(&path).await?) + Ok(read_json(&path).await.map_mm_err()?) } #[cfg_attr(feature = "new-db-arch", allow(unreachable_code, unused_variables))] @@ -244,27 +244,27 @@ mod native_impl { todo!("Fix the dummy address directory in `my_swaps_dir` below or remove this method all together"); } let path = my_swaps_dir(ctx, "has no effect in not(feature = 'new-db-arch')"); - Ok(read_dir_json(&path).await?) + Ok(read_dir_json(&path).await.map_mm_err()?) } async fn load_from_maker_stats_db(ctx: &MmArc, uuid: Uuid) -> SavedSwapResult> { let path = stats_maker_swap_file_path(ctx, &uuid); - Ok(read_json(&path).await?) + Ok(read_json(&path).await.map_mm_err()?) } async fn load_all_from_maker_stats_db(ctx: &MmArc) -> SavedSwapResult> { let path = stats_maker_swap_dir(ctx); - Ok(read_dir_json(&path).await?) + Ok(read_dir_json(&path).await.map_mm_err()?) } async fn load_from_taker_stats_db(ctx: &MmArc, uuid: Uuid) -> SavedSwapResult> { let path = stats_taker_swap_file_path(ctx, &uuid); - Ok(read_json(&path).await?) + Ok(read_json(&path).await.map_mm_err()?) } async fn load_all_from_taker_stats_db(ctx: &MmArc) -> SavedSwapResult> { let path = stats_taker_swap_dir(ctx); - Ok(read_dir_json(&path).await?) + Ok(read_dir_json(&path).await.map_mm_err()?) } async fn save_to_db(&self, ctx: &MmArc) -> SavedSwapResult<()> { @@ -273,7 +273,7 @@ mod native_impl { #[cfg(not(feature = "new-db-arch"))] let address_dir = "no address directory for old DB architecture (has no effect)"; let path = my_swap_file_path(ctx, address_dir, self.uuid()); - write_json(self, &path, USE_TMP_FILE).await?; + write_json(self, &path, USE_TMP_FILE).await.map_mm_err()?; Ok(()) } @@ -282,11 +282,11 @@ mod native_impl { match self { SavedSwap::Maker(maker) => { let path = stats_maker_swap_file_path(ctx, &maker.uuid); - write_json(self, &path, USE_TMP_FILE).await?; + write_json(self, &path, USE_TMP_FILE).await.map_mm_err()?; }, SavedSwap::Taker(taker) => { let path = stats_taker_swap_file_path(ctx, &taker.uuid); - write_json(self, &path, USE_TMP_FILE).await?; + write_json(self, &path, USE_TMP_FILE).await.map_mm_err()?; }, } Ok(()) @@ -315,27 +315,29 @@ mod wasm_impl { .reverse() .where_first() .open_cursor("migration") - .await? + .await + .map_mm_err()? .next() - .await?; + .await + .map_mm_err()?; Ok(migrations.map(|(_, m)| m.migration).unwrap_or_default()) } pub async fn migrate_swaps_data(ctx: &MmArc) -> MmResult<(), SavedSwapError> { let swaps_ctx = SwapsContext::from_ctx(ctx).map_to_mm(SavedSwapError::InternalError)?; - let db = swaps_ctx.swap_db().await?; - let transaction = db.transaction().await?; - let migration_table = transaction.table::().await?; + let db = swaps_ctx.swap_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let migration_table = transaction.table::().await.map_mm_err()?; let mut migration = get_current_migration(&migration_table).await?; info!("Current swaps data migration {}", migration); loop { match migration { 0 => { - let filters_table = transaction.table::().await?; - let swaps_table = transaction.table::().await?; - let swaps = swaps_table.get_all_items().await?; + let filters_table = transaction.table::().await.map_mm_err()?; + let swaps_table = transaction.table::().await.map_mm_err()?; + let swaps = swaps_table.get_all_items().await.map_mm_err()?; let swaps = swaps .into_iter() .map(|(_item_id, SavedSwapTable { saved_swap, .. })| saved_swap) @@ -345,17 +347,23 @@ mod wasm_impl { }) .collect::, _>>()?; for swap in swaps { - let (filter_id, mut filter_record) = - match filters_table.get_item_by_unique_index("uuid", swap.uuid()).await? { - Some(f) => f, - None => { - warn!("No MySwapsFiltersTable for {}", swap.uuid()); - continue; - }, - }; + let (filter_id, mut filter_record) = match filters_table + .get_item_by_unique_index("uuid", swap.uuid()) + .await + .map_mm_err()? + { + Some(f) => f, + None => { + warn!("No MySwapsFiltersTable for {}", swap.uuid()); + continue; + }, + }; filter_record.swap_type = LEGACY_SWAP_TYPE; filter_record.is_finished = swap.is_finished().into(); - filters_table.replace_item(filter_id, &filter_record).await?; + filters_table + .replace_item(filter_id, &filter_record) + .await + .map_mm_err()?; } }, 1 => break, @@ -367,7 +375,10 @@ mod wasm_impl { }, } migration += 1; - migration_table.add_item(&SwapsMigrationTable { migration }).await?; + migration_table + .add_item(&SwapsMigrationTable { migration }) + .await + .map_mm_err()?; } info!("Swaps data migration is completed, new version {}", migration); @@ -415,11 +426,11 @@ mod wasm_impl { uuid: Uuid, ) -> SavedSwapResult> { let swaps_ctx = SwapsContext::from_ctx(ctx).map_to_mm(SavedSwapError::InternalError)?; - let db = swaps_ctx.swap_db().await?; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; + let db = swaps_ctx.swap_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; - let saved_swap_json = match table.get_item_by_unique_index("uuid", uuid).await? { + let saved_swap_json = match table.get_item_by_unique_index("uuid", uuid).await.map_mm_err()? { Some((_item_id, SavedSwapTable { saved_swap, .. })) => saved_swap, None => return Ok(None), }; @@ -429,11 +440,11 @@ mod wasm_impl { async fn load_all_my_swaps_from_db(ctx: &MmArc) -> SavedSwapResult> { let swaps_ctx = SwapsContext::from_ctx(ctx).map_to_mm(SavedSwapError::InternalError)?; - let db = swaps_ctx.swap_db().await?; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; + let db = swaps_ctx.swap_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; - let swaps = table.get_all_items().await?; + let swaps = table.get_all_items().await.map_mm_err()?; swaps .into_iter() .map(|(_item_id, SavedSwapTable { saved_swap, .. })| saved_swap) @@ -450,13 +461,14 @@ mod wasm_impl { }; let swaps_ctx = SwapsContext::from_ctx(ctx).map_to_mm(SavedSwapError::InternalError)?; - let db = swaps_ctx.swap_db().await?; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; + let db = swaps_ctx.swap_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; table .replace_item_by_unique_index("uuid", *self.uuid(), &saved_swap_item) - .await?; + .await + .map_mm_err()?; Ok(()) } } diff --git a/mm2src/mm2_main/src/lp_swap/swap_lock.rs b/mm2src/mm2_main/src/lp_swap/swap_lock.rs index 38591deeff..5a09df019a 100644 --- a/mm2src/mm2_main/src/lp_swap/swap_lock.rs +++ b/mm2src/mm2_main/src/lp_swap/swap_lock.rs @@ -64,12 +64,12 @@ mod native_lock { .join("MY") .join(format!("{}.lock", swap_uuid)) }; - let file_lock = some_or_return_ok_none!(FileLock::lock(lock_path, ttl_sec)?); + let file_lock = some_or_return_ok_none!(FileLock::lock(lock_path, ttl_sec).map_mm_err()?); Ok(Some(SwapLock { file_lock })) } - async fn touch(&self) -> SwapLockResult<()> { Ok(self.file_lock.touch()?) } + async fn touch(&self) -> SwapLockResult<()> { Ok(self.file_lock.touch().map_mm_err()?) } } } @@ -134,26 +134,26 @@ mod wasm_lock { impl SwapLockOps for SwapLock { async fn lock(ctx: &MmArc, uuid: Uuid, ttl_sec: f64) -> SwapLockResult> { let swaps_ctx = SwapsContext::from_ctx(ctx).map_to_mm(SwapLockError::InternalError)?; - let db = swaps_ctx.swap_db().await?; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; + let db = swaps_ctx.swap_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; if let Some((item_id, SwapLockTable { timestamp, .. })) = - table.get_item_by_unique_index("uuid", uuid).await? + table.get_item_by_unique_index("uuid", uuid).await.map_mm_err()? { let time_passed = now_float() - timestamp as f64; if time_passed <= ttl_sec { return Ok(None); } // delete the timestamp from the table before the new timestamp is written - table.delete_item(item_id).await?; + table.delete_item(item_id).await.map_mm_err()?; } let item = SwapLockTable { uuid, timestamp: now_sec(), }; - let record_id = table.add_item(&item).await?; + let record_id = table.add_item(&item).await.map_mm_err()?; Ok(Some(SwapLock { ctx: ctx.clone(), @@ -164,17 +164,17 @@ mod wasm_lock { async fn touch(&self) -> SwapLockResult<()> { let swaps_ctx = SwapsContext::from_ctx(&self.ctx).map_to_mm(SwapLockError::InternalError)?; - let db = swaps_ctx.swap_db().await?; + let db = swaps_ctx.swap_db().await.map_mm_err()?; let item = SwapLockTable { uuid: self.swap_uuid, timestamp: now_sec(), }; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; - let replaced_record_id = table.replace_item(self.record_id, &item).await?; + let replaced_record_id = table.replace_item(self.record_id, &item).await.map_mm_err()?; if self.record_id != replaced_record_id { let error = format!("Expected {} record id, found {}", self.record_id, replaced_record_id); @@ -187,10 +187,10 @@ mod wasm_lock { impl SwapLock { async fn release(ctx: MmArc, record_id: ItemId) -> SwapLockResult<()> { let swaps_ctx = SwapsContext::from_ctx(&ctx).map_to_mm(SwapLockError::InternalError)?; - let db = swaps_ctx.swap_db().await?; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; - table.delete_item(record_id).await?; + let db = swaps_ctx.swap_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; + table.delete_item(record_id).await.map_mm_err()?; Ok(()) } } diff --git a/mm2src/mm2_main/src/lp_swap/swap_v2_common.rs b/mm2src/mm2_main/src/lp_swap/swap_v2_common.rs index 3624d42b8d..9ddd5f6b4c 100644 --- a/mm2src/mm2_main/src/lp_swap/swap_v2_common.rs +++ b/mm2src/mm2_main/src/lp_swap/swap_v2_common.rs @@ -107,10 +107,10 @@ pub(super) async fn has_db_record_for(ctx: MmArc, id: &Uuid) -> MmResult MmResult { let swaps_ctx = SwapsContext::from_ctx(&ctx).expect("SwapsContext::from_ctx should not fail"); - let db = swaps_ctx.swap_db().await?; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; - let maybe_item = table.get_item_by_unique_index("uuid", id).await?; + let db = swaps_ctx.swap_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; + let maybe_item = table.get_item_by_unique_index("uuid", id).await.map_mm_err()?; Ok(maybe_item.is_some()) } @@ -143,11 +143,11 @@ pub(super) async fn store_swap_event MmResult<(), SwapStateMachineError> { let swaps_ctx = SwapsContext::from_ctx(&ctx).expect("SwapsContext::from_ctx should not fail"); - let db = swaps_ctx.swap_db().await?; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; + let db = swaps_ctx.swap_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; - let saved_swap_json = match table.get_item_by_unique_index("uuid", id).await? { + let saved_swap_json = match table.get_item_by_unique_index("uuid", id).await.map_mm_err()? { Some((_item_id, SavedSwapTable { saved_swap, .. })) => saved_swap, None => return MmError::err(SwapStateMachineError::NoSwapWithUuid(id)), }; @@ -159,18 +159,21 @@ pub(super) async fn store_swap_event(ctx: &MmArc, id: Uuid) -> MmResult { let swaps_ctx = SwapsContext::from_ctx(ctx).expect("SwapsContext::from_ctx should not fail"); - let db = swaps_ctx.swap_db().await?; - let transaction = db.transaction().await?; + let db = swaps_ctx.swap_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; - let table = transaction.table::().await?; - let saved_swap_json = match table.get_item_by_unique_index("uuid", id).await? { + let table = transaction.table::().await.map_mm_err()?; + let saved_swap_json = match table.get_item_by_unique_index("uuid", id).await.map_mm_err()? { Some((_item_id, SavedSwapTable { saved_swap, .. })) => saved_swap, None => return MmError::err(SwapStateMachineError::NoSwapWithUuid(id)), }; @@ -197,14 +200,16 @@ pub(super) async fn get_unfinished_swaps_uuids( swap_type: u8, ) -> MmResult, SwapStateMachineError> { let index = MultiIndex::new(IS_FINISHED_SWAP_TYPE_INDEX) - .with_value(BoolAsInt::new(false))? - .with_value(swap_type)?; + .with_value(BoolAsInt::new(false)) + .map_mm_err()? + .with_value(swap_type) + .map_mm_err()?; let swaps_ctx = SwapsContext::from_ctx(&ctx).expect("SwapsContext::from_ctx should not fail"); - let db = swaps_ctx.swap_db().await?; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; - let table_items = table.get_items_by_multi_index(index).await?; + let db = swaps_ctx.swap_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; + let table_items = table.get_items_by_multi_index(index).await.map_mm_err()?; Ok(table_items.into_iter().map(|(_item_id, item)| item.uuid).collect()) } @@ -217,15 +222,18 @@ pub(super) async fn mark_swap_as_finished(ctx: MmArc, id: Uuid) -> MmResult<(), #[cfg(target_arch = "wasm32")] pub(super) async fn mark_swap_as_finished(ctx: MmArc, id: Uuid) -> MmResult<(), SwapStateMachineError> { let swaps_ctx = SwapsContext::from_ctx(&ctx).expect("SwapsContext::from_ctx should not fail"); - let db = swaps_ctx.swap_db().await?; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; - let mut item = match table.get_item_by_unique_index("uuid", id).await? { + let db = swaps_ctx.swap_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; + let mut item = match table.get_item_by_unique_index("uuid", id).await.map_mm_err()? { Some((_item_id, item)) => item, None => return MmError::err(SwapStateMachineError::NoSwapWithUuid(id)), }; item.is_finished = true.into(); - table.replace_item_by_unique_index("uuid", id, &item).await?; + table + .replace_item_by_unique_index("uuid", id, &item) + .await + .map_mm_err()?; Ok(()) } @@ -259,7 +267,7 @@ pub(super) fn clean_up_context_impl(ctx: &MmArc, uuid: &Uuid, maker_coin: &str, pub(super) async fn acquire_reentrancy_lock_impl(ctx: &MmArc, uuid: Uuid) -> MmResult { let mut attempts = 0; loop { - match SwapLock::lock(ctx, uuid, 40.).await? { + match SwapLock::lock(ctx, uuid, 40.).await.map_mm_err()? { Some(l) => break Ok(l), None => { if attempts >= 1 { diff --git a/mm2src/mm2_main/src/lp_swap/swap_v2_rpcs.rs b/mm2src/mm2_main/src/lp_swap/swap_v2_rpcs.rs index 92a305f252..b6490338de 100644 --- a/mm2src/mm2_main/src/lp_swap/swap_v2_rpcs.rs +++ b/mm2src/mm2_main/src/lp_swap/swap_v2_rpcs.rs @@ -80,10 +80,10 @@ pub(super) async fn get_swap_type(ctx: &MmArc, uuid: &Uuid) -> MmResult().await?; - let item = match table.get_item_by_unique_index("uuid", uuid).await? { + let db = swaps_ctx.swap_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; + let item = match table.get_item_by_unique_index("uuid", uuid).await.map_mm_err()? { Some((_item_id, item)) => item, None => return Ok(None), }; @@ -189,16 +189,20 @@ pub(super) async fn get_maker_swap_data_for_rpc( uuid: &Uuid, ) -> MmResult>, SwapV2DbError> { let swaps_ctx = SwapsContext::from_ctx(ctx).unwrap(); - let db = swaps_ctx.swap_db().await?; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; - let item = match table.get_item_by_unique_index("uuid", uuid).await? { + let db = swaps_ctx.swap_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; + let item = match table.get_item_by_unique_index("uuid", uuid).await.map_mm_err()? { Some((_item_id, item)) => item, None => return Ok(None), }; - let filters_table = transaction.table::().await?; - let filter_item = match filters_table.get_item_by_unique_index("uuid", uuid).await? { + let filters_table = transaction.table::().await.map_mm_err()?; + let filter_item = match filters_table + .get_item_by_unique_index("uuid", uuid) + .await + .map_mm_err()? + { Some((_item_id, item)) => item, None => return Ok(None), }; @@ -230,16 +234,20 @@ pub(super) async fn get_taker_swap_data_for_rpc( uuid: &Uuid, ) -> MmResult>, SwapV2DbError> { let swaps_ctx = SwapsContext::from_ctx(ctx).unwrap(); - let db = swaps_ctx.swap_db().await?; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; - let item = match table.get_item_by_unique_index("uuid", uuid).await? { + let db = swaps_ctx.swap_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; + let item = match table.get_item_by_unique_index("uuid", uuid).await.map_mm_err()? { Some((_item_id, item)) => item, None => return Ok(None), }; - let filters_table = transaction.table::().await?; - let filter_item = match filters_table.get_item_by_unique_index("uuid", uuid).await? { + let filters_table = transaction.table::().await.map_mm_err()?; + let filter_item = match filters_table + .get_item_by_unique_index("uuid", uuid) + .await + .map_mm_err()? + { Some((_item_id, item)) => item, None => return Ok(None), }; @@ -301,18 +309,18 @@ async fn get_swap_data_by_uuid_and_type( ) -> MmResult, GetSwapDataErr> { match swap_type { LEGACY_SWAP_TYPE => { - let saved_swap = SavedSwap::load_my_swap_from_db(ctx, None, uuid).await?; + let saved_swap = SavedSwap::load_my_swap_from_db(ctx, None, uuid).await.map_mm_err()?; Ok(saved_swap.map(|swap| match swap { SavedSwap::Maker(m) => SwapRpcData::MakerV1(m), SavedSwap::Taker(t) => SwapRpcData::TakerV1(t), })) }, MAKER_SWAP_V2_TYPE => { - let data = get_maker_swap_data_for_rpc(ctx, &uuid).await?; + let data = get_maker_swap_data_for_rpc(ctx, &uuid).await.map_mm_err()?; Ok(data.map(SwapRpcData::MakerV2)) }, TAKER_SWAP_V2_TYPE => { - let data = get_taker_swap_data_for_rpc(ctx, &uuid).await?; + let data = get_taker_swap_data_for_rpc(ctx, &uuid).await.map_mm_err()?; Ok(data.map(SwapRpcData::TakerV2)) }, unsupported => MmError::err(GetSwapDataErr::UnsupportedSwapType(unsupported)), @@ -367,10 +375,12 @@ pub(crate) async fn my_swap_status_rpc( req: MySwapStatusRequest, ) -> MmResult { let swap_type = get_swap_type(&ctx, &req.uuid) - .await? + .await + .map_mm_err()? .or_mm_err(|| MySwapStatusError::NoSwapWithUuid(req.uuid))?; get_swap_data_by_uuid_and_type(&ctx, req.uuid, swap_type) - .await? + .await + .map_mm_err()? .or_mm_err(|| MySwapStatusError::NoSwapWithUuid(req.uuid)) } @@ -429,7 +439,8 @@ pub(crate) async fn my_recent_swaps_rpc( ) -> MmResult { let db_result = MySwapsStorage::new(ctx.clone()) .my_recent_swaps_with_filters(&req.filter, Some(&req.paging_options)) - .await?; + .await + .map_mm_err()?; let mut swaps = Vec::with_capacity(db_result.uuids_and_types.len()); for (uuid, swap_type) in db_result.uuids_and_types.iter() { match get_swap_data_by_uuid_and_type(&ctx, *uuid, *swap_type).await { diff --git a/mm2src/mm2_main/src/lp_swap/taker_swap.rs b/mm2src/mm2_main/src/lp_swap/taker_swap.rs index 1fdb9e728f..d35391b182 100644 --- a/mm2src/mm2_main/src/lp_swap/taker_swap.rs +++ b/mm2src/mm2_main/src/lp_swap/taker_swap.rs @@ -2649,7 +2649,8 @@ pub async fn taker_swap_trade_preimage( Some(prepared_params), stage, ) - .await?; + .await + .map_mm_err()?; let conf_settings = OrderConfirmationsSettings { base_confs: base_coin.required_confirmations(), @@ -2657,7 +2658,7 @@ pub async fn taker_swap_trade_preimage( rel_confs: rel_coin.required_confirmations(), rel_nota: rel_coin.requires_notarization(), }; - let our_public_id = CryptoCtx::from_ctx(ctx)?.mm2_internal_public_id(); + let our_public_id = CryptoCtx::from_ctx(ctx).map_mm_err()?.mm2_internal_public_id(); let order_builder = TakerOrderBuilder::new(&base_coin, &rel_coin) .with_base_amount(base_amount) @@ -2746,7 +2747,7 @@ pub async fn calc_max_taker_vol( stage: FeeApproxStage, ) -> CheckBalanceResult { let my_coin = coin.ticker(); - let balance: MmNumber = coin.my_spendable_balance().compat().await?.into(); + let balance: MmNumber = coin.my_spendable_balance().compat().await.map_mm_err()?.into(); let locked = get_locked_amount(ctx, my_coin); let min_tx_amount = MmNumber::from(coin.min_tx_amount()); diff --git a/mm2src/mm2_main/src/lp_swap/taker_swap_v2.rs b/mm2src/mm2_main/src/lp_swap/taker_swap_v2.rs index 7f8270f139..2926156325 100644 --- a/mm2src/mm2_main/src/lp_swap/taker_swap_v2.rs +++ b/mm2src/mm2_main/src/lp_swap/taker_swap_v2.rs @@ -225,10 +225,10 @@ impl StateMachineStorage for TakerSwapStorage { #[cfg(target_arch = "wasm32")] async fn store_repr(&mut self, uuid: Self::MachineId, repr: Self::DbRepr) -> Result<(), Self::Error> { let swaps_ctx = SwapsContext::from_ctx(&self.ctx).expect("SwapsContext::from_ctx should not fail"); - let db = swaps_ctx.swap_db().await?; - let transaction = db.transaction().await?; + let db = swaps_ctx.swap_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; - let filters_table = transaction.table::().await?; + let filters_table = transaction.table::().await.map_mm_err()?; let item = MySwapsFiltersTable { uuid, @@ -238,14 +238,14 @@ impl StateMachineStorage for TakerSwapStorage { is_finished: false.into(), swap_type: TAKER_SWAP_V2_TYPE, }; - filters_table.add_item(&item).await?; + filters_table.add_item(&item).await.map_mm_err()?; - let table = transaction.table::().await?; + let table = transaction.table::().await.map_mm_err()?; let item = SavedSwapTable { uuid, saved_swap: serde_json::to_value(repr)?, }; - table.add_item(&item).await?; + table.add_item(&item).await.map_mm_err()?; Ok(()) } diff --git a/mm2src/mm2_main/src/lp_swap/trade_preimage.rs b/mm2src/mm2_main/src/lp_swap/trade_preimage.rs index cb31ed63e9..ceccd64241 100644 --- a/mm2src/mm2_main/src/lp_swap/trade_preimage.rs +++ b/mm2src/mm2_main/src/lp_swap/trade_preimage.rs @@ -29,8 +29,8 @@ pub async fn trade_preimage_rpc( return MmError::err(TradePreimageRpcError::CoinIsWalletOnly { coin: req.rel }); } - let base_coin = lp_coinfind_or_err(&ctx, &req.base).await?; - let rel_coin = lp_coinfind_or_err(&ctx, &req.rel).await?; + let base_coin = lp_coinfind_or_err(&ctx, &req.base).await.map_mm_err()?; + let rel_coin = lp_coinfind_or_err(&ctx, &req.rel).await.map_mm_err()?; match req.swap_method { TradePreimageMethod::SetPrice => maker_swap_trade_preimage(&ctx, req, base_coin, rel_coin) diff --git a/mm2src/mm2_main/src/lp_wallet.rs b/mm2src/mm2_main/src/lp_wallet.rs index 7743b05039..36124e7a16 100644 --- a/mm2src/mm2_main/src/lp_wallet.rs +++ b/mm2src/mm2_main/src/lp_wallet.rs @@ -118,7 +118,7 @@ async fn encrypt_and_save_passphrase( passphrase: &str, wallet_password: &str, ) -> WalletInitResult<()> { - let encrypted_passphrase_data = encrypt_mnemonic(passphrase, wallet_password)?; + let encrypted_passphrase_data = encrypt_mnemonic(passphrase, wallet_password).map_mm_err()?; save_encrypted_passphrase(ctx, wallet_name, &encrypted_passphrase_data) .await .mm_err(|e| WalletInitError::WalletsStorageError(e.to_string())) @@ -188,7 +188,10 @@ async fn retrieve_or_create_passphrase( wallet_name: &str, wallet_password: &str, ) -> WalletInitResult> { - match try_load_active_wallet_passphrase(ctx, wallet_password).await? { + match try_load_active_wallet_passphrase(ctx, wallet_password) + .await + .map_mm_err()? + { Some(passphrase_from_file) => { // If an existing passphrase is found, return it Ok(Some(passphrase_from_file)) @@ -204,9 +207,11 @@ async fn retrieve_or_create_passphrase( password_policy(wallet_password)?; } // If no passphrase is found, generate a new one - let new_passphrase = generate_mnemonic(ctx)?.to_string(); + let new_passphrase = generate_mnemonic(ctx).map_mm_err()?.to_string(); // Encrypt and save the new passphrase - encrypt_and_save_passphrase(ctx, wallet_name, &new_passphrase, wallet_password).await?; + encrypt_and_save_passphrase(ctx, wallet_name, &new_passphrase, wallet_password) + .await + .map_mm_err()?; Ok(Some(new_passphrase)) }, } @@ -219,7 +224,10 @@ async fn confirm_or_encrypt_and_store_passphrase( passphrase: &str, wallet_password: &str, ) -> WalletInitResult> { - match try_load_active_wallet_passphrase(ctx, wallet_password).await? { + match try_load_active_wallet_passphrase(ctx, wallet_password) + .await + .map_mm_err()? + { Some(passphrase_from_file) if passphrase == passphrase_from_file => { // If an existing passphrase is found and it matches the provided passphrase, return it Ok(Some(passphrase_from_file)) @@ -235,7 +243,9 @@ async fn confirm_or_encrypt_and_store_passphrase( password_policy(wallet_password)?; } // If no passphrase is found in the file, encrypt and save the provided passphrase - encrypt_and_save_passphrase(ctx, wallet_name, passphrase, wallet_password).await?; + encrypt_and_save_passphrase(ctx, wallet_name, passphrase, wallet_password) + .await + .map_mm_err()?; Ok(Some(passphrase.to_string())) }, _ => { @@ -253,9 +263,12 @@ async fn decrypt_validate_or_save_passphrase( wallet_password: &str, ) -> WalletInitResult> { // Decrypt the provided encrypted passphrase - let decrypted_passphrase = decrypt_mnemonic(&encrypted_passphrase_data, wallet_password)?; + let decrypted_passphrase = decrypt_mnemonic(&encrypted_passphrase_data, wallet_password).map_mm_err()?; - match try_load_active_wallet_passphrase(ctx, wallet_password).await? { + match try_load_active_wallet_passphrase(ctx, wallet_password) + .await + .map_mm_err()? + { Some(passphrase_from_file) if decrypted_passphrase == passphrase_from_file => { // If an existing passphrase is found and it matches the decrypted passphrase, return it Ok(Some(decrypted_passphrase)) @@ -315,8 +328,8 @@ async fn process_passphrase_logic( fn initialize_crypto_context(ctx: &MmArc, passphrase: &str) -> WalletInitResult<()> { // This defaults to false to maintain backward compatibility. match ctx.enable_hd() { - true => CryptoCtx::init_with_global_hd_account(ctx.clone(), passphrase)?, - false => CryptoCtx::init_with_iguana_passphrase(ctx.clone(), passphrase)?, + true => CryptoCtx::init_with_global_hd_account(ctx.clone(), passphrase).map_mm_err()?, + false => CryptoCtx::init_with_iguana_passphrase(ctx.clone(), passphrase).map_mm_err()?, }; Ok(()) } @@ -345,11 +358,14 @@ pub(crate) async fn initialize_wallet_passphrase(ctx: &MmArc) -> WalletInitResul let (wallet_name, passphrase) = deserialize_wallet_config(ctx)?; ctx.wallet_name .set(wallet_name.clone()) - .map_to_mm(|_| WalletInitError::InternalError("Already Initialized".to_string()))?; + .map_to_mm(|_| WalletInitError::InternalError("Already Initialized".to_string())) + .map_mm_err()?; - let passphrase = process_passphrase_logic(ctx, wallet_name.as_deref(), passphrase).await?; + let passphrase = process_passphrase_logic(ctx, wallet_name.as_deref(), passphrase) + .await + .map_mm_err()?; if let Some(passphrase) = passphrase { - initialize_crypto_context(ctx, &passphrase)?; + initialize_crypto_context(ctx, &passphrase).map_mm_err()?; } Ok(()) @@ -549,7 +565,8 @@ pub async fn get_mnemonic_rpc(ctx: MmArc, req: GetMnemonicRequest) -> MmResult MmResult { let plaintext_mnemonic = try_load_active_wallet_passphrase(&ctx, &wallet_password) - .await? + .await + .map_mm_err()? .ok_or_else(|| MnemonicRpcError::InvalidRequest("Wallet mnemonic file not found".to_string()))?; Ok(GetMnemonicResponse { mnemonic: plaintext_mnemonic.into(), @@ -576,7 +594,7 @@ pub struct GetWalletNamesResponse { /// Retrieves all created wallets and the currently activated wallet. pub async fn get_wallet_names_rpc(ctx: MmArc, _req: Json) -> MmResult { // We want to return wallet names in the same order for both native and wasm32 targets. - let wallets = read_all_wallet_names(&ctx).await?.sorted().collect(); + let wallets = read_all_wallet_names(&ctx).await.map_mm_err()?.sorted().collect(); // Note: `ok_or` is used here on `Constructible>` to handle the case where the wallet name is not set. // `wallet_name` can be `None` in the case of no-login mode. let activated_wallet = ctx.wallet_name.get().ok_or(MnemonicRpcError::Internal( @@ -620,14 +638,17 @@ pub async fn change_mnemonic_password(ctx: MmArc, req: ChangeMnemonicPasswordReq .ok_or_else(|| MnemonicRpcError::Internal("`wallet_name` cannot be None!".to_string()))?; // read mnemonic for a wallet_name using current user's password. let mnemonic = try_load_active_wallet_passphrase(&ctx, &req.current_password) - .await? + .await + .map_mm_err()? .ok_or(MmError::new(MnemonicRpcError::Internal(format!( "{wallet_name}: wallet mnemonic file not found" ))))?; // encrypt mnemonic with new passphrase. - let encrypted_data = encrypt_mnemonic(&mnemonic, &req.new_password)?; + let encrypted_data = encrypt_mnemonic(&mnemonic, &req.new_password).map_mm_err()?; // save new encrypted mnemonic data with new password - save_encrypted_passphrase(&ctx, wallet_name, &encrypted_data).await?; + save_encrypted_passphrase(&ctx, wallet_name, &encrypted_data) + .await + .map_mm_err()?; Ok(()) } @@ -659,12 +680,14 @@ pub async fn delete_wallet_rpc(ctx: MmArc, req: DeleteWalletRequest) -> MmResult } // Verify the password by attempting to decrypt the mnemonic. - let maybe_mnemonic = try_load_wallet_passphrase(&ctx, &req.wallet_name, &req.password).await?; + let maybe_mnemonic = try_load_wallet_passphrase(&ctx, &req.wallet_name, &req.password) + .await + .map_mm_err()?; match maybe_mnemonic { Some(_) => { // Password is correct, proceed with deletion. - delete_wallet(&ctx, &req.wallet_name).await?; + delete_wallet(&ctx, &req.wallet_name).await.map_mm_err()?; Ok(()) }, None => { diff --git a/mm2src/mm2_main/src/lp_wallet/mnemonics_wasm_db.rs b/mm2src/mm2_main/src/lp_wallet/mnemonics_wasm_db.rs index 6eeaebc8d4..4c3dcd023b 100644 --- a/mm2src/mm2_main/src/lp_wallet/mnemonics_wasm_db.rs +++ b/mm2src/mm2_main/src/lp_wallet/mnemonics_wasm_db.rs @@ -99,9 +99,9 @@ pub(super) async fn save_encrypted_passphrase( ) -> WalletsDBResult<()> { let wallets_ctx = WalletsContext::from_ctx(ctx).map_to_mm(WalletsDBError::Internal)?; - let db = wallets_ctx.wallets_db().await?; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; + let db = wallets_ctx.wallets_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; let mnemonics_table_item = MnemonicsTable { wallet_name: wallet_name.to_string(), @@ -114,7 +114,8 @@ pub(super) async fn save_encrypted_passphrase( }; table .replace_item_by_unique_index("wallet_name", wallet_name, &mnemonics_table_item) - .await?; + .await + .map_mm_err()?; Ok(()) } @@ -125,13 +126,14 @@ pub(super) async fn read_encrypted_passphrase( ) -> WalletsDBResult> { let wallets_ctx = WalletsContext::from_ctx(ctx).map_to_mm(WalletsDBError::Internal)?; - let db = wallets_ctx.wallets_db().await?; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; + let db = wallets_ctx.wallets_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; table .get_item_by_unique_index("wallet_name", wallet_name) - .await? + .await + .map_mm_err()? .map(|(_item_id, wallet_table_item)| { serde_json::from_str(&wallet_table_item.encrypted_mnemonic).map_to_mm(|e| { WalletsDBError::DeserializationError { @@ -146,11 +148,11 @@ pub(super) async fn read_encrypted_passphrase( pub(super) async fn read_all_wallet_names(ctx: &MmArc) -> WalletsDBResult> { let wallets_ctx = WalletsContext::from_ctx(ctx).map_to_mm(WalletsDBError::Internal)?; - let db = wallets_ctx.wallets_db().await?; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; + let db = wallets_ctx.wallets_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; - let all_items = table.get_all_items().await?; + let all_items = table.get_all_items().await.map_mm_err()?; let wallet_names = all_items.into_iter().map(|(_, item)| item.wallet_name); Ok(wallet_names) @@ -159,10 +161,13 @@ pub(super) async fn read_all_wallet_names(ctx: &MmArc) -> WalletsDBResult WalletsDBResult<()> { let wallets_ctx = WalletsContext::from_ctx(ctx).map_to_mm(WalletsDBError::Internal)?; - let db = wallets_ctx.wallets_db().await?; - let transaction = db.transaction().await?; - let table = transaction.table::().await?; + let db = wallets_ctx.wallets_db().await.map_mm_err()?; + let transaction = db.transaction().await.map_mm_err()?; + let table = transaction.table::().await.map_mm_err()?; - table.delete_item_by_unique_index("wallet_name", wallet_name).await?; + table + .delete_item_by_unique_index("wallet_name", wallet_name) + .await + .map_mm_err()?; Ok(()) } diff --git a/mm2src/mm2_main/src/rpc/lp_commands/one_inch/rpcs.rs b/mm2src/mm2_main/src/rpc/lp_commands/one_inch/rpcs.rs index 978a1d80b5..45fec7f680 100644 --- a/mm2src/mm2_main/src/rpc/lp_commands/one_inch/rpcs.rs +++ b/mm2src/mm2_main/src/rpc/lp_commands/one_inch/rpcs.rs @@ -69,7 +69,7 @@ pub async fn one_inch_v6_0_classic_swap_create_rpc( api_supports_pair(&base, &rel)?; let sell_amount = wei_from_big_decimal(&req.amount.to_decimal(), base.decimals()) .mm_err(|err| ApiIntegrationRpcError::InvalidParam(err.to_string()))?; - let single_address = base.derivation_method().single_addr_or_err().await?; + let single_address = base.derivation_method().single_addr_or_err().await.map_mm_err()?; let query_params = ClassicSwapCreateParams::new( base_contract, @@ -145,7 +145,7 @@ pub async fn one_inch_v6_0_classic_swap_tokens_rpc( } async fn get_coin_for_one_inch(ctx: &MmArc, ticker: &str) -> MmResult<(EthCoin, String), ApiIntegrationRpcError> { - let coin = match lp_coinfind_or_err(ctx, ticker).await? { + let coin = match lp_coinfind_or_err(ctx, ticker).await.map_mm_err()? { MmCoinEnum::EthCoin(coin) => coin, _ => return Err(MmError::new(ApiIntegrationRpcError::CoinTypeError)), }; diff --git a/mm2src/mm2_main/src/rpc/lp_commands/one_inch/types.rs b/mm2src/mm2_main/src/rpc/lp_commands/one_inch/types.rs index 202eb0dcf2..8324e801d4 100644 --- a/mm2src/mm2_main/src/rpc/lp_commands/one_inch/types.rs +++ b/mm2src/mm2_main/src/rpc/lp_commands/one_inch/types.rs @@ -152,7 +152,10 @@ impl ClassicSwapResponse { decimals: u8, ) -> MmResult { Ok(Self { - dst_amount: MmNumber::from(u256_to_big_decimal(U256::from_dec_str(&data.dst_amount)?, decimals)?).into(), + dst_amount: MmNumber::from( + u256_to_big_decimal(U256::from_dec_str(&data.dst_amount)?, decimals).map_mm_err()?, + ) + .into(), src_token: data.src_token, dst_token: data.dst_token, protocols: data.protocols, @@ -185,8 +188,8 @@ impl TxFields { from: tx_fields.from, to: tx_fields.to, data: BytesJson::from(hex::decode(str_strip_0x!(tx_fields.data.as_str()))?), - value: u256_to_big_decimal(U256::from_dec_str(&tx_fields.value)?, decimals)?, - gas_price: wei_to_gwei_decimal(U256::from_dec_str(&tx_fields.gas_price)?)?, + value: u256_to_big_decimal(U256::from_dec_str(&tx_fields.value)?, decimals).map_mm_err()?, + gas_price: wei_to_gwei_decimal(U256::from_dec_str(&tx_fields.gas_price)?).map_mm_err()?, gas: tx_fields.gas, }) } diff --git a/mm2src/mm2_main/src/rpc/lp_commands/pubkey.rs b/mm2src/mm2_main/src/rpc/lp_commands/pubkey.rs index f5a5a95063..6a84641f45 100644 --- a/mm2src/mm2_main/src/rpc/lp_commands/pubkey.rs +++ b/mm2src/mm2_main/src/rpc/lp_commands/pubkey.rs @@ -33,7 +33,10 @@ impl HttpStatusCode for GetPublicKeyError { } pub async fn get_public_key(ctx: MmArc, _req: Json) -> GetPublicKeyRpcResult { - let public_key = CryptoCtx::from_ctx(&ctx)?.mm2_internal_pubkey().to_string(); + let public_key = CryptoCtx::from_ctx(&ctx) + .map_mm_err()? + .mm2_internal_pubkey() + .to_string(); Ok(GetPublicKeyResponse { public_key }) } diff --git a/mm2src/mm2_main/src/rpc/lp_commands/tokens.rs b/mm2src/mm2_main/src/rpc/lp_commands/tokens.rs index 78697530c1..da54111581 100644 --- a/mm2src/mm2_main/src/rpc/lp_commands/tokens.rs +++ b/mm2src/mm2_main/src/rpc/lp_commands/tokens.rs @@ -11,6 +11,7 @@ use ethereum_types::Address as EthAddress; use futures::compat::Future01CompatExt; use http::StatusCode; use mm2_core::mm_ctx::MmArc; +use mm2_err_handle::map_mm_error::MmResultExt; use mm2_err_handle::{map_to_mm::MapToMmResult, mm_error::MmError, prelude::MmResult}; use mm2_number::BigDecimal; @@ -73,7 +74,7 @@ pub async fn get_token_info(ctx: MmArc, req: TokenInfoRequest) -> MmResult { let contract_address_str = @@ -141,8 +142,8 @@ pub struct Erc20AllowanceRequest { /// Returns BigDecimal allowance value. pub async fn get_token_allowance_rpc(ctx: MmArc, req: Erc20AllowanceRequest) -> MmResult { let eth_coin = find_erc20_eth_coin(&ctx, &req.coin).await?; - let wei = eth_coin.allowance(req.spender).compat().await?; - let amount = u256_to_big_decimal(wei, eth_coin.decimals())?; + let wei = eth_coin.allowance(req.spender).compat().await.map_mm_err()?; + let amount = u256_to_big_decimal(wei, eth_coin.decimals()).map_mm_err()?; Ok(amount) } @@ -157,7 +158,7 @@ pub struct Erc20ApproveRequest { /// Returns approval transaction hash. pub async fn approve_token_rpc(ctx: MmArc, req: Erc20ApproveRequest) -> MmResult { let eth_coin = find_erc20_eth_coin(&ctx, &req.coin).await?; - let amount = wei_from_big_decimal(&req.amount, eth_coin.decimals())?; + let amount = wei_from_big_decimal(&req.amount, eth_coin.decimals()).map_mm_err()?; let tx = eth_coin.approve(req.spender, amount).compat().await?; Ok(format!("0x{:02x}", tx.tx_hash_as_bytes())) } diff --git a/mm2src/mm2_main/src/rpc/lp_commands/trezor.rs b/mm2src/mm2_main/src/rpc/lp_commands/trezor.rs index 16698eb3cc..212c810331 100644 --- a/mm2src/mm2_main/src/rpc/lp_commands/trezor.rs +++ b/mm2src/mm2_main/src/rpc/lp_commands/trezor.rs @@ -2,6 +2,7 @@ use common::HttpStatusCode; use crypto::{CryptoCtx, CryptoCtxError, HwConnectionStatus, HwPubkey}; use http::StatusCode; use mm2_core::mm_ctx::MmArc; +use mm2_err_handle::map_mm_error::MmResultExt; use mm2_err_handle::mm_error::{MmError, MmResult}; use mm2_err_handle::or_mm_error::OrMmError; @@ -45,7 +46,7 @@ pub async fn trezor_connection_status( ctx: MmArc, req: TrezorConnectionStatusReq, ) -> MmResult { - let crypto_ctx = CryptoCtx::from_ctx(&ctx)?; + let crypto_ctx = CryptoCtx::from_ctx(&ctx).map_mm_err()?; let hw_ctx = crypto_ctx .hw_ctx() .or_mm_err(|| TrezorConnectionError::TrezorNotInitialized)?; diff --git a/mm2src/mm2_net/src/grpc_web.rs b/mm2src/mm2_net/src/grpc_web.rs index 55f796df82..2a62126c79 100644 --- a/mm2src/mm2_net/src/grpc_web.rs +++ b/mm2src/mm2_net/src/grpc_web.rs @@ -153,11 +153,11 @@ where .uri(url) .header(CONTENT_TYPE, APPLICATION_GRPC_WEB) .header(ACCEPT, APPLICATION_GRPC_WEB) - .body(encode_body(req)?)?; + .body(encode_body(req).map_mm_err()?)?; - let response = slurp_req(request).await?; + let response = slurp_req(request).await.map_mm_err()?; - let reply = decode_body(response.2.into())?; + let reply = decode_body(response.2.into()).map_mm_err()?; Ok(reply) } @@ -168,7 +168,7 @@ where Req: prost::Message + Send + 'static, Res: prost::Message + Default + Send + 'static, { - let body = encode_body(req)?; + let body = encode_body(req).map_mm_err()?; let request = FetchRequest::post(url) .body_bytes(body) .header(CONTENT_TYPE.as_str(), APPLICATION_GRPC_WEB_PROTO) @@ -176,9 +176,9 @@ where // https://github.com/grpc/grpc-web/issues/85#issue-217223001 .header(X_GRPC_WEB, "1"); - let response = request.request_array().await?; + let response = request.request_array().await.map_mm_err()?; - let reply = decode_body(response.1.into())?; + let reply = decode_body(response.1.into()).map_mm_err()?; Ok(reply) } diff --git a/mm2src/mm2_net/src/native_http.rs b/mm2src/mm2_net/src/native_http.rs index 6837c04655..b056c4ec03 100644 --- a/mm2src/mm2_net/src/native_http.rs +++ b/mm2src/mm2_net/src/native_http.rs @@ -245,7 +245,7 @@ pub async fn send_request_to_uri(uri: &str, auth_header: Option<&str>) -> MmResu } let request = request_builder.body(Body::empty())?; - let (status, _header, body) = slurp_req_body(request).await?; + let (status, _header, body) = slurp_req_body(request).await.map_mm_err()?; if !status.is_success() { return Err(MmError::new(GetInfoFromUriError::Transport(format!( "Status code not in 2xx range from {}: {}, {}", diff --git a/mm2src/mm2_net/src/transport.rs b/mm2src/mm2_net/src/transport.rs index 750d2561c2..cad2d553ed 100644 --- a/mm2src/mm2_net/src/transport.rs +++ b/mm2src/mm2_net/src/transport.rs @@ -113,7 +113,7 @@ impl From for GetInfoFromUriError { /// /// Returns an error if the HTTP status code of the response is not in the 2xx range. pub async fn send_post_request_to_uri(uri: &str, body: String) -> MmResult, GetInfoFromUriError> { - let (status, _header, body) = slurp_post_json(uri, body).await?; + let (status, _header, body) = slurp_post_json(uri, body).await.map_mm_err()?; if !status.is_success() { return Err(MmError::new(GetInfoFromUriError::Transport(format!( "Status code not in 2xx range from {}: {}", diff --git a/mm2src/mm2_net/src/wasm/tonic_client.rs b/mm2src/mm2_net/src/wasm/tonic_client.rs index 84df389e73..ccdb3ae4a4 100644 --- a/mm2src/mm2_net/src/wasm/tonic_client.rs +++ b/mm2src/mm2_net/src/wasm/tonic_client.rs @@ -6,7 +6,7 @@ use common::{APPLICATION_GRPC_WEB_PROTO, X_GRPC_WEB}; use futures_util::Future; use http::header::{ACCEPT, CONTENT_TYPE}; use http::{Request, Response}; -use mm2_err_handle::prelude::{MmError, MmResult}; +use mm2_err_handle::prelude::*; use std::pin::Pin; use std::task::{Context, Poll}; use tonic::body::BoxBody; @@ -48,6 +48,7 @@ async fn call(base_url: String, request: Request) -> MmResult return Ok(result), TrezorResponse::ButtonRequest(button_req) => { - processor_req.on_button_request().await?; - button_req.ack().await? + processor_req.on_button_request().await.map_mm_err()?; + button_req.ack().await.map_mm_err()? }, TrezorResponse::PinMatrixRequest(pin_req) => { - let pin_response = processor_req.on_pin_request().await?; - pin_req.ack_pin(pin_response.pin).await? + let pin_response = processor_req.on_pin_request().await.map_mm_err()?; + pin_req.ack_pin(pin_response.pin).await.map_mm_err()? }, TrezorResponse::PassphraseRequest(passphrase_req) => { - let passphrase_response = processor_req.on_passphrase_request().await?; - passphrase_req.ack_passphrase(passphrase_response.passphrase).await? + let passphrase_response = processor_req.on_passphrase_request().await.map_mm_err()?; + passphrase_req + .ack_passphrase(passphrase_response.passphrase) + .await + .map_mm_err()? }, }; } }; let res = fut.await; - processor.on_ready().await?; + processor.on_ready().await.map_mm_err()?; res } } diff --git a/mm2src/trezor/src/response_processor.rs b/mm2src/trezor/src/response_processor.rs index 33a3e0c46a..dba89a38c6 100644 --- a/mm2src/trezor/src/response_processor.rs +++ b/mm2src/trezor/src/response_processor.rs @@ -17,9 +17,6 @@ impl From for TrezorProcessingError { fn from(e: TrezorError) -> Self { TrezorProcessingError::TrezorError(e) } } -/// This is required for implementing `MmError>: From>`. -impl NotEqual for TrezorProcessingError {} - #[async_trait] pub trait TrezorRequestProcessor where diff --git a/mm2src/trezor/src/transport/usb.rs b/mm2src/trezor/src/transport/usb.rs index cfdba0d36c..bf69871154 100644 --- a/mm2src/trezor/src/transport/usb.rs +++ b/mm2src/trezor/src/transport/usb.rs @@ -6,6 +6,7 @@ use crate::TrezorResult; use async_trait::async_trait; use hw_common::transport::libusb::{GetDevicesFilters, UsbAvailableDevice as UsbAvailableDeviceImpl, UsbContext, UsbDevice}; +use mm2_err_handle::prelude::MmResultExt; use std::time::Duration; pub use hw_common::transport::libusb::UsbDeviceInfo; @@ -44,17 +45,21 @@ struct UsbLink { impl Link for UsbLink { async fn write_chunk(&mut self, chunk: Vec) -> TrezorResult<()> { // don't try to reconnect since libusb requires to enumerate all devices, ope and, claim interface again - Ok(self.device.write_chunk(chunk, WRITE_TIMEOUT).await?) + Ok(self.device.write_chunk(chunk, WRITE_TIMEOUT).await.map_mm_err()?) } async fn read_chunk(&mut self, chunk_len: u32) -> TrezorResult> { // don't try to reconnect since libusb requires to enumerate all devices, ope and, claim interface again - Ok(self.device.read_chunk(chunk_len as usize, READ_TIMEOUT).await?) + Ok(self + .device + .read_chunk(chunk_len as usize, READ_TIMEOUT) + .await + .map_mm_err()?) } } async fn find_devices() -> TrezorResult> { - let context = UsbContext::new()?; + let context = UsbContext::new().map_mm_err()?; let filters = GetDevicesFilters { config_id: CONFIG_ID, interface_id: INTERFACE, @@ -62,7 +67,8 @@ async fn find_devices() -> TrezorResult> { interface_class_code: LIBUSB_CLASS_VENDOR_SPEC, }; Ok(context - .get_devices(filters)? + .get_devices(filters) + .map_mm_err()? .into_iter() .filter(is_trezor) .map(UsbAvailableDevice) @@ -75,7 +81,7 @@ impl UsbAvailableDevice { /// Please note [`hw_common::transport::libusb::UsbAvailableDevice::connect`] spawns a thread. async fn connect(&self) -> TrezorResult { let link = UsbLink { - device: self.0.connect()?, + device: self.0.connect().map_mm_err()?, }; Ok(UsbTransport { protocol: ProtocolV1 { link }, diff --git a/mm2src/trezor/src/transport/webusb.rs b/mm2src/trezor/src/transport/webusb.rs index 6c438cea74..a1fc4cf1d9 100644 --- a/mm2src/trezor/src/transport/webusb.rs +++ b/mm2src/trezor/src/transport/webusb.rs @@ -44,17 +44,22 @@ struct WebUsbLink { #[async_trait] impl Link for WebUsbLink { async fn write_chunk(&mut self, chunk: Vec) -> TrezorResult<()> { - if !self.device.is_open().await? { + if !self.device.is_open().await.map_mm_err()? { return MmError::err(TrezorError::DeviceDisconnected); } - Ok(self.device.write_chunk(self.endpoint_number, chunk).await?) + + self.device.write_chunk(self.endpoint_number, chunk).await.map_mm_err() } async fn read_chunk(&mut self, chunk_len: u32) -> TrezorResult> { - if !self.device.is_open().await? { + if !self.device.is_open().await.map_mm_err()? { return MmError::err(TrezorError::DeviceDisconnected); } - Ok(self.device.read_chunk(self.endpoint_number, chunk_len).await?) + + self.device + .read_chunk(self.endpoint_number, chunk_len) + .await + .map_mm_err() } } @@ -66,15 +71,15 @@ impl WebUsbLink { /// Configure the WebUSB device. async fn establish_connection(&self, first: bool) -> TrezorResult<()> { - self.device.open().await?; + self.device.open().await.map_mm_err()?; if first { - self.device.select_configuration(CONFIGURATION_ID).await?; + self.device.select_configuration(CONFIGURATION_ID).await.map_mm_err()?; if let Err(e) = self.device.reset_device().await { // Reset fails on ChromeOS and Windows. warn!("{}", e); } } - self.device.claim_interface(self.interface_number).await?; + self.device.claim_interface(self.interface_number).await.map_mm_err()?; Ok(()) } } @@ -115,11 +120,12 @@ pub struct FoundDevices { /// /// This function **must** be called via a user gesture like a touch or mouse click. pub async fn find_devices() -> TrezorResult { - let wrapper = WebUsbWrapper::new()?; + let wrapper = WebUsbWrapper::new().map_mm_err()?; wrapper .request_device(TREZOR_DEVICES.iter().copied().map(DeviceFilter::from).collect()) - .await?; - let devices_iter = wrapper.get_devices().await?.into_iter().filter(is_trezor); + .await + .map_mm_err()?; + let devices_iter = wrapper.get_devices().await.map_mm_err()?.into_iter().filter(is_trezor); let mut available = Vec::new(); let mut not_supported = Vec::new(); for device in devices_iter {