Skip to content

Commit

Permalink
Merge branch 'dev' of github.com:KomodoPlatform/atomicDEX-API into wa…
Browse files Browse the repository at this point in the history
…tchtower
  • Loading branch information
caglaryucekaya committed Sep 24, 2022
2 parents 281fb4b + 36392fd commit 56aac96
Show file tree
Hide file tree
Showing 47 changed files with 2,906 additions and 1,029 deletions.
97 changes: 90 additions & 7 deletions mm2src/coins/coin_balance.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
use crate::hd_pubkey::HDXPubExtractor;
use crate::hd_wallet::{HDAddressId, HDWalletCoinOps, NewAccountCreatingError, NewAddressDerivingError};
use crate::hd_wallet::{HDAccountOps, HDAddressId, HDWalletCoinOps, HDWalletOps, NewAccountCreatingError,
NewAddressDerivingError};
use crate::{BalanceError, BalanceResult, CoinBalance, CoinWithDerivationMethod, DerivationMethod, HDAddress,
MarketCoinOps};
use async_trait::async_trait;
use common::log::{debug, info};
use crypto::{Bip44Chain, RpcDerivationPath};
use futures::compat::Future01CompatExt;
use mm2_err_handle::prelude::*;
use mm2_number::BigDecimal;
#[cfg(test)] use mocktopus::macros::*;
use std::fmt;
use std::collections::HashMap;
use std::ops::Range;
use std::{fmt, iter};

pub type AddressIdRange = Range<u32>;

