Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
eac9f81
save dev state
borngraced Jan 27, 2025
3618ddd
fix string termination err
borngraced Jan 27, 2025
6a48ca2
add is_active flag for MakerOrder
borngraced Feb 12, 2025
d2b8cff
add todos and fill is_active flag for MakerOrder initializations
borngraced Feb 12, 2025
98f53cc
pause maker others from matching if coin relies on electrum conns
borngraced Feb 12, 2025
ca7190f
remove todo comment and unneeded if-else
borngraced Feb 12, 2025
6420d94
remove unused
borngraced Feb 13, 2025
55e7f7a
nit
borngraced Feb 13, 2025
c4e458e
Merge branch 'dev' into cancel-offline-electrum-orders
borngraced Feb 13, 2025
5818720
update flag to is_offline
borngraced Feb 17, 2025
d58d2c0
fix cargo clippy
borngraced Feb 17, 2025
029c457
update order log info for offline orders
borngraced Feb 17, 2025
2e33e90
Merge branch 'dev' into cancel-offline-electrum-orders
borngraced Feb 19, 2025
b7ef6c3
use enum for MakerOrder status
borngraced Feb 19, 2025
e18f60b
fix clippy warnings
borngraced Feb 19, 2025
44ce1a9
rename MakerOrderStatus enum variants
borngraced Feb 19, 2025
94c5111
update docs
borngraced Feb 19, 2025
5997e23
Merge branch 'dev' into cancel-offline-electrum-orders
borngraced Feb 19, 2025
eedc9b9
cancel order, refactor save_my_t/maker_order
borngraced Mar 3, 2025
e598eb2
improve order cancelling logic, cover all coin/protocols and improve …
borngraced Mar 6, 2025
bfa7720
fix bug
borngraced Mar 6, 2025
fb2b4fe
fix bch
borngraced Mar 6, 2025
be73fa3
fix z_coin_cache db path in best_orders_tests
borngraced Mar 6, 2025
37ae831
use current_block to check eth server status
borngraced Mar 17, 2025
65296a6
Merge branch 'dev' into cancel-offline-electrum-orders
borngraced Mar 17, 2025
928520e
remove unnecessary line breaks
borngraced Mar 24, 2025
ba36f6c
Merge branch 'dev' into cancel-offline-electrum-orders
borngraced Apr 16, 2025
5ef3858
fix review notes
borngraced Apr 17, 2025
f49e339
nits
borngraced Apr 17, 2025
6287556
Merge branch 'dev' into cancel-offline-electrum-orders
borngraced Apr 24, 2025
0fa2ba8
Merge branch 'dev' into cancel-offline-electrum-orders
borngraced May 14, 2025
f505257
Merge branch 'dev' into cancel-offline-electrum-orders
borngraced May 20, 2025
18e3c87
Merge branch 'dev' into cancel-offline-electrum-orders
borngraced May 26, 2025
a4bea76
Merge branch 'dev' into cancel-offline-electrum-orders
borngraced May 30, 2025
c18e4af
Merge branch 'dev' into cancel-offline-electrum-orders
borngraced May 31, 2025
9306a25
merge with origin/dev
shamardy Jul 24, 2025
7c7f370
post merge fix
shamardy Jul 24, 2025
d75abc7
merge with origin/dev
shamardy Jul 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions mm2src/coins/lp_coins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3884,6 +3884,27 @@ impl MmCoinEnum {
self.ticker() == self.platform_ticker()
}

