Skip to content

Commit

Permalink
fix review notes
Browse files Browse the repository at this point in the history
Signed-off-by: ozkanonur <work@onurozkan.dev>
  • Loading branch information
onur-ozkan committed Dec 2, 2022
1 parent e5308d9 commit 2b95017
Show file tree
Hide file tree
Showing 26 changed files with 772 additions and 392 deletions.
16 changes: 8 additions & 8 deletions mm2src/coins/lp_coins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,8 @@ use rpc_command::{init_account_balance::{AccountBalanceTaskManager, AccountBalan
init_withdraw::{WithdrawTaskManager, WithdrawTaskManagerShared}};

pub mod tendermint;
use tendermint::{CosmosTransaction, TendermintCoin, TendermintFeeDetails, TendermintProtocolInfo, TendermintToken,
TendermintTokenProtocolInfo};
use tendermint::{CosmosTransaction, CustomTendermintMsgType, TendermintCoin, TendermintFeeDetails,
TendermintProtocolInfo, TendermintToken, TendermintTokenProtocolInfo};

#[doc(hidden)]
#[allow(unused_variables)]
Expand Down Expand Up @@ -1036,17 +1036,17 @@ impl KmdRewardsDetails {
}
}

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[derive(Default, Clone, Debug, Deserialize, PartialEq, Serialize)]
pub enum TransactionType {
StakingDelegation,
RemoveDelegation,
#[default]
StandardTransfer,
TokenTransfer(BytesJson),
Fee(BytesJson),
}

impl Default for TransactionType {
fn default() -> Self { TransactionType::StandardTransfer }
CustomTendermintMsg {
msg_type: CustomTendermintMsgType,
token_id: Option<BytesJson>,
},
}

/// Transaction details
Expand Down
140 changes: 88 additions & 52 deletions mm2src/coins/my_tx_history_v2.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::hd_wallet::{AddressDerivingError, InvalidBip44ChainError};
use crate::tendermint::{TENDERMINT_ASSET_PROTOCOL_TYPE, TENDERMINT_COIN_PROTOCOL_TYPE};
use crate::tendermint::{CustomTendermintMsgType, TENDERMINT_ASSET_PROTOCOL_TYPE, TENDERMINT_COIN_PROTOCOL_TYPE};
use crate::tx_history_storage::{CreateTxHistoryStorageError, FilteringAddresses, GetTxHistoryFilters,
TxHistoryStorageBuilder, WalletId};
use crate::utxo::utxo_common::big_decimal_from_sat_unsigned;
Expand All @@ -18,7 +18,6 @@ use mm2_number::BigDecimal;
use num_traits::ToPrimitive;
use rpc::v1::types::{Bytes as BytesJson, ToTxHash};
use std::collections::HashSet;
use std::mem::discriminant;

