Skip to content

Commit

Permalink
[r2r] Add get_locked_amount RPC. (KomodoPlatform#1627)
Browse files Browse the repository at this point in the history
* get_locked_amount_rpc

* WIP.

* WIP.

* WIP.

* Fix WASM tests.

* Fix review notes.

Co-authored-by: Alright <mzlot555@gmail.com>
Co-authored-by: Artem Vitae <email@not.set>
  • Loading branch information
3 people authored Jan 23, 2023
1 parent 7201146 commit a53daab
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 27 deletions.
53 changes: 50 additions & 3 deletions mm2src/mm2_main/src/lp_swap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,19 +59,19 @@

use crate::mm2::lp_network::{broadcast_p2p_msg, Libp2pPeerId};
use bitcrypto::{dhash160, sha256};
use coins::{lp_coinfind, MmCoinEnum, TradeFee, TransactionEnum};
use coins::{lp_coinfind, lp_coinfind_or_err, CoinFindError, MmCoinEnum, TradeFee, TransactionEnum};
use common::log::{debug, warn};
use common::time_cache::DuplicateCache;
use common::{bits256, calc_total_pages,
executor::{spawn_abortable, AbortOnDropHandle, SpawnFuture, Timer},
log::{error, info},
now_ms, var, PagingOptions};
now_ms, var, HttpStatusCode, PagingOptions, StatusCode};
use derive_more::Display;
use http::Response;
use mm2_core::mm_ctx::{from_ctx, MmArc};
use mm2_err_handle::prelude::*;
use mm2_libp2p::{decode_signed, encode_and_sign, pub_sub_topic, PeerId, TopicPrefix};
use mm2_number::{BigDecimal, BigRational, MmNumber};
use mm2_number::{BigDecimal, BigRational, MmNumber, MmNumberMultiRepr};
use parking_lot::Mutex as PaMutex;
use rpc::v1::types::{Bytes as BytesJson, H256 as H256Json};
use serde::Serialize;
Expand Down Expand Up @@ -445,6 +445,53 @@ impl SwapsContext {
pub async fn swap_db(&self) -> InitDbResult<SwapDbLocked<'_>> { Ok(self.swap_db.get_or_initialize().await?) }
}

#[derive(Debug, Deserialize)]
pub struct GetLockedAmountReq {
coin: String,
}

#[derive(Serialize)]
pub struct GetLockedAmountResp {
coin: String,
locked_amount: MmNumberMultiRepr,
}

#[derive(Debug, Display, Serialize, SerializeErrorType)]
#[serde(tag = "error_type", content = "error_data")]
pub enum GetLockedAmountRpcError {
#[display(fmt = "No such coin: {}", coin)]
NoSuchCoin { coin: String },
}

impl HttpStatusCode for GetLockedAmountRpcError {
fn status_code(&self) -> StatusCode {
match self {
GetLockedAmountRpcError::NoSuchCoin { .. } => StatusCode::INTERNAL_SERVER_ERROR,
}
}
}

impl From<CoinFindError> for GetLockedAmountRpcError {
fn from(e: CoinFindError) -> Self {
match e {
CoinFindError::NoSuchCoin { coin } => GetLockedAmountRpcError::NoSuchCoin { coin },
}
}
}

pub async fn get_locked_amount_rpc(
ctx: MmArc,
req: GetLockedAmountReq,
) -> Result<GetLockedAmountResp, MmError<GetLockedAmountRpcError>> {
lp_coinfind_or_err(&ctx, &req.coin).await?;
let locked_amount = get_locked_amount(&ctx, &req.coin);

Ok(GetLockedAmountResp {
coin: req.coin,
locked_amount: locked_amount.into(),
})
}