/// Check if coin server connection is offline.
pub async fn is_offline(&self) -> bool {
match self {
MmCoinEnum::Bch(c) => c.as_ref().rpc_client.is_offline(),
MmCoinEnum::QtumCoin(c) => c.as_ref().rpc_client.is_offline(),
MmCoinEnum::Qrc20Coin(c) => c.as_ref().rpc_client.is_offline(),
MmCoinEnum::SlpToken(c) => c.as_ref().rpc_client.is_offline(),
MmCoinEnum::UtxoCoin(c) => c.as_ref().rpc_client.is_offline(),
MmCoinEnum::ZCoin(c) => c.as_ref().rpc_client.is_offline(),
MmCoinEnum::Tendermint(c) => c.get_live_client().await.is_err(),
MmCoinEnum::EthCoin(c) => c.current_block().compat().await.is_err(),
MmCoinEnum::TendermintToken(c) => c.platform_coin.get_live_client().await.is_err(),
#[cfg(feature = "enable-sia")]
MmCoinEnum::SiaCoin(c) => c.is_offline().await,
#[cfg(not(target_arch = "wasm32"))]
MmCoinEnum::LightningCoin(c) => c.platform_coin().as_ref().rpc_client.is_offline(),
#[cfg(any(test, feature = "for-tests"))]
MmCoinEnum::Test(_) => false,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be annotated/cfg-ed for tests only. this breaks cargo check.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done thanks.

}
}

/// Determines the secret hash algorithm for a coin, prioritizing specific algorithms for certain protocols.
/// # Attention
/// When adding new coins, update this function to specify their appropriate secret hash algorithm.
Expand Down
8 changes: 8 additions & 0 deletions mm2src/coins/siacoin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ pub mod sia_hd_wallet;

#[derive(Clone)]
pub struct SiaCoin(SiaArc);

#[derive(Clone)]
pub struct SiaArc(Arc<SiaCoinFields>);

