Skip to content

Commit

Permalink
Tendermint missing implementations #1432 (#1526)
Browse files Browse the repository at this point in the history
* increase simulated gas to predict better values for real tx operations

Signed-off-by: Onur Özkan <work@onurozkan.dev>

* remove couple TODO notes and impelement `lp_coins::wait_for_confirmations` for tendermint

Signed-off-by: Onur Özkan <work@onurozkan.dev>

* create new fn `tendermint_coin::get_tx_status_code_or_none`

Signed-off-by: Onur Özkan <work@onurozkan.dev>

* if no `gui_auth` was given, consider it as `false`

Signed-off-by: ozkanonur <work@onurozkan.dev>

* implement `get_sender_trade_fee`

Signed-off-by: ozkanonur <work@onurozkan.dev>

* implement `trade_fee` functionalities for cosmos

Signed-off-by: ozkanonur <work@onurozkan.dev>

* group wasm and native rpcs under the rpc mod

Signed-off-by: ozkanonur <work@onurozkan.dev>

* Create TendermintResultOrder and impl it's required traits

Signed-off-by: ozkanonur <work@onurozkan.dev>

* fix wasm compilation

Signed-off-by: ozkanonur <work@onurozkan.dev>

* fix avg_blocktime confusion

Signed-off-by: ozkanonur <work@onurozkan.dev>

* save dev state

Signed-off-by: ozkanonur <work@onurozkan.dev>

* save dev state

Signed-off-by: ozkanonur <work@onurozkan.dev>

* save dev state

Signed-off-by: ozkanonur <work@onurozkan.dev>

* add iris mod

Signed-off-by: ozkanonur <work@onurozkan.dev>

* fix wasm compilation

Signed-off-by: ozkanonur <work@onurozkan.dev>

* save dev state

Signed-off-by: ozkanonur <work@onurozkan.dev>

* save dev state

Signed-off-by: ozkanonur <work@onurozkan.dev>

* add TODO notes

Signed-off-by: ozkanonur <work@onurozkan.dev>

* add TODO note

Signed-off-by: ozkanonur <work@onurozkan.dev>

* avoid memory pressure, skip existed txs in tx_history, add fee_details

Signed-off-by: ozkanonur <work@onurozkan.dev>

* remove no-longer required notes

Signed-off-by: ozkanonur <work@onurozkan.dev>

* save dev state

Signed-off-by: ozkanonur <work@onurozkan.dev>

* implement `WaitForHistoryUpdateTrigger` for tendermint tx_history v2

Signed-off-by: ozkanonur <work@onurozkan.dev>

* remove not required todo notes

Signed-off-by: ozkanonur <work@onurozkan.dev>

* update `fn process_history_loop`

Signed-off-by: ozkanonur <work@onurozkan.dev>

* update TODO notes of tendermint_token

Signed-off-by: ozkanonur <work@onurozkan.dev>

* save dev state

Signed-off-by: ozkanonur <work@onurozkan.dev>

* complete tx_history_v2 functionality for tendermint

Signed-off-by: ozkanonur <work@onurozkan.dev>

* move token insert to right before of result returning

Signed-off-by: ozkanonur <work@onurozkan.dev>

* implement better error handling for tx_history v2 on tendermint

Signed-off-by: ozkanonur <work@onurozkan.dev>

* shorten `fn is_tx_exists`

Signed-off-by: ozkanonur <work@onurozkan.dev>

* rename `iris_swap_poc` into `iris_swap` remove ingored flag from the test

Signed-off-by: ozkanonur <work@onurozkan.dev>

* update name of the iris swap test function

Signed-off-by: ozkanonur <work@onurozkan.dev>

* re-ignore iris swap integration tests because of iris bug

Signed-off-by: ozkanonur <work@onurozkan.dev>

* fix review notes

Signed-off-by: ozkanonur <work@onurozkan.dev>

* show extra tx for platform fees on token txs

Signed-off-by: ozkanonur <work@onurozkan.dev>