Expand All @@ -33,11 +36,32 @@ impl From<BalanceError> for EnableCoinBalanceError {

#[derive(Clone, Debug, PartialEq, Serialize)]
#[serde(tag = "wallet_type")]
pub enum EnableCoinBalance {
pub enum CoinBalanceReport {
Iguana(IguanaWalletBalance),
HD(HDWalletBalance),
}

impl CoinBalanceReport {
/// Returns a map where the key is address, and the value is the address's total balance [`CoinBalance::total`].
pub fn to_addresses_total_balances(&self) -> HashMap<String, BigDecimal> {
match self {
CoinBalanceReport::Iguana(IguanaWalletBalance {
ref address,
ref balance,
}) => iter::once((address.clone(), balance.get_total())).collect(),
CoinBalanceReport::HD(HDWalletBalance { ref accounts }) => accounts
.iter()
.flat_map(|account_balance| {
account_balance
.addresses
.iter()
.map(|addr_balance| (addr_balance.address.clone(), addr_balance.balance.get_total()))
})
.collect(),
}
}
}

#[derive(Clone, Debug, PartialEq, Serialize)]
pub struct IguanaWalletBalance {
pub address: String,
Expand Down Expand Up @@ -88,13 +112,48 @@ pub struct EnabledCoinBalanceParams {
pub min_addresses_number: Option<u32>,
}

#[async_trait]
pub trait CoinBalanceReportOps {
async fn coin_balance_report(&self) -> BalanceResult<CoinBalanceReport>;
}

#[async_trait]
impl<Coin> CoinBalanceReportOps for Coin
where
Coin: CoinWithDerivationMethod<HDWallet = <Coin as HDWalletCoinOps>::HDWallet>
+ HDWalletBalanceOps
+ MarketCoinOps
+ Sync,
<Coin as CoinWithDerivationMethod>::Address: fmt::Display + Sync,
{
async fn coin_balance_report(&self) -> BalanceResult<CoinBalanceReport> {
match self.derivation_method() {
DerivationMethod::Iguana(my_address) => self
.my_balance()
.compat()
.await
.map(|balance| {
CoinBalanceReport::Iguana(IguanaWalletBalance {
address: my_address.to_string(),
balance,
})
})
.mm_err(BalanceError::from),
DerivationMethod::HDWallet(hd_wallet) => self
.all_accounts_balances(hd_wallet)
.await
.map(|accounts| CoinBalanceReport::HD(HDWalletBalance { accounts })),
}
}
}

#[async_trait]
pub trait EnableCoinBalanceOps {
async fn enable_coin_balance<XPubExtractor>(
&self,
xpub_extractor: &XPubExtractor,
params: EnabledCoinBalanceParams,
) -> MmResult<EnableCoinBalance, EnableCoinBalanceError>
) -> MmResult<CoinBalanceReport, EnableCoinBalanceError>
where
XPubExtractor: HDXPubExtractor + Sync;
}
Expand All @@ -112,7 +171,7 @@ where
&self,
xpub_extractor: &XPubExtractor,
params: EnabledCoinBalanceParams,
) -> MmResult<EnableCoinBalance, EnableCoinBalanceError>
) -> MmResult<CoinBalanceReport, EnableCoinBalanceError>
where
XPubExtractor: HDXPubExtractor + Sync,
{
Expand All @@ -122,7 +181,7 @@ where
.compat()
.await
.map(|balance| {
EnableCoinBalance::Iguana(IguanaWalletBalance {
CoinBalanceReport::Iguana(IguanaWalletBalance {
address: my_address.to_string(),
balance,
})
Expand All @@ -131,7 +190,7 @@ where
DerivationMethod::HDWallet(hd_wallet) => self
.enable_hd_wallet(hd_wallet, xpub_extractor, params)
.await
.map(EnableCoinBalance::HD),
.map(CoinBalanceReport::HD),
}
}
}
Expand Down Expand Up @@ -164,6 +223,30 @@ pub trait HDWalletBalanceOps: HDWalletCoinOps {
gap_limit: u32,
) -> BalanceResult<Vec<HDAddressBalance>>;

/// Requests balances of every activated HD account.
async fn all_accounts_balances(&self, hd_wallet: &Self::HDWallet) -> BalanceResult<Vec<HDAccountBalance>> {
let accounts = hd_wallet.get_accounts().await;

let mut result = Vec::with_capacity(accounts.len());
for (_account_id, hd_account) in accounts {
let addresses = self.all_known_addresses_balances(&hd_account).await?;

let total_balance = addresses.iter().fold(CoinBalance::default(), |total, addr_balance| {
total + addr_balance.balance.clone()
});
let account_balance = HDAccountBalance {
account_index: hd_account.account_id(),
derivation_path: RpcDerivationPath(hd_account.account_derivation_path()),
total_balance,
addresses,
};

result.push(account_balance);
}

Ok(result)
}

/// Requests balances of every known addresses of the given `hd_account`.
async fn all_known_addresses_balances(&self, hd_account: &Self::HDAccount) -> BalanceResult<Vec<HDAddressBalance>>;

Expand Down
27 changes: 8 additions & 19 deletions mm2src/coins/eth/eth_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use common::block_on;
use mm2_core::mm_ctx::{MmArc, MmCtxBuilder};
use mocktopus::mocking::*;

const ETH_MAINNET_NODE: &str = "https://mainnet.infura.io/v3/c01c1b4cf66642528547624e1d6d9d6b";
/// The gas price for the tests
const GAS_PRICE: u64 = 50_000_000_000;
// `GAS_PRICE` increased by 3%
Expand Down Expand Up @@ -976,7 +977,7 @@ fn test_get_fee_to_send_taker_fee_insufficient_balance() {
platform: "ETH".to_string(),
token_addr: Address::from("0xaD22f63404f7305e4713CcBd4F296f34770513f4"),
},
vec!["http://eth1.cipig.net:8555".into()],
vec![ETH_MAINNET_NODE.into()],
None,
);
let dex_fee_amount = u256_to_big_decimal(DEX_FEE_AMOUNT.into(), 18).expect("!u256_to_big_decimal");
Expand All @@ -992,11 +993,7 @@ fn test_get_fee_to_send_taker_fee_insufficient_balance() {

#[test]
fn validate_dex_fee_invalid_sender_eth() {
let (_ctx, coin) = eth_coin_for_test(
EthCoinType::Eth,
vec!["https://mainnet.infura.io/v3/c01c1b4cf66642528547624e1d6d9d6b".into()],
None,
);
let (_ctx, coin) = eth_coin_for_test(EthCoinType::Eth, vec![ETH_MAINNET_NODE.into()], None);
// the real dex fee sent on mainnet
// https://etherscan.io/tx/0x7e9ca16c85efd04ee5e31f2c1914b48f5606d6f9ce96ecce8c96d47d6857278f
let tx = coin
Expand Down Expand Up @@ -1031,7 +1028,7 @@ fn validate_dex_fee_invalid_sender_erc() {
platform: "ETH".to_string(),
token_addr: "0xa1d6df714f91debf4e0802a542e13067f31b8262".into(),
},
vec!["http://eth1.cipig.net:8555".into()],
vec![ETH_MAINNET_NODE.into()],
None,
);
// the real dex fee sent on mainnet
Expand Down Expand Up @@ -1072,11 +1069,7 @@ fn sender_compressed_pub(tx: &SignedEthTx) -> [u8; 33] {

#[test]
fn validate_dex_fee_eth_confirmed_before_min_block() {
let (_ctx, coin) = eth_coin_for_test(
EthCoinType::Eth,
vec!["https://mainnet.infura.io/v3/c01c1b4cf66642528547624e1d6d9d6b".into()],
None,
);
let (_ctx, coin) = eth_coin_for_test(EthCoinType::Eth, vec![ETH_MAINNET_NODE.into()], None);
// the real dex fee sent on mainnet
// https://etherscan.io/tx/0x7e9ca16c85efd04ee5e31f2c1914b48f5606d6f9ce96ecce8c96d47d6857278f
let tx = coin
Expand Down Expand Up @@ -1113,7 +1106,7 @@ fn validate_dex_fee_erc_confirmed_before_min_block() {
platform: "ETH".to_string(),
token_addr: "0xa1d6df714f91debf4e0802a542e13067f31b8262".into(),
},
vec!["http://eth1.cipig.net:8555".into()],
vec![ETH_MAINNET_NODE.into()],
None,
);
// the real dex fee sent on mainnet
Expand Down Expand Up @@ -1148,7 +1141,7 @@ fn validate_dex_fee_erc_confirmed_before_min_block() {

#[test]
fn test_negotiate_swap_contract_addr_no_fallback() {
let (_, coin) = eth_coin_for_test(EthCoinType::Eth, vec!["http://eth1.cipig.net:8555".into()], None);
let (_, coin) = eth_coin_for_test(EthCoinType::Eth, vec![ETH_MAINNET_NODE.into()], None);

let input = None;
let error = coin.negotiate_swap_contract_addr(input).unwrap_err().into_inner();
Expand Down Expand Up @@ -1177,11 +1170,7 @@ fn test_negotiate_swap_contract_addr_no_fallback() {
fn test_negotiate_swap_contract_addr_has_fallback() {
let fallback = "0x8500AFc0bc5214728082163326C2FF0C73f4a871".into();

let (_, coin) = eth_coin_for_test(
EthCoinType::Eth,
vec!["http://eth1.cipig.net:8555".into()],
Some(fallback),
);
let (_, coin) = eth_coin_for_test(EthCoinType::Eth, vec![ETH_MAINNET_NODE.into()], Some(fallback));

let input = None;
let result = coin.negotiate_swap_contract_addr(input).unwrap();
Expand Down
131 changes: 131 additions & 0 deletions mm2src/coins/for_tests/MORTY_HD_tx_history_fixtures.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
[
{
"tx_hex": "0400008085202f890189cb3d4e9d36a7c2c6bb1b76dcfc1ee7c9d3d83b364c50a3f3a791c5efb6f392030000006b483045022100a0b910ecbf5ed1c473507c3e1a5a06ad612c982d3204d2dc066bfbbeb39c5e400220559a82d151cbcdcb097786127f499863e0864662519a9caf758c929f1659bc34012102d09f2cb1693be9c0ea73bb48d45ce61805edd1c43590681b02f877206078a5b3ffffffff0400e1f505000000001976a914ab19b1f2bd2337a58c1b5d198468951ac42d796788ac00c2eb0b000000001976a914ab19b1f2bd2337a58c1b5d198468951ac42d796788aca01f791c000000001976a914ab19b1f2bd2337a58c1b5d198468951ac42d796788ac3091cce2e80000001976a91490a0d8ba62c339ade97a14e81b6f531de03fdbb288ac00000000000000000000000000000000000000",
"tx_hash": "6ca27dd058b939c98a33625b9f68eaeebca5a3058aec062647ca6fd7634bb339",
"from": [
"RNTv4xTLLm26p3SvsQCBy9qNK7s1RgGYSB"
],
"to": [
"RNTv4xTLLm26p3SvsQCBy9qNK7s1RgGYSB",
"RQstQeTUEZLh6c3YWJDkeVTTQoZUsfvNCr"
],
"total_amount": "10010.1518",
"spent_by_me": "0",
"received_by_me": "7.777",
"my_balance_change": "7.777",
"block_height": 1629306,
"timestamp": 1663619097,
"fee_details": {
"type": "Utxo",
"coin": "MORTY",
"amount": "0.0001"
},
"coin": "MORTY",
"internal_id": "6ca27dd058b939c98a33625b9f68eaeebca5a3058aec062647ca6fd7634bb339",
"transaction_type": "StandardTransfer",
"confirmations": 4
},
{
"tx_hex": "0400008085202f89011b8746195a7e80172d948e1eb7f2d6710bd2ecbe7750e653bb8d345b940da55b030000006a4730440220482c7a7762977ed3a8afcf751b7413d5ef978f604e550eb4fd35199e1f4d52400220486fb4f3831a7f512dba1271a4f793e7050ea123bcb4922e3848bb18c7cac4c4012102d09f2cb1693be9c0ea73bb48d45ce61805edd1c43590681b02f877206078a5b3ffffffff0400e1f505000000001976a914bd658bdd369c8bb98ac837071639819e5f8dd3cb88ac00c2eb0b000000001976a914bd658bdd369c8bb98ac837071639819e5f8dd3cb88aca01f791c000000001976a914bd658bdd369c8bb98ac837071639819e5f8dd3cb88acf037389ce90000001976a91490a0d8ba62c339ade97a14e81b6f531de03fdbb288ac00000000000000000000000000000000000000",
"tx_hash": "70c62f42d65f9d71a8fb7f4560057b80dc2ecd9e4990621323faf1de9a53ca97",
"from": [
"RNTv4xTLLm26p3SvsQCBy9qNK7s1RgGYSB"
],
"to": [
"RNTv4xTLLm26p3SvsQCBy9qNK7s1RgGYSB",
"RSYdSLRYWuzBson2GDbWBa632q2PmFnCaH"
],
"total_amount": "10041.2602",
"spent_by_me": "0",
"received_by_me": "7.777",
"my_balance_change": "7.777",
"block_height": 1617702,
"timestamp": 1662914954,
"fee_details": {
"type": "Utxo",
"coin": "MORTY",
"amount": "0.0001"
},
"coin": "MORTY",
"internal_id": "70c62f42d65f9d71a8fb7f4560057b80dc2ecd9e4990621323faf1de9a53ca97",
"transaction_type": "StandardTransfer",
"confirmations": 11603
},
{
"tx_hex": "0400008085202f890175fb4250e95dc0c89cd89a9487324aa8dd7a2f8fd8581fc90881567ca6be02bf000000006b483045022100be3e58c5d4dbe5ea35ab831d610b42bb1ae01fc0df1786f11cbe6969d8d45c6302207b8747b4012a6c4aefecf670eaf8d787445909ebd7775b85c77d723e9d6445a8012103f7f831c6fbe62b987e4b2f455e5b7f27375cf59b57eb3ffa9e122b2c9b395f6bffffffff0200e1f505000000001976a914c23136f831b15dd4522eb1c6eb4c5cd3abbfbe3b88aca8b66428000000001976a914bd658bdd369c8bb98ac837071639819e5f8dd3cb88ac00000000000000000000000000000000000000",
"tx_hash": "bd031dc681cdc63491fd71902c5960985127b04eb02211a1049bff0d0c8ebce3",
"from": [
"RPj9JXUVnewWwVpxZDeqGB25qVqz5qJzwP"
],
"to": [
"RSYdSLRYWuzBson2GDbWBa632q2PmFnCaH",
"RSyz8EJaTzhkT6uZinAtHhFu5bfsvqcLqg"
],
"total_amount": "7.77699",
"spent_by_me": "7.77699",
"received_by_me": "6.77689",
"my_balance_change": "-1.00010",
"block_height": 1499070,
"timestamp": 1655738171,
"fee_details": {
"type": "Utxo",
"coin": "MORTY",
"amount": "0.0001"
},
"coin": "MORTY",
"internal_id": "bd031dc681cdc63491fd71902c5960985127b04eb02211a1049bff0d0c8ebce3",
"transaction_type": "StandardTransfer",
"confirmations": 130235
},
{
"tx_hex": "0400008085202f89038dea273bcc9194a80b19ea1a8ca076d3d00c590b4571808f10f3eee5aa38c07d000000006b483045022100ff31b7c36145dc9fa06346fe38b75b81273b41b7d236b900322154ba136799bb02204ddd253eb93e95c9d24f8e36a8a5a42022c63d6edd81c453f24cbb5db785037d012102d6a78b71b10459bd0757a614ca1eef62f4a65514225d10e95df31ee9cb23ffd5ffffffff8dea273bcc9194a80b19ea1a8ca076d3d00c590b4571808f10f3eee5aa38c07d010000006a47304402202d3e0fd3ce7b4753725adc0175a050c919f93b564682ffd8d65974c15996b3560220211b8120acb3ad80dbdd9160f639884f0e15c0c5703c86c069b3abe85cb6c4fd012102d6a78b71b10459bd0757a614ca1eef62f4a65514225d10e95df31ee9cb23ffd5ffffffff8dea273bcc9194a80b19ea1a8ca076d3d00c590b4571808f10f3eee5aa38c07d020000006b483045022100c788b064db34e961479393bad19d8c5f7d437b02c64c3172381fbe2b7d104efd022027167b2e5a6f29a7567e43b39a3d5b8f50c20767162ec29328067a6fcbd87409012102d6a78b71b10459bd0757a614ca1eef62f4a65514225d10e95df31ee9cb23ffd5ffffffff01b8be5a2e000000001976a9149e7a424abb2f341d655ce6af1143409edef4d55588acbdb1d661000000000000000000000000000000",
"tx_hash": "bf02bea67c568108c91f58d88f2f7adda84a3287949ad89cc8c05de95042fb75",
"from": [
"RYM6yDMn8vdqtkYKLzY5dNe7p3T6YmMWvq"
],
"to": [
"RPj9JXUVnewWwVpxZDeqGB25qVqz5qJzwP"
],
"total_amount": "7.777",
"spent_by_me": "7.777",
"received_by_me": "7.77699",
"my_balance_change": "-0.00001",
"block_height": 1263905,
"timestamp": 1641460263,
"fee_details": {
"type": "Utxo",
"coin": "MORTY",
"amount": "0.00001"
},
"coin": "MORTY",
"internal_id": "bf02bea67c568108c91f58d88f2f7adda84a3287949ad89cc8c05de95042fb75",
"transaction_type": "StandardTransfer",
"confirmations": 365400
},
{
"tx_hex": "0400008085202f8901fe0ccc272929c811b20ab910f5478a99229a5304480b5897cf9507149a044c63030000006b483045022100c5b24fbd1ce11736760ebc0edccad6bde2dcbbff090528db4602a485a5ec645f02201340e5f818b9d7ab75e39abaacaa5d94c03fdb8e41698182eeff389a45c5ad15012102d09f2cb1693be9c0ea73bb48d45ce61805edd1c43590681b02f877206078a5b3ffffffff0400e1f505000000001976a914fd084ad97ae0313bba5717acedfba629b8bd426988ac00c2eb0b000000001976a914fd084ad97ae0313bba5717acedfba629b8bd426988aca01f791c000000001976a914fd084ad97ae0313bba5717acedfba629b8bd426988ac40053045260100001976a91490a0d8ba62c339ade97a14e81b6f531de03fdbb288ac00000000000000000000000000000000000000",
"tx_hash": "7dc038aae5eef3108f8071450b590cd0d376a08c1aea190ba89491cc3b27ea8d",
"from": [
"RNTv4xTLLm26p3SvsQCBy9qNK7s1RgGYSB"
],
"to": [
"RNTv4xTLLm26p3SvsQCBy9qNK7s1RgGYSB",
"RYM6yDMn8vdqtkYKLzY5dNe7p3T6YmMWvq"
],
"total_amount": "12646.5887",
"spent_by_me": "0",
"received_by_me": "7.777",
"my_balance_change": "7.777",
"block_height": 1263875,
"timestamp": 1641458818,
"fee_details": {
"type": "Utxo",
"coin": "MORTY",
"amount": "0.0001"
},
"coin": "MORTY",
"internal_id": "7dc038aae5eef3108f8071450b590cd0d376a08c1aea190ba89491cc3b27ea8d",
"transaction_type": "StandardTransfer",
"confirmations": 365430
}
]
Loading

0 comments on commit 56aac96

Please sign in to comment.