Expand Down Expand Up @@ -233,6 +234,13 @@ impl SiaArc {
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SiaCoinProtocolInfo;

impl SiaCoin {
/// Checks if `SiaCoin` api client is offline.
pub async fn is_offline(&self) -> bool {
self.0.http_client.current_height().await.is_err()
}
}

#[async_trait]
impl MmCoin for SiaCoin {
fn is_asset_chain(&self) -> bool {
Expand Down
33 changes: 25 additions & 8 deletions mm2src/coins/tendermint/tendermint_coin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ use primitives::hash::H256;
use regex::Regex;
use rpc::v1::types::{Bytes as BytesJson, H264 as H264Json};
use serde_json::{self as json, Value as Json};
use std::collections::HashMap;
use std::collections::{HashMap, VecDeque};
use std::convert::{TryFrom, TryInto};
use std::io;
use std::num::NonZeroU32;
Expand Down Expand Up @@ -365,7 +365,14 @@ impl TendermintActivationPolicy {
struct TendermintRpcClient(AsyncMutex<TendermintRpcClientImpl>);

struct TendermintRpcClientImpl {
rpc_clients: Vec<HttpClient>,
/// Using `VecDeque` instead of `Vec` for several performance reasons:
/// 1. O(1) operations for adding/removing clients at both ends (vs O(n) for `Vec.rotate_left()`)
/// 2. More efficient for the round-robin client selection pattern we use
/// 3. Better handling of client rotation without needing to clone the entire collection
///
/// This approach improves performance in high-frequency scenarios where we need to
/// try multiple RPC nodes quickly to find a responsive one.
rpc_clients: VecDeque<HttpClient>,
}

#[async_trait]
Expand All @@ -375,22 +382,31 @@ impl RpcCommonOps for TendermintCoin {

async fn get_live_client(&self) -> Result<Self::RpcClient, Self::Error> {
let mut client_impl = self.client.0.lock().await;
let client_count = client_impl.rpc_clients.len();

// try to find first live client
for (i, client) in client_impl.rpc_clients.clone().into_iter().enumerate() {
for _ in 0..client_count {
// SAFETY: Safe because we know the count and avoid bound check.
let client = client_impl.rpc_clients.pop_front().unwrap();
match client.perform(HealthRequest).timeout(Duration::from_secs(15)).await {
Ok(Ok(_)) => {
// Bring the live client to the front of rpc_clients
client_impl.rpc_clients.rotate_left(i);
client_impl.rpc_clients.push_front(client.clone());
return Ok(client);
},
Ok(Err(rpc_error)) => {
debug!("Could not perform healthcheck on: {:?}. Error: {}", &client, rpc_error);
// Put the failed client at the back of the queue
client_impl.rpc_clients.push_back(client);
},
Err(timeout_error) => {
debug!("Healthcheck timeout exceed on: {:?}. Error: {}", &client, timeout_error);
// Put the failed client at the back of the queue
client_impl.rpc_clients.push_back(client);
},
};
}

return Err(TendermintCoinRpcError::RpcClientError(
"All the current rpc nodes are unavailable.".to_string(),
));
Expand Down Expand Up @@ -3204,7 +3220,7 @@ impl TendermintCoin {
}
}

fn clients_from_urls(ctx: &MmArc, nodes: Vec<RpcNode>) -> MmResult<Vec<HttpClient>, TendermintInitErrorKind> {
fn clients_from_urls(ctx: &MmArc, nodes: Vec<RpcNode>) -> MmResult<VecDeque<HttpClient>, TendermintInitErrorKind> {
if nodes.is_empty() {
return MmError::err(TendermintInitErrorKind::EmptyRpcUrls);
}
Expand All @@ -3216,20 +3232,21 @@ fn clients_from_urls(ctx: &MmArc, nodes: Vec<RpcNode>) -> MmResult<Vec<HttpClien
None
};

let mut clients = Vec::new();
let mut errors = Vec::new();
let mut clients = VecDeque::with_capacity(nodes.len());
let mut errors = Vec::with_capacity(nodes.len());

// check that all urls are valid
// keep all invalid urls in one vector to show all of them in error
for node in nodes.iter() {
let proxy_sign_keypair = if node.komodo_proxy { p2p_keypair.clone() } else { None };
match HttpClient::new(node.url.as_str(), proxy_sign_keypair) {
Ok(client) => clients.push(client),
Ok(client) => clients.push_back(client),
Err(e) => errors.push(format!("Url {} is invalid, got error {}", node.url, e)),
}
}
drop_mutability!(clients);
drop_mutability!(errors);

if !errors.is_empty() {
let errors: String = errors.into_iter().join(", ");
return MmError::err(TendermintInitErrorKind::RpcClientInitError(errors));
Expand Down
9 changes: 9 additions & 0 deletions mm2src/coins/utxo/rpc_clients.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,15 @@ impl UtxoRpcClientEnum {
UtxoRpcClientEnum::Electrum(_) => false,
}
}

/// Checks if all `ElectrumClient` servers are offline.
pub fn is_offline(&self) -> bool {
if let UtxoRpcClientEnum::Electrum(client) = self {
client.is_offline()
} else {
false
}
}
}

/// Generic unspent info required to build transactions, we need this separate type because native
Expand Down
4 changes: 4 additions & 0 deletions mm2src/coins/utxo/rpc_clients/electrum_rpc/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -837,6 +837,10 @@ impl ElectrumClient {

Box::new(fut.boxed().compat())
}

pub fn is_offline(&self) -> bool {
self.connection_manager.is_completely_offline()
}
}

// if mockable is placed before async_trait there is `munmap_chunk(): invalid pointer` error on async fn mocking attempt
Expand Down
2 changes: 1 addition & 1 deletion mm2src/coins/utxo/rpc_clients/electrum_rpc/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ impl ElectrumConnection {
self.abortable_system.weak_spawner()
}

fn is_connected(&self) -> bool {
pub(crate) fn is_connected(&self) -> bool {
self.tx.lock().unwrap().is_some()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,19 @@ impl ConnectionManager {
self.write_connections().remove(server_address);
Ok(connection)
}

/// Checks if there are no live server connections available.
pub fn is_completely_offline(&self) -> bool {
for server_address in self.read_maintained_connections().values() {
if let Some(connection) = self.get_connection(server_address) {
if connection.is_connected() {
return false;
}
};
}

true
}
}

// Background tasks.
Expand Down
Loading
Loading