remsed
Version:
A JavaScript cryptocurrency trading library with support for fairdesk.com
1,205 lines (1,203 loc) • 151 kB
JavaScript
'use strict';
var Exchange = require('./base/Exchange.js');
var errors = require('./base/errors.js');
var Precise = require('./base/Precise.js');
var number = require('./base/functions/number.js');
// ----------------------------------------------------------------------------
// ---------------------------------------------------------------------------
class mexc extends Exchange["default"] {
describe() {
return this.deepExtend(super.describe(), {
'id': 'mexc',
'name': 'MEXC Global',
'countries': ['SC'],
'rateLimit': 50,
'version': 'v2',
'certified': true,
'pro': true,
'has': {
'CORS': undefined,
'spot': true,
'margin': undefined,
'swap': true,
'future': false,
'option': false,
'addMargin': true,
'cancelAllOrders': true,
'cancelOrder': true,
'createMarketOrder': false,
'createOrder': true,
'createReduceOnlyOrder': false,
'createStopLimitOrder': true,
'createStopMarketOrder': false,
'createStopOrder': true,
'fetchBalance': true,
'fetchCanceledOrders': true,
'fetchClosedOrders': true,
'fetchCurrencies': true,
'fetchDepositAddress': true,
'fetchDepositAddressesByNetwork': true,
'fetchDeposits': true,
'fetchFundingHistory': true,
'fetchFundingRate': true,
'fetchFundingRateHistory': true,
'fetchFundingRates': false,
'fetchIndexOHLCV': true,
'fetchLeverage': undefined,
'fetchLeverageTiers': true,
'fetchMarginMode': false,
'fetchMarketLeverageTiers': 'emulated',
'fetchMarkets': true,
'fetchMarkOHLCV': true,
'fetchMyTrades': true,
'fetchOHLCV': true,
'fetchOpenInterestHistory': false,
'fetchOpenOrders': true,
'fetchOrder': true,
'fetchOrderBook': true,
'fetchOrderTrades': true,
'fetchPosition': true,
'fetchPositionMode': true,
'fetchPositions': true,
'fetchPositionsRisk': false,
'fetchPremiumIndexOHLCV': true,
'fetchStatus': true,
'fetchTicker': true,
'fetchTickers': true,
'fetchTime': true,
'fetchTrades': true,
'fetchTradingFee': false,
'fetchTradingFees': true,
'fetchTransfer': true,
'fetchTransfers': true,
'fetchWithdrawals': true,
'reduceMargin': true,
'setLeverage': true,
'setMarginMode': false,
'setPositionMode': true,
'transfer': true,
'withdraw': true,
},
'timeframes': {
'1m': '1m',
'5m': '5m',
'15m': '15m',
'30m': '30m',
'1h': '1h',
'1d': '1d',
'1w': '1w',
'1M': '1M',
},
'urls': {
'logo': 'https://user-images.githubusercontent.com/1294454/137283979-8b2a818d-8633-461b-bfca-de89e8c446b2.jpg',
'api': {
'spot': {
'public': 'https://www.mexc.com/open/api/v2',
'private': 'https://www.mexc.com/open/api/v2',
},
'contract': {
'public': 'https://contract.mexc.com/api/v1/contract',
'private': 'https://contract.mexc.com/api/v1/private',
},
},
'www': 'https://www.mexc.com/',
'doc': [
'https://mxcdevelop.github.io/APIDoc/',
],
'fees': [
'https://www.mexc.com/fee',
],
'referral': 'https://m.mexc.com/auth/signup?inviteCode=1FQ1G',
},
'api': {
'contract': {
'public': {
'get': {
'ping': 2,
'detail': 2,
'support_currencies': 2,
'depth/{symbol}': 2,
'depth_commits/{symbol}/{limit}': 2,
'index_price/{symbol}': 2,
'fair_price/{symbol}': 2,
'funding_rate/{symbol}': 2,
'kline/{symbol}': 2,
'kline/index_price/{symbol}': 2,
'kline/fair_price/{symbol}': 2,
'deals/{symbol}': 2,
'ticker': 2,
'risk_reverse': 2,
'risk_reverse/history': 2,
'funding_rate/history': 2,
},
},
'private': {
'get': {
'account/assets': 2,
'account/asset/{currency}': 2,
'account/transfer_record': 2,
'position/list/history_positions': 2,
'position/open_positions': 2,
'position/funding_records': 2,
'position/position_mode': 2,
'order/list/open_orders/{symbol}': 2,
'order/list/history_orders': 2,
'order/external/{symbol}/{external_oid}': 2,
'order/get/{order_id}': 2,
'order/batch_query': 8,
'order/deal_details/{order_id}': 2,
'order/list/order_deals': 2,
'planorder/list/orders': 2,
'stoporder/list/orders': 2,
'stoporder/order_details/{stop_order_id}': 2,
'account/risk_limit': 2,
'account/tiered_fee_rate': 2,
},
'post': {
'position/change_margin': 2,
'position/change_leverage': 2,
'position/change_position_mode': 2,
'order/submit': 2,
'order/submit_batch': 40,
'order/cancel': 2,
'order/cancel_with_external': 2,
'order/cancel_all': 2,
'account/change_risk_level': 2,
'planorder/place': 2,
'planorder/cancel': 2,
'planorder/cancel_all': 2,
'stoporder/cancel': 2,
'stoporder/cancel_all': 2,
'stoporder/change_price': 2,
'stoporder/change_plan_price': 2,
},
},
},
'spot': {
'public': {
'get': {
'market/symbols': 1,
'market/coin/list': 2,
'common/timestamp': 1,
'common/ping': 1,
'market/ticker': 1,
'market/depth': 1,
'market/deals': 1,
'market/kline': 1,
'market/api_default_symbols': 2,
},
},
'private': {
'get': {
'account/info': 1,
'order/open_orders': 1,
'order/list': 1,
'order/query': 1,
'order/deals': 1,
'order/deal_detail': 1,
'asset/deposit/address/list': 2,
'asset/deposit/list': 2,
'asset/address/list': 2,
'asset/withdraw/list': 2,
'asset/internal/transfer/record': 10,
'account/balance': 10,
'asset/internal/transfer/info': 10,
'market/api_symbols': 2,
},
'post': {
'order/place': 1,
'order/place_batch': 1,
'asset/withdraw': 2,
'asset/internal/transfer': 10,
},
'delete': {
'order/cancel': 1,
'order/cancel_by_symbol': 1,
'asset/withdraw': 2,
},
},
},
},
'precisionMode': number.TICK_SIZE,
'fees': {
'trading': {
'tierBased': false,
'percentage': true,
'maker': this.parseNumber('0.002'),
'taker': this.parseNumber('0.002'),
},
},
'options': {
'timeframes': {
'spot': {
'1m': '1m',
'5m': '5m',
'15m': '15m',
'30m': '30m',
'1h': '1h',
'1d': '1d',
'1M': '1M',
},
'contract': {
'1m': 'Min1',
'5m': 'Min5',
'15m': 'Min15',
'30m': 'Min30',
'1h': 'Min60',
'4h': 'Hour4',
'8h': 'Hour8',
'1d': 'Day1',
'1w': 'Week1',
'1M': 'Month1',
},
},
'defaultType': 'spot',
'networks': {
'TRX': 'TRC20',
'ETH': 'ERC20',
'BEP20': 'BEP20(BSC)',
'BSC': 'BEP20(BSC)',
},
'accountsByType': {
'spot': 'MAIN',
'swap': 'CONTRACT',
},
'transfer': {
'accountsById': {
'MAIN': 'spot',
'CONTRACT': 'swap',
},
'status': {
'SUCCESS': 'ok',
'FAILED': 'failed',
'WAIT': 'pending',
},
},
'fetchOrdersByState': {
'method': 'spotPrivateGetOrderList', // contractPrivateGetPlanorderListOrders
},
'cancelOrder': {
'method': 'spotPrivateDeleteOrderCancel', // contractPrivatePostOrderCancel contractPrivatePostPlanorderCancel
},
'broker': 'CCXT',
},
'commonCurrencies': {
'BEYONDPROTOCOL': 'BEYOND',
'BIFI': 'BIFIF',
'BYN': 'BeyondFi',
'COFI': 'COFIX',
'DFI': 'DfiStarter',
'DFT': 'dFuture',
'DRK': 'DRK',
'EGC': 'Egoras Credit',
'FLUX1': 'FLUX',
'FLUX': 'FLUX1',
'FREE': 'FreeRossDAO',
'GAS': 'GASDAO',
'GASNEO': 'GAS',
'GMT': 'GMT Token',
'HERO': 'Step Hero',
'MIMO': 'Mimosa',
'PROS': 'Pros.Finance',
'SIN': 'Sin City Token',
'SOUL': 'Soul Swap',
'STEPN': 'GMT',
},
'exceptions': {
'exact': {
'400': errors.BadRequest,
'401': errors.AuthenticationError,
'402': errors.AuthenticationError,
'403': errors.PermissionDenied,
'429': errors.RateLimitExceeded,
'703': errors.PermissionDenied,
'1000': errors.AccountNotEnabled,
'1002': errors.InvalidOrder,
'10072': errors.AuthenticationError,
'10073': errors.AuthenticationError,
'10075': errors.PermissionDenied,
'10101': errors.InsufficientFunds,
'10216': errors.InvalidAddress,
'10232': errors.BadSymbol,
'30000': errors.BadSymbol,
'30001': errors.InvalidOrder,
'30002': errors.InvalidOrder,
'30003': errors.InvalidOrder,
'30004': errors.InsufficientFunds,
'30005': errors.InvalidOrder,
'30010': errors.InvalidOrder,
'30014': errors.BadSymbol,
'30016': errors.BadSymbol,
'30019': errors.InvalidOrder,
'30020': errors.BadSymbol,
'30021': errors.BadSymbol,
'33333': errors.BadSymbol, // {"code":33333,"msg":"currency can not be null"}
},
'broad': {
'price and quantity must be positive': errors.InvalidOrder, // {"msg":"price and quantity must be positive","code":400}
},
},
});
}
async fetchTime(params = {}) {
/**
* @method
* @name mexc#fetchTime
* @description fetches the current integer timestamp in milliseconds from the exchange server
* @param {object} params extra parameters specific to the mexc api endpoint
* @returns {int} the current integer timestamp in milliseconds from the exchange server
*/
const [marketType, query] = this.handleMarketTypeAndParams('fetchTime', undefined, params);
const method = this.getSupportedMapping(marketType, {
'spot': 'spotPublicGetCommonTimestamp',
'swap': 'contractPublicGetPing',
});
const response = await this[method](this.extend(query));
//
// spot
//
// {
// "code":200,
// "data":1633375641837
// }
//
// contract
//
// {
// "success":true,
// "code":0,
// "data":1634095541710
// }
//
return this.safeInteger(response, 'data');
}
async fetchStatus(params = {}) {
/**
* @method
* @name mexc#fetchStatus
* @description the latest known information on the availability of the exchange API
* @param {object} params extra parameters specific to the mexc api endpoint
* @returns {object} a [status structure]{@link https://docs.ccxt.com/#/?id=exchange-status-structure}
*/
const response = await this.spotPublicGetCommonPing(params);
//
// { "code":200 }
//
const code = this.safeInteger(response, 'code');
const status = (code === 200) ? 'ok' : 'maintenance';
return {
'status': status,
'updated': undefined,
'eta': undefined,
'url': undefined,
'info': response,
};
}
async fetchCurrencies(params = {}) {
/**
* @method
* @name mexc#fetchCurrencies
* @description fetches all available currencies on an exchange
* @param {object} params extra parameters specific to the mexc api endpoint
* @returns {object} an associative dictionary of currencies
*/
const response = await this.spotPublicGetMarketCoinList(params);
//
// {
// "code":200,
// "data":[
// {
// "currency":"AGLD",
// "coins":[
// {
// "chain":"ERC20",
// "precision":18,
// "fee":8.09,
// "is_withdraw_enabled":true,
// "is_deposit_enabled":true,
// "deposit_min_confirm":16,
// "withdraw_limit_max":500000.0,
// "withdraw_limit_min":14.0
// }
// ],
// "full_name":"Adventure Gold"
// },
// ]
// }
//
const data = this.safeValue(response, 'data', []);
const result = {};
for (let i = 0; i < data.length; i++) {
const currency = data[i];
const id = this.safeString(currency, 'currency');
const code = this.safeCurrencyCode(id);
const name = this.safeString(currency, 'full_name');
let currencyActive = false;
let minPrecision = undefined;
let currencyFee = undefined;
let currencyWithdrawMin = undefined;
let currencyWithdrawMax = undefined;
const networks = {};
const chains = this.safeValue(currency, 'coins', []);
let depositEnabled = false;
let withdrawEnabled = false;
for (let j = 0; j < chains.length; j++) {
const chain = chains[j];
const networkId = this.safeString(chain, 'chain');
const network = this.safeNetwork(networkId);
const isDepositEnabled = this.safeValue(chain, 'is_deposit_enabled', false);
const isWithdrawEnabled = this.safeValue(chain, 'is_withdraw_enabled', false);
const active = (isDepositEnabled && isWithdrawEnabled);
currencyActive = active || currencyActive;
const withdrawMin = this.safeString(chain, 'withdraw_limit_min');
const withdrawMax = this.safeString(chain, 'withdraw_limit_max');
currencyWithdrawMin = (currencyWithdrawMin === undefined) ? withdrawMin : currencyWithdrawMin;
currencyWithdrawMax = (currencyWithdrawMax === undefined) ? withdrawMax : currencyWithdrawMax;
if (Precise["default"].stringGt(currencyWithdrawMin, withdrawMin)) {
currencyWithdrawMin = withdrawMin;
}
if (Precise["default"].stringLt(currencyWithdrawMax, withdrawMax)) {
currencyWithdrawMax = withdrawMax;
}
if (isDepositEnabled) {
depositEnabled = true;
}
if (isWithdrawEnabled) {
withdrawEnabled = true;
}
const precision = this.parsePrecision(this.safeString(chain, 'precision'));
if (precision !== undefined) {
minPrecision = (minPrecision === undefined) ? precision : Precise["default"].stringMin(precision, minPrecision);
}
networks[network] = {
'info': chain,
'id': networkId,
'network': network,
'active': active,
'deposit': isDepositEnabled,
'withdraw': isWithdrawEnabled,
'fee': this.safeNumber(chain, 'fee'),
'precision': this.parseNumber(minPrecision),
'limits': {
'withdraw': {
'min': withdrawMin,
'max': withdrawMax,
},
},
};
}
const networkKeys = Object.keys(networks);
const networkKeysLength = networkKeys.length;
if ((networkKeysLength === 1) || ('NONE' in networks)) {
const defaultNetwork = this.safeValue2(networks, 'NONE', networkKeysLength - 1);
if (defaultNetwork !== undefined) {
currencyFee = defaultNetwork['fee'];
}
}
result[code] = {
'id': id,
'code': code,
'info': currency,
'name': name,
'active': currencyActive,
'deposit': depositEnabled,
'withdraw': withdrawEnabled,
'fee': currencyFee,
'precision': this.parseNumber(minPrecision),
'limits': {
'amount': {
'min': undefined,
'max': undefined,
},
'withdraw': {
'min': currencyWithdrawMin,
'max': currencyWithdrawMax,
},
},
'networks': networks,
};
}
return result;
}
async fetchMarkets(params = {}) {
/**
* @method
* @name mexc#fetchMarkets
* @description retrieves data on all markets for mexc
* @param {object} params extra parameters specific to the exchange api endpoint
* @returns {[object]} an array of objects representing market data
*/
const defaultType = this.safeString2(this.options, 'fetchMarkets', 'defaultType', 'spot');
const type = this.safeString(params, 'type', defaultType);
const query = this.omit(params, 'type');
const spot = (type === 'spot');
const swap = (type === 'swap');
if (!spot && !swap) {
throw new errors.ExchangeError(this.id + " does not support '" + type + "' type, set exchange.options['defaultType'] to 'spot' or 'swap''"); // eslint-disable-line quotes
}
if (spot) {
return await this.fetchSpotMarkets(query);
}
else if (swap) {
return await this.fetchContractMarkets(query);
}
}
async fetchContractMarkets(params = {}) {
const response = await this.contractPublicGetDetail(params);
//
// {
// "success":true,
// "code":0,
// "data":[
// {
// "symbol":"BTC_USDT",
// "displayName":"BTC_USDT永续",
// "displayNameEn":"BTC_USDT SWAP",
// "positionOpenType":3,
// "baseCoin":"BTC",
// "quoteCoin":"USDT",
// "settleCoin":"USDT",
// "contractSize":0.0001,
// "minLeverage":1,
// "maxLeverage":125,
// "priceScale":2,
// "volScale":0,
// "amountScale":4,
// "priceUnit":0.5,
// "volUnit":1,
// "minVol":1,
// "maxVol":1000000,
// "bidLimitPriceRate":0.1,
// "askLimitPriceRate":0.1,
// "takerFeeRate":0.0006,
// "makerFeeRate":0.0002,
// "maintenanceMarginRate":0.004,
// "initialMarginRate":0.008,
// "riskBaseVol":10000,
// "riskIncrVol":200000,
// "riskIncrMmr":0.004,
// "riskIncrImr":0.004,
// "riskLevelLimit":5,
// "priceCoefficientVariation":0.1,
// "indexOrigin":["BINANCE","GATEIO","HUOBI","MXC"],
// "state":0, // 0 enabled, 1 delivery, 2 completed, 3 offline, 4 pause
// "isNew":false,
// "isHot":true,
// "isHidden":false
// },
// ]
// }
//
const data = this.safeValue(response, 'data', []);
const result = [];
for (let i = 0; i < data.length; i++) {
const market = data[i];
const id = this.safeString(market, 'symbol');
const baseId = this.safeString(market, 'baseCoin');
const quoteId = this.safeString(market, 'quoteCoin');
const settleId = this.safeString(market, 'settleCoin');
const base = this.safeCurrencyCode(baseId);
const quote = this.safeCurrencyCode(quoteId);
const settle = this.safeCurrencyCode(settleId);
const state = this.safeString(market, 'state');
result.push({
'id': id,
'symbol': base + '/' + quote + ':' + settle,
'base': base,
'quote': quote,
'settle': settle,
'baseId': baseId,
'quoteId': quoteId,
'settleId': settleId,
'type': 'swap',
'spot': false,
'margin': false,
'swap': true,
'future': false,
'option': false,
'active': (state === '0'),
'contract': true,
'linear': true,
'inverse': false,
'taker': this.safeNumber(market, 'takerFeeRate'),
'maker': this.safeNumber(market, 'makerFeeRate'),
'contractSize': this.safeNumber(market, 'contractSize'),
'expiry': undefined,
'expiryDatetime': undefined,
'strike': undefined,
'optionType': undefined,
'precision': {
'amount': this.safeNumber(market, 'volUnit'),
'price': this.safeNumber(market, 'priceUnit'),
},
'limits': {
'leverage': {
'min': this.safeNumber(market, 'minLeverage'),
'max': this.safeNumber(market, 'maxLeverage'),
},
'amount': {
'min': this.safeNumber(market, 'minVol'),
'max': this.safeNumber(market, 'maxVol'),
},
'price': {
'min': undefined,
'max': undefined,
},
'cost': {
'min': undefined,
'max': undefined,
},
},
'info': market,
});
}
return result;
}
async fetchSpotMarkets(params = {}) {
const response = await this.spotPublicGetMarketSymbols(params);
//
// {
// "code":200,
// "data":[
// {
// "symbol":"DFD_USDT",
// "state":"ENABLED",
// "countDownMark":1,
// "vcoinName":"DFD",
// "vcoinStatus":1,
// "price_scale":4,
// "quantity_scale":2,
// "min_amount":"5", // not an amount = cost
// "max_amount":"5000000",
// "maker_fee_rate":"0.002",
// "taker_fee_rate":"0.002",
// "limited":true,
// "etf_mark":0,
// "symbol_partition":"ASSESS"
// },
// ]
// }
//
const data = this.safeValue(response, 'data', []);
const response2 = await this.spotPublicGetMarketApiDefaultSymbols(params);
//
// {
// "code":200,
// "data":{
// "symbol":[
// "ALEPH_USDT","OGN_USDT","HC_USDT",
// ]
// }
// }
//
const data2 = this.safeValue(response2, 'data', {});
const symbols = this.safeValue(data2, 'symbol', []);
const result = [];
for (let i = 0; i < data.length; i++) {
const market = data[i];
const id = this.safeString(market, 'symbol');
const [baseId, quoteId] = id.split('_');
const base = this.safeCurrencyCode(baseId);
const quote = this.safeCurrencyCode(quoteId);
const state = this.safeString(market, 'state');
let active = false;
for (let j = 0; j < symbols.length; j++) {
if (symbols[j] === id) {
if (state === 'ENABLED') {
active = true;
}
break;
}
}
result.push({
'id': id,
'symbol': base + '/' + quote,
'base': base,
'quote': quote,
'settle': undefined,
'baseId': baseId,
'quoteId': quoteId,
'settleId': undefined,
'type': 'spot',
'spot': true,
'margin': false,
'swap': false,
'future': false,
'option': false,
'active': active,
'contract': false,
'linear': undefined,
'inverse': undefined,
'taker': this.safeNumber(market, 'taker_fee_rate'),
'maker': this.safeNumber(market, 'maker_fee_rate'),
'contractSize': undefined,
'expiry': undefined,
'expiryDatetime': undefined,
'strike': undefined,
'optionType': undefined,
'precision': {
'amount': this.parseNumber(this.parsePrecision(this.safeString(market, 'quantity_scale'))),
'price': this.parseNumber(this.parsePrecision(this.safeString(market, 'price_scale'))),
},
'limits': {
'leverage': {
'min': undefined,
'max': undefined,
},
'amount': {
'min': undefined,
'max': undefined,
},
'price': {
'min': undefined,
'max': undefined,
},
'cost': {
'min': this.safeNumber(market, 'min_amount'),
'max': this.safeNumber(market, 'max_amount'),
},
},
'info': market,
});
}
return result;
}
async fetchTickers(symbols = undefined, params = {}) {
/**
* @method
* @name mexc#fetchTickers
* @description fetches price tickers for multiple markets, statistical calculations with the information calculated over the past 24 hours each market
* @param {[string]|undefined} symbols unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
* @param {object} params extra parameters specific to the mexc api endpoint
* @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure}
*/
await this.loadMarkets();
symbols = this.marketSymbols(symbols);
const first = this.safeString(symbols, 0);
let market = undefined;
if (first !== undefined) {
market = this.market(first);
}
const [marketType, query] = this.handleMarketTypeAndParams('fetchTickers', market, params);
const method = this.getSupportedMapping(marketType, {
'spot': 'spotPublicGetMarketTicker',
'swap': 'contractPublicGetTicker',
});
const response = await this[method](this.extend(query));
//
// {
// "success":true,
// "code":0,
// "data":[
// {
// "symbol":"NKN_USDT",
// "lastPrice":0.36199,
// "bid1":0.35908,
// "ask1":0.36277,
// "volume24":657754,
// "amount24":239024.53998,
// "holdVol":149969,
// "lower24Price":0.34957,
// "high24Price":0.37689,
// "riseFallRate":0.0117,
// "riseFallValue":0.00419,
// "indexPrice":0.36043,
// "fairPrice":0.36108,
// "fundingRate":0.000535,
// "maxBidPrice":0.43251,
// "minAskPrice":0.28834,
// "timestamp":1634163352075
// },
// ]
// }
//
const data = this.safeValue(response, 'data', []);
return this.parseTickers(data, symbols);
}
async fetchTicker(symbol, params = {}) {
/**
* @method
* @name mexc#fetchTicker
* @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
* @param {string} symbol unified symbol of the market to fetch the ticker for
* @param {object} params extra parameters specific to the mexc api endpoint
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
*/
await this.loadMarkets();
const market = this.market(symbol);
const request = {
'symbol': market['id'],
};
let method = undefined;
if (market['spot']) {
method = 'spotPublicGetMarketTicker';
}
else if (market['swap']) {
method = 'contractPublicGetTicker';
}
const response = await this[method](this.extend(request, params));
//
// spot
//
// {
// "code":200,
// "data":[
// {
// "symbol":"BTC_USDT",
// "volume":"880.821523",
// "high":"49496.95", // highest price over the past 24 hours
// "low":"46918.4", // lowest
// "bid":"49297.64", // current buying price == the best price you can sell for
// "ask":"49297.75", // current selling price == the best price you can buy for
// "open":"48764.9", // open price 24h ago
// "last":"49297.73", // last = close
// "time":1633378200000, // timestamp
// "change_rate":"0.0109265" // (last / open) - 1
// }
// ]
// }
//
// swap / contract
//
// {
// "success":true,
// "code":0,
// "data":{
// "symbol":"ETH_USDT",
// "lastPrice":3581.3,
// "bid1":3581.25,
// "ask1":3581.5,
// "volume24":4045530,
// "amount24":141331823.5755,
// "holdVol":5832946,
// "lower24Price":3413.4,
// "high24Price":3588.7,
// "riseFallRate":0.0275,
// "riseFallValue":95.95,
// "indexPrice":3580.7852,
// "fairPrice":3581.08,
// "fundingRate":0.000063,
// "maxBidPrice":3938.85,
// "minAskPrice":3222.7,
// "timestamp":1634162885016
// }
// }
//
if (market['spot']) {
const data = this.safeValue(response, 'data', []);
const ticker = this.safeValue(data, 0);
return this.parseTicker(ticker, market);
}
else if (market['swap']) {
const data = this.safeValue(response, 'data', {});
return this.parseTicker(data, market);
}
}
parseTicker(ticker, market = undefined) {
//
// spot
//
// {
// "symbol":"BTC_USDT",
// "volume":"880.821523",
// "high":"49496.95",
// "low":"46918.4",
// "bid":"49297.64",
// "ask":"49297.75",
// "open":"48764.9",
// "last":"49297.73",
// "time":1633378200000,
// "change_rate":"0.0109265"
// }
//
// contract
//
// {
// "symbol":"ETH_USDT",
// "lastPrice":3581.3,
// "bid1":3581.25,
// "ask1":3581.5,
// "volume24":4045530,
// "amount24":141331823.5755,
// "holdVol":5832946,
// "lower24Price":3413.4,
// "high24Price":3588.7,
// "riseFallRate":0.0275,
// "riseFallValue":95.95,
// "indexPrice":3580.7852,
// "fairPrice":3581.08,
// "fundingRate":0.000063,
// "maxBidPrice":3938.85,
// "minAskPrice":3222.7,
// "timestamp":1634162885016
// }
//
const timestamp = this.safeInteger2(ticker, 'time', 'timestamp');
const marketId = this.safeString(ticker, 'symbol');
const symbol = this.safeSymbol(marketId, market, '_');
const baseVolume = this.safeString2(ticker, 'volume', 'volume24');
const quoteVolume = this.safeString(ticker, 'amount24');
const open = this.safeString(ticker, 'open');
const last = this.safeString2(ticker, 'last', 'lastPrice');
const change = this.safeString(ticker, 'riseFallValue');
const riseFallRate = this.safeString(ticker, 'riseFallRate');
const percentage = Precise["default"].stringAdd(riseFallRate, '1');
return this.safeTicker({
'symbol': symbol,
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'high': this.safeString2(ticker, 'high', 'high24Price'),
'low': this.safeString2(ticker, 'low', 'lower24Price'),
'bid': this.safeString2(ticker, 'bid', 'bid1'),
'bidVolume': undefined,
'ask': this.safeString2(ticker, 'ask', 'ask1'),
'askVolume': undefined,
'vwap': undefined,
'open': open,
'close': last,
'last': last,
'previousClose': undefined,
'change': change,
'percentage': percentage,
'average': undefined,
'baseVolume': baseVolume,
'quoteVolume': quoteVolume,
'info': ticker,
}, market);
}
async fetchOrderBook(symbol, limit = undefined, params = {}) {
/**
* @method
* @name mexc#fetchOrderBook
* @description fetches 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|undefined} limit the maximum amount of order book entries to return
* @param {object} params extra parameters specific to the mexc api endpoint
* @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
*/
await this.loadMarkets();
const market = this.market(symbol);
const request = {
'symbol': market['id'],
};
let method = undefined;
if (market['spot']) {
method = 'spotPublicGetMarketDepth';
if (limit === undefined) {
limit = 100; // the spot api requires a limit
}
request['depth'] = limit;
}
else if (market['swap']) {
method = 'contractPublicGetDepthSymbol';
if (limit !== undefined) {
request['limit'] = limit;
}
}
const response = await this[method](this.extend(request, params));
//
// spot
//
// {
// "code":200,
// "data":{
// "asks":[
// {"price":"49060.56","quantity":"0.099842"},
// {"price":"49060.58","quantity":"0.016003"},
// {"price":"49060.6","quantity":"0.023677"}
// ],
// "bids":[
// {"price":"49060.45","quantity":"1.693009"},
// {"price":"49060.44","quantity":"0.000843"},
// {"price":"49059.98","quantity":"0.735"},
// ],
// "version":"202454074",
// }
// }
//
// swap / contract
//
// {
// "success":true,
// "code":0,
// "data":{
// "asks":[
// [3445.7,48379,1],
// [3445.75,34994,1],
// [3445.8,68634,2],
// ],
// "bids":[
// [3445.55,44081,1],
// [3445.5,24857,1],
// [3445.45,50272,1],
// ],
// "version":2827730444,
// "timestamp":1634117846232
// }
// }
//
const data = this.safeValue(response, 'data', {});
const priceKey = market['spot'] ? 'price' : 0;
const amountKey = market['spot'] ? 'quantity' : 1;
const timestamp = this.safeInteger(data, 'timestamp');
const orderbook = this.parseOrderBook(data, symbol, timestamp, 'bids', 'asks', priceKey, amountKey);
orderbook['nonce'] = this.safeInteger(data, 'version');
return orderbook;
}
async fetchTrades(symbol, since = undefined, limit = undefined, params = {}) {
/**
* @method
* @name mexc#fetchTrades
* @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|undefined} since timestamp in ms of the earliest trade to fetch
* @param {int|undefined} limit the maximum amount of trades to fetch
* @param {object} params extra parameters specific to the mexc api endpoint
* @returns {[object]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html?#public-trades}
*/
await this.loadMarkets();
const market = this.market(symbol);
const request = {
'symbol': market['id'],
};
if (limit !== undefined) {
request['limit'] = limit; // default 100, max 100
}
let method = undefined;
if (market['spot']) {
method = 'spotPublicGetMarketDeals';
}
else if (market['swap']) {
method = 'contractPublicGetDealsSymbol';
}
const response = await this[method](this.extend(request, params));
//
// spot
//
// {
// "code":200,
// "data":[
// {"trade_time":1633381766725,"trade_price":"0.068981","trade_quantity":"0.005","trade_type":"BID"},
// {"trade_time":1633381732705,"trade_price":"0.068979","trade_quantity":"0.006","trade_type":"BID"},
// {"trade_time":1633381694604,"trade_price":"0.068975","trade_quantity":"0.011","trade_type":"ASK"},
// ]
// }
//
// swap / contract
//
// {
// "success":true,
// "code":0,
// "data":[
// {"p":3598.85,"v":52,"T":1,"O":2,"M":2,"t":1634169038038},
// {"p":3599.2,"v":15,"T":2,"O":3,"M":1,"t":1634169035603},
// {"p":3600.15,"v":229,"T":2,"O":1,"M":2,"t":1634169026354},
// ]
// }
//
const data = this.safeValue(response, 'data', []);
return this.parseTrades(data, market, since, limit);
}
parseTrade(trade, market = undefined) {
//
// public fetchTrades
//
// spot
//
// {
// "trade_time":1633381766725,
// "trade_price":"0.068981",
// "trade_quantity":"0.005",
// "trade_type":"BID"
// }
//
// swap / contract
//
// {
// "p":3598.85,
// "v":52,
// "T":1, // 1 buy, 2 sell
// "O":2, // 1 opens a position, 2 does not open a position
// "M":2, // self-trading, 1 yes, 2 no
// "t":1634169038038
// }
//
// private fetchMyTrades, fetchOrderTrades
//
// {
// "id":"b160b8f072d9403e96289139d5544809",
// "symbol":"USDC_USDT",
// "quantity":"150",
// "price":"0.9997",
// "amount":"149.955",
// "fee":"0.29991",
// "trade_type":"ASK",
// "order_id":"d798765285374222990bbd14decb86cd",
// "is_taker":true,
// "fee_currency":"USDT",
// "create_time":1633984904000
// }
//
let timestamp = this.safeInteger2(trade, 'create_time', 'trade_time');
timestamp = this.safeInteger(trade, 't', timestamp);
const marketId = this.safeString(trade, 'symbol');
market = this.safeMarket(marketId, market, '_');
const symbol = market['symbol'];
let priceString = this.safeString2(trade, 'price', 'trade_price');
priceString = this.safeString(trade, 'p', priceString);
let amountString = this.safeString2(trade, 'quantity', 'trade_quantity');
amountString = this.safeString(trade, 'v', amountString);
const costString = this.safeString(trade, 'amount');
let side = this.safeString2(trade, 'trade_type', 'T');
if ((side === 'BID') || (side === '1')) {
side = 'buy';
}
else if ((side === 'ASK') || (side === '2')) {
side = 'sell';
}
let id = this.safeString2(trade, 'id', 'trade_time');
if (id === undefined) {
id = this.safeString(trade, 't', id);
if (id !== undefined) {
id += '-' + market['id'] + '-' + amountString;
}
}
const feeCostString = this.safeString(trade, 'fee');
let fee = undefined;
if (feeCostString !== undefined) {
const feeCurrencyId = this.safeString(trade, 'fee_currency');
const feeCurrencyCode = this.safeCurrencyCode(feeCurrencyId);
fee = {
'cost': feeCostString,
'currency': feeCurrencyCode,
};
}
const orderId = this.safeString(trade, 'order_id');
const isTaker = this.safeValue(trade, 'is_taker', true);
const takerOrMaker = isTaker ? 'taker' : 'maker';
return this.safeTrade({
'info': trade,
'id': id,
'order': orderId,
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'symbol': symbol,
'type': undefined,
'side': side,
'takerOrMaker': takerOrMaker,
'price': priceString,
'amount': amountString,
'cost': costString,
'fee': fee,
}, market);
}
async fetchTradingFees(params = {}) {
/**
* @method
* @name mexc#fetchTradingFees
* @description fetch the trading fees for multiple markets
* @param {object} params extra parameters specific to the mexc api endpoint
* @returns {object} a dictionary of [fee structures]{@link https://docs.ccxt.com/#/?id=fee-structure} indexed by market symbols
*/
await this.loadMarkets();
const response = await this.spotPublicGetMarketSy