* partial fixes for review notes

Signed-off-by: ozkanonur <work@onurozkan.dev>

* update expected log for tendermint tx history test

Signed-off-by: ozkanonur <work@onurozkan.dev>

* read highest height for tendermint history

Signed-off-by: ozkanonur <work@onurozkan.dev>

* remap tx amounts and insert all possible assets for tendermint

Signed-off-by: ozkanonur <work@onurozkan.dev>

* fix balance problem

Signed-off-by: ozkanonur <work@onurozkan.dev>

* skip `uamount` field for `TendermintFeeDetails`

Signed-off-by: ozkanonur <work@onurozkan.dev>

* parse multiple tx events

Signed-off-by: ozkanonur <work@onurozkan.dev>

* save dev state

Signed-off-by: ozkanonur <work@onurozkan.dev>

* remove debug lines

Signed-off-by: ozkanonur <work@onurozkan.dev>

* refactor tendermit tx history test

Signed-off-by: ozkanonur <work@onurozkan.dev>

* fix review notes

Signed-off-by: ozkanonur <work@onurozkan.dev>

Signed-off-by: Onur Özkan <work@onurozkan.dev>
Signed-off-by: ozkanonur <work@onurozkan.dev>
  • Loading branch information
onur-ozkan committed Dec 4, 2022
1 parent 1f30ec7 commit 15ff4c5
Show file tree
Hide file tree
Showing 56 changed files with 2,527 additions and 323 deletions.
2 changes: 1 addition & 1 deletion mm2src/coins/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3258,7 +3258,7 @@ impl MmCoin for EthCoin {
})
}