#[derive(Debug)]
pub enum RemoveTxResult {
Expand Down Expand Up @@ -217,11 +216,20 @@ impl<'a, Addr: Clone + DisplayAddress + Eq + std::hash::Hash, Tx: Transaction> T

let tx_hash = self.tx.tx_hash();
let internal_id = match &self.transaction_type {
TransactionType::TokenTransfer(token_id) | TransactionType::Fee(token_id) => {
TransactionType::TokenTransfer(token_id) => {
let mut bytes_for_hash = tx_hash.0.clone();
bytes_for_hash.extend_from_slice(&token_id.0);
sha256(&bytes_for_hash).to_vec().into()
},
TransactionType::CustomTendermintMsg { token_id, .. } => {
if let Some(token_id) = token_id {
let mut bytes_for_hash = tx_hash.0.clone();
bytes_for_hash.extend_from_slice(&token_id.0);
sha256(&bytes_for_hash).to_vec().into()
} else {
tx_hash.clone()
}
},
TransactionType::StakingDelegation
| TransactionType::RemoveDelegation
| TransactionType::StandardTransfer => tx_hash.clone(),
Expand Down Expand Up @@ -419,58 +427,86 @@ where
let protocol_type = coin_conf["protocol"]["type"].as_str().unwrap_or_default();
let decimals = coin.decimals();

let transactions =
history
.transactions
.into_iter()
.map(|mut details| {
// checking if transaction type is not `Fee`
if discriminant(&details.transaction_type) != discriminant(&TransactionType::Fee(BytesJson::default()))
{
// it can be the platform ticker instead of the token ticker for a pre-saved record
if details.coin != request.coin {
details.coin = request.coin.clone();
let transactions = history
.transactions
.into_iter()
.map(|mut details| {
// it can be the platform ticker instead of the token ticker for a pre-saved record
if details.coin != request.coin {
details.coin = request.coin.clone();
}

// TODO
// !! temporary solution !!
// Tendermint specific mapping
match protocol_type {
TENDERMINT_COIN_PROTOCOL_TYPE | TENDERMINT_ASSET_PROTOCOL_TYPE => {
// TODO
// see this https://github.com/KomodoPlatform/atomicDEX-API/pull/1526#discussion_r1037001780
if let Some(TxFeeDetails::Utxo(fee)) = &mut details.fee_details {
let mapped_fee = crate::tendermint::TendermintFeeDetails {
// We make sure this is filled in `tendermint_tx_history_v2`
coin: fee.coin.as_ref().expect("can't be empty").to_owned(),
amount: fee.amount.clone(),
gas_limit: crate::tendermint::GAS_LIMIT_DEFAULT,
// ignored anyway
uamount: 0,
};
details.fee_details = Some(TxFeeDetails::Tendermint(mapped_fee));
}

match protocol_type {
// for tendermint, tx_history_v2 implementation doesn't include amount parsing logic.
// therefore, re-mapping is required
TENDERMINT_COIN_PROTOCOL_TYPE | TENDERMINT_ASSET_PROTOCOL_TYPE => {
// In order to use error result instead of panicking, we should do an extra iteration above this map.
// Because all the values are inserted by u64 convertion in tx_history_v2 implementation, using `panic`
// shouldn't harm.

let u_total_amount = details.total_amount.to_u64().unwrap_or_else(|| {
panic!("Parsing '{}' into u64 should not fail", details.total_amount)
});
details.total_amount = big_decimal_from_sat_unsigned(u_total_amount, decimals);

let u_spent_by_me = details.spent_by_me.to_u64().unwrap_or_else(|| {
panic!("Parsing '{}' into u64 should not fail", details.spent_by_me)
});
details.spent_by_me = big_decimal_from_sat_unsigned(u_spent_by_me, decimals);

let u_received_by_me = details.received_by_me.to_u64().unwrap_or_else(|| {
panic!("Parsing '{}' into u64 should not fail", details.received_by_me)
});
details.received_by_me = big_decimal_from_sat_unsigned(u_received_by_me, decimals);

// Because this can be negative values, no need to read and parse
// this since it's always 0 from tx_history_v2 implementation.
details.my_balance_change = &details.received_by_me - &details.spent_by_me;
match &details.transaction_type {
// By-passed when `CustomTendermintMsg` is `FeeForTokenTx`
TransactionType::CustomTendermintMsg { msg_type, .. }
if matches!(msg_type, CustomTendermintMsgType::FeeForTokenTx) => {},
TransactionType::StakingDelegation
| TransactionType::RemoveDelegation
| TransactionType::StandardTransfer
| TransactionType::TokenTransfer(_)
| TransactionType::CustomTendermintMsg { .. } => {
match protocol_type {
// for tendermint, tx_history_v2 implementation doesn't include amount parsing logic.
// therefore, re-mapping is required
TENDERMINT_COIN_PROTOCOL_TYPE | TENDERMINT_ASSET_PROTOCOL_TYPE => {
// In order to use error result instead of panicking, we should do an extra iteration above this map.
// Because all the values are inserted by u64 convertion in tx_history_v2 implementation, using `panic`
// shouldn't harm.

let u_total_amount = details.total_amount.to_u64().unwrap_or_else(|| {
panic!("Parsing '{}' into u64 should not fail", details.total_amount)
});
details.total_amount = big_decimal_from_sat_unsigned(u_total_amount, decimals);

let u_spent_by_me = details.spent_by_me.to_u64().unwrap_or_else(|| {
panic!("Parsing '{}' into u64 should not fail", details.spent_by_me)
});
details.spent_by_me = big_decimal_from_sat_unsigned(u_spent_by_me, decimals);

let u_received_by_me = details.received_by_me.to_u64().unwrap_or_else(|| {
panic!("Parsing '{}' into u64 should not fail", details.received_by_me)
});
details.received_by_me = big_decimal_from_sat_unsigned(u_received_by_me, decimals);

// Because this can be negative values, no need to read and parse
// this since it's always 0 from tx_history_v2 implementation.
details.my_balance_change = &details.received_by_me - &details.spent_by_me;
},
_ => {},
};
},
_ => {},
};
}

let confirmations = if details.block_height == 0 || details.block_height > current_block {
0
} else {
current_block + 1 - details.block_height
};
MyTxHistoryDetails { confirmations, details }
})
.collect();
}
},
_ => {},
};

let confirmations = if details.block_height == 0 || details.block_height > current_block {
0
} else {
current_block + 1 - details.block_height
};
MyTxHistoryDetails { confirmations, details }
})
.collect();

Ok(MyTxHistoryResponseV2 {
coin: request.coin,
Expand Down
12 changes: 12 additions & 0 deletions mm2src/coins/tendermint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,18 @@ pub mod tendermint_tx_history_v2;
pub use tendermint_coin::*;
pub use tendermint_token::*;

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub enum CustomTendermintMsgType {
/// Create HTLC as sender
SendHtlcAmount,
/// Claim HTLC as reciever
ClaimHtlcAmount,
/// Claim HTLC for reciever
SignClaimHtlc,
/// Extra tx display for token txs (because cosmos uses platform coin for paying fees)
FeeForTokenTx,
}

pub(crate) const TENDERMINT_COIN_PROTOCOL_TYPE: &str = "TENDERMINT";
pub(crate) const TENDERMINT_ASSET_PROTOCOL_TYPE: &str = "TENDERMINTTOKEN";

Expand Down
2 changes: 1 addition & 1 deletion mm2src/coins/tendermint/rpc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ pub(crate) const TX_SUCCESS_CODE: u32 = 0;

#[repr(u8)]
pub enum TendermintResultOrder {
Ascending = 0,
Ascending = 1,
Descending,
}

Expand Down
108 changes: 69 additions & 39 deletions mm2src/coins/tendermint/tendermint_coin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,19 @@ pub(crate) const TX_DEFAULT_MEMO: &str = "";
const MAX_TIME_LOCK: i64 = 34560;
const MIN_TIME_LOCK: i64 = 50;

#[async_trait]
pub trait TendermintCommons {
fn platform_denom(&self) -> String;

fn set_history_sync_state(&self, new_state: HistorySyncState);

async fn get_block_timestamp(&self, block: i64) -> MmResult<Option<u64>, TendermintCoinRpcError>;

async fn all_balances(&self) -> MmResult<AllBalancesResult, TendermintCoinRpcError>;

async fn rpc_client(&self) -> MmResult<HttpClient, TendermintCoinRpcError>;
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct TendermintFeeDetails {
pub coin: String,
Expand Down Expand Up @@ -332,6 +345,62 @@ impl From<DecodeError> for SearchForSwapTxSpendErr {
fn from(e: DecodeError) -> Self { SearchForSwapTxSpendErr::Proto(e) }
}

#[async_trait]
impl TendermintCommons for TendermintCoin {
fn platform_denom(&self) -> String { self.denom.to_string() }

fn set_history_sync_state(&self, new_state: HistorySyncState) {
*self.history_sync_state.lock().unwrap() = new_state;
}

async fn get_block_timestamp(&self, block: i64) -> MmResult<Option<u64>, TendermintCoinRpcError> {
let block_response = self.get_block_by_height(block).await?;
let block_header = some_or_return_ok_none!(some_or_return_ok_none!(block_response.block).header);
let timestamp = some_or_return_ok_none!(block_header.time);

Ok(u64::try_from(timestamp.seconds).ok())
}

async fn all_balances(&self) -> MmResult<AllBalancesResult, TendermintCoinRpcError> {
let platform_balance_denom = self.balance_for_denom(self.denom.to_string()).await?;
let platform_balance = big_decimal_from_sat_unsigned(platform_balance_denom, self.decimals);
let ibc_assets_info = self.tokens_info.lock().clone();

let mut result = AllBalancesResult {
platform_balance,
tokens_balances: HashMap::new(),
};
for (ticker, info) in ibc_assets_info {
let balance_denom = self.balance_for_denom(info.denom.to_string()).await?;
let balance_decimal = big_decimal_from_sat_unsigned(balance_denom, info.decimals);
result.tokens_balances.insert(ticker, balance_decimal);
}

Ok(result)
}

// TODO
// Save one working client to the coin context, only try others once it doesn't
// work anymore.
// Also, try couple times more on health check errors.
async fn rpc_client(&self) -> MmResult<HttpClient, TendermintCoinRpcError> {
for rpc_client in self.rpc_clients.iter() {
match rpc_client.perform(HealthRequest).timeout(Duration::from_secs(3)).await {
Ok(Ok(_)) => return Ok(rpc_client.clone()),
Ok(Err(e)) => log::warn!(
"Recieved error from Tendermint rpc node during health check. Error: {:?}",
e
),
Err(_) => log::warn!("Tendermint rpc node: {:?} got timeout during health check", rpc_client),
};
}

MmError::err(TendermintCoinRpcError::PerformError(
"All the current rpc nodes are unavailable.".to_string(),
))
}
}

impl TendermintCoin {
pub async fn init(
ctx: &MmArc,
Expand Down Expand Up @@ -415,27 +484,6 @@ impl TendermintCoin {
})))
}

// TODO
// Save one working client to the coin context, only try others once it doesn't
// work anymore.
// Also, try couple times more on health check errors.
pub(crate) async fn rpc_client(&self) -> MmResult<HttpClient, TendermintCoinRpcError> {
for rpc_client in self.rpc_clients.iter() {
match rpc_client.perform(HealthRequest).timeout(Duration::from_secs(3)).await {
Ok(Ok(_)) => return Ok(rpc_client.clone()),
Ok(Err(e)) => log::warn!(
"Recieved error from Tendermint rpc node during health check. Error: {:?}",
e
),
Err(_) => log::warn!("Tendermint rpc node: {:?} got timeout during health check", rpc_client),
};
}

MmError::err(TendermintCoinRpcError::PerformError(
"All the current rpc nodes are unavailable.".to_string(),
))
}

#[inline(always)]
fn gas_price(&self) -> f64 { self.gas_price.unwrap_or(DEFAULT_GAS_PRICE) }

Expand Down Expand Up @@ -628,24 +676,6 @@ impl TendermintCoin {
.map_to_mm(|e| TendermintCoinRpcError::InvalidResponse(format!("balance is not u64, err {}", e)))
}

pub async fn all_balances(&self) -> MmResult<AllBalancesResult, TendermintCoinRpcError> {
let platform_balance_denom = self.balance_for_denom(self.denom.to_string()).await?;
let platform_balance = big_decimal_from_sat_unsigned(platform_balance_denom, self.decimals);
let ibc_assets_info = self.tokens_info.lock().clone();

let mut result = AllBalancesResult {
platform_balance,
tokens_balances: HashMap::new(),
};
for (ticker, info) in ibc_assets_info {
let balance_denom = self.balance_for_denom(info.denom.to_string()).await?;
let balance_decimal = big_decimal_from_sat_unsigned(balance_denom, info.decimals);
result.tokens_balances.insert(ticker, balance_decimal);
}

Ok(result)
}

fn gen_create_htlc_tx(
&self,
denom: Denom,
Expand Down
Loading

0 comments on commit 2b95017

Please sign in to comment.