From 7d10c66c033ae4e6cfccaea318e2bddc3db7ea35 Mon Sep 17 00:00:00 2001 From: sergeyboyko0791 <58207208+sergeyboyko0791@users.noreply.github.com> Date: Wed, 15 Apr 2020 14:39:51 +0700 Subject: [PATCH] Electrum extended error msg #611 (#614) * Add host:port to RPC electrum error #611 * Add coin name to RPC electrum error #611 * Change order of imports * Add ignore attribute for the unstable on MacOS mm2::mm2_tests::test_multiple_buy_sell_no_delay test * Refactor the test_electrum_rpc_client_error test * Remove ignore attribute * Add comparing of expected and actual error strings --- mm2src/coins/coins_tests.rs | 3 ++ mm2src/coins/utxo.rs | 7 ++-- mm2src/coins/utxo/rpc_clients.rs | 62 ++++++++++++++++++++++++++------ mm2src/coins/utxo/utxo_tests.rs | 43 +++++++++++++++++----- mm2src/common/jsonrpc_client.rs | 47 ++++++++++++++++++++---- mm2src/mm2_tests.rs | 2 ++ 6 files changed, 136 insertions(+), 28 deletions(-) diff --git a/mm2src/coins/coins_tests.rs b/mm2src/coins/coins_tests.rs index 2f9bcc726e..8b544bf650 100644 --- a/mm2src/coins/coins_tests.rs +++ b/mm2src/coins/coins_tests.rs @@ -5,6 +5,7 @@ use crate::utxo::rpc_clients::NativeClientImpl; pub fn test_list_unspent() { let client = NativeClientImpl { + coin_ticker: "RICK".into(), uri: "http://127.0.0.1:10271".to_owned(), auth: fomat!("Basic " (base64_encode("user481805103:pass97a61c8d048bcf468c6c39a314970e557f57afd1d8a5edee917fb29bafb3a43371", URL_SAFE))), }; @@ -15,6 +16,7 @@ pub fn test_list_unspent() { pub fn test_get_block_count() { let client = NativeClientImpl { + coin_ticker: "RICK".into(), uri: "http://127.0.0.1:10271".to_owned(), auth: fomat!("Basic " (base64_encode("user481805103:pass97a61c8d048bcf468c6c39a314970e557f57afd1d8a5edee917fb29bafb3a43371", URL_SAFE))), }; @@ -24,6 +26,7 @@ pub fn test_get_block_count() { pub fn test_import_address() { let client = NativeClientImpl { + coin_ticker: "RICK".into(), uri: "http://127.0.0.1:10271".to_owned(), auth: fomat!("Basic " (base64_encode("user481805103:pass97a61c8d048bcf468c6c39a314970e557f57afd1d8a5edee917fb29bafb3a43371", URL_SAFE))), }; diff --git a/mm2src/coins/utxo.rs b/mm2src/coins/utxo.rs index c2a3cfc7bc..9e94645e84 100644 --- a/mm2src/coins/utxo.rs +++ b/mm2src/coins/utxo.rs @@ -1516,12 +1516,12 @@ impl MmCoin for UtxoCoin { Ok(value) => value, Err(e) => { match &e.error { - JsonRpcErrorType::Transport(e) | JsonRpcErrorType::Parse(e) => { + JsonRpcErrorType::Transport(e) | JsonRpcErrorType::Parse(_, e) => { ctx.log.log("", &[&"tx_history", &self.ticker], &ERRL!("Error {} on scripthash_get_history, retrying", e)); thread::sleep(Duration::from_secs(10)); continue; }, - JsonRpcErrorType::Response(err) => { + JsonRpcErrorType::Response(_addr, err) => { if *err == history_too_large { ctx.log.log("", &[&"tx_history", &self.ticker], &ERRL!("Got `history too large`, stopping further attempts to retrieve it")); *unwrap!(self.history_sync_state.lock()) = HistorySyncState::Error(json!({ @@ -1885,6 +1885,7 @@ pub async fn utxo_coin_from_conf_and_request( None => try_s!(conf["rpcport"].as_u64().ok_or(ERRL!("Rpc port is not set neither in `coins` file nor in native daemon config"))) as u16, }; let client = Arc::new(NativeClientImpl { + coin_ticker: ticker.to_string(), uri: fomat!("http://127.0.0.1:"(rpc_port)), auth: format!("Basic {}", base64_encode(&auth_str, URL_SAFE)), }); @@ -1898,7 +1899,7 @@ pub async fn utxo_coin_from_conf_and_request( let mut servers: Vec = try_s!(json::from_value(req["servers"].clone())); let mut rng = small_rng(); servers.as_mut_slice().shuffle(&mut rng); - let mut client = ElectrumClientImpl::new(); + let mut client = ElectrumClientImpl::new(ticker.to_string()); for server in servers.iter() { match client.add_server(server) { Ok(_) => (), diff --git a/mm2src/coins/utxo/rpc_clients.rs b/mm2src/coins/utxo/rpc_clients.rs index 8cbf97f6dc..7575db3139 100644 --- a/mm2src/coins/utxo/rpc_clients.rs +++ b/mm2src/coins/utxo/rpc_clients.rs @@ -9,7 +9,7 @@ use common::{StringError}; use common::wio::{slurp_req}; use common::executor::{spawn, Timer}; use common::custom_futures::{join_all_sequential, select_ok_sequential}; -use common::jsonrpc_client::{JsonRpcClient, JsonRpcResponseFut, JsonRpcRequest, JsonRpcResponse, RpcRes}; +use common::jsonrpc_client::{JsonRpcClient, JsonRpcRemoteAddr, JsonRpcResponseFut, JsonRpcRequest, JsonRpcResponse, RpcRes}; use futures01::{Future, Poll, Sink, Stream}; use futures01::future::{Either, loop_fn, Loop, select_ok}; use futures01::sync::{mpsc, oneshot}; @@ -254,6 +254,8 @@ pub enum EstimateFeeMethod { /// This description will be updated with more info #[derive(Clone, Debug)] pub struct NativeClientImpl { + /// Name of coin the rpc client is intended to work with + pub coin_ticker: String, /// The uri to send requests to pub uri: String, /// Value of Authorization header, e.g. "Basic base64(user:password)" @@ -264,13 +266,33 @@ pub struct NativeClientImpl { pub struct NativeClient(pub Arc); impl Deref for NativeClient {type Target = NativeClientImpl; fn deref (&self) -> &NativeClientImpl {&*self.0}} +/// The trait provides methods to generate the JsonRpcClient instance info such as name of coin. +pub trait UtxoJsonRpcClientInfo: JsonRpcClient { + /// Name of coin the rpc client is intended to work with + fn coin_name(&self) -> &str; + + /// Generate client info from coin name + fn client_info(&self) -> String { + format!("coin: {}", self.coin_name()) + } +} + +impl UtxoJsonRpcClientInfo for NativeClientImpl { + fn coin_name(&self) -> &str { + self.coin_ticker.as_str() + } +} + impl JsonRpcClient for NativeClientImpl { fn version(&self) -> &'static str { "1.0" } fn next_id(&self) -> String { "0".into() } + fn client_info(&self) -> String { UtxoJsonRpcClientInfo::client_info(self) } + fn transport(&self, request: JsonRpcRequest) -> JsonRpcResponseFut { let request_body = try_fus!(json::to_string(&request)); + let uri = self.uri.clone(); let http_request = try_fus!( Request::builder() @@ -279,17 +301,19 @@ impl JsonRpcClient for NativeClientImpl { AUTHORIZATION, self.auth.clone() ) - .uri(self.uri.clone()) + .uri(uri.clone()) .body(Vec::from(request_body)) ); - Box::new(slurp_req(http_request).then(move |result| -> Result { + Box::new(slurp_req(http_request).then(move |result| -> Result<(JsonRpcRemoteAddr, JsonRpcResponse), String> { let res = try_s!(result); let body = try_s!(std::str::from_utf8(&res.2)); if res.0 != StatusCode::OK { return ERR!("Rpc request {:?} failed with HTTP status code {}, response body: {}", request, res.0, body); } - Ok(try_s!(json::from_str(body))) + + let response = try_s!(json::from_str(body)); + Ok((uri.into(), response)) })) } } @@ -753,6 +777,7 @@ impl Drop for ElectrumConnection { #[derive(Debug)] pub struct ElectrumClientImpl { + coin_ticker: String, connections: Vec, next_id: AtomicU64, } @@ -761,11 +786,16 @@ pub struct ElectrumClientImpl { async fn electrum_request_multi( client: ElectrumClient, request: JsonRpcRequest, -) -> Result { +) -> Result<(JsonRpcRemoteAddr, JsonRpcResponse), String> { let mut futures = vec![]; for connection in client.connections.iter() { + let connection_addr = connection.addr.clone(); match &*connection.tx.lock().await { - Some(tx) => futures.push(electrum_request(request.clone(), tx.clone(), connection.responses.clone())), + Some(tx) => { + let fut = electrum_request(request.clone(), tx.clone(), connection.responses.clone()) + .map(|response| (JsonRpcRemoteAddr(connection_addr), response)); + futures.push(fut) + }, None => (), } } @@ -797,7 +827,7 @@ pub extern fn electrum_replied (ri: i32, id: i32) { /// I haven't looked into this because we'll probably use a websocket or Java implementation instead. #[cfg(not(feature = "native"))] async fn electrum_request_multi (client: ElectrumClient, request: JsonRpcRequest) --> Result { +-> Result<(JsonRpcRemoteAddr, JsonRpcResponse), String> { use futures::future::{select, Either}; use std::mem::MaybeUninit; use std::os::raw::c_char; @@ -806,6 +836,8 @@ async fn electrum_request_multi (client: ElectrumClient, request: JsonRpcRequest let req = try_s! (json::to_string (&request)); let id: i32 = try_s! (request.id.parse()); let mut jres: Option = None; + // address of server from which an Rpc response was received + let mut remote_address = JsonRpcRemoteAddr::default(); for connection in client.connections.iter() { let (tx, rx) = futures::channel::oneshot::channel(); @@ -834,11 +866,12 @@ async fn electrum_request_multi (client: ElectrumClient, request: JsonRpcRequest result: res, error: Json::Null }); + remote_address = JsonRpcRemoteAddr(connection.addr.clone()); // server.ping must be sent to all servers to keep all connections alive if request.method != "server.ping" {break} } let jres = try_s! (jres.ok_or ("!jres")); - Ok (jres) + Ok ((remote_address, jres)) } impl ElectrumClientImpl { @@ -865,6 +898,12 @@ impl Deref for ElectrumClient {type Target = ElectrumClientImpl; fn deref (&self const BLOCKCHAIN_HEADERS_SUB_ID: &'static str = "blockchain.headers.subscribe"; +impl UtxoJsonRpcClientInfo for ElectrumClient { + fn coin_name(&self) -> &str { + self.coin_ticker.as_str() + } +} + impl JsonRpcClient for ElectrumClient { fn version(&self) -> &'static str { "2.0" } @@ -872,6 +911,8 @@ impl JsonRpcClient for ElectrumClient { self.next_id.fetch_add(1, AtomicOrdering::Relaxed).to_string() } + fn client_info(&self) -> String { UtxoJsonRpcClientInfo::client_info(self) } + fn transport(&self, request: JsonRpcRequest) -> JsonRpcResponseFut { Box::new(electrum_request_multi(self.clone(), request).boxed().compat()) } @@ -1063,8 +1104,9 @@ impl UtxoRpcClientOps for ElectrumClient { #[cfg_attr(test, mockable)] impl ElectrumClientImpl { - pub fn new() -> ElectrumClientImpl { + pub fn new(coin_ticker: String) -> ElectrumClientImpl { ElectrumClientImpl { + coin_ticker, connections: vec![], next_id: 0.into(), } @@ -1378,7 +1420,7 @@ fn electrum_request( request: JsonRpcRequest, tx: mpsc::Sender>, responses: Arc>>> -) -> JsonRpcResponseFut { +) -> Box + Send + 'static> { let send_fut = async move { let mut json = try_s!(json::to_string(&request)); // Electrum request and responses must end with \n diff --git a/mm2src/coins/utxo/utxo_tests.rs b/mm2src/coins/utxo/utxo_tests.rs index 7e203ac587..1514696eb1 100644 --- a/mm2src/coins/utxo/utxo_tests.rs +++ b/mm2src/coins/utxo/utxo_tests.rs @@ -5,9 +5,12 @@ use crate::utxo::rpc_clients::{ElectrumProtocol, ListSinceBlockRes}; use futures::future::join_all; use mocktopus::mocking::*; use super::*; +use rpc::v1::types::H256 as H256Json; + +const TEST_COIN_NAME: &'static str = "ETOMIC"; fn electrum_client_for_test(servers: &[&str]) -> UtxoRpcClientEnum { - let mut client = ElectrumClientImpl::new(); + let mut client = ElectrumClientImpl::new(TEST_COIN_NAME.into()); for server in servers { client.add_server(&ElectrumRpcRequest { url: server.to_string(), @@ -66,7 +69,7 @@ fn utxo_coin_for_test(rpc_client: UtxoRpcClientEnum, force_seed: Option<&str>) - p2sh_t_addr_prefix: 0, pub_addr_prefix: 60, pub_t_addr_prefix: 0, - ticker: "ETOMIC".into(), + ticker: TEST_COIN_NAME.into(), wif_prefix: 0, tx_fee: TxFee::Fixed(1000), version_group_id: 0x892f2085, @@ -246,6 +249,7 @@ fn test_sat_from_big_decimal() { #[test] fn test_wait_for_payment_spend_timeout_native() { let client = NativeClientImpl { + coin_ticker: "RICK".into(), uri: "http://127.0.0.1:10271".to_owned(), auth: fomat!("Basic " (base64_encode("user481805103:pass97a61c8d048bcf468c6c39a314970e557f57afd1d8a5edee917fb29bafb3a43371", URL_SAFE))), }; @@ -273,7 +277,7 @@ fn test_wait_for_payment_spend_timeout_electrum() { MockResult::Return(Box::new(futures01::future::ok(None))) }); - let client = ElectrumClientImpl::new(); + let client = ElectrumClientImpl::new(TEST_COIN_NAME.into()); let client = UtxoRpcClientEnum::Electrum(ElectrumClient(Arc::new(client))); let coin = utxo_coin_for_test(client, None); let transaction = unwrap!(hex::decode("01000000000102fff7f7881a8099afa6940d42d1e7f6362bec38171ea3edf433541db4e4ad969f00000000494830450221008b9d1dc26ba6a9cb62127b02742fa9d754cd3bebf337f7a55d114c8e5cdd30be022040529b194ba3f9281a99f2b1c0a19c0489bc22ede944ccf4ecbab4cc618ef3ed01eeffffffef51e1b804cc89d182d279655c3aa89e815b1b309fe287d9b2b55d57b90ec68a0100000000ffffffff02202cb206000000001976a9148280b37df378db99f66f85c95a783a76ac7a6d5988ac9093510d000000001976a9143bde42dbee7e4dbe6a21b2d50ce2f0167faa815988ac000247304402203609e17b84f6a7d30c80bfa610b5b4542f32a8a0d5447a12fb1366d7f01cc44a0220573a954c4518331561406f90300e8f3358f51928d43c212a8caed02de67eebee0121025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee635711000000")); @@ -337,6 +341,7 @@ fn test_withdraw_impl_set_fixed_fee() { }); let client = NativeClient(Arc::new(NativeClientImpl { + coin_ticker: TEST_COIN_NAME.into(), uri: "http://127.0.0.1".to_owned(), auth: fomat!("Basic " (base64_encode("user481805103:pass97a61c8d048bcf468c6c39a314970e557f57afd1d8a5edee917fb29bafb3a43371", URL_SAFE))), })); @@ -346,7 +351,7 @@ fn test_withdraw_impl_set_fixed_fee() { let withdraw_req = WithdrawRequest { amount: 1.into(), to: "RQq6fWoy8aGGMLjvRfMY5mBNVm2RQxJyLa".to_string(), - coin: "ETOMIC".to_string(), + coin: TEST_COIN_NAME.into(), max: false, fee: Some(WithdrawFee::UtxoFixed { amount: "0.1".parse().unwrap() }), }; @@ -365,6 +370,7 @@ fn test_withdraw_impl_sat_per_kb_fee() { }); let client = NativeClient(Arc::new(NativeClientImpl { + coin_ticker: TEST_COIN_NAME.into(), uri: "http://127.0.0.1".to_owned(), auth: fomat!("Basic " (base64_encode("user481805103:pass97a61c8d048bcf468c6c39a314970e557f57afd1d8a5edee917fb29bafb3a43371", URL_SAFE))), })); @@ -374,7 +380,7 @@ fn test_withdraw_impl_sat_per_kb_fee() { let withdraw_req = WithdrawRequest { amount: 1.into(), to: "RQq6fWoy8aGGMLjvRfMY5mBNVm2RQxJyLa".to_string(), - coin: "ETOMIC".to_string(), + coin: TEST_COIN_NAME.into(), max: false, fee: Some(WithdrawFee::UtxoPerKbyte { amount: "0.1".parse().unwrap() }), }; @@ -396,6 +402,7 @@ fn test_withdraw_impl_sat_per_kb_fee_amount_equal_to_max() { }); let client = NativeClient(Arc::new(NativeClientImpl { + coin_ticker: TEST_COIN_NAME.into(), uri: "http://127.0.0.1".to_owned(), auth: fomat!("Basic " (base64_encode("user481805103:pass97a61c8d048bcf468c6c39a314970e557f57afd1d8a5edee917fb29bafb3a43371", URL_SAFE))), })); @@ -405,7 +412,7 @@ fn test_withdraw_impl_sat_per_kb_fee_amount_equal_to_max() { let withdraw_req = WithdrawRequest { amount: "9.9789".parse().unwrap(), to: "RQq6fWoy8aGGMLjvRfMY5mBNVm2RQxJyLa".to_string(), - coin: "ETOMIC".to_string(), + coin: TEST_COIN_NAME.into(), max: false, fee: Some(WithdrawFee::UtxoPerKbyte { amount: "0.1".parse().unwrap() }), }; @@ -429,6 +436,7 @@ fn test_withdraw_impl_sat_per_kb_fee_amount_equal_to_max_dust_included_to_fee() }); let client = NativeClient(Arc::new(NativeClientImpl { + coin_ticker: TEST_COIN_NAME.into(), uri: "http://127.0.0.1".to_owned(), auth: fomat!("Basic " (base64_encode("user481805103:pass97a61c8d048bcf468c6c39a314970e557f57afd1d8a5edee917fb29bafb3a43371", URL_SAFE))), })); @@ -438,7 +446,7 @@ fn test_withdraw_impl_sat_per_kb_fee_amount_equal_to_max_dust_included_to_fee() let withdraw_req = WithdrawRequest { amount: "9.9789".parse().unwrap(), to: "RQq6fWoy8aGGMLjvRfMY5mBNVm2RQxJyLa".to_string(), - coin: "ETOMIC".to_string(), + coin: TEST_COIN_NAME.into(), max: false, fee: Some(WithdrawFee::UtxoPerKbyte { amount: "0.09999999".parse().unwrap() }), }; @@ -462,6 +470,7 @@ fn test_withdraw_impl_sat_per_kb_fee_amount_over_max() { }); let client = NativeClient(Arc::new(NativeClientImpl { + coin_ticker: TEST_COIN_NAME.into(), uri: "http://127.0.0.1".to_owned(), auth: fomat!("Basic " (base64_encode("user481805103:pass97a61c8d048bcf468c6c39a314970e557f57afd1d8a5edee917fb29bafb3a43371", URL_SAFE))), })); @@ -471,7 +480,7 @@ fn test_withdraw_impl_sat_per_kb_fee_amount_over_max() { let withdraw_req = WithdrawRequest { amount: "9.97939455".parse().unwrap(), to: "RQq6fWoy8aGGMLjvRfMY5mBNVm2RQxJyLa".to_string(), - coin: "ETOMIC".to_string(), + coin: TEST_COIN_NAME.into(), max: false, fee: Some(WithdrawFee::UtxoPerKbyte { amount: "0.1".parse().unwrap() }), }; @@ -486,6 +495,7 @@ fn test_withdraw_impl_sat_per_kb_fee_max() { }); let client = NativeClient(Arc::new(NativeClientImpl { + coin_ticker: TEST_COIN_NAME.into(), uri: "http://127.0.0.1".to_owned(), auth: fomat!("Basic " (base64_encode("user481805103:pass97a61c8d048bcf468c6c39a314970e557f57afd1d8a5edee917fb29bafb3a43371", URL_SAFE))), })); @@ -495,7 +505,7 @@ fn test_withdraw_impl_sat_per_kb_fee_max() { let withdraw_req = WithdrawRequest { amount: 0.into(), to: "RQq6fWoy8aGGMLjvRfMY5mBNVm2RQxJyLa".to_string(), - coin: "ETOMIC".to_string(), + coin: TEST_COIN_NAME.into(), max: true, fee: Some(WithdrawFee::UtxoPerKbyte { amount: "0.1".parse().unwrap() }), }; @@ -601,3 +611,18 @@ fn get_tx_details_coinbase_transaction() { block_on(fut); } + +#[test] +fn test_electrum_rpc_client_error() { + let client = electrum_client_for_test(&["electrum1.cipig.net:10060"]); + + let empty_hash = H256Json::default(); + let err = unwrap_err!(client.get_verbose_transaction(empty_hash).wait()); + + // use the static string instead because the actual error message cannot be obtain + // by serde_json serialization + let expected = r#"JsonRpcError { client_info: "coin: ETOMIC", request: JsonRpcRequest { jsonrpc: "2.0", id: "0", method: "blockchain.transaction.get", params: [String("0000000000000000000000000000000000000000000000000000000000000000"), Bool(true)] }, error: Response(electrum1.cipig.net:10060, Object({"code": Number(2), "message": String("daemon error: DaemonError({\'code\': -5, \'message\': \'No such mempool or blockchain transaction. Use gettransaction for wallet transactions.\'})")})) }"#; + let actual = format!("{}", err); + + assert_eq!(expected, actual); +} diff --git a/mm2src/common/jsonrpc_client.rs b/mm2src/common/jsonrpc_client.rs index cf9bab981b..7a4cacfe4c 100644 --- a/mm2src/common/jsonrpc_client.rs +++ b/mm2src/common/jsonrpc_client.rs @@ -23,6 +23,28 @@ macro_rules! rpc_func { }} } +/// Address of server from which an Rpc response was received +#[derive(Default)] +pub struct JsonRpcRemoteAddr(pub String); + +impl fmt::Debug for JsonRpcRemoteAddr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +impl From for String { + fn from(addr: JsonRpcRemoteAddr) -> Self { + addr.0 + } +} + +impl From for JsonRpcRemoteAddr { + fn from(addr: String) -> Self { + JsonRpcRemoteAddr(addr) + } +} + /// Serializable RPC request #[derive(Serialize, Deserialize, Debug, Clone)] pub struct JsonRpcRequest { @@ -53,7 +75,12 @@ pub struct JsonRpcResponse { #[derive(Debug)] pub struct JsonRpcError { + /// Additional member contains an instance info that implements the JsonRpcClient trait. + /// The info is used in particular to supplement the error info. + client_info: String, + /// Source Rpc request. request: JsonRpcRequest, + /// Error type. pub error: JsonRpcErrorType, } @@ -62,9 +89,9 @@ pub enum JsonRpcErrorType { /// Error from transport layer Transport(String), /// Response parse error - Parse(String), + Parse(JsonRpcRemoteAddr, String), /// The JSON-RPC error returned from server - Response(Json) + Response(JsonRpcRemoteAddr, Json) } impl fmt::Display for JsonRpcError { @@ -73,7 +100,7 @@ impl fmt::Display for JsonRpcError { } } -pub type JsonRpcResponseFut = Box + Send + 'static>; +pub type JsonRpcResponseFut = Box + Send + 'static>; pub type RpcRes = Box + Send + 'static>; pub trait JsonRpcClient { @@ -81,29 +108,37 @@ pub trait JsonRpcClient { fn next_id(&self) -> String; + /// Get info that is used in particular to supplement the error info + fn client_info(&self) -> String; + fn transport(&self, request: JsonRpcRequest) -> JsonRpcResponseFut; fn send_request(&self, request: JsonRpcRequest) -> RpcRes { + let client_info = self.client_info(); let request_f = self.transport(request.clone()).map_err({ + let client_info = client_info.clone(); let request = request.clone(); move |e| JsonRpcError { + client_info, request, error: JsonRpcErrorType::Transport(e) } }); - Box::new(request_f.and_then(move |response| -> Result { + Box::new(request_f.and_then(move |(addr, response)| -> Result { if !response.error.is_null() { return Err(JsonRpcError { + client_info, request, - error: JsonRpcErrorType::Response(response.error), + error: JsonRpcErrorType::Response(addr, response.error), }); } match json::from_value(response.result.clone()) { Ok(res) => Ok(res), Err(e) => Err(JsonRpcError { + client_info, request, - error: JsonRpcErrorType::Parse(ERRL!("error {:?} parsing result from response {:?}", e, response)), + error: JsonRpcErrorType::Parse(addr, ERRL!("error {:?} parsing result from response {:?}", e, response)), }), } })) diff --git a/mm2src/mm2_tests.rs b/mm2src/mm2_tests.rs index 72510cb4fb..b49d8af551 100644 --- a/mm2src/mm2_tests.rs +++ b/mm2src/mm2_tests.rs @@ -1403,7 +1403,9 @@ fn test_startup_passphrase() { /// MM2 should allow to issue several buy/sell calls in a row without delays. /// https://github.com/artemii235/SuperNET/issues/245 +/// TODO: Fix the test and delete the ignore attribute #[test] +#[ignore] #[cfg(feature = "native")] fn test_multiple_buy_sell_no_delay() { let coins = json!([