fn get_receiver_trade_fee(&self, stage: FeeApproxStage) -> TradePreimageFut<TradeFee> {
fn get_receiver_trade_fee(&self, _send_amount: BigDecimal, stage: FeeApproxStage) -> TradePreimageFut<TradeFee> {
let coin = self.clone();
let fut = async move {
let gas_price = coin.get_gas_price().compat().await?;
Expand Down
2 changes: 1 addition & 1 deletion mm2src/coins/eth/eth_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -932,7 +932,7 @@ fn get_receiver_trade_preimage() {
};

let actual = coin
.get_receiver_trade_fee(FeeApproxStage::WithoutApprox)
.get_receiver_trade_fee(Default::default(), FeeApproxStage::WithoutApprox)
.wait()
.expect("!get_sender_trade_fee");
assert_eq!(actual, expected_fee);
Expand Down
2 changes: 1 addition & 1 deletion mm2src/coins/lightning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1056,7 +1056,7 @@ impl MmCoin for LightningCoin {
}

// Todo: This uses dummy data for now for the sake of swap P.O.C., this should be implemented probably after agreeing on how fees will work for lightning
fn get_receiver_trade_fee(&self, _stage: FeeApproxStage) -> TradePreimageFut<TradeFee> {
fn get_receiver_trade_fee(&self, _send_amount: BigDecimal, _stage: FeeApproxStage) -> TradePreimageFut<TradeFee> {
Box::new(futures01::future::ok(TradeFee {
coin: self.ticker().to_owned(),
amount: Default::default(),
Expand Down
18 changes: 10 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,16 +1036,18 @@ impl KmdRewardsDetails {
}
}

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

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

/// Transaction details
Expand Down Expand Up @@ -1908,7 +1910,7 @@ pub trait MmCoin: SwapOps + WatcherOps + MarketCoinOps + Send + Sync + 'static {
) -> TradePreimageResult<TradeFee>;

/// Get fee to be paid by receiver per whole swap and check if the wallet has sufficient balance to pay the fee.
fn get_receiver_trade_fee(&self, stage: FeeApproxStage) -> TradePreimageFut<TradeFee>;
fn get_receiver_trade_fee(&self, send_amount: BigDecimal, stage: FeeApproxStage) -> TradePreimageFut<TradeFee>;

/// Get transaction fee the Taker has to pay to send a `TakerFee` transaction and check if the wallet has sufficient balance to pay the fee.
async fn get_fee_to_send_taker_fee(
Expand Down
79 changes: 77 additions & 2 deletions mm2src/coins/my_tx_history_v2.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use crate::hd_wallet::{AddressDerivingError, InvalidBip44ChainError};
use crate::tendermint::{TENDERMINT_ASSET_PROTOCOL_TYPE, TENDERMINT_COIN_PROTOCOL_TYPE};
use crate::tx_history_storage::{CreateTxHistoryStorageError, FilteringAddresses, GetTxHistoryFilters,
TxHistoryStorageBuilder, WalletId};
use crate::{lp_coinfind_or_err, BlockHeightAndTime, CoinFindError, HDAccountAddressId, HistorySyncState, MmCoin,
MmCoinEnum, Transaction, TransactionDetails, TransactionType, TxFeeDetails, UtxoRpcError};
use crate::utxo::utxo_common::big_decimal_from_sat_unsigned;
use crate::{coin_conf, lp_coinfind_or_err, BlockHeightAndTime, CoinFindError, HDAccountAddressId, HistorySyncState,
MmCoin, MmCoinEnum, Transaction, TransactionDetails, TransactionType, TxFeeDetails, UtxoRpcError};
use async_trait::async_trait;
use bitcrypto::sha256;
use common::{calc_total_pages, ten, HttpStatusCode, PagingOptionsEnum, StatusCode};
Expand All @@ -13,6 +15,7 @@ use keys::{Address, CashAddress};
use mm2_core::mm_ctx::MmArc;
use mm2_err_handle::prelude::*;
use mm2_number::BigDecimal;
use num_traits::ToPrimitive;
use rpc::v1::types::{Bytes as BytesJson, ToTxHash};
use std::collections::HashSet;

Expand Down Expand Up @@ -69,6 +72,9 @@ pub trait TxHistoryStorage: Send + Sync + 'static {
internal_id: &BytesJson,
) -> Result<Option<TransactionDetails>, MmError<Self::Error>>;

/// Gets the highest block_height from the selected wallet's history
async fn get_highest_block_height(&self, wallet_id: &WalletId) -> Result<Option<u32>, MmError<Self::Error>>;

/// Returns whether the history contains unconfirmed transactions.
async fn history_contains_unconfirmed_txes(
&self,
Expand Down Expand Up @@ -215,8 +221,18 @@ impl<'a, Addr: Clone + DisplayAddress + Eq + std::hash::Hash, Tx: Transaction> T
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::FeeForTokenTx
| TransactionType::StandardTransfer => tx_hash.clone(),
};

Expand Down Expand Up @@ -375,6 +391,8 @@ pub async fn my_tx_history_v2_rpc(
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,
MmCoinEnum::QtumCoin(qtum) => my_tx_history_v2_impl(ctx, &qtum, request).await,
MmCoinEnum::Tendermint(tendermint) => my_tx_history_v2_impl(ctx, &tendermint, request).await,
MmCoinEnum::TendermintToken(tendermint_token) => my_tx_history_v2_impl(ctx, &tendermint_token, request).await,
other => MmError::err(MyTxHistoryErrorV2::NotSupportedFor(other.ticker().to_owned())),
}
}
Expand Down Expand Up @@ -406,6 +424,10 @@ where
.get_history(&wallet_id, filters, request.paging_options.clone(), request.limit)
.await?;

let coin_conf = coin_conf(&ctx, coin.ticker());
let protocol_type = coin_conf["protocol"]["type"].as_str().unwrap_or_default();
let decimals = coin.decimals();

let transactions = history
.transactions
.into_iter()
Expand All @@ -414,6 +436,59 @@ where
if details.coin != request.coin {
details.coin = request.coin.clone();
}

// TODO
// !! temporary solution !!
// for tendermint, tx_history_v2 implementation doesn't include amount parsing logic.
// therefore, re-mapping is required
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 &details.transaction_type {
// Amount mappings are by-passed when `TransactionType` is `FeeForTokenTx`
TransactionType::FeeForTokenTx => {},
_ => {
// 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 {
Expand Down
2 changes: 1 addition & 1 deletion mm2src/coins/qrc20.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1316,7 +1316,7 @@ impl MmCoin for Qrc20Coin {
})
}

fn get_receiver_trade_fee(&self, stage: FeeApproxStage) -> TradePreimageFut<TradeFee> {
fn get_receiver_trade_fee(&self, _send_amount: BigDecimal, stage: FeeApproxStage) -> TradePreimageFut<TradeFee> {
let selfi = self.clone();
let fut = async move {
// pass the dummy params
Expand Down
2 changes: 1 addition & 1 deletion mm2src/coins/qrc20/qrc20_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -876,7 +876,7 @@ fn test_receiver_trade_preimage() {
check_tx_fee(&coin, ActualTxFee::FixedPerKb(EXPECTED_TX_FEE as u64));

let actual = coin
.get_receiver_trade_fee(FeeApproxStage::WithoutApprox)
.get_receiver_trade_fee(Default::default(), FeeApproxStage::WithoutApprox)
.wait()
.expect("!get_receiver_trade_fee");
// only one contract call should be included into the expected trade fee
Expand Down
12 changes: 7 additions & 5 deletions mm2src/coins/solana.rs
Original file line number Diff line number Diff line change
Expand Up @@ -672,18 +672,20 @@ impl MmCoin for SolanaCoin {

async fn get_sender_trade_fee(
&self,
value: TradePreimageValue,
stage: FeeApproxStage,
_value: TradePreimageValue,
_stage: FeeApproxStage,
) -> TradePreimageResult<TradeFee> {
unimplemented!()
}

fn get_receiver_trade_fee(&self, _stage: FeeApproxStage) -> TradePreimageFut<TradeFee> { unimplemented!() }
fn get_receiver_trade_fee(&self, _send_amount: BigDecimal, _stage: FeeApproxStage) -> TradePreimageFut<TradeFee> {
unimplemented!()
}

async fn get_fee_to_send_taker_fee(
&self,
dex_fee_amount: BigDecimal,
stage: FeeApproxStage,
_dex_fee_amount: BigDecimal,
_stage: FeeApproxStage,
) -> TradePreimageResult<TradeFee> {
unimplemented!()
}
Expand Down
4 changes: 3 additions & 1 deletion mm2src/coins/solana/spl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,9 @@ impl MmCoin for SplToken {
unimplemented!()
}

fn get_receiver_trade_fee(&self, _stage: FeeApproxStage) -> TradePreimageFut<TradeFee> { unimplemented!() }
fn get_receiver_trade_fee(&self, _send_amount: BigDecimal, _stage: FeeApproxStage) -> TradePreimageFut<TradeFee> {
unimplemented!()
}

async fn get_fee_to_send_taker_fee(
&self,
Expand Down
5 changes: 2 additions & 3 deletions mm2src/coins/tendermint/iris/htlc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
// check this page https://www.irisnet.org/docs/get-started/testnet.html#faucet

use super::htlc_proto::{ClaimHtlcProtoRep, CreateHtlcProtoRep};

use crate::tendermint::type_urls::{CLAIM_HTLC_TYPE_URL, CREATE_HTLC_TYPE_URL};
use cosmrs::{tx::{Msg, MsgProto},
AccountId, Coin, ErrorReport};
use std::convert::TryFrom;
Expand All @@ -30,9 +32,6 @@ pub const HTLC_STATE_OPEN: i32 = 0;
pub const HTLC_STATE_COMPLETED: i32 = 1;
pub const HTLC_STATE_REFUNDED: i32 = 2;

const CREATE_HTLC_TYPE_URL: &str = "/irismod.htlc.MsgCreateHTLC";
const CLAIM_HTLC_TYPE_URL: &str = "/irismod.htlc.MsgClaimHTLC";

#[allow(dead_code)]
pub(crate) struct IrisHtlc {
/// Generated HTLC's ID.
Expand Down
4 changes: 2 additions & 2 deletions mm2src/coins/tendermint/iris/htlc_proto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,14 @@ pub(crate) struct QueryHtlcRequestProto {

#[derive(prost::Enumeration, Debug)]
#[repr(i32)]
pub(crate) enum HtlcState {
pub enum HtlcState {
Open = 0,
Completed = 1,
Refunded = 2,
}

#[derive(prost::Message)]
pub(crate) struct HtlcProto {
pub struct HtlcProto {
#[prost(string, tag = "1")]
pub(crate) id: prost::alloc::string::String,
#[prost(string, tag = "2")]
Expand Down
2 changes: 2 additions & 0 deletions mm2src/coins/tendermint/iris/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub(crate) mod htlc;
pub(crate) mod htlc_proto;
26 changes: 22 additions & 4 deletions mm2src/coins/tendermint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,29 @@
// Useful resources
// https://docs.cosmos.network/

#[path = "iris/htlc.rs"] mod htlc;
#[path = "iris/htlc_proto.rs"] mod htlc_proto;
mod iris;
mod rpc;
mod tendermint_coin;
#[cfg(not(target_arch = "wasm32"))] mod tendermint_native_rpc;
mod tendermint_token;
#[cfg(target_arch = "wasm32")] mod tendermint_wasm_rpc;
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,
}

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

pub(crate) mod type_urls {
pub(crate) const CREATE_HTLC_TYPE_URL: &str = "/irismod.htlc.MsgCreateHTLC";
pub(crate) const CLAIM_HTLC_TYPE_URL: &str = "/irismod.htlc.MsgClaimHTLC";
}
23 changes: 23 additions & 0 deletions mm2src/coins/tendermint/rpc/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#[cfg(not(target_arch = "wasm32"))] mod tendermint_native_rpc;
#[cfg(not(target_arch = "wasm32"))]
pub use tendermint_native_rpc::*;

#[cfg(target_arch = "wasm32")] mod tendermint_wasm_rpc;
#[cfg(target_arch = "wasm32")] pub use tendermint_wasm_rpc::*;

pub(crate) const TX_SUCCESS_CODE: u32 = 0;

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

impl From<TendermintResultOrder> for Order {
fn from(order: TendermintResultOrder) -> Self {
match order {
TendermintResultOrder::Ascending => Self::Ascending,
TendermintResultOrder::Descending => Self::Descending,
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ use tendermint_rpc::endpoint::*;
pub use tendermint_rpc::endpoint::{abci_query::Request as AbciRequest, health::Request as HealthRequest,
tx_search::Request as TxSearchRequest};
use tendermint_rpc::Paging;
pub use tendermint_rpc::{query::Query as TendermintQuery, Error, Order as TendermintResultOrder, Scheme,
SimpleRequest, Url};
pub use tendermint_rpc::{query::Query as TendermintQuery, Error, Order, Scheme, SimpleRequest, Url};
use tokio::time;

/// Provides lightweight access to the Tendermint RPC. It gives access to all
Expand Down Expand Up @@ -80,7 +79,7 @@ pub trait Client {
query: TendermintQuery,
page: u32,
per_page: u8,
order: TendermintResultOrder,
order: Order,
) -> Result<block_search::Response, Error> {
self.perform(block_search::Request::new(query, page, per_page, order))
.await
Expand Down Expand Up @@ -229,7 +228,7 @@ pub trait Client {
prove: bool,
page: u32,
per_page: u8,
order: TendermintResultOrder,
order: Order,
) -> Result<tx_search::Response, Error> {
self.perform(tx_search::Request::new(query, prove, page, per_page, order))
.await
Expand Down
Loading

0 comments on commit 15ff4c5

Please sign in to comment.