// PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
// https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
#![allow(unused, non_snake_case, clippy::all)]
use crate::Value;
use crate::get_value;
use crate::runtime::*;
// Base methods are now trait methods (review #1: static dispatch). Bring the
// traits into scope so `self.market(...)`, `self.safe_market(...)`,
// `self.load_markets(...)`, … on this Core resolve to the base defaults.
use crate::exchange_generated::ExchangeBase;
use crate::exchange::ExchangeRuntime;
// Dynamic `this[method](...)` re-entries are emitted as
// `self.call_dynamic_checked(...)` (blanket-impl'd on every Core) so an
// unresolvable name raises NotSupported instead of yielding a silent Null.
use crate::exchange::CallDynamicChecked;
use crate::pro::*;
pub struct MexcCore {
pub parent: crate::exchanges::mexc::MexcCore,
}
impl MexcCore {
pub fn new(config: Option<crate::Value>) -> Self {
let mut s = Self { parent: crate::exchanges::mexc::MexcCore::new(config) };
s.init();
s
}
pub fn init(&mut self) {
let described = MexcCore::describe(self);
self.initialize_properties(described);
<Self as crate::exchange_generated::ExchangeBase>::after_construct(self);
}
/// Compatibility no-op. The old pointer-based dispatch needed a post-move
/// `bind()`; static trait dispatch (review #1) needs no binding, so this
/// just exists so callers that still call it keep compiling.
#[inline]
pub fn bind(&mut self) {}
}
impl crate::exchange::DerivedExchange for MexcCore {
fn nonce(&self, ) -> crate::Value {
crate::exchange::DerivedExchange::nonce(&self.parent)
}
fn parse_ticker(&self, ticker: crate::Value, market: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_ticker(&self.parent, ticker, market)
}
fn parse_trade(&self, trade: crate::Value, market: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_trade(&self.parent, trade, market)
}
fn parse_order(&self, order: crate::Value, market: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_order(&self.parent, order, market)
}
fn parse_market(&self, market: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_market(&self.parent, market)
}
fn parse_ohlcv(&self, ohlcv: crate::Value, market: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_ohlcv(&self.parent, ohlcv, market)
}
fn parse_order_book(&self, ob: crate::Value, symbol: crate::Value, ts: crate::Value, bk: crate::Value, ak: crate::Value, pk: crate::Value, ak2: crate::Value, ck: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_order_book(&self.parent, ob, symbol, ts, bk, ak, pk, ak2, ck)
}
fn parse_balance(&self, response: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_balance(&self.parent, response)
}
fn parse_position(&self, position: crate::Value, market: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_position(&self.parent, position, market)
}
fn parse_funding_rate(&self, rate: crate::Value, market: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_funding_rate(&self.parent, rate, market)
}
fn parse_deposit(&self, tx: crate::Value, currency: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_deposit(&self.parent, tx, currency)
}
fn parse_deposit_address(&self, depositAddress: crate::Value, currency: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_deposit_address(&self.parent, depositAddress, currency)
}
fn parse_last_price(&self, entry: crate::Value, market: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_last_price(&self.parent, entry, market)
}
fn parse_withdrawal(&self, tx: crate::Value, currency: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_withdrawal(&self.parent, tx, currency)
}
fn parse_ledger_entry(&self, entry: crate::Value, currency: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_ledger_entry(&self.parent, entry, currency)
}
fn parse_transfer(&self, transfer: crate::Value, currency: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_transfer(&self.parent, transfer, currency)
}
fn parse_currency(&self, currency: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_currency(&self.parent, currency)
}
fn parse_bid_ask(&self, bidask: crate::Value, price_key: crate::Value, amount_key: crate::Value, market: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_bid_ask(&self.parent, bidask, price_key, amount_key, market)
}
fn parse_open_interest(&self, interest: crate::Value, market: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_open_interest(&self.parent, interest, market)
}
fn parse_liquidation(&self, liquidation: crate::Value, market: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_liquidation(&self.parent, liquidation, market)
}
fn parse_funding_rate_history(&self, entry: crate::Value, market: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_funding_rate_history(&self.parent, entry, market)
}
fn parse_margin_modification(&self, data: crate::Value, market: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_margin_modification(&self.parent, data, market)
}
fn parse_account(&self, account: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_account(&self.parent, account)
}
fn parse_my_trade(&self, trade: crate::Value, market: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_my_trade(&self.parent, trade, market)
}
fn parse_transaction(&self, transaction: crate::Value, currency: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_transaction(&self.parent, transaction, currency)
}
fn parse_borrow_interest(&self, info: crate::Value, market: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_borrow_interest(&self.parent, info, market)
}
fn parse_adl_rank(&self, info: crate::Value, market: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_adl_rank(&self.parent, info, market)
}
fn parse_income(&self, info: crate::Value, market: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_income(&self.parent, info, market)
}
fn parse_greeks(&self, greeks: crate::Value, market: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_greeks(&self.parent, greeks, market)
}
fn parse_margin_mode(&self, margin_mode: crate::Value, market: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_margin_mode(&self.parent, margin_mode, market)
}
fn parse_conversion(&self, conversion: crate::Value, from_currency: crate::Value, to_currency: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_conversion(&self.parent, conversion, from_currency, to_currency)
}
fn parse_borrow_rate(&self, info: crate::Value, currency: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_borrow_rate(&self.parent, info, currency)
}
fn parse_leverage(&self, leverage: crate::Value, market: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_leverage(&self.parent, leverage, market)
}
fn parse_market_leverage_tiers(&self, info: crate::Value, market: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_market_leverage_tiers(&self.parent, info, market)
}
fn parse_deposit_withdraw_fee(&self, fee: crate::Value, currency: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_deposit_withdraw_fee(&self.parent, fee, currency)
}
fn parse_prediction_trade(&self, trade: crate::Value, market: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_prediction_trade(&self.parent, trade, market)
}
fn parse_prediction_order(&self, order: crate::Value, market: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_prediction_order(&self.parent, order, market)
}
fn parse_prediction_position(&self, position: crate::Value, market: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::parse_prediction_position(&self.parent, position, market)
}
fn create_expired_option_market(&self, symbol: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::create_expired_option_market(&self.parent, symbol)
}
fn sign(&self, path: crate::Value, api: crate::Value, method: crate::Value, params: crate::Value, headers: crate::Value, body: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::sign(&self.parent, path, api, method, params, headers, body)
}
fn handle_errors(&self, code: crate::Value, reason: crate::Value, url: crate::Value, method: crate::Value, headers: crate::Value, body: crate::Value, response: crate::Value, request_headers: crate::Value, request_body: crate::Value) -> crate::Value {
crate::exchange::DerivedExchange::handle_errors(&self.parent, code, reason, url, method, headers, body, response, request_headers, request_body)
}
}
impl crate::exchange_generated::ExchangeBase for MexcCore {
fn call_dynamic<'a>(&'a mut self, method: &'a str, args: Vec<crate::Value>)
-> std::pin::Pin<Box<dyn std::future::Future<Output = crate::Value> + Send + 'a>>
{
Box::pin(async move {
match method {
"authenticate" => self.authenticate(args.get(0).cloned().unwrap_or(crate::Value::Null), &args[1.min(args.len())..]).await,
"get_cache_index" => self.get_cache_index(args.get(0).cloned().unwrap_or(crate::Value::Null), args.get(1).cloned().unwrap_or(crate::Value::Null)),
"handle_message" => { self.handle_message(args.get(0).cloned().unwrap_or(crate::Value::Null), args.get(1).cloned().unwrap_or(crate::Value::Null)); crate::Value::Null },
"handle_pong" => self.handle_pong(args.get(0).cloned().unwrap_or(crate::Value::Null), args.get(1).cloned().unwrap_or(crate::Value::Null)),
"handle_protobuf_message" => self.handle_protobuf_message(args.get(0).cloned().unwrap_or(crate::Value::Null), args.get(1).cloned().unwrap_or(crate::Value::Null)),
"keep_alive_listen_key" => self.keep_alive_listen_key(args.get(0).cloned().unwrap_or(crate::Value::Null), &args[1.min(args.len())..]).await,
"parse_ws_bid_ask" => self.parse_ws_bid_ask(args.get(0).cloned().unwrap_or(crate::Value::Null), &args[1.min(args.len())..]),
"parse_ws_ohlcv" => self.parse_ws_ohlcv(args.get(0).cloned().unwrap_or(crate::Value::Null), &args[1.min(args.len())..]),
"parse_ws_order" => self.parse_ws_order(args.get(0).cloned().unwrap_or(crate::Value::Null), &args[1.min(args.len())..]),
"parse_ws_ticker" => self.parse_ws_ticker(args.get(0).cloned().unwrap_or(crate::Value::Null), &args[1.min(args.len())..]),
"parse_ws_trade" => self.parse_ws_trade(args.get(0).cloned().unwrap_or(crate::Value::Null), &args[1.min(args.len())..]),
"ping" => self.ping(args.get(0).cloned().unwrap_or(crate::Value::Null)),
"un_watch_bids_asks" => self.un_watch_bids_asks(&args[..]).await,
"un_watch_funding_rate" => self.un_watch_funding_rate(args.get(0).cloned().unwrap_or(crate::Value::Null), &args[1.min(args.len())..]).await,
"un_watch_ohlcv" => self.un_watch_ohlcv(args.get(0).cloned().unwrap_or(crate::Value::Null), &args[1.min(args.len())..]).await,
"un_watch_order_book" => self.un_watch_order_book(args.get(0).cloned().unwrap_or(crate::Value::Null), &args[1.min(args.len())..]).await,
"un_watch_ticker" => self.un_watch_ticker(args.get(0).cloned().unwrap_or(crate::Value::Null), &args[1.min(args.len())..]).await,
"un_watch_tickers" => self.un_watch_tickers(&args[..]).await,
"un_watch_trades" => self.un_watch_trades(args.get(0).cloned().unwrap_or(crate::Value::Null), &args[1.min(args.len())..]).await,
"watch_balance" => self.watch_balance(&args[..]).await,
"watch_bids_asks" => self.watch_bids_asks(&args[..]).await,
"watch_funding_rate" => self.watch_funding_rate(args.get(0).cloned().unwrap_or(crate::Value::Null), &args[1.min(args.len())..]).await,
"watch_my_trades" => self.watch_my_trades(&args[..]).await,
"watch_ohlcv" => self.watch_ohlcv(args.get(0).cloned().unwrap_or(crate::Value::Null), &args[1.min(args.len())..]).await,
"watch_order_book" => self.watch_order_book(args.get(0).cloned().unwrap_or(crate::Value::Null), &args[1.min(args.len())..]).await,
"watch_orders" => self.watch_orders(&args[..]).await,
"watch_spot_private" => self.watch_spot_private(args.get(0).cloned().unwrap_or(crate::Value::Null), args.get(1).cloned().unwrap_or(crate::Value::Null), &args[2.min(args.len())..]).await,
"watch_spot_public" => self.watch_spot_public(args.get(0).cloned().unwrap_or(crate::Value::Null), args.get(1).cloned().unwrap_or(crate::Value::Null), &args[2.min(args.len())..]).await,
"watch_swap_private" => self.watch_swap_private(args.get(0).cloned().unwrap_or(crate::Value::Null), &args[1.min(args.len())..]).await,
"watch_swap_public" => self.watch_swap_public(args.get(0).cloned().unwrap_or(crate::Value::Null), args.get(1).cloned().unwrap_or(crate::Value::Null), args.get(2).cloned().unwrap_or(crate::Value::Null), &args[3.min(args.len())..]).await,
"watch_ticker" => self.watch_ticker(args.get(0).cloned().unwrap_or(crate::Value::Null), &args[1.min(args.len())..]).await,
"watch_tickers" => self.watch_tickers(&args[..]).await,
"watch_trades" => self.watch_trades(args.get(0).cloned().unwrap_or(crate::Value::Null), &args[1.min(args.len())..]).await,
// Go-style inheritance: an un-overridden method dispatches to the parent core.
_ => crate::exchange_generated::ExchangeBase::call_dynamic(&mut self.parent, method, args).await,
}
})
}
}
impl MexcCore {
/// Synchronous WS handler dispatch — routes a handler-name string (from the
/// venue's handle_message dispatch table) to the real handler method.
#[allow(dead_code, unreachable_patterns, clippy::all)]
pub fn dispatch_ws_handler(&mut self, __name: &crate::Value, args: &[crate::Value]) -> crate::Value {
let __n = match __name { crate::Value::Str(s) => s.as_ref(), _ => return crate::Value::Null };
match __n {
"authenticate" => { crate::exchange_stubs::enqueue_spawn("authenticate", args.to_vec()); crate::Value::Null },
"get_cache_index" => self.get_cache_index(args.get(0).cloned().unwrap_or(crate::Value::Null), args.get(1).cloned().unwrap_or(crate::Value::Null)),
"handle_balance" => { self.handle_balance(args.get(0).cloned().unwrap_or(crate::Value::Null), args.get(1).cloned().unwrap_or(crate::Value::Null)); crate::Value::Null },
"handle_bid_ask" => { self.handle_bid_ask(args.get(0).cloned().unwrap_or(crate::Value::Null), args.get(1).cloned().unwrap_or(crate::Value::Null)); crate::Value::Null },
"handle_bookside_delta" => { self.handle_bookside_delta(args.get(0).cloned().unwrap_or(crate::Value::Null), args.get(1).cloned().unwrap_or(crate::Value::Null)); crate::Value::Null },
"handle_delta" => { self.handle_delta(args.get(0).cloned().unwrap_or(crate::Value::Null), args.get(1).cloned().unwrap_or(crate::Value::Null)); crate::Value::Null },
"handle_funding_rate" => { self.handle_funding_rate(args.get(0).cloned().unwrap_or(crate::Value::Null), args.get(1).cloned().unwrap_or(crate::Value::Null)); crate::Value::Null },
"handle_message" => { self.handle_message(args.get(0).cloned().unwrap_or(crate::Value::Null), args.get(1).cloned().unwrap_or(crate::Value::Null)); crate::Value::Null },
"handle_my_trade" => { self.handle_my_trade(args.get(0).cloned().unwrap_or(crate::Value::Null), args.get(1).cloned().unwrap_or(crate::Value::Null), &args[2.min(args.len())..]); crate::Value::Null },
"handle_ohlcv" => { self.handle_ohlcv(args.get(0).cloned().unwrap_or(crate::Value::Null), args.get(1).cloned().unwrap_or(crate::Value::Null)); crate::Value::Null },
"handle_order" => { self.handle_order(args.get(0).cloned().unwrap_or(crate::Value::Null), args.get(1).cloned().unwrap_or(crate::Value::Null)); crate::Value::Null },
"handle_order_book" => { self.handle_order_book(args.get(0).cloned().unwrap_or(crate::Value::Null), args.get(1).cloned().unwrap_or(crate::Value::Null)); crate::Value::Null },
"handle_order_book_subscription" => { self.handle_order_book_subscription(args.get(0).cloned().unwrap_or(crate::Value::Null), args.get(1).cloned().unwrap_or(crate::Value::Null)); crate::Value::Null },
"handle_pong" => self.handle_pong(args.get(0).cloned().unwrap_or(crate::Value::Null), args.get(1).cloned().unwrap_or(crate::Value::Null)),
"handle_protobuf_message" => self.handle_protobuf_message(args.get(0).cloned().unwrap_or(crate::Value::Null), args.get(1).cloned().unwrap_or(crate::Value::Null)),
"handle_subscription_status" => { self.handle_subscription_status(args.get(0).cloned().unwrap_or(crate::Value::Null), args.get(1).cloned().unwrap_or(crate::Value::Null)); crate::Value::Null },
"handle_ticker" => { self.handle_ticker(args.get(0).cloned().unwrap_or(crate::Value::Null), args.get(1).cloned().unwrap_or(crate::Value::Null)); crate::Value::Null },
"handle_tickers" => { self.handle_tickers(args.get(0).cloned().unwrap_or(crate::Value::Null), args.get(1).cloned().unwrap_or(crate::Value::Null)); crate::Value::Null },
"handle_trades" => { self.handle_trades(args.get(0).cloned().unwrap_or(crate::Value::Null), args.get(1).cloned().unwrap_or(crate::Value::Null)); crate::Value::Null },
"handle_unsubscriptions" => { self.handle_unsubscriptions(args.get(0).cloned().unwrap_or(crate::Value::Null), args.get(1).cloned().unwrap_or(crate::Value::Null)); crate::Value::Null },
"keep_alive_listen_key" => { crate::exchange_stubs::enqueue_spawn("keep_alive_listen_key", args.to_vec()); crate::Value::Null },
"parse_ws_bid_ask" => self.parse_ws_bid_ask(args.get(0).cloned().unwrap_or(crate::Value::Null), &args[1.min(args.len())..]),
"parse_ws_ohlcv" => self.parse_ws_ohlcv(args.get(0).cloned().unwrap_or(crate::Value::Null), &args[1.min(args.len())..]),
"parse_ws_order" => self.parse_ws_order(args.get(0).cloned().unwrap_or(crate::Value::Null), &args[1.min(args.len())..]),
"parse_ws_ticker" => self.parse_ws_ticker(args.get(0).cloned().unwrap_or(crate::Value::Null), &args[1.min(args.len())..]),
"parse_ws_trade" => self.parse_ws_trade(args.get(0).cloned().unwrap_or(crate::Value::Null), &args[1.min(args.len())..]),
"ping" => self.ping(args.get(0).cloned().unwrap_or(crate::Value::Null)),
"un_watch_bids_asks" => { crate::exchange_stubs::enqueue_spawn("un_watch_bids_asks", args.to_vec()); crate::Value::Null },
"un_watch_funding_rate" => { crate::exchange_stubs::enqueue_spawn("un_watch_funding_rate", args.to_vec()); crate::Value::Null },
"un_watch_ohlcv" => { crate::exchange_stubs::enqueue_spawn("un_watch_ohlcv", args.to_vec()); crate::Value::Null },
"un_watch_order_book" => { crate::exchange_stubs::enqueue_spawn("un_watch_order_book", args.to_vec()); crate::Value::Null },
"un_watch_ticker" => { crate::exchange_stubs::enqueue_spawn("un_watch_ticker", args.to_vec()); crate::Value::Null },
"un_watch_tickers" => { crate::exchange_stubs::enqueue_spawn("un_watch_tickers", args.to_vec()); crate::Value::Null },
"un_watch_trades" => { crate::exchange_stubs::enqueue_spawn("un_watch_trades", args.to_vec()); crate::Value::Null },
"watch_balance" => { crate::exchange_stubs::enqueue_spawn("watch_balance", args.to_vec()); crate::Value::Null },
"watch_bids_asks" => { crate::exchange_stubs::enqueue_spawn("watch_bids_asks", args.to_vec()); crate::Value::Null },
"watch_funding_rate" => { crate::exchange_stubs::enqueue_spawn("watch_funding_rate", args.to_vec()); crate::Value::Null },
"watch_my_trades" => { crate::exchange_stubs::enqueue_spawn("watch_my_trades", args.to_vec()); crate::Value::Null },
"watch_ohlcv" => { crate::exchange_stubs::enqueue_spawn("watch_ohlcv", args.to_vec()); crate::Value::Null },
"watch_order_book" => { crate::exchange_stubs::enqueue_spawn("watch_order_book", args.to_vec()); crate::Value::Null },
"watch_orders" => { crate::exchange_stubs::enqueue_spawn("watch_orders", args.to_vec()); crate::Value::Null },
"watch_spot_private" => { crate::exchange_stubs::enqueue_spawn("watch_spot_private", args.to_vec()); crate::Value::Null },
"watch_spot_public" => { crate::exchange_stubs::enqueue_spawn("watch_spot_public", args.to_vec()); crate::Value::Null },
"watch_swap_private" => { crate::exchange_stubs::enqueue_spawn("watch_swap_private", args.to_vec()); crate::Value::Null },
"watch_swap_public" => { crate::exchange_stubs::enqueue_spawn("watch_swap_public", args.to_vec()); crate::Value::Null },
"watch_ticker" => { crate::exchange_stubs::enqueue_spawn("watch_ticker", args.to_vec()); crate::Value::Null },
"watch_tickers" => { crate::exchange_stubs::enqueue_spawn("watch_tickers", args.to_vec()); crate::Value::Null },
"watch_trades" => { crate::exchange_stubs::enqueue_spawn("watch_trades", args.to_vec()); crate::Value::Null },
_ => crate::Value::Null,
}
}
}
impl std::ops::Deref for MexcCore {
type Target = crate::exchange::Exchange;
fn deref(&self) -> &crate::exchange::Exchange { std::ops::Deref::deref(&self.parent) }
}
impl std::ops::DerefMut for MexcCore {
fn deref_mut(&mut self) -> &mut crate::exchange::Exchange { std::ops::DerefMut::deref_mut(&mut self.parent) }
}
impl MexcCore {
pub fn describe(&self) -> Value {
return self.deep_extend(self.parent.describe(), &[Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("has".to_string(), Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("ws".to_string(), Value::Bool(true));
m.insert("cancelAllOrdersWs".to_string(), Value::Bool(false));
m.insert("cancelOrdersWs".to_string(), Value::Bool(false));
m.insert("cancelOrderWs".to_string(), Value::Bool(false));
m.insert("createOrderWs".to_string(), Value::Bool(false));
m.insert("editOrderWs".to_string(), Value::Bool(false));
m.insert("fetchBalanceWs".to_string(), Value::Bool(false));
m.insert("fetchOpenOrdersWs".to_string(), Value::Bool(false));
m.insert("fetchOrderWs".to_string(), Value::Bool(false));
m.insert("fetchTradesWs".to_string(), Value::Bool(false));
m.insert("watchBalance".to_string(), Value::Bool(true));
m.insert("watchFundingRate".to_string(), Value::Bool(true));
m.insert("watchFundingRates".to_string(), Value::Bool(false));
m.insert("watchMyTrades".to_string(), Value::Bool(true));
m.insert("watchOHLCV".to_string(), Value::Bool(true));
m.insert("watchOrderBook".to_string(), Value::Bool(true));
m.insert("watchOrders".to_string(), Value::Bool(true));
m.insert("watchTicker".to_string(), Value::Bool(true));
m.insert("watchTickers".to_string(), Value::Bool(true));
m.insert("watchBidsAsks".to_string(), Value::Bool(true));
m.insert("watchTrades".to_string(), Value::Bool(true));
m.insert("watchTradesForSymbols".to_string(), Value::Bool(false));
m.insert("unWatchTicker".to_string(), Value::Bool(true));
m.insert("unWatchTickers".to_string(), Value::Bool(true));
m.insert("unWatchBidsAsks".to_string(), Value::Bool(true));
m.insert("unWatchOHLCV".to_string(), Value::Bool(true));
m.insert("unWatchOrderBook".to_string(), Value::Bool(true));
m.insert("unWatchTrades".to_string(), Value::Bool(true));
m
}));
m.insert("urls".to_string(), Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("api".to_string(), Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("ws".to_string(), Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("spot".to_string(), Value::Str("wss://wbs-api.mexc.com/ws".into()));
m.insert("swap".to_string(), Value::Str("wss://contract.mexc.com/edge".into()));
m
}));
m
}));
m
}));
m.insert("options".to_string(), Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("listenKeyRefreshRate".to_string(), Value::Int(1200000));
m.insert("decompressBinary".to_string(), Value::Bool(false));
m.insert("timeframes".to_string(), Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("1m".to_string(), Value::Str("Min1".into()));
m.insert("5m".to_string(), Value::Str("Min5".into()));
m.insert("15m".to_string(), Value::Str("Min15".into()));
m.insert("30m".to_string(), Value::Str("Min30".into()));
m.insert("1h".to_string(), Value::Str("Min60".into()));
m.insert("4h".to_string(), Value::Str("Hour4".into()));
m.insert("8h".to_string(), Value::Str("Hour8".into()));
m.insert("1d".to_string(), Value::Str("Day1".into()));
m.insert("1w".to_string(), Value::Str("Week1".into()));
m.insert("1M".to_string(), Value::Str("Month1".into()));
m
}));
m.insert("watchOrderBook".to_string(), Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("snapshotDelay".to_string(), Value::Int(25));
m.insert("snapshotMaxRetries".to_string(), Value::Int(3));
m
}));
m.insert("listenKey".to_string(), Value::Null);
m
}));
m.insert("streaming".to_string(), Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("ping".to_string(), Value::Str("ping".into()).clone());
m.insert("keepAlive".to_string(), Value::Int(8000));
m
}));
m.insert("exceptions".to_string(), Value::Map({
let mut m = indexmap::IndexMap::new();
m
}));
m
})]);
Value::Null
}
/*
* @method
* @name mexc#watchTicker
* @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
* @see https://www.mexc.com/api-docs/spot-v3/websocket-market-streams/individual-symbol-book-ticker-streams // spot
* @see https://www.mexc.com/api-docs/futures/websocket-api/get-a-single-ticker // swap
* @param {string} symbol unified symbol of the market to fetch the ticker for
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/?id=ticker-structure}
*/
pub async fn watch_ticker(&mut self, mut symbol: Value, optional_args: &[Value]) -> Value {
let mut params = get_arg(optional_args, 0, Value::Map({
let mut m = indexmap::IndexMap::new();
m
}));
if (self.markets.clone() == Value::Null) {
self.load_markets(&[]).await;
}
let mut market: Value = self.market(symbol);
let mut messageHash: Value = Value::Str(format!("{}{}", Value::Str("ticker:".into()), market.as_map().and_then(|__m| __m.get("symbol")).cloned().unwrap_or(Value::Null)).into());
if (market.as_map().and_then(|__m| __m.get("spot")).cloned().unwrap_or(Value::Null).as_bool() == Some(true)) {
let mut channel: Value = Value::Str(format!("{}{}", Value::Str("spot@public.aggre.bookTicker.v3.api.pb@100ms@".into()), market.as_map().and_then(|__m| __m.get("id")).cloned().unwrap_or(Value::Null)).into());
return self.watch_spot_public(channel.clone(), messageHash.clone(), &[params.clone()]).await;
} else {
let mut channel: Value = Value::Str("sub.ticker".into());
let mut requestParams: Value = Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("symbol".to_string(), market.as_map().and_then(|__m| __m.get("id")).cloned().unwrap_or(Value::Null));
m
});
return self.watch_swap_public(channel, messageHash, requestParams, &[params]).await;
}
Value::Null
}
pub fn handle_ticker(&mut self, mut client: Value, mut message: Value) {
//
// swap
//
// {
// "symbol": "BTC_USDT",
// "data": {
// "symbol": "BTC_USDT",
// "lastPrice": 76376.1,
// "riseFallRate": -0.0006,
// "fairPrice": 76374.4,
// "indexPrice": 76385.8,
// "volume24": 962062810,
// "amount24": 7344207079.96768,
// "maxBidPrice": 84024.3,
// "minAskPrice": 68747.2,
// "lower24Price": 75620.2,
// "high24Price": 77210,
// "timestamp": 1731137509138,
// "bid1": 76376.2,
// "ask1": 76376.3,
// "holdVol": 95479623,
// "riseFallValue": -46.5,
// "fundingRate": 0.0001,
// "zone": "UTC+8",
// "riseFallRates": [ -0.0006, 0.1008, 0.2262, 0.2628, 0.2439, 1.0564 ],
// "riseFallRatesOfTimezone": [ 0.0065, -0.0013, -0.0006 ]
// },
// "channel": "push.ticker",
// "ts": 1731137509138
// }
//
// spot
//
// {
// "c": "spot@public.bookTicker.v3.api@BTCUSDT",
// "d": {
// "A": "4.70432",
// "B": "6.714863",
// "a": "20744.54",
// "b": "20744.17"
// },
// "s": "BTCUSDT",
// "t": 1678643605721
// }
//
// spot miniTicker
//
// {
// "d": {
// "s": "BTCUSDT",
// "p": "76522",
// "r": "0.0012",
// "tr": "0.0012",
// "h": "77196.3",
// "l": "75630.77",
// "v": "584664223.92",
// "q": "7666.720258",
// "lastRT": "-1",
// "MT": "0",
// "NV": "--",
// "t": "1731135533126"
// },
// "c": "spot@public.miniTicker.v3.api@BTCUSDT@UTC+8",
// "t": 1731135533126,
// "s": "BTCUSDT"
// }
//
self.handle_bid_ask(client.clone(), message.clone());
let mut rawTicker: Value = self.safe_dict_n(message.clone(), Value::from(vec![Value::Str("d".into()), Value::Str("data".into()), Value::Str("publicAggreBookTicker".into())]), &[]);
let mut marketId: Value = self.safe_string2(message.clone(), Value::Str("s".into()), Value::Str("symbol".into()), &[]);
let mut timestamp: Value = self.safe_integer2(message, Value::Str("t".into()), Value::Str("sendTime".into()), &[]);
let mut market: Value = self.safe_market(&[marketId]);
let mut symbol: Value = market.as_map().and_then(|__m| __m.get("symbol")).cloned().unwrap_or(Value::Null);
let mut ticker: Value = Value::Null;
if (market.as_map().and_then(|__m| __m.get("spot")).cloned().unwrap_or(Value::Null).as_bool() == Some(true)) {
ticker = self.parse_ws_ticker(rawTicker.clone(), &[market.clone()]);
add_element_to_object(&mut ticker, &Value::Str("timestamp".into()), timestamp.clone());
add_element_to_object(&mut ticker, &Value::Str("datetime".into()), self.iso8601(timestamp));
} else if (rawTicker != Value::Null) {
ticker = self.parse_ticker(rawTicker, &[market]);
} else {
return;
}
if let Value::Dict(__d) = &mut self.tickers { std::sync::Arc::make_mut(__d).insert(crate::runtime::stringify_param(&symbol), ticker.clone()); }
let mut messageHash: Value = Value::Str(format!("{}{}", Value::Str("ticker:".into()), symbol).into());
client.resolve(&[ticker, messageHash]);
}
/*
* @method
* @name mexc#watchTickers
* @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
* @see https://www.mexc.com/api-docs/futures/websocket-api/tickers
* @param {string[]} symbols unified symbol of the market to fetch the ticker for
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/?id=ticker-structure}
*/
pub async fn watch_tickers(&mut self, optional_args: &[Value]) -> Value {
let mut symbols = get_arg(optional_args, 0, Value::Null);
let mut params = get_arg(optional_args, 1, Value::Map({
let mut m = indexmap::IndexMap::new();
m
}));
if (self.markets.clone() == Value::Null) {
self.load_markets(&[]).await;
}
symbols = self.market_symbols(&[symbols.clone(), Value::Null]);
let mut messageHashes: Value = Value::from(vec![]);
let mut firstSymbol: Value = self.safe_string(symbols.clone(), Value::Int(0), &[]);
let mut market: Value = Value::Null;
if (firstSymbol != Value::Null) {
market = self.market(firstSymbol);
}
let mut type_var: Value = Value::Null;
{ let __destr_tmp = self.handle_market_type_and_params(Value::Str("watchTickers".into()), &[market, params.clone()]); type_var = __destr_tmp.as_array().and_then(|__arr| __arr.get(0)).cloned().unwrap_or(Value::Null); params = __destr_tmp.as_array().and_then(|__arr| __arr.get(1)).cloned().unwrap_or(Value::Null); }
let mut isSpot: bool = type_var.as_str() == Some("spot");
let mut url: Value = (if (isSpot) { crate::value::get_value_k(&self.urls.as_map().and_then(|__m| __m.get("api")).cloned().unwrap_or(Value::Null).as_map().and_then(|__m| __m.get("ws")).cloned().unwrap_or(Value::Null), "spot") } else { crate::value::get_value_k(&self.urls.as_map().and_then(|__m| __m.get("api")).cloned().unwrap_or(Value::Null).as_map().and_then(|__m| __m.get("ws")).cloned().unwrap_or(Value::Null), "swap") });
let mut request: Value = Value::Map({
let mut m = indexmap::IndexMap::new();
m
});
if isSpot {
panic!("{}", crate::exchange_errors::not_supported(format!("{}{}", self.id.clone(), Value::Str(" watchTickers does not support spot markets".into()))));
} else {
if let Value::Dict(__d) = &mut request { std::sync::Arc::make_mut(__d).insert("method".into(), Value::Str("sub.tickers".into())); }
if let Value::Dict(__d) = &mut request { std::sync::Arc::make_mut(__d).insert("params".into(), Value::Map({
let mut m = indexmap::IndexMap::new();
m
})); }
append_to_array(&mut messageHashes, Value::Str("ticker".into()));
}
let __ws_arg_0 = self.extend(request, &[params]);
let mut ticker: Value = self.watch_multiple(url, messageHashes.clone(), &[__ws_arg_0, messageHashes.clone()]).await;
if isSpot && is_true(&self.newUpdates) {
let mut result: Value = Value::Map({
let mut m = indexmap::IndexMap::new();
m
});
add_element_to_object(&mut result, &crate::value::get_value_k(&ticker, "symbol"), ticker.clone());
return result;
}
return self.filter_by_array(self.tickers.clone(), Value::Str("symbol".into()), &[symbols]);
Value::Null
}
pub fn handle_tickers(&mut self, mut client: Value, mut message: Value) {
let __pro_message_arc: std::sync::Arc<indexmap::IndexMap<String, Value>> = (match &message { Value::Dict(__d) => __d.clone(), _ => std::sync::Arc::new(indexmap::IndexMap::new()) });
let __pro_message: &indexmap::IndexMap<String, Value> = &__pro_message_arc;
//
// swap
//
// {
// "channel": "push.tickers",
// "data": [
// {
// "symbol": "ETH_USDT",
// "lastPrice": 2324.5,
// "riseFallRate": 0.0356,
// "fairPrice": 2324.32,
// "indexPrice": 2325.44,
// "volume24": 25868309,
// "amount24": 591752573.9792,
// "maxBidPrice": 2557.98,
// "minAskPrice": 2092.89,
// "lower24Price": 2239.39,
// "high24Price": 2332.59,
// "timestamp": 1725872514111
// }
// ],
// "ts": 1725872514111
// }
//
// spot
//
// {
// "c": "spot@public.bookTicker.v3.api@BTCUSDT",
// "d": {
// "A": "4.70432",
// "B": "6.714863",
// "a": "20744.54",
// "b": "20744.17"
// },
// "s": "BTCUSDT",
// "t": 1678643605721
// }
//
// spot miniTicker
//
// {
// "d": {
// "s": "BTCUSDT",
// "p": "76522",
// "r": "0.0012",
// "tr": "0.0012",
// "h": "77196.3",
// "l": "75630.77",
// "v": "584664223.92",
// "q": "7666.720258",
// "lastRT": "-1",
// "MT": "0",
// "NV": "--",
// "t": "1731135533126"
// },
// "c": "spot@public.miniTicker.v3.api@BTCUSDT@UTC+8",
// "t": 1731135533126,
// "s": "BTCUSDT"
// }
//
let mut data: Value = self.safe_list2(message, Value::Str("data".into()), Value::Str("d".into()), &[Value::from(vec![])]);
let mut channel: Value = (match __pro_message.get("c").cloned() { Some(Value::Str(__s)) if !__s.is_empty() => Value::Str(__s), Some(Value::Int(__n)) => Value::Str(__n.to_string().into()), Some(Value::Float(__f)) => Value::Str(__f.to_string().into()), _ => Value::Str("".into()) });
let mut marketId: Value = (match __pro_message.get("s").cloned() { Some(Value::Str(__s)) if !__s.is_empty() => Value::Str(__s), Some(Value::Int(__n)) => Value::Str(__n.to_string().into()), Some(Value::Float(__f)) => Value::Str(__f.to_string().into()), _ => Value::Null });
let mut market: Value = self.safe_market(&[marketId.clone()]);
let mut channelStartsWithSpot: Value = Value::Bool(starts_with(&channel, &Value::Str("spot".into())));
let mut marketIdIsUndefined: bool = marketId == Value::Null;
let mut isSpot: Value = (if marketIdIsUndefined { channelStartsWithSpot } else { market.as_map().and_then(|__m| __m.get("spot")).cloned().unwrap_or(Value::Null) });
let mut spotPrefix: Value = Value::Str("spot:".into());
let mut messageHashPrefix: Value = (if (isSpot.as_bool() == Some(true)) { spotPrefix } else { Value::Str("".into()) });
let mut topic: Value = Value::Str(format!("{}{}", messageHashPrefix, Value::Str("ticker".into())).into());
let mut result: Value = Value::from(vec![]);
{
let mut i: Value = Value::Int(0);
let mut __for_first_471: bool = true;
while { if !__for_first_471 { i = (match (&(i), &(Value::Int(1))) { (Value::Int(x), Value::Int(y)) => Value::Int(x + y), (Value::Int(x), Value::Float(y)) => Value::Float(*x as f64 + *y), (Value::Float(x), Value::Int(y)) => Value::Float(*x + *y as f64), (Value::Float(x), Value::Float(y)) => Value::Float(x + y), _ => Value::Null }); } __for_first_471 = false; i.as_f64().unwrap_or(f64::NAN) < ((data.len() as i64) as f64) } {
let mut entry: Value = data.as_array().and_then(|__arr| match &i { Value::Int(__n) => __arr.get(*__n as usize), Value::Str(__s) => __s.parse::<usize>().ok().and_then(|__n| __arr.get(__n)), _ => None }).cloned().unwrap_or(Value::Null);
let mut ticker: Value = Value::Null;
if (isSpot.as_bool() == Some(true)) {
ticker = self.parse_ws_ticker(entry.clone(), &[market.clone()]);
} else {
ticker = self.parse_ticker(entry, &[]);
}
let mut symbol: Value = ticker.as_map().and_then(|__m| __m.get("symbol")).cloned().unwrap_or(Value::Null);
if (symbol != Value::Null) {
if let Value::Dict(__d) = &mut self.tickers { std::sync::Arc::make_mut(__d).insert(crate::runtime::stringify_param(&symbol), ticker.clone()); }
}
append_to_array(&mut result, ticker.clone());
let mut messageHash: Value = Value::Str(format!("{}{}", Value::Str("ticker:".into()), symbol).into());
client.resolve(&[ticker, messageHash]);
}
}
client.resolve(&[result, topic]);
}
pub fn parse_ws_ticker(&self, mut ticker: Value, optional_args: &[Value]) -> Value {
let mut market = get_arg(optional_args, 0, Value::Null);
// protobuf ticker
// "bidprice": "93387.28", // Best bid price
// "bidquantity": "3.73485", // Best bid quantity
// "askprice": "93387.29", // Best ask price
// "askquantity": "7.669875" // Best ask quantity
//
// spot
//
// {
// "A": "4.70432",
// "B": "6.714863",
// "a": "20744.54",
// "b": "20744.17"
// }
//
// spot miniTicker
//
// {
// "s": "BTCUSDT",
// "p": "76521",
// "r": "0.0012",
// "tr": "0.0012",
// "h": "77196.3",
// "l": "75630.77",
// "v": "584664223.92",
// "q": "7666.720258",
// "lastRT": "-1",
// "MT": "0",
// "NV": "--",
// "t": "1731135533126"
// }
//
let mut marketId: Value = self.safe_string_k(ticker.clone(), "s", &[]);
let mut timestamp: Value = self.safe_integer_k(ticker.clone(), "t", &[]);
let mut price: Value = self.safe_string_k(ticker.clone(), "p", &[]);
return self.safe_ticker(Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("info".to_string(), ticker.clone());
m.insert("symbol".to_string(), self.safe_symbol(marketId, &[market.clone()]));
m.insert("timestamp".to_string(), timestamp.clone());
m.insert("datetime".to_string(), self.iso8601(timestamp));
m.insert("open".to_string(), Value::Null);
m.insert("high".to_string(), self.safe_number_k(ticker.clone(), "h", &[]));
m.insert("low".to_string(), self.safe_number_k(ticker.clone(), "l", &[]));
m.insert("close".to_string(), price.clone());
m.insert("last".to_string(), price);
m.insert("bid".to_string(), self.safe_number2(ticker.clone(), Value::Str("b".into()), Value::Str("bidPrice".into()), &[]));
m.insert("bidVolume".to_string(), self.safe_number2(ticker.clone(), Value::Str("B".into()), Value::Str("bidQuantity".into()), &[]));
m.insert("ask".to_string(), self.safe_number2(ticker.clone(), Value::Str("a".into()), Value::Str("askPrice".into()), &[]));
m.insert("askVolume".to_string(), self.safe_number2(ticker.clone(), Value::Str("A".into()), Value::Str("askQuantity".into()), &[]));
m.insert("vwap".to_string(), Value::Null);
m.insert("previousClose".to_string(), Value::Null);
m.insert("change".to_string(), Value::Null);
m.insert("percentage".to_string(), self.safe_number_k(ticker.clone(), "tr", &[]));
m.insert("average".to_string(), Value::Null);
m.insert("baseVolume".to_string(), self.safe_number_k(ticker.clone(), "v", &[]));
m.insert("quoteVolume".to_string(), self.safe_number_k(ticker, "q", &[]));
m
}), &[market]);
Value::Null
}
/*
* @method
* @name mexc#watchBidsAsks
* @see https://www.mexc.com/api-docs/spot-v3/websocket-market-streams/individual-symbol-book-ticker-streams
* @description watches best bid & ask for symbols
* @param {string[]} symbols unified symbol of the market to fetch the ticker for
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/?id=ticker-structure}
*/
pub async fn watch_bids_asks(&mut self, optional_args: &[Value]) -> Value {
let mut symbols = get_arg(optional_args, 0, Value::Null);
let mut params = get_arg(optional_args, 1, Value::Map({
let mut m = indexmap::IndexMap::new();
m
}));
if (self.markets.clone() == Value::Null) {
self.load_markets(&[]).await;
}
symbols = self.market_symbols(&[symbols.clone(), Value::Null, Value::Bool(true), Value::Bool(false), Value::Bool(true)]);
let mut marketType: Value = Value::Null;
if (symbols == Value::Null) {
panic!("{}", crate::exchange_errors::arguments_required(format!("{}{}", self.id.clone(), Value::Str(" watchBidsAsks required symbols argument".into()))));
}
let mut markets: Value = self.require_value(self.markets_for_symbols(&[symbols.clone()]), &[Value::Str("watchBidsAsks() markets is required".into())]);
{ let __destr_tmp = self.handle_market_type_and_params(Value::Str("watchBidsAsks".into()), &[markets.as_array().and_then(|__arr| __arr.get(0)).cloned().unwrap_or(Value::Null), params.clone()]); marketType = __destr_tmp.as_array().and_then(|__arr| __arr.get(0)).cloned().unwrap_or(Value::Null); params = __destr_tmp.as_array().and_then(|__arr| __arr.get(1)).cloned().unwrap_or(Value::Null); }
let mut isSpot: bool = marketType.as_str() == Some("spot");
if !isSpot {
panic!("{}", crate::exchange_errors::not_supported(format!("{}{}", self.id.clone(), Value::Str(" watchBidsAsks only support spot market".into()))));
}
let mut messageHashes: Value = Value::from(vec![]);
let mut topics: Value = Value::from(vec![]);
{
let mut i: Value = Value::Int(0);
let mut __for_first_472: bool = true;
while { if !__for_first_472 { i = (match (&(i), &(Value::Int(1))) { (Value::Int(x), Value::Int(y)) => Value::Int(x + y), (Value::Int(x), Value::Float(y)) => Value::Float(*x as f64 + *y), (Value::Float(x), Value::Int(y)) => Value::Float(*x + *y as f64), (Value::Float(x), Value::Float(y)) => Value::Float(x + y), _ => Value::Null }); } __for_first_472 = false; i.as_f64().unwrap_or(f64::NAN) < ((symbols.len() as i64) as f64) } {
if isSpot {
let mut market: Value = self.market(symbols.as_array().and_then(|__arr| match &i { Value::Int(__n) => __arr.get(*__n as usize), Value::Str(__s) => __s.parse::<usize>().ok().and_then(|__n| __arr.get(__n)), _ => None }).cloned().unwrap_or(Value::Null));
append_to_array(&mut topics, Value::Str(format!("{}{}", Value::Str("spot@public.aggre.bookTicker.v3.api.pb@100ms@".into()), market.as_map().and_then(|__m| __m.get("id")).cloned().unwrap_or(Value::Null)).into()));
}
append_to_array(&mut messageHashes, Value::Str(format!("{}{}", Value::Str("bidask:".into()), symbols.as_array().and_then(|__arr| match &i { Value::Int(__n) => __arr.get(*__n as usize), Value::Str(__s) => __s.parse::<usize>().ok().and_then(|__n| __arr.get(__n)), _ => None }).cloned().unwrap_or(Value::Null)).into()));
}
}
let mut url: Value = crate::value::get_value_k(&self.urls.as_map().and_then(|__m| __m.get("api")).cloned().unwrap_or(Value::Null).as_map().and_then(|__m| __m.get("ws")).cloned().unwrap_or(Value::Null), "spot");
let mut request: Value = Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("method".to_string(), Value::Str("SUBSCRIPTION".into()));
m.insert("params".to_string(), topics);
m
});
let __ws_arg_1 = self.extend(request, &[params]);
let mut ticker: Value = self.watch_multiple(url, messageHashes.clone(), &[__ws_arg_1, messageHashes.clone()]).await;
if is_true(&self.newUpdates) {
let mut tickers: Value = Value::Map({
let mut m = indexmap::IndexMap::new();
m
});
add_element_to_object(&mut tickers, &crate::value::get_value_k(&ticker, "symbol"), ticker.clone());
return tickers;
}
return self.filter_by_array(self.bidsasks.clone(), Value::Str("symbol".into()), &[symbols]);
Value::Null
}
pub fn handle_bid_ask(&mut self, mut client: Value, mut message: Value) {
//
// {
// "c": "spot@public.bookTicker.v3.api@BTCUSDT",
// "d": {
// "A": "4.70432",
// "B": "6.714863",
// "a": "20744.54",
// "b": "20744.17"
// },
// "s": "BTCUSDT",
// "t": 1678643605721
// }
//
let mut parsedTicker: Value = self.parse_ws_bid_ask(message, &[]);
let mut symbol: Value = self.safe_string_k(parsedTicker.clone(), "symbol", &[]);
if (symbol == Value::Null) {
return;
}
if let Value::Dict(__d) = &mut self.bidsasks { std::sync::Arc::make_mut(__d).insert(crate::runtime::stringify_param(&symbol), parsedTicker.clone()); }
let mut messageHash: Value = Value::Str(format!("{}{}", Value::Str("bidask:".into()), symbol).into());
client.resolve(&[parsedTicker, messageHash]);
}
pub fn parse_ws_bid_ask(&self, mut ticker: Value, optional_args: &[Value]) -> Value {
let mut market = get_arg(optional_args, 0, Value::Null);
let mut data: Value = self.safe_dict_k(ticker.clone(), "d", &[]);
let mut marketId: Value = self.safe_string_k(ticker.clone(), "s", &[]);
market = self.safe_market(&[marketId, market.clone()]);
let mut symbol: Value = self.safe_string_k(market.clone(), "symbol", &[]);
let mut timestamp: Value = self.safe_integer_k(ticker.clone(), "t", &[]);
return self.safe_ticker(Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("symbol".to_string(), symbol);
m.insert("timestamp".to_string(), timestamp.clone());
m.insert("datetime".to_string(), self.iso8601(timestamp));
m.insert("ask".to_string(), self.safe_number_k(data.clone(), "a", &[]));
m.insert("askVolume".to_string(), self.safe_number_k(data.clone(), "A", &[]));
m.insert("bid".to_string(), self.safe_number_k(data.clone(), "b", &[]));
m.insert("bidVolume".to_string(), self.safe_number_k(data, "B", &[]));
m.insert("info".to_string(), ticker);
m
}), &[market]);
Value::Null
}
pub async fn watch_spot_public(&mut self, mut channel: Value, mut messageHash: Value, optional_args: &[Value]) -> Value {
let mut params = get_arg(optional_args, 0, Value::Map({
let mut m = indexmap::IndexMap::new();
m
}));
let mut unsubscribed: Value = self.safe_bool_k(params.clone(), "unsubscribed", &[Value::Bool(false)]);
params = self.omit(params.clone(), Value::from(vec![Value::Str("unsubscribed".into())]), &[]);
let mut url: Value = crate::value::get_value_k(&self.urls.as_map().and_then(|__m| __m.get("api")).cloned().unwrap_or(Value::Null).as_map().and_then(|__m| __m.get("ws")).cloned().unwrap_or(Value::Null), "spot");
let mut method: Value = (if (unsubscribed.as_bool() == Some(true)) { Value::Str("UNSUBSCRIPTION".into()) } else { Value::Str("SUBSCRIPTION".into()) });
let mut request: Value = Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("method".to_string(), method);
m.insert("params".to_string(), Value::from(vec![channel]));
m
});
let __ws_arg_2 = self.extend(request, &[params]);
return self.watch(url, messageHash.clone(), &[__ws_arg_2, messageHash.clone()]).await;
Value::Null
}
pub async fn watch_spot_private(&mut self, mut channel: Value, mut messageHash: Value, optional_args: &[Value]) -> Value {
let mut params = get_arg(optional_args, 0, Value::Map({
let mut m = indexmap::IndexMap::new();
m
}));
self.check_required_credentials(&[]);
let mut listenKey: Value = self.authenticate(channel.clone(), &[]).await;
let mut url: Value = Value::Str(format!("{}{}", add(&crate::value::get_value_k(&self.urls.as_map().and_then(|__m| __m.get("api")).cloned().unwrap_or(Value::Null).as_map().and_then(|__m| __m.get("ws")).cloned().unwrap_or(Value::Null), "spot"), &Value::Str("?listenKey=".into())), listenKey).into());
let mut request: Value = Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("method".to_string(), Value::Str("SUBSCRIPTION".into()));
m.insert("params".to_string(), Value::from(vec![channel.clone()]));
m
});
let __ws_arg_3 = self.extend(request, &[params]);
return self.watch(url, messageHash, &[__ws_arg_3, channel]).await;
Value::Null
}
pub async fn watch_swap_public(&mut self, mut channel: Value, mut messageHash: Value, mut requestParams: Value, optional_args: &[Value]) -> Value {
let mut params = get_arg(optional_args, 0, Value::Map({
let mut m = indexmap::IndexMap::new();
m
}));
let mut url: Value = crate::value::get_value_k(&self.urls.as_map().and_then(|__m| __m.get("api")).cloned().unwrap_or(Value::Null).as_map().and_then(|__m| __m.get("ws")).cloned().unwrap_or(Value::Null), "swap");
let mut request: Value = Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("method".to_string(), channel);
m.insert("param".to_string(), requestParams);
m
});
let mut message: Value = self.extend(request, &[params]);
return self.watch(url, messageHash.clone(), &[message, messageHash.clone()]).await;
Value::Null
}
pub async fn watch_swap_private(&mut self, mut messageHash: Value, optional_args: &[Value]) -> Value {
let mut params = get_arg(optional_args, 0, Value::Map({
let mut m = indexmap::IndexMap::new();
m
}));
self.check_required_credentials(&[]);
let mut channel: Value = Value::Str("login".into());
let mut url: Value = crate::value::get_value_k(&self.urls.as_map().and_then(|__m| __m.get("api")).cloned().unwrap_or(Value::Null).as_map().and_then(|__m| __m.get("ws")).cloned().unwrap_or(Value::Null), "swap");
let mut timestamp: Value = to_string_val(&self.milliseconds());
let mut payload: Value = Value::Str(format!("{}{}", self.apiKey.clone(), timestamp).into());
let mut signature: Value = self.hmac(self.encode(payload), self.encode(self.secret.clone()), Value::Str("sha256".into()), &[]);
let mut request: Value = Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("method".to_string(), channel.clone());
m.insert("param".to_string(), Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("apiKey".to_string(), self.apiKey.clone());
m.insert("signature".to_string(), signature);
m.insert("reqTime".to_string(), timestamp);
m
}));
m
});
let mut message: Value = self.extend(request, &[params]);
return self.watch(url, messageHash, &[message, channel]).await;
Value::Null
}
/*
* @method
* @name mexc#watchOHLCV
* @see https://www.mexc.com/api-docs/spot-v3/websocket-market-streams/k-line-streams // spot
* @see https://www.mexc.com/api-docs/futures/websocket-api/k-line-data // swap
* @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
* @param {string} symbol unified symbol of the market to fetch OHLCV data for
* @param {string} timeframe the length of time each candle represents
* @param {int} [since] timestamp in ms of the earliest candle to fetch
* @param {int} [limit] the maximum amount of candles to fetch
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
*/
pub async fn watch_ohlcv(&mut self, mut symbol: Value, optional_args: &[Value]) -> Value {
let mut timeframe = get_arg(optional_args, 0, Value::Str("1m".into()));
let mut since = get_arg(optional_args, 1, Value::Null);
let mut limit = get_arg(optional_args, 2, Value::Null);
let mut params = get_arg(optional_args, 3, Value::Map({
let mut m = indexmap::IndexMap::new();
m
}));
if (self.markets.clone() == Value::Null) {
self.load_markets(&[]).await;
}
let mut market: Value = self.market(symbol.clone());
symbol = market.as_map().and_then(|__m| __m.get("symbol")).cloned().unwrap_or(Value::Null);
let mut timeframes: Value = self.safe_dict_k(self.options.clone(), "timeframes", &[Value::Map({
let mut m = indexmap::IndexMap::new();
m
})]);
let mut timeframeId: Value = self.safe_string(timeframes, timeframe.clone(), &[]);
let mut messageHash: Value = Value::Str(format!("{}{}", Value::Str(format!("{}{}", Value::Str(format!("{}{}", Value::Str("candles:".into()), symbol).into()), Value::Str(":".into())).into()), timeframe).into());
let mut ohlcv: Value = Value::Null;
if (market.as_map().and_then(|__m| __m.get("spot")).cloned().unwrap_or(Value::Null).as_bool() == Some(true)) {
let mut channel: Value = Value::Str(format!("{}{}", Value::Str(format!("{}{}", Value::Str(format!("{}{}", Value::Str("spot@public.kline.v3.api.pb@".into()), market.as_map().and_then(|__m| __m.get("id")).cloned().unwrap_or(Value::Null)).into()), Value::Str("@".into())).into()), timeframeId).into());
ohlcv = self.watch_spot_public(channel.clone(), messageHash.clone(), &[params.clone()]).await;
} else {
let mut channel: Value = Value::Str("sub.kline".into());
let mut requestParams: Value = Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("symbol".to_string(), market.as_map().and_then(|__m| __m.get("id")).cloned().unwrap_or(Value::Null));
m.insert("interval".to_string(), timeframeId);
m
});
ohlcv = self.watch_swap_public(channel, messageHash, requestParams, &[params]).await;
}
ohlcv = self.require_value(ohlcv.clone(), &[Value::Str("watchOHLCV() ohlcv is required".into())]);
if is_true(&self.newUpdates) {
limit = ohlcv.get_limit(symbol, limit.clone());
}
return self.filter_by_since_limit(ohlcv, &[since, limit, Value::Int(0), Value::Bool(true)]);
Value::Null
}
pub fn handle_ohlcv(&mut self, mut client: Value, mut message: Value) {
let __pro_message_arc: std::sync::Arc<indexmap::IndexMap<String, Value>> = (match &message { Value::Dict(__d) => __d.clone(), _ => std::sync::Arc::new(indexmap::IndexMap::new()) });
let __pro_message: &indexmap::IndexMap<String, Value> = &__pro_message_arc;
//
// spot
//
// {
// "d": {
// "e": "spot@public.kline.v3.api",
// "k": {
// "t": 1678642261,
// "o": 20626.94,
// "c": 20599.69,
// "h": 20626.94,
// "l": 20597.06,
// "v": 27.678686,
// "a": 570332.77,
// "T": 1678642320,
// "i": "Min1"
// }
// },
// "c": "spot@public.kline.v3.api@BTCUSDT@Min1",
// "t": 1678642276459,
// "s": "BTCUSDT"
// }
//
// swap
//
// {
// "channel": "push.kline",
// "data": {
// "a": 325653.3287,
// "c": 38839,
// "h": 38909.5,
// "interval": "Min1",
// "l": 38833,
// "o": 38901.5,
// "q": 83808,
// "rc": 38839,
// "rh": 38909.5,
// "rl": 38833,
// "ro": 38909.5,
// "symbol": "BTC_USDT",
// "t": 1651230660
// },
// "symbol": "BTC_USDT",
// "ts": 1651230713067
// }
// protobuf
// {
// "channel":"spot@public.kline.v3.api.pb@BTCUSDT@Min1",
// "symbol":"BTCUSDT",
// "symbolId":"2fb942154ef44a4ab2ef98c8afb6a4a7",
// "createTime":"1754737941062",
// "publicSpotKline":{
// "interval":"Min1",
// "windowStart":"1754737920",
// "openingPrice":"117317.31",
// "closingPrice":"117325.26",
// "highestPrice":"117341",
// "lowestPrice":"117317.3",
// "volume":"3.12599854",
// "amount":"366804.43",
// "windowEnd":"1754737980"
// }
// }
//
let mut parsed: Value = Value::Null;
let mut symbol: Value = Value::Null;
let mut timeframe: Value = Value::Null;
if (matches!(&message, Value::Dict(__d) if __d.contains_key("publicSpotKline"))) {
symbol = self.symbol(self.safe_string_k(message.clone(), "symbol", &[]));
let mut data: Value = (match __pro_message.get("publicSpotKline").cloned() { Some(__v) if matches!(__v, Value::Dict(_)) => __v, _ => Value::Map({
let mut m = indexmap::IndexMap::new();
m
}) });
let mut timeframeId: Value = self.safe_string_k(data.clone(), "interval", &[]);
timeframe = self.find_timeframe(timeframeId.clone(), &[self.options.as_map().and_then(|__m| __m.get("timeframes")).cloned().unwrap_or(Value::Null)]);
parsed = self.parse_ws_ohlcv(data, &[self.safe_market(&[symbol.clone()])]);
} else {
let mut d: Value = self.safe_dict2(message.clone(), Value::Str("d".into()), Value::Str("data".into()), &[Value::Map({
let mut m = indexmap::IndexMap::new();
m
})]);
let mut rawOhlcv: Value = self.safe_dict_k(d.clone(), "k", &[d.clone()]);
let mut timeframeId: Value = self.safe_string2(rawOhlcv.clone(), Value::Str("i".into()), Value::Str("interval".into()), &[]);
let mut timeframes: Value = self.safe_dict_k(self.options.clone(), "timeframes", &[Value::Map({
let mut m = indexmap::IndexMap::new();
m
})]);
timeframe = self.find_timeframe(timeframeId, &[timeframes]);
let mut marketId: Value = self.safe_string2(message, Value::Str("s".into()), Value::Str("symbol".into()), &[]);
let mut market: Value = self.safe_market(&[marketId]);
symbol = market.as_map().and_then(|__m| __m.get("symbol")).cloned().unwrap_or(Value::Null);
parsed = self.parse_ws_ohlcv(rawOhlcv, &[market]);
}
let mut messageHash: Value = Value::Str(format!("{}{}", Value::Str(format!("{}{}", Value::Str(format!("{}{}", Value::Str("candles:".into()), symbol).into()), Value::Str(":".into())).into()), timeframe).into());
let mut symbolOhlcvs: Value = self.safe_dict(self.ohlcvs.clone(), symbol.clone(), &[Value::Map({
let mut m = indexmap::IndexMap::new();
m
})]);
if let Value::Dict(__d) = &mut self.ohlcvs { std::sync::Arc::make_mut(__d).insert(crate::runtime::stringify_param(&symbol), symbolOhlcvs.clone()); }
let mut stored: Value = self.safe_value(symbolOhlcvs.clone(), timeframe.clone(), &[]);
if (stored == Value::Null) {
let mut limit: Value = self.safe_integer_k(self.options.clone(), "OHLCVLimit", &[Value::Int(1000)]);
stored = ArrayCacheByTimestamp::new(limit);
if (timeframe != Value::Null) {
if let Value::Dict(__d) = &mut symbolOhlcvs { std::sync::Arc::make_mut(__d).insert(crate::runtime::stringify_param(&timeframe), stored.clone()); }
}
}
stored.append(parsed);
client.resolve(&[stored, messageHash]);
}
pub fn parse_ws_ohlcv(&self, mut ohlcv: Value, optional_args: &[Value]) -> Value {
let mut market = get_arg(optional_args, 0, Value::Null);
//
// spot
//
// {
// "t": 1678642260,
// "o": 20626.94,
// "c": 20599.69,
// "h": 20626.94,
// "l": 20597.06,
// "v": 27.678686,
// "a": 570332.77,
// "T": 1678642320,
// "i": "Min1"
// }
//
// swap
// {
// "symbol": "BTC_USDT",
// "interval": "Min1",
// "t": 1680055080,
// "o": 27301.9,
// "c": 27301.8,
// "h": 27301.9,
// "l": 27301.8,
// "a": 8.19054,
// "q": 3,
// "ro": 27301.8,
// "rc": 27301.8,
// "rh": 27301.8,
// "rl": 27301.8
// }
// protobuf
//
// "interval":"Min1",
// "windowStart":"1754737920",
// "openingPrice":"117317.31",
// "closingPrice":"117325.26",
// "highestPrice":"117341",
// "lowestPrice":"117317.3",
// "volume":"3.12599854",
// "amount":"366804.43",
// "windowEnd":"1754737980"
//
let mut volume: Value = self.safe_number2(ohlcv.clone(), Value::Str("v".into()), Value::Str("volume".into()), &[]);
// MEXC swap websocket klines publish contracts volume in `q`,
// while spot/protobuf uses `v`/`volume`.
if (market != Value::Null) && (self.safe_bool_k(market, "spot", &[]).as_bool() != Some(true)) && (volume == Value::Null) {
volume = self.safe_number2(ohlcv.clone(), Value::Str("q".into()), Value::Str("v".into()), &[]);
}
return Value::from(vec![self.safe_timestamp2(ohlcv.clone(), Value::Str("t".into()), Value::Str("windowStart".into()), &[]), self.safe_number2(ohlcv.clone(), Value::Str("o".into()), Value::Str("openingPrice".into()), &[]), self.safe_number2(ohlcv.clone(), Value::Str("h".into()), Value::Str("highestPrice".into()), &[]), self.safe_number2(ohlcv.clone(), Value::Str("l".into()), Value::Str("lowestPrice".into()), &[]), self.safe_number2(ohlcv, Value::Str("c".into()), Value::Str("closingPrice".into()), &[]), volume]);
Value::Null
}
/*
* @method
* @name mexc#watchOrderBook
* @see https://www.mexc.com/api-docs/spot-v3/websocket-market-streams/diffdepth-stream // spot
* @see https://www.mexc.com/api-docs/futures/websocket-api/order-book-depth // swap
* @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
* @param {string} symbol unified symbol of the market to fetch the order book for
* @param {int} [limit] the maximum amount of order book entries to return
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string} [params.frequency] the frequency of the order book updates, default is '10ms', can be '100ms' or '10ms
* @returns {object} an [order book structure]{@link https://docs.ccxt.com/?id=order-book-structure}
*/
pub async fn watch_order_book(&mut self, mut symbol: Value, optional_args: &[Value]) -> Value {
let mut limit = get_arg(optional_args, 0, Value::Null);
let mut params = get_arg(optional_args, 1, Value::Map({
let mut m = indexmap::IndexMap::new();
m
}));
if (self.markets.clone() == Value::Null) {
self.load_markets(&[]).await;
}
let mut market: Value = self.market(symbol.clone());
symbol = market.as_map().and_then(|__m| __m.get("symbol")).cloned().unwrap_or(Value::Null);
let mut messageHash: Value = Value::Str(format!("{}{}", Value::Str("orderbook:".into()), symbol).into());
let mut orderbook: Value = Value::Null;
if (market.as_map().and_then(|__m| __m.get("spot")).cloned().unwrap_or(Value::Null).as_bool() == Some(true)) {
let mut frequency: Value = Value::Null;
{ let __destr_tmp = self.handle_option_and_params(params.clone(), Value::Str("watchOrderBook".into()), Value::Str("frequency".into()), &[Value::Str("100ms".into())]); frequency = __destr_tmp.as_array().and_then(|__arr| __arr.get(0)).cloned().unwrap_or(Value::Null); params = __destr_tmp.as_array().and_then(|__arr| __arr.get(1)).cloned().unwrap_or(Value::Null); }
let mut channel: Value = Value::Str(format!("{}{}", Value::Str(format!("{}{}", Value::Str(format!("{}{}", Value::Str("spot@public.aggre.depth.v3.api.pb@".into()), frequency).into()), Value::Str("@".into())).into()), market.as_map().and_then(|__m| __m.get("id")).cloned().unwrap_or(Value::Null)).into());
orderbook = self.watch_spot_public(channel.clone(), messageHash.clone(), &[params.clone()]).await;
} else {
let mut channel: Value = Value::Str("sub.depth".into());
let mut requestParams: Value = Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("symbol".to_string(), market.as_map().and_then(|__m| __m.get("id")).cloned().unwrap_or(Value::Null));
m
});
orderbook = self.watch_swap_public(channel, messageHash, requestParams, &[params]).await;
}
orderbook = self.require_value(orderbook.clone(), &[Value::Str("watchOrderBook() orderbook is required".into())]);
return orderbook.limit();
Value::Null
}
pub fn handle_order_book_subscription(&mut self, mut client: Value, mut message: Value) {
let __message_empty = indexmap::IndexMap::new();
let message = message.as_map().unwrap_or(&__message_empty);
// spot
// { id: 0, code: 0, msg: "spot@public.increase.depth.v3.api@BTCUSDT" }
//
let mut msg: Value = (match message.get("msg") { Some(Value::Str(__s)) if !__s.is_empty() => Value::Str(__s.clone()), Some(Value::Int(__n)) => Value::Str(__n.to_string().into()), Some(Value::Float(__f)) => Value::Str(__f.to_string().into()), _ => Value::Str("".into()) });
let mut parts: Value = split(&msg, &Value::Str("@".into()));
let mut marketId: Value = self.safe_string(parts, Value::Int(2), &[]);
let mut symbol: Value = self.safe_symbol(marketId, &[]);
{ let __be_tmp = self.order_book(&[Value::Map({
let mut m = indexmap::IndexMap::new();
m
})]); if let Value::Dict(__d) = &mut self.orderbooks { std::sync::Arc::make_mut(__d).insert(crate::runtime::stringify_param(&symbol), __be_tmp); } }
}
pub fn get_cache_index(&self, mut orderbook: Value, mut cache: Value) -> Value {
// return the first index of the cache that can be applied to the orderbook or -1 if not possible
let mut nonce: Value = self.safe_integer_k(orderbook, "nonce", &[]);
let mut firstDelta: Value = self.safe_dict(cache.clone(), Value::Int(0), &[]);
let mut firstDeltaNonce: Value = self.safe_integer_n(firstDelta, Value::from(vec![Value::Str("r".into()), Value::Str("version".into()), Value::Str("fromVersion".into())]), &[]);
if (nonce == Value::Null) || (firstDeltaNonce == Value::Null) {
return Value::Int(-1);
}
if nonce.as_f64().unwrap_or(f64::NAN) < (match (&(firstDeltaNonce), &(Value::Int(1))) { (Value::Int(x), Value::Int(y)) => Value::Int(x - y), (Value::Int(x), Value::Float(y)) => Value::Float(*x as f64 - *y), (Value::Float(x), Value::Int(y)) => Value::Float(*x - *y as f64), (Value::Float(x), Value::Float(y)) => Value::Float(x - y), _ => Value::Null }).as_f64().unwrap_or(f64::NAN) {
return Value::Int(-1);
}
{
let mut i: Value = Value::Int(0);
let mut __for_first_473: bool = true;
while { if !__for_first_473 { i = (match (&(i), &(Value::Int(1))) { (Value::Int(x), Value::Int(y)) => Value::Int(x + y), (Value::Int(x), Value::Float(y)) => Value::Float(*x as f64 + *y), (Value::Float(x), Value::Int(y)) => Value::Float(*x + *y as f64), (Value::Float(x), Value::Float(y)) => Value::Float(x + y), _ => Value::Null }); } __for_first_473 = false; i.as_f64().unwrap_or(f64::NAN) < get_array_length(&cache).as_f64().unwrap_or(f64::NAN) } {
let mut delta: Value = get_value(&cache, &i);
let mut delta: Value = get_value(&cache, &i);
let mut deltaNonce: Value = self.safe_integer_n(delta, Value::from(vec![Value::Str("r".into()), Value::Str("version".into()), Value::Str("fromVersion".into())]), &[]);
if (deltaNonce == Value::Null) {
continue;
}
if deltaNonce.as_f64().unwrap_or(f64::NAN) >= nonce.as_f64().unwrap_or(f64::NAN) {
return i;
}
}
}
return get_array_length(&cache);
Value::Null
}
pub fn handle_order_book(&mut self, mut client: Value, mut message: Value) {
//
// spot
// {
// "c": "spot@public.increase.depth.v3.api@BTCUSDT",
// "d": {
// "asks": [{
// "p": "20290.89",
// "v": "0.000000"
// }],
// "e": "spot@public.increase.depth.v3.api",
// "r": "3407459756"
// },
// "s": "BTCUSDT",
// "t": 1661932660144
// }
//
//
//
// swap
// {
// "channel":"push.depth",
// "data":{
// "asks":[
// [
// 39146.5,
// 11264,
// 1
// ]
// ],
// "bids":[
// [
// 39144,
// 35460,
// 1
// ]
// ],
// "end":4895965272,
// "begin":4895965271
// },
// "symbol":"BTC_USDT",
// "ts":1651239652372
// }
// protofbuf
// {
// "channel":"spot@public.aggre.depth.v3.api.pb@100ms@BTCUSDT",
// "symbol":"BTCUSDT",
// "sendTime":"1754741322152",
// "publicAggreDepths":{
// "asks":[
// {
// "price":"117145.49",
// "quantity":"0"
// }
// ],
// "bids":[
// {
// "price":"117053.41",
// "quantity":"1.86837271"
// }
// ],
// "eventType":"spot@public.aggre.depth.v3.api.pb@100ms",
// "fromVersion":"43296363236",
// "toVersion":"43296363255"
// }
// }
//
let mut data: Value = self.safe_dict_n(message.clone(), Value::from(vec![Value::Str("d".into()), Value::Str("data".into()), Value::Str("publicAggreDepths".into())]), &[]);
let mut marketId: Value = self.safe_string2(message.clone(), Value::Str("s".into()), Value::Str("symbol".into()), &[]);
let mut symbol: Value = self.safe_symbol(marketId, &[]);
let mut messageHash: Value = Value::Str(format!("{}{}", Value::Str("orderbook:".into()), symbol).into());
let mut subscription: Value = self.safe_dict(get_value(&client, &Value::Str("subscriptions".into())), messageHash.clone(), &[]);
let mut limit: Value = self.safe_integer_k(subscription, "limit", &[]);
if !(in_op(&self.orderbooks, &symbol)) {
{ let __be_tmp = self.order_book(&[]); if let Value::Dict(__d) = &mut self.orderbooks { std::sync::Arc::make_mut(__d).insert(crate::runtime::stringify_param(&symbol), __be_tmp); } }
}
let mut storedOrderBook: Value = get_value(&self.orderbooks, &symbol);
let mut nonce: Option<i64> = self.safe_integer_k(storedOrderBook.clone(), "nonce", &[]).as_i64();
let mut shouldReturn: bool = false;
if (nonce.is_none()) {
let mut cacheLength: Value = Value::Int(get_value(&storedOrderBook, &Value::Str("cache".into())).len() as i64);
let mut snapshotDelay: Value = self.handle_option(Value::Str("watchOrderBook".into()), Value::Str("snapshotDelay".into()), &[Value::Int(25)]);
if is_equal(&cacheLength, &snapshotDelay) {
self.spawn(&[Value::Str("load_order_book".into()).clone(), client.clone(), messageHash.clone(), symbol, limit, Value::Map({
let mut m = indexmap::IndexMap::new();
m
})]);
}
crate::runtime::append_to_object_array(&mut storedOrderBook, &Value::Str("cache".into()), data.clone());
return;
}
let _try_result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
self.handle_delta(storedOrderBook.clone(), data.clone());
let mut timestamp: Value = self.safe_integer_n(message.clone(), Value::from(vec![Value::Str("t".into()), Value::Str("ts".into()), Value::Str("sendTime".into())]), &[]);
add_element_to_object(&mut storedOrderBook, &Value::Str("timestamp".into()), timestamp.clone());
add_element_to_object(&mut storedOrderBook, &Value::Str("datetime".into()), self.iso8601(timestamp.clone()));
#[allow(unreachable_code)] { Value::Null }}));
if let Err(_try_err) = _try_result { let e: Value = panic_to_value(_try_err);
remove(&mut get_value(&client, &Value::Str("subscriptions".into())), &messageHash);
client.reject(&[e, messageHash.clone()]);
// return;
shouldReturn = true;
}
if shouldReturn {
return;
}
client.resolve(&[storedOrderBook.clone(), messageHash]);
}
pub fn handle_bookside_delta(&self, mut bookside: Value, mut bidasks: Value) {
{
let mut i: Value = Value::Int(0);
let mut __for_first_474: bool = true;
while { if !__for_first_474 { i = (match (&(i), &(Value::Int(1))) { (Value::Int(x), Value::Int(y)) => Value::Int(x + y), (Value::Int(x), Value::Float(y)) => Value::Float(*x as f64 + *y), (Value::Float(x), Value::Int(y)) => Value::Float(*x + *y as f64), (Value::Float(x), Value::Float(y)) => Value::Float(x + y), _ => Value::Null }); } __for_first_474 = false; i.as_f64().unwrap_or(f64::NAN) < get_array_length(&bidasks).as_f64().unwrap_or(f64::NAN) } {
let mut bidask: Value = get_value(&bidasks, &i);
let mut bidask: Value = get_value(&bidasks, &i);
if (matches!(&bidask, Value::Arr(_))) {
bookside.store_array(bidask.clone());
} else {
let mut price: Value = self.safe_float2(bidask.clone(), Value::Str("p".into()), Value::Str("price".into()), &[]);
let mut amount: Value = self.safe_float2(bidask, Value::Str("v".into()), Value::Str("quantity".into()), &[]);
bookside.store(price, amount);
}
}
}
}
pub fn handle_delta(&self, mut orderbook: Value, mut delta: Value) {
let mut existingNonce: Value = self.safe_integer_k(orderbook.clone(), "nonce", &[]);
let mut deltaNonce: Value = self.safe_integer_n(delta.clone(), Value::from(vec![Value::Str("r".into()), Value::Str("version".into()), Value::Str("fromVersion".into())]), &[]);
if (deltaNonce != Value::Null) && (existingNonce != Value::Null) && (deltaNonce.as_f64().unwrap_or(f64::NAN) < existingNonce.as_f64().unwrap_or(f64::NAN)) {
return;
}
add_element_to_object(&mut orderbook, &Value::Str("nonce".into()), deltaNonce);
let mut asks: Value = self.safe_list_k(delta.clone(), "asks", &[Value::from(vec![])]);
let mut bids: Value = self.safe_list_k(delta, "bids", &[Value::from(vec![])]);
let mut asksOrderSide: Value = crate::value::get_value_k(&orderbook, "asks");
let mut bidsOrderSide: Value = crate::value::get_value_k(&orderbook, "bids");
self.handle_bookside_delta(asksOrderSide, asks);
self.handle_bookside_delta(bidsOrderSide, bids);
}
/*
* @method
* @name mexc#watchTrades
* @see https://www.mexc.com/api-docs/spot-v3/websocket-market-streams/trade-streams // spot
* @see https://www.mexc.com/api-docs/futures/websocket-api/deal // swap
* @description get the list of most recent trades for a particular symbol
* @param {string} symbol unified symbol of the market to fetch trades for
* @param {int} [since] timestamp in ms of the earliest trade to fetch
* @param {int} [limit] the maximum amount of trades to fetch
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/?id=public-trades}
*/
pub async fn watch_trades(&mut self, mut symbol: Value, optional_args: &[Value]) -> Value {
let mut since = get_arg(optional_args, 0, Value::Null);
let mut limit = get_arg(optional_args, 1, Value::Null);
let mut params = get_arg(optional_args, 2, Value::Map({
let mut m = indexmap::IndexMap::new();
m
}));
if (self.markets.clone() == Value::Null) {
self.load_markets(&[]).await;
}
let mut market: Value = self.market(symbol.clone());
symbol = market.as_map().and_then(|__m| __m.get("symbol")).cloned().unwrap_or(Value::Null);
let mut messageHash: Value = Value::Str(format!("{}{}", Value::Str("trades:".into()), symbol).into());
let mut trades: Value = Value::Null;
if (market.as_map().and_then(|__m| __m.get("spot")).cloned().unwrap_or(Value::Null).as_bool() == Some(true)) {
let mut channel: Value = Value::Str(format!("{}{}", Value::Str("spot@public.aggre.deals.v3.api.pb@100ms@".into()), market.as_map().and_then(|__m| __m.get("id")).cloned().unwrap_or(Value::Null)).into());
trades = self.watch_spot_public(channel.clone(), messageHash.clone(), &[params.clone()]).await;
} else {
let mut channel: Value = Value::Str("sub.deal".into());
let mut requestParams: Value = Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("symbol".to_string(), market.as_map().and_then(|__m| __m.get("id")).cloned().unwrap_or(Value::Null));
m
});
trades = self.watch_swap_public(channel, messageHash, requestParams, &[params]).await;
}
trades = self.require_value(trades.clone(), &[Value::Str("watchTrades() trades is required".into())]);
if is_true(&self.newUpdates) {
limit = trades.get_limit(symbol, limit.clone());
}
return self.filter_by_since_limit(trades, &[since, limit, Value::Str("timestamp".into()), Value::Bool(true)]);
Value::Null
}
pub fn handle_trades(&mut self, mut client: Value, mut message: Value) {
let __pro_message_arc: std::sync::Arc<indexmap::IndexMap<String, Value>> = (match &message { Value::Dict(__d) => __d.clone(), _ => std::sync::Arc::new(indexmap::IndexMap::new()) });
let __pro_message: &indexmap::IndexMap<String, Value> = &__pro_message_arc;
// protobuf
// {
// "channel": "spot@public.aggre.deals.v3.api.pb@100ms@BTCUSDT",
// "publicdeals": {
// "dealsList": [
// {
// "price": "93220.00", // Trade price
// "quantity": "0.04438243", // Trade quantity
// "tradetype": 2, // Trade type (1: Buy, 2: Sell)
// "time": 1736409765051 // Trade time
// }
// ],
// "eventtype": "spot@public.aggre.deals.v3.api.pb@100ms" // Event type
// },
// "symbol": "BTCUSDT", // Trading pair
// "sendtime": 1736409765052 // Event time
// }
//
// {
// "c": "spot@public.deals.v3.api@BTCUSDT",
// "d": {
// "deals": [{
// "p": "20382.70",
// "v": "0.043800",
// "S": 1,
// "t": 1678593222456,
// }, ],
// "e": "spot@public.deals.v3.api",
// },
// "s": "BTCUSDT",
// "t": 1678593222460,
// }
//
// swap
// {
// "symbol": "BTC_USDT",
// "data": [
// {
// "p": 114350.4,
// "v": 4,
// "T": 2,
// "O": 3,
// "M": 2,
// "t": 1760368563597
// }
// ],
// "channel": "push.deal",
// "ts": 1680055941870
// }
//
let mut marketId: Value = self.safe_string2(message.clone(), Value::Str("s".into()), Value::Str("symbol".into()), &[]);
let mut market: Value = self.safe_market(&[marketId]);
let mut symbol: Value = market.as_map().and_then(|__m| __m.get("symbol")).cloned().unwrap_or(Value::Null);
let mut messageHash: Value = Value::Str(format!("{}{}", Value::Str("trades:".into()), symbol).into());
let mut stored: Value = self.safe_value(self.trades.clone(), symbol.clone(), &[]);
if (stored == Value::Null) {
let mut limit: Value = self.safe_integer_k(self.options.clone(), "tradesLimit", &[Value::Int(1000)]);
stored = ArrayCache::new(limit);
if let Value::Dict(__d) = &mut self.trades { std::sync::Arc::make_mut(__d).insert(crate::runtime::stringify_param(&symbol), stored.clone()); }
}
let mut d: Value = self.safe_dict_n(message.clone(), Value::from(vec![Value::Str("d".into()), Value::Str("publicAggreDeals".into())]), &[]);
let mut trades: Value = self.safe_list2(d.clone(), Value::Str("deals".into()), Value::Str("dealsList".into()), &[Value::from(vec![d.clone()])]);
if (d == Value::Null) {
trades = (match __pro_message.get("data").cloned() { Some(__v) if matches!(__v, Value::Arr(_)) => __v, _ => Value::from(vec![]) });
}
{
let mut j: Value = Value::Int(0);
let mut __for_first_475: bool = true;
while { if !__for_first_475 { j = (match (&(j), &(Value::Int(1))) { (Value::Int(x), Value::Int(y)) => Value::Int(x + y), (Value::Int(x), Value::Float(y)) => Value::Float(*x as f64 + *y), (Value::Float(x), Value::Int(y)) => Value::Float(*x + *y as f64), (Value::Float(x), Value::Float(y)) => Value::Float(x + y), _ => Value::Null }); } __for_first_475 = false; j.as_f64().unwrap_or(f64::NAN) < ((trades.len() as i64) as f64) } {
let mut parsedTrade: Value = Value::Null;
if (market.as_map().and_then(|__m| __m.get("spot")).cloned().unwrap_or(Value::Null).as_bool() == Some(true)) {
parsedTrade = self.parse_ws_trade(trades.as_array().and_then(|__arr| match &j { Value::Int(__n) => __arr.get(*__n as usize), Value::Str(__s) => __s.parse::<usize>().ok().and_then(|__n| __arr.get(__n)), _ => None }).cloned().unwrap_or(Value::Null), &[market.clone()]);
} else {
parsedTrade = self.parse_trade(trades.as_array().and_then(|__arr| match &j { Value::Int(__n) => __arr.get(*__n as usize), Value::Str(__s) => __s.parse::<usize>().ok().and_then(|__n| __arr.get(__n)), _ => None }).cloned().unwrap_or(Value::Null), &[market.clone()]);
}
stored.append(parsedTrade);
}
}
client.resolve(&[stored, messageHash]);
}
/*
* @method
* @name mexc#watchMyTrades
* @see https://www.mexc.com/api-docs/spot-v3/websocket-user-data-streams/spot-account-deals // spot
* @see https://www.mexc.com/api-docs/futures/websocket-api/fill-details // swap
* @description watches information on multiple trades made by the user
* @param {string} symbol unified market symbol of the market trades were made in
* @param {int} [since] the earliest time in ms to fetch trades for
* @param {int} [limit] the maximum number of trade structures to retrieve
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/?id=trade-structure}
*/
pub async fn watch_my_trades(&mut self, optional_args: &[Value]) -> Value {
let mut symbol = get_arg(optional_args, 0, Value::Null);
let mut since = get_arg(optional_args, 1, Value::Null);
let mut limit = get_arg(optional_args, 2, Value::Null);
let mut params = get_arg(optional_args, 3, Value::Map({
let mut m = indexmap::IndexMap::new();
m
}));
if (self.markets.clone() == Value::Null) {
self.load_markets(&[]).await;
}
let mut messageHash: Value = Value::Str("myTrades".into());
let mut market: Value = Value::Null;
if (symbol != Value::Null) {
market = self.market(symbol.clone());
symbol = market.as_map().and_then(|__m| __m.get("symbol")).cloned().unwrap_or(Value::Null);
messageHash = Value::Str(format!("{}{}", Value::Str(format!("{}{}", messageHash, Value::Str(":".into())).into()), symbol).into());
}
let mut type_var: Value = Value::Null;
{ let __destr_tmp = self.handle_market_type_and_params(Value::Str("watchMyTrades".into()), &[market, params.clone()]); type_var = __destr_tmp.as_array().and_then(|__arr| __arr.get(0)).cloned().unwrap_or(Value::Null); params = __destr_tmp.as_array().and_then(|__arr| __arr.get(1)).cloned().unwrap_or(Value::Null); }
let mut trades: Value = Value::Null;
if (type_var.as_str() == Some("spot")) {
let mut channel: Value = Value::Str("spot@private.deals.v3.api.pb".into());
trades = self.watch_spot_private(channel, messageHash.clone(), &[params.clone()]).await;
} else {
trades = self.watch_swap_private(messageHash, &[params]).await;
}
trades = self.require_value(trades.clone(), &[Value::Str("watchMyTrades() trades is required".into())]);
if is_true(&self.newUpdates) {
limit = trades.get_limit(symbol.clone(), limit.clone());
}
return self.filter_by_symbol_since_limit(trades, &[symbol, since, limit, Value::Bool(true)]);
Value::Null
}
pub fn handle_my_trade(&mut self, mut client: Value, mut message: Value, optional_args: &[Value]) {
let mut subscription = get_arg(optional_args, 0, Value::Null);
//
// {
// "c": "spot@private.deals.v3.api",
// "d": {
// "p": "22339.99",
// "v": "0.000235",
// "S": 1,
// "T": 1678670940695,
// "t": "9f6a47fb926442e496c5c4c104076ae3",
// "c": '',
// "i": "e2b9835d1b6745f8a10ab74a81a16d50",
// "m": 0,
// "st": 0
// },
// "s": "BTCUSDT",
// "t": 1678670940700
// }
// {
// channel: "spot@private.deals.v3.api.pb",
// symbol: "MXUSDT",
// sendTime: 1736417034332,
// privateDeals {
// price: "3.6962",
// quantity: "1",
// amount: "3.6962",
// tradeType: 2,
// tradeId: "505979017439002624X1",
// orderId: "C02__505979017439002624115",
// feeAmount: "0.0003998377369698171",
// feeCurrency: "MX",
// time: 1736417034280
// }
// }
//
let mut messageHash: Value = Value::Str("myTrades".into());
let mut data: Value = self.safe_dict_n(message.clone(), Value::from(vec![Value::Str("d".into()), Value::Str("data".into()), Value::Str("privateDeals".into())]), &[]);
let mut futuresMarketId: Value = self.safe_string_k(data.clone(), "symbol", &[]);
let mut marketId: Value = self.safe_string2(message.clone(), Value::Str("s".into()), Value::Str("symbol".into()), &[futuresMarketId]);
let mut market: Value = self.safe_market(&[marketId]);
let mut symbol: Value = market.as_map().and_then(|__m| __m.get("symbol")).cloned().unwrap_or(Value::Null);
let mut trade: Value = Value::Null;
if (market.as_map().and_then(|__m| __m.get("spot")).cloned().unwrap_or(Value::Null).as_bool() == Some(true)) {
trade = self.parse_ws_trade(data.clone(), &[market.clone()]);
} else if (data != Value::Null) {
trade = self.parse_trade(data.clone(), &[market]);
} else {
return;
}
let mut trades: Value = self.myTrades.clone();
if (trades == Value::Null) {
let mut limit: Value = self.safe_integer_k(self.options.clone(), "tradesLimit", &[Value::Int(1000)]);
trades = ArrayCacheBySymbolById::new(limit);
self.myTrades = trades.clone();
}
trades.append(trade);
client.resolve(&[trades.clone(), messageHash.clone()]);
let mut symbolSpecificMessageHash: Value = Value::Str(format!("{}{}", Value::Str(format!("{}{}", messageHash, Value::Str(":".into())).into()), symbol).into());
client.resolve(&[trades, symbolSpecificMessageHash]);
}
pub fn parse_ws_trade(&self, mut trade: Value, optional_args: &[Value]) -> Value {
let mut market = get_arg(optional_args, 0, Value::Null);
//
// public trade (protobuf)
// {
// "p": "20382.70",
// "v": "0.043800",
// "S": 1,
// "t": 1678593222456,
// }
// private trade
// {
// "S": 1,
// "T": 1661938980268,
// "c": "",
// "i": "c079b0fcb80a46e8b128b281ce4e4f38",
// "m": 1,
// "p": "1.008",
// "st": 0,
// "t": "4079b1522a0b40e7919f609e1ea38d44",
// "v": "5"
// }
//
// d: {
// p: '1.0005',
// v: '5.71',
// a: '5.712855',
// S: 1,
// T: 1714325698237,
// t: 'edafcd9fdc2f426e82443d114691f724',
// c: '',
// i: 'C02__413321238354677760043',
// m: 0,
// st: 0,
// n: '0.005712855',
// N: 'USDT'
// }
// protobuf
//
// {
// price: "3.6962",
// quantity: "1",
// amount: "3.6962",
// tradeType: 2,
// tradeId: "505979017439002624X1",
// orderId: "C02__505979017439002624115",
// feeAmount: "0.0003998377369698171",
// feeCurrency: "MX",
// time: 1736417034280
// }
//
let mut timestamp: Value = self.safe_integer2(trade.clone(), Value::Str("T".into()), Value::Str("time".into()), &[]);
let mut tradeId: Value = self.safe_string2(trade.clone(), Value::Str("t".into()), Value::Str("tradeId".into()), &[]);
if (timestamp == Value::Null) {
timestamp = self.safe_integer_k(trade.clone(), "t", &[]);
tradeId = Value::Null;
}
let mut priceString: Value = self.safe_string2(trade.clone(), Value::Str("p".into()), Value::Str("price".into()), &[]);
let mut amountString: Value = self.safe_string2(trade.clone(), Value::Str("v".into()), Value::Str("quantity".into()), &[]);
let mut rawSide: Option<String> = self.safe_string2(trade.clone(), Value::Str("S".into()), Value::Str("tradeType".into()), &[]).as_str().map(str::to_owned);
let mut side: Value = (if (rawSide.as_deref() == Some("1")) { Value::Str("buy".into()) } else { Value::Str("sell".into()) });
let mut isMaker: Option<i64> = self.safe_integer_k(trade.clone(), "m", &[]).as_i64();
let mut feeAmount: Value = self.safe_string2(trade.clone(), Value::Str("n".into()), Value::Str("feeAmount".into()), &[]);
let mut feeCurrencyId: Value = self.safe_string2(trade.clone(), Value::Str("N".into()), Value::Str("feeCurrency".into()), &[]);
return self.safe_trade(Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("info".to_string(), trade.clone());
m.insert("id".to_string(), tradeId);
m.insert("order".to_string(), self.safe_string2(trade.clone(), Value::Str("i".into()), Value::Str("orderId".into()), &[]));
m.insert("timestamp".to_string(), timestamp.clone());
m.insert("datetime".to_string(), self.iso8601(timestamp.clone()));
m.insert("symbol".to_string(), self.safe_symbol(Value::Null, &[market.clone()]));
m.insert("type".to_string(), Value::Null);
m.insert("side".to_string(), side);
m.insert("takerOrMaker".to_string(), (if ((isMaker.is_some()) && (isMaker != Some(0))) { Value::Str("maker".into()) } else { Value::Str("taker".into()) }));
m.insert("price".to_string(), priceString);
m.insert("amount".to_string(), amountString);
m.insert("cost".to_string(), self.safe_string_k(trade, "amount", &[]));
m.insert("fee".to_string(), Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("cost".to_string(), feeAmount);
m.insert("currency".to_string(), self.safe_currency_code(feeCurrencyId, &[]));
m
}));
m
}), &[market]);
Value::Null
}
/*
* @method
* @name mexc#watchOrders
* @see https://www.mexc.com/api-docs/spot-v3/websocket-user-data-streams/spot-account-orders // spot
* @see https://www.mexc.com/api-docs/futures/websocket-api/order // swap
* @description watches information on multiple orders made by the user
* @param {string} symbol unified market symbol of the market orders were made in
* @param {int} [since] the earliest time in ms to fetch orders for
* @param {int} [limit] the maximum number of order structures to retrieve
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string|undefined} params.type the type of orders to retrieve, can be 'spot' or 'swap'
* @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/?id=order-structure}
*/
pub async fn watch_orders(&mut self, optional_args: &[Value]) -> Value {
let mut symbol = get_arg(optional_args, 0, Value::Null);
let mut since = get_arg(optional_args, 1, Value::Null);
let mut limit = get_arg(optional_args, 2, Value::Null);
let mut params = get_arg(optional_args, 3, Value::Map({
let mut m = indexmap::IndexMap::new();
m
}));
if (self.markets.clone() == Value::Null) {
self.load_markets(&[]).await;
}
let mut messageHash: Value = Value::Str("orders".into());
let mut market: Value = Value::Null;
if (symbol != Value::Null) {
market = self.market(symbol.clone());
symbol = market.as_map().and_then(|__m| __m.get("symbol")).cloned().unwrap_or(Value::Null);
messageHash = Value::Str(format!("{}{}", Value::Str(format!("{}{}", messageHash, Value::Str(":".into())).into()), symbol).into());
}
let mut type_var: Value = Value::Null;
{ let __destr_tmp = self.handle_market_type_and_params(Value::Str("watchOrders".into()), &[market, params.clone()]); type_var = __destr_tmp.as_array().and_then(|__arr| __arr.get(0)).cloned().unwrap_or(Value::Null); params = __destr_tmp.as_array().and_then(|__arr| __arr.get(1)).cloned().unwrap_or(Value::Null); }
let mut orders: Value = Value::Null;
if (type_var.as_str() == Some("spot")) {
let mut channel: Value = Value::Str("spot@private.orders.v3.api.pb".into());
orders = self.watch_spot_private(channel, messageHash.clone(), &[params.clone()]).await;
} else {
orders = self.watch_swap_private(messageHash, &[params]).await;
}
orders = self.require_value(orders.clone(), &[Value::Str("watchOrders() orders is required".into())]);
if is_true(&self.newUpdates) {
limit = orders.get_limit(symbol.clone(), limit.clone());
}
return self.filter_by_symbol_since_limit(orders, &[symbol, since, limit, Value::Bool(true)]);
Value::Null
}
pub fn handle_order(&mut self, mut client: Value, mut message: Value) {
let __pro_message_arc: std::sync::Arc<indexmap::IndexMap<String, Value>> = (match &message { Value::Dict(__d) => __d.clone(), _ => std::sync::Arc::new(indexmap::IndexMap::new()) });
let __pro_message: &indexmap::IndexMap<String, Value> = &__pro_message_arc;
//
// spot
// {
// "c": "spot@private.orders.v3.api",
// "d": {
// "A":8.0,
// "O":1661938138000,
// "S":1,
// "V":10,
// "a":8,
// "c":"",
// "i":"e03a5c7441e44ed899466a7140b71391",
// "m":0,
// "o":1,
// "p":0.8,
// "s":1,
// "v":10,
// "ap":0,
// "cv":0,
// "ca":0
// },
// "s": "MXUSDT",
// "t": 1661938138193
// }
// spot - stop
// {
// "c": "spot@private.orders.v3.api",
// "d": {
// "N":"USDT",
// "O":1661938853715,
// "P":0.9,
// "S":1,
// "T":"LE",
// "i":"f6d82e5f41d745f59fe9d3cafffd80b5",
// "o":100,
// "p":1.01,
// "s":"NEW",
// "v":6
// },
// "s": "MXUSDT",
// "t": 1661938853727
// }
// margin
// {
// "c": "margin@private.orders.v3.api",
// "d":{
// "O":1661938138000,
// "p":"0.8",
// "a":"8",
// "v":"10",
// "da":"0",
// "dv":"0",
// "A":"8.0",
// "V":"10",
// "n": "0",
// "N": "USDT",
// "S":1,
// "o":1,
// "s":1,
// "i":"e03a5c7441e44ed899466a7140b71391",
// },
// "s": "MXUSDT",
// "t":1661938138193
// }
// protobuf
// {
// channel: "spot@private.orders.v3.api.pb",
// symbol: "MXUSDT",
// sendTime: 1736417034281,
// privateOrders {}
// }
//
let mut messageHash: Value = Value::Str("orders".into());
let mut data: Value = self.safe_dict_n(message.clone(), Value::from(vec![Value::Str("d".into()), Value::Str("data".into()), Value::Str("privateOrders".into())]), &[]);
let mut futuresMarketId: Value = self.safe_string_k(data.clone(), "symbol", &[]);
let mut marketId: Value = self.safe_string2(message.clone(), Value::Str("s".into()), Value::Str("symbol".into()), &[futuresMarketId]);
let mut market: Value = self.safe_market(&[marketId]);
let mut symbol: Value = market.as_map().and_then(|__m| __m.get("symbol")).cloned().unwrap_or(Value::Null);
let mut parsed: Value = Value::Null;
if (market.as_map().and_then(|__m| __m.get("spot")).cloned().unwrap_or(Value::Null).as_bool() == Some(true)) {
parsed = self.parse_ws_order(data.clone(), &[market.clone()]);
let mut sendTime: Value = (match __pro_message.get("sendTime").cloned() { Some(Value::Int(__n)) => Value::Int(__n), Some(Value::Float(__f)) => Value::Int(__f as i64), Some(Value::Str(__s)) if !__s.is_empty() => match __s.parse::<i64>() { Ok(__n) => Value::Int(__n), Err(_) => match __s.parse::<f64>() { Ok(__f) if __f.is_finite() => Value::Int(__f as i64), _ => Value::Null } }, _ => Value::Null });
if (sendTime != Value::Null) {
add_element_to_object(&mut parsed, &Value::Str("lastTradeTimestamp".into()), sendTime);
}
} else if (data != Value::Null) {
parsed = self.parse_order(data.clone(), &[market]);
} else {
return;
}
let mut orders: Value = self.orders.clone();
if (orders == Value::Null) {
let mut limit: Value = self.safe_integer_k(self.options.clone(), "ordersLimit", &[Value::Int(1000)]);
orders = ArrayCacheBySymbolById::new(limit);
self.orders = orders.clone();
}
orders.append(parsed);
client.resolve(&[orders.clone(), messageHash.clone()]);
let mut symbolSpecificMessageHash: Value = Value::Str(format!("{}{}", Value::Str(format!("{}{}", messageHash, Value::Str(":".into())).into()), symbol).into());
client.resolve(&[orders, symbolSpecificMessageHash]);
}
pub fn parse_ws_order(&self, mut order: Value, optional_args: &[Value]) -> Value {
let mut market = get_arg(optional_args, 0, Value::Null);
//
// spot
// {
// "A":8.0,
// "O":1661938138000,
// "S":1,
// "V":10,
// "a":8,
// "c":"",
// "i":"e03a5c7441e44ed899466a7140b71391",
// "m":0,
// "o":1,
// "p":0.8,
// "s":1,
// "v":10,
// "ap":0,
// "cv":0,
// "ca":0
// }
// spot - stop
// {
// "N":"USDT",
// "O":1661938853715,
// "P":0.9,
// "S":1,
// "T":"LE",
// "i":"f6d82e5f41d745f59fe9d3cafffd80b5",
// "o":100,
// "p":1.01,
// "s":"NEW",
// "v":6
// }
// margin
// {
// "O":1661938138000,
// "p":"0.8",
// "a":"8",
// "v":"10",
// "da":"0",
// "dv":"0",
// "A":"8.0",
// "V":"10",
// "n": "0",
// "N": "USDT",
// "S":1,
// "o":1,
// "s":1,
// "i":"e03a5c7441e44ed899466a7140b71391",
// }
// protofbuf spot order
// {
// "id":"C02__583905164440776704043",
// "price":"0.001053",
// "quantity":"2000",
// "amount":"0",
// "avgPrice":"0.001007",
// "orderType":5,
// "tradeType":1,
// "remainAmount":"0.092",
// "remainQuantity":"0",
// "lastDealQuantity":"2000",
// "cumulativeQuantity":"2000",
// "cumulativeAmount":"2.014",
// "status":2,
// "createTime":"1754996075502"
// }
//
let mut timestamp: Value = self.safe_integer_k(order.clone(), "createTime", &[]);
let mut side: Option<String> = self.safe_string_k(order.clone(), "tradeType", &[]).as_str().map(str::to_owned);
let mut status: Value = self.safe_string2(order.clone(), Value::Str("status".into()), Value::Str("state".into()), &[]);
let mut type_var: Value = self.safe_string_k(order.clone(), "orderType", &[]);
let mut fee: Value = Value::Null;
let mut feeCurrency: Value = self.safe_string_k(order.clone(), "N", &[]);
if (feeCurrency != Value::Null) {
fee = Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("currency".to_string(), feeCurrency);
m.insert("cost".to_string(), Value::Null);
m
});
}
return self.safe_order(Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("id".to_string(), self.safe_string_k(order.clone(), "id", &[]));
m.insert("clientOrderId".to_string(), self.safe_string_k(order.clone(), "clientId", &[]));
m.insert("timestamp".to_string(), timestamp.clone());
m.insert("datetime".to_string(), self.iso8601(timestamp.clone()));
m.insert("lastTradeTimestamp".to_string(), Value::Null);
m.insert("status".to_string(), self.parse_ws_order_status(status, &[market.clone()]).map(|__s| Value::Str(__s.into())).unwrap_or(Value::Null));
m.insert("symbol".to_string(), self.safe_symbol(Value::Null, &[market.clone()]));
m.insert("type".to_string(), self.parse_ws_order_type(type_var.clone()).map(|__s| Value::Str(__s.into())).unwrap_or(Value::Null));
m.insert("timeInForce".to_string(), self.parse_ws_time_in_force(type_var).map(|__s| Value::Str(__s.into())).unwrap_or(Value::Null));
m.insert("side".to_string(), (if (side.as_deref() == Some("1")) { Value::Str("buy".into()) } else { Value::Str("sell".into()) }));
m.insert("price".to_string(), self.safe_string_k(order.clone(), "price", &[]));
m.insert("stopPrice".to_string(), self.safe_string2(order.clone(), Value::Str("triggerPrice".into()), Value::Str("P".into()), &[]));
m.insert("triggerPrice".to_string(), self.safe_string2(order.clone(), Value::Str("triggerPrice".into()), Value::Str("P".into()), &[]));
m.insert("average".to_string(), self.safe_string_k(order.clone(), "avgPrice", &[]));
m.insert("amount".to_string(), self.safe_string_k(order.clone(), "quantity", &[]));
m.insert("cost".to_string(), self.safe_string_k(order.clone(), "amount", &[]));
m.insert("filled".to_string(), self.safe_string_k(order.clone(), "cumulativeQuantity", &[]));
m.insert("remaining".to_string(), self.safe_string_k(order.clone(), "remainQuantity", &[]));
m.insert("fee".to_string(), fee);
m.insert("trades".to_string(), Value::Null);
m.insert("info".to_string(), order);
m
}), &[market]);
Value::Null
}
pub fn parse_ws_order_status(&self, mut status: Value, optional_args: &[Value]) -> Option<String> {
let mut market = get_arg(optional_args, 0, Value::Null);
let mut statuses: Value = Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("0".to_string(), Value::Str("open".into()));
m.insert("1".to_string(), Value::Str("open".into()));
m.insert("2".to_string(), Value::Str("closed".into()));
m.insert("3".to_string(), Value::Str("open".into()));
m.insert("4".to_string(), Value::Str("canceled".into()));
m.insert("5".to_string(), Value::Str("closed".into()));
m.insert("NEW".to_string(), Value::Str("open".into()));
m.insert("CANCELED".to_string(), Value::Str("canceled".into()));
m.insert("EXECUTED".to_string(), Value::Str("closed".into()));
m.insert("FAILED".to_string(), Value::Str("rejected".into()));
m
});
return self.safe_string(statuses, status.clone(), &[status.clone()]).as_str().map(str::to_owned);
}
pub fn parse_ws_order_type(&self, mut type_var: Value) -> Option<String> {
let mut types: Value = Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("1".to_string(), Value::Str("limit".into()));
m.insert("2".to_string(), Value::Str("limit".into()));
m.insert("3".to_string(), Value::Null);
m.insert("4".to_string(), Value::Null);
m.insert("5".to_string(), Value::Str("market".into()));
m.insert("100".to_string(), Value::Str("limit".into()));
m.insert("101".to_string(), Value::Str("limit".into()));
m.insert("102".to_string(), Value::Str("limit".into()));
m
});
return self.safe_string(types, type_var, &[]).as_str().map(str::to_owned);
}
pub fn parse_ws_time_in_force(&self, mut timeInForce: Value) -> Option<String> {
let mut timeInForceIds: Value = Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("1".to_string(), Value::Str("GTC".into()));
m.insert("2".to_string(), Value::Str("PO".into()));
m.insert("3".to_string(), Value::Str("IOC".into()));
m.insert("4".to_string(), Value::Str("FOK".into()));
m.insert("5".to_string(), Value::Str("GTC".into()));
m.insert("100".to_string(), Value::Str("GTC".into()));
m.insert("101".to_string(), Value::Str("GTC".into()));
m.insert("102".to_string(), Value::Str("GTC".into()));
m
});
return self.safe_string(timeInForceIds, timeInForce, &[]).as_str().map(str::to_owned);
}
/*
* @method
* @name mexc#watchBalance
* @see https://www.mexc.com/api-docs/spot-v3/websocket-user-data-streams/spot-account-update // spot
* @see https://www.mexc.com/api-docs/futures/websocket-api/assets // swap
* @description watch balance and get the amount of funds available for trading or funds locked in orders
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [balance structure]{@link https://docs.ccxt.com/?id=balance-structure}
*/
pub async fn watch_balance(&mut self, optional_args: &[Value]) -> Value {
let mut params = get_arg(optional_args, 0, Value::Map({
let mut m = indexmap::IndexMap::new();
m
}));
if (self.markets.clone() == Value::Null) {
self.load_markets(&[]).await;
}
let mut type_var: Value = Value::Null;
{ let __destr_tmp = self.handle_market_type_and_params(Value::Str("watchBalance".into()), &[Value::Null, params.clone()]); type_var = __destr_tmp.as_array().and_then(|__arr| __arr.get(0)).cloned().unwrap_or(Value::Null); params = __destr_tmp.as_array().and_then(|__arr| __arr.get(1)).cloned().unwrap_or(Value::Null); }
let mut messageHash: Value = Value::Str(format!("{}{}", Value::Str("balance:".into()), type_var).into());
if (type_var.as_str() == Some("spot")) {
let mut channel: Value = Value::Str("spot@private.account.v3.api.pb".into());
return self.watch_spot_private(channel, messageHash.clone(), &[params.clone()]).await;
} else {
return self.watch_swap_private(messageHash, &[params]).await;
}
Value::Null
}
pub fn handle_balance(&mut self, mut client: Value, mut message: Value) {
let __pro_message_arc: std::sync::Arc<indexmap::IndexMap<String, Value>> = (match &message { Value::Dict(__d) => __d.clone(), _ => std::sync::Arc::new(indexmap::IndexMap::new()) });
let __pro_message: &indexmap::IndexMap<String, Value> = &__pro_message_arc;
//
// spot
//
// {
// channel: "spot@private.account.v3.api.pb",
// createTime: "1758134605364",
// sendTime: "1758134605373",
// privateAccount: {
// vcoinName: "USDT",
// coinId: "128f589271cb4951b03e71e6323eb7be",
// balanceAmount: "0.006016465074677006",
// balanceAmountChange: "-4.4022",
// frozenAmount: "4.4022",
// frozenAmountChange: "4.4022",
// type: "ENTRUST_PLACE",
// time: "1758134605364",
// }
// }
//
//
// swap balance
//
// {
// "channel": "push.personal.asset",
// "data": {
// "availableBalance": 67.2426683348,
// "bonus": 0,
// "currency": "USDT",
// "frozenBalance": 0,
// "positionMargin": 1.36945756
// },
// "ts": 1680059188191
// }
//
let mut channel: Option<String> = (match __pro_message.get("channel").cloned() { Some(Value::Str(__s)) if !__s.is_empty() => Value::Str(__s), Some(Value::Int(__n)) => Value::Str(__n.to_string().into()), Some(Value::Float(__f)) => Value::Str(__f.to_string().into()), _ => Value::Null }).as_str().map(str::to_owned);
let mut type_var: Value = (if (channel.as_deref() == Some("spot@private.account.v3.api.pb")) { Value::Str("spot".into()) } else { Value::Str("swap".into()) });
let mut messageHash: Value = Value::Str(format!("{}{}", Value::Str("balance:".into()), type_var).into());
let mut data: Value = self.safe_dict_n(message.clone(), Value::from(vec![Value::Str("data".into()), Value::Str("privateAccount".into())]), &[]);
let mut futuresTimestamp: Value = self.safe_integer2(message.clone(), Value::Str("ts".into()), Value::Str("createTime".into()), &[]);
let mut timestamp: Value = self.safe_integer2(data.clone(), Value::Str("time".into()), futuresTimestamp, &[]);
if !(in_op(&self.balance, &type_var)) {
if let Value::Dict(__d) = &mut self.balance { std::sync::Arc::make_mut(__d).insert(crate::runtime::stringify_param(&type_var), Value::Map({
let mut m = indexmap::IndexMap::new();
m
})); }
}
add_element_to_object(get_value_mut(&mut self.balance, &type_var), &Value::Str("info".into()), data.clone());
add_element_to_object(get_value_mut(&mut self.balance, &type_var), &Value::Str("timestamp".into()), timestamp.clone());
{ let __be_tmp = self.iso8601(timestamp.clone()); add_element_to_object(get_value_mut(&mut self.balance, &type_var), &Value::Str("datetime".into()), __be_tmp); };
let mut currencyId: Value = self.safe_string2(data.clone(), Value::Str("currency".into()), Value::Str("vcoinName".into()), &[]);
let mut code: Value = self.safe_currency_code(currencyId, &[]);
let mut account: Value = self.account();
if let Value::Dict(__d) = &mut account { std::sync::Arc::make_mut(__d).insert("free".into(), self.safe_string2(data.clone(), Value::Str("balanceAmount".into()), Value::Str("availableBalance".into()), &[])); }
if let Value::Dict(__d) = &mut account { std::sync::Arc::make_mut(__d).insert("used".into(), self.safe_string2(data.clone(), Value::Str("frozenBalance".into()), Value::Str("frozenAmount".into()), &[])); }
if (code != Value::Null) {
add_element_to_object(get_value_mut(&mut self.balance, &type_var), &code, account);
}
{ let __be_tmp = self.safe_balance(get_value(&self.balance, &type_var)); if let Value::Dict(__d) = &mut self.balance { std::sync::Arc::make_mut(__d).insert(crate::runtime::stringify_param(&type_var), __be_tmp); } }
client.resolve(&[get_value(&self.balance, &type_var), messageHash]);
}
/*
* @method
* @name mexc#watchFundingRate
* @description watch the current funding rate
* @see https://www.mexc.com/api-docs/futures/websocket-api/funding-rate
* @param {string} symbol unified market symbol
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [funding rate structure]{@link https://docs.ccxt.com/?id=funding-rate-structure}
*/
pub async fn watch_funding_rate(&mut self, mut symbol: Value, optional_args: &[Value]) -> Value {
let mut params = get_arg(optional_args, 0, Value::Map({
let mut m = indexmap::IndexMap::new();
m
}));
if (self.markets.clone() == Value::Null) {
self.load_markets(&[]).await;
}
let mut market: Value = self.market(symbol);
let mut messageHash: Value = Value::Str(format!("{}{}", Value::Str("fundingRate:".into()), market.as_map().and_then(|__m| __m.get("symbol")).cloned().unwrap_or(Value::Null)).into());
let mut channel: Value = Value::Str("sub.funding.rate".into());
let mut requestParams: Value = Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("symbol".to_string(), market.as_map().and_then(|__m| __m.get("id")).cloned().unwrap_or(Value::Null));
m
});
return self.watch_swap_public(channel, messageHash, requestParams, &[params]).await;
Value::Null
}
/*
* @method
* @name mexc#unWatchFundingRate
* @description unWatches the current funding rate for a symbol
* @see https://www.mexc.com/api-docs/futures/websocket-api/funding-rate
* @param {string} symbol unified symbol of the market
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [funding rate structure]{@link https://docs.ccxt.com/?id=funding-rate-structure}
*/
pub async fn un_watch_funding_rate(&mut self, mut symbol: Value, optional_args: &[Value]) -> Value {
let mut params = get_arg(optional_args, 0, Value::Map({
let mut m = indexmap::IndexMap::new();
m
}));
if (self.markets.clone() == Value::Null) {
self.load_markets(&[]).await;
}
let mut market: Value = self.market(symbol);
let mut messageHash: Value = Value::Str(format!("{}{}", Value::Str("unsubscribe:fundingRate:".into()), market.as_map().and_then(|__m| __m.get("symbol")).cloned().unwrap_or(Value::Null)).into());
let mut url: Value = Value::Null;
let mut channel: Value = Value::Str("unsub.funding.rate".into());
let mut requestParams: Value = Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("symbol".to_string(), market.as_map().and_then(|__m| __m.get("id")).cloned().unwrap_or(Value::Null));
m
});
url = crate::value::get_value_k(&self.urls.as_map().and_then(|__m| __m.get("api")).cloned().unwrap_or(Value::Null).as_map().and_then(|__m| __m.get("ws")).cloned().unwrap_or(Value::Null), "swap");
self.spawn(&[Value::Str("watch_swap_public".into()).clone(), channel, messageHash.clone(), requestParams, params]);
let mut client: Value = self.client(&[url]);
self.handle_unsubscriptions(client, Value::from(vec![messageHash]));
return Value::Null;
Value::Null
}
pub fn handle_funding_rate(&mut self, mut client: Value, mut message: Value) {
let __message_empty = indexmap::IndexMap::new();
let message = message.as_map().unwrap_or(&__message_empty);
//
// {
// "symbol": "BTC_USDT",
// "data": {
// "symbol": "BTC_USDT",
// "rate": -0.000021,
// "nextSettleTime": 1771084800000
// },
// "channel": "push.funding.rate",
// "ts": 1771069020506
// }
//
let mut data: Value = (match message.get("data") { Some(__v) if matches!(__v, Value::Dict(_)) => __v.clone(), _ => Value::Map({
let mut m = indexmap::IndexMap::new();
m
}) });
let mut fundingRate: Value = self.parse_funding_rate(data.clone(), &[]);
let mut symbol: Value = fundingRate.as_map().and_then(|__m| __m.get("symbol")).cloned().unwrap_or(Value::Null);
if (symbol != Value::Null) {
if let Value::Dict(__d) = &mut self.fundingRates { std::sync::Arc::make_mut(__d).insert(crate::runtime::stringify_param(&symbol), fundingRate.clone()); }
}
let mut messageHash: Value = Value::Str(format!("{}{}", Value::Str("fundingRate:".into()), symbol).into());
client.resolve(&[fundingRate, messageHash]);
}
/*
* @method
* @name mexc#unWatchTicker
* @description unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
* @param {string} symbol unified symbol of the market to fetch the ticker for
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/?id=ticker-structure}
*/
pub async fn un_watch_ticker(&mut self, mut symbol: Value, optional_args: &[Value]) -> Value {
let mut params = get_arg(optional_args, 0, Value::Map({
let mut m = indexmap::IndexMap::new();
m
}));
if (self.markets.clone() == Value::Null) {
self.load_markets(&[]).await;
}
let mut market: Value = self.market(symbol);
let mut messageHash: Value = Value::Str(format!("{}{}", Value::Str("unsubscribe:ticker:".into()), market.as_map().and_then(|__m| __m.get("symbol")).cloned().unwrap_or(Value::Null)).into());
let mut url: Value = Value::Null;
let mut channel: Value = Value::Null;
if (market.as_map().and_then(|__m| __m.get("spot")).cloned().unwrap_or(Value::Null).as_bool() == Some(true)) {
channel = Value::Str(format!("{}{}", Value::Str("spot@public.aggre.bookTicker.v3.api.pb@100ms@".into()), market.as_map().and_then(|__m| __m.get("id")).cloned().unwrap_or(Value::Null)).into());
url = crate::value::get_value_k(&self.urls.as_map().and_then(|__m| __m.get("api")).cloned().unwrap_or(Value::Null).as_map().and_then(|__m| __m.get("ws")).cloned().unwrap_or(Value::Null), "spot");
if let Value::Dict(__d) = &mut params { std::sync::Arc::make_mut(__d).insert("unsubscribed".into(), Value::Bool(true)); }
self.spawn(&[Value::Str("watch_spot_public".into()).clone(), channel.clone(), messageHash.clone(), params.clone()]);
} else {
channel = Value::Str("unsub.ticker".into());
let mut requestParams: Value = Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("symbol".to_string(), market.as_map().and_then(|__m| __m.get("id")).cloned().unwrap_or(Value::Null));
m
});
url = crate::value::get_value_k(&self.urls.as_map().and_then(|__m| __m.get("api")).cloned().unwrap_or(Value::Null).as_map().and_then(|__m| __m.get("ws")).cloned().unwrap_or(Value::Null), "swap");
self.spawn(&[Value::Str("watch_swap_public".into()).clone(), channel, messageHash.clone(), requestParams, params]);
}
let mut client: Value = self.client(&[url]);
self.handle_unsubscriptions(client, Value::from(vec![messageHash]));
return Value::Null;
Value::Null
}
/*
* @method
* @name mexc#unWatchTickers
* @description unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
* @param {string[]} symbols unified symbol of the market to fetch the ticker for
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/?id=ticker-structure}
*/
pub async fn un_watch_tickers(&mut self, optional_args: &[Value]) -> Value {
let mut symbols = get_arg(optional_args, 0, Value::Null);
let mut params = get_arg(optional_args, 1, Value::Map({
let mut m = indexmap::IndexMap::new();
m
}));
if (self.markets.clone() == Value::Null) {
self.load_markets(&[]).await;
}
symbols = self.market_symbols(&[symbols.clone(), Value::Null]);
let mut messageHashes: Value = Value::from(vec![]);
let mut firstSymbol: Value = self.safe_string(symbols, Value::Int(0), &[]);
let mut market: Value = Value::Null;
if (firstSymbol != Value::Null) {
market = self.market(firstSymbol);
}
let mut type_var: Value = Value::Null;
{ let __destr_tmp = self.handle_market_type_and_params(Value::Str("watchTickers".into()), &[market, params.clone()]); type_var = __destr_tmp.as_array().and_then(|__arr| __arr.get(0)).cloned().unwrap_or(Value::Null); params = __destr_tmp.as_array().and_then(|__arr| __arr.get(1)).cloned().unwrap_or(Value::Null); }
let mut isSpot: bool = type_var.as_str() == Some("spot");
let mut url: Value = (if (isSpot) { crate::value::get_value_k(&self.urls.as_map().and_then(|__m| __m.get("api")).cloned().unwrap_or(Value::Null).as_map().and_then(|__m| __m.get("ws")).cloned().unwrap_or(Value::Null), "spot") } else { crate::value::get_value_k(&self.urls.as_map().and_then(|__m| __m.get("api")).cloned().unwrap_or(Value::Null).as_map().and_then(|__m| __m.get("ws")).cloned().unwrap_or(Value::Null), "swap") });
let mut request: Value = Value::Map({
let mut m = indexmap::IndexMap::new();
m
});
if isSpot {
panic!("{}", crate::exchange_errors::not_supported(format!("{}{}", self.id.clone(), Value::Str(" watchTickers does not support spot markets".into()))));
} else {
if let Value::Dict(__d) = &mut request { std::sync::Arc::make_mut(__d).insert("method".into(), Value::Str("unsub.tickers".into())); }
if let Value::Dict(__d) = &mut request { std::sync::Arc::make_mut(__d).insert("params".into(), Value::Map({
let mut m = indexmap::IndexMap::new();
m
})); }
append_to_array(&mut messageHashes, Value::Str("unsubscribe:ticker".into()));
}
let mut client: Value = self.client(&[url.clone()]);
let __ws_arg_4 = self.extend(request, &[params]);
self.watch_multiple(url, messageHashes.clone(), &[__ws_arg_4, messageHashes.clone()]).await;
self.handle_unsubscriptions(client, messageHashes);
return Value::Null;
Value::Null
}
/*
* @method
* @name mexc#unWatchBidsAsks
* @description unWatches best bid & ask for symbols
* @param {string[]} symbols unified symbol of the market to fetch the ticker for
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/?id=ticker-structure}
*/
pub async fn un_watch_bids_asks(&mut self, optional_args: &[Value]) -> Value {
let mut symbols = get_arg(optional_args, 0, Value::Null);
let mut params = get_arg(optional_args, 1, Value::Map({
let mut m = indexmap::IndexMap::new();
m
}));
if (self.markets.clone() == Value::Null) {
self.load_markets(&[]).await;
}
symbols = self.market_symbols(&[symbols.clone(), Value::Null, Value::Bool(true), Value::Bool(false), Value::Bool(true)]);
let mut marketType: Value = Value::Null;
if (symbols == Value::Null) {
panic!("{}", crate::exchange_errors::arguments_required(format!("{}{}", self.id.clone(), Value::Str(" watchBidsAsks required symbols argument".into()))));
}
let mut markets: Value = self.require_value(self.markets_for_symbols(&[symbols.clone()]), &[Value::Str("unWatchBidsAsks() markets is required".into())]);
{ let __destr_tmp = self.handle_market_type_and_params(Value::Str("watchBidsAsks".into()), &[markets.as_array().and_then(|__arr| __arr.get(0)).cloned().unwrap_or(Value::Null), params.clone()]); marketType = __destr_tmp.as_array().and_then(|__arr| __arr.get(0)).cloned().unwrap_or(Value::Null); params = __destr_tmp.as_array().and_then(|__arr| __arr.get(1)).cloned().unwrap_or(Value::Null); }
let mut isSpot: bool = marketType.as_str() == Some("spot");
if !isSpot {
panic!("{}", crate::exchange_errors::not_supported(format!("{}{}", self.id.clone(), Value::Str(" watchBidsAsks only support spot market".into()))));
}
let mut messageHashes: Value = Value::from(vec![]);
let mut topics: Value = Value::from(vec![]);
{
let mut i: Value = Value::Int(0);
let mut __for_first_476: bool = true;
while { if !__for_first_476 { i = (match (&(i), &(Value::Int(1))) { (Value::Int(x), Value::Int(y)) => Value::Int(x + y), (Value::Int(x), Value::Float(y)) => Value::Float(*x as f64 + *y), (Value::Float(x), Value::Int(y)) => Value::Float(*x + *y as f64), (Value::Float(x), Value::Float(y)) => Value::Float(x + y), _ => Value::Null }); } __for_first_476 = false; i.as_f64().unwrap_or(f64::NAN) < ((symbols.len() as i64) as f64) } {
if isSpot {
let mut market: Value = self.market(symbols.as_array().and_then(|__arr| match &i { Value::Int(__n) => __arr.get(*__n as usize), Value::Str(__s) => __s.parse::<usize>().ok().and_then(|__n| __arr.get(__n)), _ => None }).cloned().unwrap_or(Value::Null));
append_to_array(&mut topics, Value::Str(format!("{}{}", Value::Str("spot@public.aggre.bookTicker.v3.api.pb@100ms@".into()), market.as_map().and_then(|__m| __m.get("id")).cloned().unwrap_or(Value::Null)).into()));
}
append_to_array(&mut messageHashes, Value::Str(format!("{}{}", Value::Str("unsubscribe:bidask:".into()), symbols.as_array().and_then(|__arr| match &i { Value::Int(__n) => __arr.get(*__n as usize), Value::Str(__s) => __s.parse::<usize>().ok().and_then(|__n| __arr.get(__n)), _ => None }).cloned().unwrap_or(Value::Null)).into()));
}
}
let mut url: Value = crate::value::get_value_k(&self.urls.as_map().and_then(|__m| __m.get("api")).cloned().unwrap_or(Value::Null).as_map().and_then(|__m| __m.get("ws")).cloned().unwrap_or(Value::Null), "spot");
let mut request: Value = Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("method".to_string(), Value::Str("UNSUBSCRIPTION".into()));
m.insert("params".to_string(), topics);
m
});
let mut client: Value = self.client(&[url.clone()]);
let __ws_arg_5 = self.extend(request, &[params]);
self.watch_multiple(url, messageHashes.clone(), &[__ws_arg_5, messageHashes.clone()]).await;
self.handle_unsubscriptions(client, messageHashes);
return Value::Null;
Value::Null
}
/*
* @method
* @name mexc#unWatchOHLCV
* @description unWatches historical candlestick data containing the open, high, low, and close price, and the volume of a market
* @param {string} symbol unified symbol of the market to fetch OHLCV data for
* @param {string} timeframe the length of time each candle represents
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {object} [params.timezone] if provided, kline intervals are interpreted in that timezone instead of UTC, example '+08:00'
* @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
*/
pub async fn un_watch_ohlcv(&mut self, mut symbol: Value, optional_args: &[Value]) -> Value {
let mut timeframe = get_arg(optional_args, 0, Value::Str("1m".into()));
let mut params = get_arg(optional_args, 1, Value::Map({
let mut m = indexmap::IndexMap::new();
m
}));
if (self.markets.clone() == Value::Null) {
self.load_markets(&[]).await;
}
let mut market: Value = self.market(symbol.clone());
symbol = market.as_map().and_then(|__m| __m.get("symbol")).cloned().unwrap_or(Value::Null);
let mut timeframes: Value = self.safe_dict_k(self.options.clone(), "timeframes", &[Value::Map({
let mut m = indexmap::IndexMap::new();
m
})]);
let mut timeframeId: Value = self.safe_string(timeframes, timeframe.clone(), &[]);
let mut messageHash: Value = Value::Str(format!("{}{}", Value::Str(format!("{}{}", Value::Str(format!("{}{}", Value::Str("unsubscribe:candles:".into()), symbol).into()), Value::Str(":".into())).into()), timeframe).into());
let mut url: Value = Value::Null;
if (market.as_map().and_then(|__m| __m.get("spot")).cloned().unwrap_or(Value::Null).as_bool() == Some(true)) {
url = crate::value::get_value_k(&self.urls.as_map().and_then(|__m| __m.get("api")).cloned().unwrap_or(Value::Null).as_map().and_then(|__m| __m.get("ws")).cloned().unwrap_or(Value::Null), "spot");
let mut channel: Value = Value::Str(format!("{}{}", Value::Str(format!("{}{}", Value::Str(format!("{}{}", Value::Str("spot@public.kline.v3.api.pb@".into()), market.as_map().and_then(|__m| __m.get("id")).cloned().unwrap_or(Value::Null)).into()), Value::Str("@".into())).into()), timeframeId).into());
if let Value::Dict(__d) = &mut params { std::sync::Arc::make_mut(__d).insert("unsubscribed".into(), Value::Bool(true)); }
self.spawn(&[Value::Str("watch_spot_public".into()).clone(), channel.clone(), messageHash.clone(), params.clone()]);
} else {
url = crate::value::get_value_k(&self.urls.as_map().and_then(|__m| __m.get("api")).cloned().unwrap_or(Value::Null).as_map().and_then(|__m| __m.get("ws")).cloned().unwrap_or(Value::Null), "swap");
let mut channel: Value = Value::Str("unsub.kline".into());
let mut requestParams: Value = Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("symbol".to_string(), market.as_map().and_then(|__m| __m.get("id")).cloned().unwrap_or(Value::Null));
m.insert("interval".to_string(), timeframeId);
m
});
self.spawn(&[Value::Str("watch_swap_public".into()).clone(), channel, messageHash.clone(), requestParams, params]);
}
let mut client: Value = self.client(&[url]);
self.handle_unsubscriptions(client, Value::from(vec![messageHash]));
return Value::Null;
Value::Null
}
/*
* @method
* @name mexc#unWatchOrderBook
* @description unWatches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
* @param {string} symbol unified array of symbols
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string} [params.frequency] the frequency of the order book updates, default is '10ms', can be '100ms' or '10ms
* @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/?id=order-book-structure}
*/
pub async fn un_watch_order_book(&mut self, mut symbol: Value, optional_args: &[Value]) -> Value {
let mut params = get_arg(optional_args, 0, Value::Map({
let mut m = indexmap::IndexMap::new();
m
}));
if (self.markets.clone() == Value::Null) {
self.load_markets(&[]).await;
}
let mut market: Value = self.market(symbol.clone());
symbol = market.as_map().and_then(|__m| __m.get("symbol")).cloned().unwrap_or(Value::Null);
let mut messageHash: Value = Value::Str(format!("{}{}", Value::Str("unsubscribe:orderbook:".into()), symbol).into());
let mut url: Value = Value::Null;
if (market.as_map().and_then(|__m| __m.get("spot")).cloned().unwrap_or(Value::Null).as_bool() == Some(true)) {
url = crate::value::get_value_k(&self.urls.as_map().and_then(|__m| __m.get("api")).cloned().unwrap_or(Value::Null).as_map().and_then(|__m| __m.get("ws")).cloned().unwrap_or(Value::Null), "spot");
let mut frequency: Value = Value::Null;
{ let __destr_tmp = self.handle_option_and_params(params.clone(), Value::Str("watchOrderBook".into()), Value::Str("frequency".into()), &[Value::Str("100ms".into())]); frequency = __destr_tmp.as_array().and_then(|__arr| __arr.get(0)).cloned().unwrap_or(Value::Null); params = __destr_tmp.as_array().and_then(|__arr| __arr.get(1)).cloned().unwrap_or(Value::Null); }
let mut channel: Value = Value::Str(format!("{}{}", Value::Str(format!("{}{}", Value::Str(format!("{}{}", Value::Str("spot@public.aggre.depth.v3.api.pb@".into()), frequency).into()), Value::Str("@".into())).into()), market.as_map().and_then(|__m| __m.get("id")).cloned().unwrap_or(Value::Null)).into());
if let Value::Dict(__d) = &mut params { std::sync::Arc::make_mut(__d).insert("unsubscribed".into(), Value::Bool(true)); }
self.spawn(&[Value::Str("watch_spot_public".into()).clone(), channel.clone(), messageHash.clone(), params.clone()]);
} else {
url = crate::value::get_value_k(&self.urls.as_map().and_then(|__m| __m.get("api")).cloned().unwrap_or(Value::Null).as_map().and_then(|__m| __m.get("ws")).cloned().unwrap_or(Value::Null), "swap");
let mut channel: Value = Value::Str("unsub.depth".into());
let mut requestParams: Value = Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("symbol".to_string(), market.as_map().and_then(|__m| __m.get("id")).cloned().unwrap_or(Value::Null));
m
});
self.spawn(&[Value::Str("watch_swap_public".into()).clone(), channel, messageHash.clone(), requestParams, params]);
}
let mut client: Value = self.client(&[url]);
self.handle_unsubscriptions(client, Value::from(vec![messageHash]));
return Value::Null;
Value::Null
}
/*
* @method
* @name mexc#unWatchTrades
* @description unsubscribes from the trades channel
* @param {string} symbol unified symbol of the market to fetch trades for
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string} [params.name] the name of the method to call, 'trade' or 'aggTrade', default is 'trade'
* @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/?id=public-trades}
*/
pub async fn un_watch_trades(&mut self, mut symbol: Value, optional_args: &[Value]) -> Value {
let mut params = get_arg(optional_args, 0, Value::Map({
let mut m = indexmap::IndexMap::new();
m
}));
if (self.markets.clone() == Value::Null) {
self.load_markets(&[]).await;
}
let mut market: Value = self.market(symbol.clone());
symbol = market.as_map().and_then(|__m| __m.get("symbol")).cloned().unwrap_or(Value::Null);
let mut messageHash: Value = Value::Str(format!("{}{}", Value::Str("unsubscribe:trades:".into()), symbol).into());
let mut url: Value = Value::Null;
if (market.as_map().and_then(|__m| __m.get("spot")).cloned().unwrap_or(Value::Null).as_bool() == Some(true)) {
url = crate::value::get_value_k(&self.urls.as_map().and_then(|__m| __m.get("api")).cloned().unwrap_or(Value::Null).as_map().and_then(|__m| __m.get("ws")).cloned().unwrap_or(Value::Null), "spot");
let mut channel: Value = Value::Str(format!("{}{}", Value::Str("spot@public.aggre.deals.v3.api.pb@100ms@".into()), market.as_map().and_then(|__m| __m.get("id")).cloned().unwrap_or(Value::Null)).into());
if let Value::Dict(__d) = &mut params { std::sync::Arc::make_mut(__d).insert("unsubscribed".into(), Value::Bool(true)); }
self.spawn(&[Value::Str("watch_spot_public".into()).clone(), channel.clone(), messageHash.clone(), params.clone()]);
} else {
url = crate::value::get_value_k(&self.urls.as_map().and_then(|__m| __m.get("api")).cloned().unwrap_or(Value::Null).as_map().and_then(|__m| __m.get("ws")).cloned().unwrap_or(Value::Null), "swap");
let mut channel: Value = Value::Str("unsub.deal".into());
let mut requestParams: Value = Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("symbol".to_string(), market.as_map().and_then(|__m| __m.get("id")).cloned().unwrap_or(Value::Null));
m
});
self.spawn(&[Value::Str("watch_swap_public".into()).clone(), channel, messageHash.clone(), requestParams, params]);
}
let mut client: Value = self.client(&[url]);
self.handle_unsubscriptions(client, Value::from(vec![messageHash]));
return Value::Null;
Value::Null
}
pub fn handle_unsubscriptions(&mut self, mut client: Value, mut messageHashes: Value) {
{
let mut i: Value = Value::Int(0);
let mut __for_first_478: bool = true;
while { if !__for_first_478 { i = (match (&(i), &(Value::Int(1))) { (Value::Int(x), Value::Int(y)) => Value::Int(x + y), (Value::Int(x), Value::Float(y)) => Value::Float(*x as f64 + *y), (Value::Float(x), Value::Int(y)) => Value::Float(*x + *y as f64), (Value::Float(x), Value::Float(y)) => Value::Float(x + y), _ => Value::Null }); } __for_first_478 = false; i.as_f64().unwrap_or(f64::NAN) < ((messageHashes.len() as i64) as f64) } {
let mut messageHash: Value = messageHashes.as_array().and_then(|__arr| match &i { Value::Int(__n) => __arr.get(*__n as usize), Value::Str(__s) => __s.parse::<usize>().ok().and_then(|__n| __arr.get(__n)), _ => None }).cloned().unwrap_or(Value::Null);
let mut subMessageHash: Value = replace_str(&messageHash, &Value::Str("unsubscribe:".into()), &Value::Str("".into()));
self.clean_unsubscription(client.clone(), subMessageHash, messageHash.clone(), &[]);
if Value::Int(messageHash.as_str().and_then(|__s| __s.find("ticker")).map(|__i| __i as i64).unwrap_or(-1)).as_f64().unwrap_or(f64::NAN) >= ((0i64) as f64) {
let mut symbol: Value = replace_str(&messageHash, &Value::Str("unsubscribe:ticker:".into()), &Value::Str("".into()));
if Value::Int(symbol.as_str().and_then(|__s| __s.find("unsubscribe")).map(|__i| __i as i64).unwrap_or(-1)).as_f64().unwrap_or(f64::NAN) >= ((0i64) as f64) {
// unWatchTickers
let mut symbols: Value = object_keys(&self.tickers);
{
let mut j: Value = Value::Int(0);
let mut __for_first_477: bool = true;
while { if !__for_first_477 { j = (match (&(j), &(Value::Int(1))) { (Value::Int(x), Value::Int(y)) => Value::Int(x + y), (Value::Int(x), Value::Float(y)) => Value::Float(*x as f64 + *y), (Value::Float(x), Value::Int(y)) => Value::Float(*x + *y as f64), (Value::Float(x), Value::Float(y)) => Value::Float(x + y), _ => Value::Null }); } __for_first_477 = false; j.as_f64().unwrap_or(f64::NAN) < ((symbols.len() as i64) as f64) } {
remove(&mut self.tickers, &symbols.as_array().and_then(|__arr| match &j { Value::Int(__n) => __arr.get(*__n as usize), Value::Str(__s) => __s.parse::<usize>().ok().and_then(|__n| __arr.get(__n)), _ => None }).cloned().unwrap_or(Value::Null));
}
}
} else if (in_op(&self.tickers, &symbol)) {
remove(&mut self.tickers, &symbol);
}
} else if Value::Int(messageHash.as_str().and_then(|__s| __s.find("bidask")).map(|__i| __i as i64).unwrap_or(-1)).as_f64().unwrap_or(f64::NAN) >= ((0i64) as f64) {
let mut symbol: Value = replace_str(&messageHash, &Value::Str("unsubscribe:bidask:".into()), &Value::Str("".into()));
if (in_op(&self.bidsasks, &symbol)) {
remove(&mut self.bidsasks, &symbol);
}
} else if Value::Int(messageHash.as_str().and_then(|__s| __s.find("candles")).map(|__i| __i as i64).unwrap_or(-1)).as_f64().unwrap_or(f64::NAN) >= ((0i64) as f64) {
let mut splitHashes: Value = split(&messageHash, &Value::Str(":".into()));
let mut symbol: Value = self.safe_string(splitHashes.clone(), Value::Int(2), &[]);
let mut splitHashesLength: f64 = ((splitHashes.len() as i64) as f64); // hoisted - inline .length within conditionals becomes strlen for php, fatal on arrays
if splitHashesLength > ((4i64) as f64) {
symbol = Value::Str(format!("{}{}", symbol, Value::Str(format!("{}{}", Value::Str(":".into()), self.safe_string(splitHashes, Value::Int(3), &[])).into())).into());
}
if (symbol != Value::Null) && (in_op(&self.ohlcvs, &symbol)) {
remove(&mut self.ohlcvs, &symbol);
}
} else if Value::Int(messageHash.as_str().and_then(|__s| __s.find("orderbook")).map(|__i| __i as i64).unwrap_or(-1)).as_f64().unwrap_or(f64::NAN) >= ((0i64) as f64) {
let mut symbol: Value = replace_str(&messageHash, &Value::Str("unsubscribe:orderbook:".into()), &Value::Str("".into()));
if (in_op(&self.orderbooks, &symbol)) {
remove(&mut self.orderbooks, &symbol);
}
} else if Value::Int(messageHash.as_str().and_then(|__s| __s.find("trades")).map(|__i| __i as i64).unwrap_or(-1)).as_f64().unwrap_or(f64::NAN) >= ((0i64) as f64) {
let mut symbol: Value = replace_str(&messageHash, &Value::Str("unsubscribe:trades:".into()), &Value::Str("".into()));
if (in_op(&self.trades, &symbol)) {
remove(&mut self.trades, &symbol);
}
} else if Value::Int(messageHash.as_str().and_then(|__s| __s.find("fundingRate")).map(|__i| __i as i64).unwrap_or(-1)).as_f64().unwrap_or(f64::NAN) >= ((0i64) as f64) {
let mut symbol: Value = replace_str(&messageHash, &Value::Str("unsubscribe:fundingRate:".into()), &Value::Str("".into()));
if (in_op(&self.fundingRates, &symbol)) {
remove(&mut self.fundingRates, &symbol);
}
}
}
}
}
pub async fn authenticate(&mut self, mut subscriptionHash: Value, optional_args: &[Value]) -> Value {
let mut params = get_arg(optional_args, 0, Value::Map({
let mut m = indexmap::IndexMap::new();
m
}));
// we only need one listenKey since ccxt shares connections
let mut listenKey: Value = self.safe_string_k(self.options.clone(), "listenKey", &[]);
if (listenKey != Value::Null) {
return listenKey;
}
// guard against concurrent listenKey requests with a future on the base
// spot ws client - the first caller fetches the listenKey, concurrent
// callers wait on the future and resume when the listenKey is ready,
// otherwise the user-data subscriptions would be split across two connections
let __ws_arg_6 = crate::value::get_value_k(&self.urls, "api");
let mut client: Value = self.client(&[crate::value::get_value_k(&crate::value::get_value_k(&__ws_arg_6, "ws"), "spot")]);
let mut messageHash: Value = Value::Str("authenticate:listenKey".into());
let mut isFetching: Value = self.safe_bool_k(self.options.clone(), "listenKeyFetching", &[Value::Bool(false)]);
if (isFetching.as_bool() == Some(true)) {
crate::exchange_stubs::ws_await_flight(&client.future(&[messageHash.clone()])).await;
return self.safe_string_k(self.options.clone(), "listenKey", &[]);
}
if let Value::Dict(__d) = &mut self.options { std::sync::Arc::make_mut(__d).insert("listenKeyFetching".into(), Value::Bool(true)); }
client.future(&[messageHash.clone()]); // created ahead of the request below, so concurrent callers can find it
let mut response: Value = Value::Null;
let _try_result = futures::FutureExt::catch_unwind(std::panic::AssertUnwindSafe(async {
response = self.parent.spot_private_post_user_data_stream(&[params.clone()]).await;
#[allow(unreachable_code)] { Value::Null }})).await;
if let Err(_try_err) = _try_result { let e: Value = panic_to_value(_try_err);
if let Value::Dict(__d) = &mut self.options { std::sync::Arc::make_mut(__d).insert("listenKeyFetching".into(), Value::Bool(false)); }
client.reject(&[e.clone(), messageHash.clone()]);
panic!("{}", e);
}
if let Value::Dict(__d) = &mut self.options { std::sync::Arc::make_mut(__d).insert("listenKeyFetching".into(), Value::Bool(false)); }
//
// {
// "listenKey": "pqia91ma19a5s61cv6a81va65sdf19v8a65a1a5s61cv6a81va65sdf19v8a65a1"
// }
//
listenKey = self.safe_string_k(response, "listenKey", &[]);
if let Value::Dict(__d) = &mut self.options { std::sync::Arc::make_mut(__d).insert("listenKey".into(), listenKey.clone()); }
client.resolve(&[listenKey.clone(), messageHash]);
let mut listenKeyRefreshRate: Value = self.safe_integer_k(self.options.clone(), "listenKeyRefreshRate", &[Value::Int(1200000)]);
self.delay(listenKeyRefreshRate, &[Value::Str("keep_alive_listen_key".into()).clone(), listenKey.clone(), params]).await;
return listenKey;
Value::Null
}
pub async fn keep_alive_listen_key(&mut self, mut listenKey: Value, optional_args: &[Value]) -> Value {
let mut params = get_arg(optional_args, 0, Value::Map({
let mut m = indexmap::IndexMap::new();
m
}));
if (listenKey == Value::Null) {
return Value::Null;
}
let mut request: Value = Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("listenKey".to_string(), listenKey.clone());
m
});
let _try_result = futures::FutureExt::catch_unwind(std::panic::AssertUnwindSafe(async {
let __ws_arg_7 = self.extend(request, &[params.clone()]);
self.parent.spot_private_put_user_data_stream(&[__ws_arg_7]).await;
let mut listenKeyRefreshRate: Value = self.safe_integer_k(self.options.clone(), "listenKeyRefreshRate", &[Value::Int(1200000)]);
self.delay(listenKeyRefreshRate, &[Value::Str("keep_alive_listen_key".into()).clone(), listenKey.clone(), params]).await;
#[allow(unreachable_code)] { Value::Null }})).await;
if let Err(_try_err) = _try_result { let error: Value = panic_to_value(_try_err);
let mut url: Value = Value::Str(format!("{}{}", add(&crate::value::get_value_k(&self.urls.as_map().and_then(|__m| __m.get("api")).cloned().unwrap_or(Value::Null).as_map().and_then(|__m| __m.get("ws")).cloned().unwrap_or(Value::Null), "spot"), &Value::Str("?listenKey=".into())), listenKey).into());
let mut client: Value = self.client(&[url.clone()]);
if let Value::Dict(__d) = &mut self.options { std::sync::Arc::make_mut(__d).insert("listenKey".into(), Value::Null); }
client.reject(&[Value::from(error)]);
remove(&mut self.clients, &url);
}
Value::Null
}
pub fn handle_pong(&self, mut client: Value, mut message: Value) -> Value {
crate::set_value(&mut client, &Value::Str("lastPong".into()), self.milliseconds());
return message;
Value::Null
}
pub fn handle_subscription_status(&mut self, mut client: Value, mut message: Value) {
let __pro_message_arc: std::sync::Arc<indexmap::IndexMap<String, Value>> = (match &message { Value::Dict(__d) => __d.clone(), _ => std::sync::Arc::new(indexmap::IndexMap::new()) });
let __pro_message: &indexmap::IndexMap<String, Value> = &__pro_message_arc;
//
// {
// "id": 0,
// "code": 0,
// "msg": "spot@public.increase.depth.v3.api@BTCUSDT"
// }
// Set the default to an empty string if the message is empty during the test.
let mut msg: Value = (match __pro_message.get("msg").cloned() { Some(Value::Str(__s)) if !__s.is_empty() => Value::Str(__s), Some(Value::Int(__n)) => Value::Str(__n.to_string().into()), Some(Value::Float(__f)) => Value::Str(__f.to_string().into()), _ => Value::Str("".into()) });
if (msg.as_str() == Some("PONG")) {
self.handle_pong(client.clone(), message.clone());
} else if Value::Int(msg.as_str().and_then(|__s| __s.find("@")).map(|__i| __i as i64).unwrap_or(-1)).as_f64().unwrap_or(f64::NAN) > ((-1i64) as f64) {
let mut parts: Value = split(&msg, &Value::Str("@".into()));
let mut channel: Value = self.safe_string(parts, Value::Int(1), &[]);
let mut methods: Value = Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("public.increase.depth.v3.api".to_string(), Value::Str("handle_order_book_subscription".into()).clone());
m.insert("public.aggre.depth.v3.api.pb".to_string(), Value::Str("handle_order_book_subscription".into()).clone());
m
});
let mut method: Value = self.safe_value(methods, channel, &[]);
if (method != Value::Null) {
self.dispatch_ws_handler(&method, &[client, message.clone()]);
}
}
}
pub fn handle_protobuf_message(&mut self, mut client: Value, mut message: Value) -> Value {
let __pro_message_arc: std::sync::Arc<indexmap::IndexMap<String, Value>> = (match &message { Value::Dict(__d) => __d.clone(), _ => std::sync::Arc::new(indexmap::IndexMap::new()) });
let __pro_message: &indexmap::IndexMap<String, Value> = &__pro_message_arc;
// protobuf message decoded
// {
// "channel":"spot@public.kline.v3.api.pb@BTCUSDT@Min1",
// "symbol":"BTCUSDT",
// "symbolId":"2fb942154ef44a4ab2ef98c8afb6a4a7",
// "createTime":"1754737941062",
// "publicSpotKline":{
// "interval":"Min1",
// "windowStart":"1754737920",
// "openingPrice":"117317.31",
// "closingPrice":"117325.26",
// "highestPrice":"117341",
// "lowestPrice":"117317.3",
// "volume":"3.12599854",
// "amount":"366804.43",
// "windowEnd":"1754737980"
// }
// }
let mut channel: Value = (match __pro_message.get("channel").cloned() { Some(Value::Str(__s)) if !__s.is_empty() => Value::Str(__s), Some(Value::Int(__n)) => Value::Str(__n.to_string().into()), Some(Value::Float(__f)) => Value::Str(__f.to_string().into()), _ => Value::Str("".into()) });
let mut channelParts: Value = split(&channel, &Value::Str("@".into()));
let mut channelId: Option<String> = self.safe_string(channelParts, Value::Int(1), &[]).as_str().map(str::to_owned);
if (channelId.as_deref() == Some("public.kline.v3.api.pb")) {
self.handle_ohlcv(client.clone(), message.clone());
} else if (channelId.as_deref() == Some("public.aggre.deals.v3.api.pb")) {
self.handle_trades(client.clone(), message.clone());
} else if (channelId.as_deref() == Some("public.aggre.bookTicker.v3.api.pb")) {
self.handle_ticker(client.clone(), message.clone());
} else if (channelId.as_deref() == Some("public.aggre.depth.v3.api.pb")) {
self.handle_order_book(client.clone(), message.clone());
} else if (channelId.as_deref() == Some("private.account.v3.api.pb")) {
self.handle_balance(client.clone(), message.clone());
} else if (channelId.as_deref() == Some("private.deals.v3.api.pb")) {
self.handle_my_trade(client.clone(), message.clone(), &[]);
} else if (channelId.as_deref() == Some("private.orders.v3.api.pb")) {
self.handle_order(client, message.clone());
}
return Value::Bool(true);
Value::Null
}
pub fn handle_message(&mut self, mut client: Value, mut message: Value) {
if matches!(&message, Value::Str(_)) {
if (message.as_str() == Some("Invalid listen key")) {
let mut error = Value::from(crate::exchange_errors::authentication_error(format!("{}{}", self.id.clone(), Value::Str(" invalid listen key".into()))));
client.reject(&[Value::from(error)]);
return;
}
}
if self.is_binary_message(message.clone(), &[]).as_bool() == Some(true) {
message = self.decode_proto_msg(&[message.clone()]);
self.handle_protobuf_message(client.clone(), message.clone());
return;
}
if (in_op(&message, &Value::Str("msg".into()))) {
self.handle_subscription_status(client.clone(), message.clone());
return;
}
let mut c: Value = self.safe_string_k(message.clone(), "c", &[]);
let mut channel: Value = Value::Null;
if (c == Value::Null) {
channel = self.safe_string_k(message.clone(), "channel", &[]);
} else {
let mut parts: Value = split(&c, &Value::Str("@".into()));
channel = self.safe_string(parts, Value::Int(1), &[Value::Str("".into())]);
}
let mut methods: Value = Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("public.deals.v3.api".to_string(), Value::Str("handle_trades".into()).clone());
m.insert("push.deal".to_string(), Value::Str("handle_trades".into()).clone());
m.insert("public.kline.v3.api".to_string(), Value::Str("handle_ohlcv".into()).clone());
m.insert("push.kline".to_string(), Value::Str("handle_ohlcv".into()).clone());
m.insert("public.bookTicker.v3.api".to_string(), Value::Str("handle_ticker".into()).clone());
m.insert("public.miniTicker.v3.api".to_string(), Value::Str("handle_ticker".into()).clone());
m.insert("public.miniTickers.v3.api".to_string(), Value::Str("handle_tickers".into()).clone());
m.insert("push.ticker".to_string(), Value::Str("handle_ticker".into()).clone());
m.insert("push.tickers".to_string(), Value::Str("handle_tickers".into()).clone());
m.insert("public.increase.depth.v3.api".to_string(), Value::Str("handle_order_book".into()).clone());
m.insert("push.depth".to_string(), Value::Str("handle_order_book".into()).clone());
m.insert("private.orders.v3.api".to_string(), Value::Str("handle_order".into()).clone());
m.insert("push.personal.order".to_string(), Value::Str("handle_order".into()).clone());
m.insert("private.account.v3.api".to_string(), Value::Str("handle_balance".into()).clone());
m.insert("push.personal.asset".to_string(), Value::Str("handle_balance".into()).clone());
m.insert("private.deals.v3.api".to_string(), Value::Str("handle_my_trade".into()).clone());
m.insert("push.personal.order.deal".to_string(), Value::Str("handle_my_trade".into()).clone());
m.insert("pong".to_string(), Value::Str("handle_pong".into()).clone());
m.insert("push.funding.rate".to_string(), Value::Str("handle_funding_rate".into()).clone());
m
});
if (channel != Value::Null) && (in_op(&methods, &channel)) {
let mut method: Value = methods.as_map().and_then(|__m| channel.as_str().and_then(|__k| __m.get(__k))).cloned().unwrap_or(Value::Null);
self.dispatch_ws_handler(&method, &[client, message.clone()]);
}
}
pub fn ping(&self, mut client: Value) -> Value {
return Value::Map({
let mut m = indexmap::IndexMap::new();
m.insert("method".to_string(), Value::Str("ping".into()));
m
});
Value::Null
}
}