/// Get total amount of selected coin locked by all currently ongoing swaps
pub fn get_locked_amount(ctx: &MmArc, coin: &str) -> MmNumber {
let swap_ctx = SwapsContext::from_ctx(ctx).unwrap();
Expand Down
6 changes: 6 additions & 0 deletions mm2src/mm2_main/src/lp_swap/maker_swap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,12 @@ impl MakerSwap {
match event {
MakerSwapEvent::Started(data) => {
self.w().data = data;
log_tag!(
self.ctx,
"";
fmt = "Maker swap {} has successfully started",
self.uuid
);
},
MakerSwapEvent::StartFailed(err) => self.errors.lock().push(err),
MakerSwapEvent::Negotiated(data) => {
Expand Down
6 changes: 6 additions & 0 deletions mm2src/mm2_main/src/lp_swap/taker_swap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,12 @@ impl TakerSwap {
match event {
TakerSwapEvent::Started(data) => {
self.w().data = data;
log_tag!(
self.ctx,
"";
fmt = "Taker swap {} has successfully started",
self.uuid
);
},
TakerSwapEvent::StartFailed(err) => self.errors.lock().push(err),
TakerSwapEvent::Negotiated(data) => {
Expand Down
3 changes: 2 additions & 1 deletion mm2src/mm2_main/src/rpc/dispatcher/dispatcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::mm2::lp_ordermatch::{best_orders_rpc_v2, orderbook_rpc_v2, start_simp
use crate::mm2::rpc::rate_limiter::{process_rate_limit, RateLimitContext};
use crate::{mm2::lp_stats::{add_node_to_version_stat, remove_node_from_version_stat, start_version_stat_collection,
stop_version_stat_collection, update_version_stat_collection},
mm2::lp_swap::{max_maker_vol, recreate_swap_data, trade_preimage_rpc},
mm2::lp_swap::{get_locked_amount_rpc, max_maker_vol, recreate_swap_data, trade_preimage_rpc},
mm2::rpc::lp_commands::{get_public_key, get_public_key_hash}};
use coins::eth::EthCoin;
use coins::my_tx_history_v2::my_tx_history_v2_rpc;
Expand Down Expand Up @@ -157,6 +157,7 @@ async fn dispatcher_v2(request: MmRpcRequest, ctx: MmArc) -> DispatcherResult<Re
"enable_tendermint_token" => handle_mmrpc(ctx, request, enable_token::<TendermintToken>).await,
"get_current_mtp" => handle_mmrpc(ctx, request, get_current_mtp_rpc).await,
"get_enabled_coins" => handle_mmrpc(ctx, request, get_enabled_coins).await,
"get_locked_amount" => handle_mmrpc(ctx, request, get_locked_amount_rpc).await,
"get_new_address" => handle_mmrpc(ctx, request, get_new_address).await,
"get_public_key" => handle_mmrpc(ctx, request, get_public_key).await,
"get_public_key_hash" => handle_mmrpc(ctx, request, get_public_key_hash).await,
Expand Down
47 changes: 45 additions & 2 deletions mm2src/mm2_main/tests/docker_tests/docker_tests_inner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ use coins::{FoundSwapTxSpend, MarketCoinOps, MmCoin, SearchForSwapTxSpendInput,
use common::{block_on, now_ms};
use futures01::Future;
use mm2_number::{BigDecimal, MmNumber};
use mm2_test_helpers::for_tests::{check_my_swap_status_amounts, eth_testnet_conf, kmd_conf, max_maker_vol, mm_dump,
mycoin1_conf, mycoin_conf, set_price, MarketMakerIt, Mm2TestConf};
use mm2_test_helpers::for_tests::{check_my_swap_status_amounts, eth_testnet_conf, get_locked_amount, kmd_conf,
max_maker_vol, mm_dump, mycoin1_conf, mycoin_conf, set_price, start_swaps,
MarketMakerIt, Mm2TestConf};
use mm2_test_helpers::structs::*;
use serde_json::Value as Json;
use std::collections::HashMap;
Expand Down Expand Up @@ -3449,3 +3450,45 @@ fn test_match_utxo_with_eth_taker_buy() {
block_on(mm_bob.stop()).unwrap();
block_on(mm_alice.stop()).unwrap();
}

#[test]
fn test_locked_amount() {
let (_ctx, _, bob_priv_key) = generate_utxo_coin_with_random_privkey("MYCOIN", 1000.into());
let (_ctx, _, alice_priv_key) = generate_utxo_coin_with_random_privkey("MYCOIN1", 1000.into());
let coins = json!([mycoin_conf(1000), mycoin1_conf(1000)]);
let bob_conf = Mm2TestConf::seednode(&format!("0x{}", hex::encode(bob_priv_key)), &coins);
let mut mm_bob = MarketMakerIt::start(bob_conf.conf, bob_conf.rpc_password, None).unwrap();
let (_bob_dump_log, _bob_dump_dashboard) = mm_dump(&mm_bob.log_path);

let alice_conf = Mm2TestConf::light_node(&format!("0x{}", hex::encode(alice_priv_key)), &coins, &[&mm_bob
.ip
.to_string()]);
let mut mm_alice = MarketMakerIt::start(alice_conf.conf, alice_conf.rpc_password, None).unwrap();
let (_alice_dump_log, _alice_dump_dashboard) = mm_dump(&mm_alice.log_path);

log!("{:?}", block_on(enable_native(&mm_bob, "MYCOIN", &[])));
log!("{:?}", block_on(enable_native(&mm_bob, "MYCOIN1", &[])));
log!("{:?}", block_on(enable_native(&mm_alice, "MYCOIN", &[])));
log!("{:?}", block_on(enable_native(&mm_alice, "MYCOIN1", &[])));

block_on(start_swaps(
&mut mm_bob,
&mut mm_alice,
&[("MYCOIN", "MYCOIN1")],
1.,
1.,
777.,
));

let locked_bob = block_on(get_locked_amount(&mm_bob, "MYCOIN"));
assert_eq!(locked_bob.coin, "MYCOIN");

let expected_result: MmNumberMultiRepr = MmNumber::from("777.00001").into();
assert_eq!(expected_result, locked_bob.locked_amount);

let locked_alice = block_on(get_locked_amount(&mm_alice, "MYCOIN1"));
assert_eq!(locked_alice.coin, "MYCOIN1");

let expected_result: MmNumberMultiRepr = MmNumber::from("778.00002").into();
assert_eq!(expected_result, locked_alice.locked_amount);
}
20 changes: 8 additions & 12 deletions mm2src/mm2_main/tests/mm2_tests/tendermint_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,13 @@ fn test_tendermint_withdraw() {
println!("Activation {}", json::to_string(&activation_res).unwrap());

// just call withdraw without sending to check response correctness
let withdraw_result = block_on(withdraw_v1(
let tx_details = block_on(withdraw_v1(
&mm,
ATOM_TICKER,
"cosmos1svaw0aqc4584x825ju7ua03g5xtxwd0ahl86hz",
"0.1",
));
println!("Withdraw to other {}", json::to_string(&withdraw_result).unwrap());
let tx_details: TransactionDetails = json::from_value(withdraw_result).unwrap();
println!("Withdraw to other {}", json::to_string(&tx_details).unwrap());
// TODO how to check it if the fee is dynamic?
/*
let expected_total: BigDecimal = "0.15".parse().unwrap();
Expand All @@ -83,15 +82,14 @@ fn test_tendermint_withdraw() {
]);

// withdraw and send transaction to ourselves
let withdraw_result = block_on(withdraw_v1(
let tx_details = block_on(withdraw_v1(
&mm,
ATOM_TICKER,
"cosmos1w5h6wud7a8zpa539rc99ehgl9gwkad3wjsjq8v",
"0.1",
));
println!("Withdraw to self {}", json::to_string(&withdraw_result).unwrap());
println!("Withdraw to self {}", json::to_string(&tx_details).unwrap());

let tx_details: TransactionDetails = json::from_value(withdraw_result).unwrap();
// TODO how to check it if the fee is dynamic?
/*
let expected_total: BigDecimal = "0.15".parse().unwrap();
Expand Down Expand Up @@ -131,15 +129,14 @@ fn test_tendermint_token_activation_and_withdraw() {
println!("Token activation {}", json::to_string(&activation_res).unwrap());

// just call withdraw without sending to check response correctness
let withdraw_result = block_on(withdraw_v1(
let tx_details = block_on(withdraw_v1(
&mm,
token,
"iaa1llp0f6qxemgh4g4m5ewk0ew0hxj76avuz8kwd5",
"0.1",
));

println!("Withdraw to other {}", json::to_string(&withdraw_result).unwrap());
let tx_details: TransactionDetails = json::from_value(withdraw_result).unwrap();
println!("Withdraw to other {}", json::to_string(&tx_details).unwrap());

let expected_total: BigDecimal = "0.1".parse().unwrap();
assert_eq!(tx_details.total_amount, expected_total);
Expand All @@ -162,15 +159,14 @@ fn test_tendermint_token_activation_and_withdraw() {
]);

// withdraw and send transaction to ourselves
let withdraw_result = block_on(withdraw_v1(
let tx_details = block_on(withdraw_v1(
&mm,
token,
"iaa1e0rx87mdj79zejewuc4jg7ql9ud2286g2us8f2",
"0.1",
));
println!("Withdraw to self {}", json::to_string(&withdraw_result).unwrap());
println!("Withdraw to self {}", json::to_string(&tx_details).unwrap());

let tx_details: TransactionDetails = json::from_value(withdraw_result).unwrap();
let expected_total: BigDecimal = "0.1".parse().unwrap();
let expected_received: BigDecimal = "0.1".parse().unwrap();

Expand Down
39 changes: 32 additions & 7 deletions mm2src/mm2_test_helpers/src/for_tests.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
//! Helpers used in the unit and integration tests.
use crate::electrums::qtum_electrums;
use crate::structs::{MyBalanceResponse, RpcResponse, SetPriceResponse, WatcherConf};
use crate::structs::*;

use common::custom_futures::repeatable::{Ready, Retry};
use common::executor::Timer;
use common::log::debug;
Expand Down Expand Up @@ -2132,7 +2133,7 @@ pub async fn init_withdraw(mm: &MarketMakerIt, coin: &str, to: &str, amount: &st
json::from_str(&request.1).unwrap()
}

pub async fn withdraw_v1(mm: &MarketMakerIt, coin: &str, to: &str, amount: &str) -> Json {
pub async fn withdraw_v1(mm: &MarketMakerIt, coin: &str, to: &str, amount: &str) -> TransactionDetails {
let request = mm
.rpc(&json!({
"userpass": mm.userpass,
Expand Down Expand Up @@ -2559,12 +2560,18 @@ pub async fn start_swaps(
uuids.push(buy_json["result"]["uuid"].as_str().unwrap().to_owned());
}

for (base, rel) in pairs.iter() {
for uuid in uuids.iter() {
// ensure the swaps are started
let expected_log = format!("Entering the taker_swap_loop {}/{}", base, rel);
taker.wait_for_log(5., |log| log.contains(&expected_log)).await.unwrap();
let expected_log = format!("Entering the maker_swap_loop {}/{}", base, rel);
maker.wait_for_log(5., |log| log.contains(&expected_log)).await.unwrap()
let expected_log = format!("Taker swap {} has successfully started", uuid);
taker
.wait_for_log(10., |log| log.contains(&expected_log))
.await
.unwrap();
let expected_log = format!("Maker swap {} has successfully started", uuid);
maker
.wait_for_log(10., |log| log.contains(&expected_log))
.await
.unwrap()
}

uuids
Expand Down Expand Up @@ -2732,3 +2739,21 @@ pub async fn test_qrc20_history_impl(local_start: Option<LocalStart>) {
assert_eq!(tx["internal_id"].as_str().unwrap(), expected_tx);
}
}

pub async fn get_locked_amount(mm: &MarketMakerIt, coin: &str) -> GetLockedAmountResponse {
let request = json!({
"userpass": mm.userpass,
"method": "get_locked_amount",
"mmrpc": "2.0",
"params": {
"coin": coin
}
});
println!("get_locked_amount request {}", json::to_string(&request).unwrap());

let request = mm.rpc(&request).await.unwrap();
assert_eq!(request.0, StatusCode::OK, "'get_locked_amount' failed: {}", request.1);
println!("get_locked_amount response {}", request.1);
let response: RpcV2Response<GetLockedAmountResponse> = json::from_str(&request.1).unwrap();
response.result
}
11 changes: 9 additions & 2 deletions mm2src/mm2_test_helpers/src/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,7 @@ pub enum TransactionType {
},
}

#[derive(Debug, Deserialize, PartialEq)]
#[derive(Debug, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct TransactionDetails {
pub tx_hex: String,
Expand Down Expand Up @@ -1020,7 +1020,7 @@ pub struct AggregatedOrderbookEntryV2 {
pub rel_max_volume_aggr: MmNumberMultiRepr,
}

#[derive(Debug, Deserialize, PartialEq)]
#[derive(Debug, Deserialize, Eq, PartialEq)]
#[serde(deny_unknown_fields)]
pub struct MmNumberMultiRepr {
pub decimal: BigDecimal,
Expand Down Expand Up @@ -1092,6 +1092,13 @@ pub struct TendermintActivationResult {
pub ticker: String,
}

#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct GetLockedAmountResponse {
pub coin: String,
pub locked_amount: MmNumberMultiRepr,
}

pub mod gui_storage {
use mm2_number::BigDecimal;
use std::collections::BTreeSet;
Expand Down

0 comments on commit a53daab

Please sign in to comment.