@jalmonter/ccxt
Version:
1,150 lines • 237 kB
JavaScript
// ---------------------------------------------------------------------------
import Exchange from './abstract/mexc.js';
import { BadRequest, InvalidNonce, BadSymbol, InvalidOrder, InvalidAddress, ExchangeError, ArgumentsRequired, NotSupported, InsufficientFunds, PermissionDenied, AuthenticationError, AccountSuspended, OnMaintenance } from './base/errors.js';
import { TICK_SIZE } from './base/functions/number.js';
import { Precise } from './base/Precise.js';
import { sha256 } from './static_dependencies/noble-hashes/sha256.js';
// ---------------------------------------------------------------------------
/**
* @class mexc
* @augments Exchange
*/
export default class mexc extends Exchange {
describe() {
return this.deepExtend(super.describe(), {
'id': 'mexc',
'name': 'MEXC Global',
'countries': ['SC'],
'rateLimit': 50,
'version': 'v3',
'certified': true,
'pro': true,
'has': {
'CORS': undefined,
'spot': true,
'margin': true,
'swap': true,
'future': false,
'option': false,
'addMargin': true,
'cancelAllOrders': true,
'cancelOrder': true,
'cancelOrders': undefined,
'closeAllPositions': false,
'closePosition': false,
'createDepositAddress': true,
'createMarketBuyOrderWithCost': true,
'createMarketOrderWithCost': false,
'createMarketSellOrderWithCost': false,
'createOrder': true,
'createOrders': true,
'createReduceOnlyOrder': true,
'deposit': undefined,
'editOrder': undefined,
'fetchAccounts': true,
'fetchBalance': true,
'fetchBidsAsks': true,
'fetchBorrowRateHistory': undefined,
'fetchCanceledOrders': true,
'fetchClosedOrder': undefined,
'fetchClosedOrders': true,
'fetchCrossBorrowRate': false,
'fetchCrossBorrowRates': false,
'fetchCurrencies': true,
'fetchDeposit': undefined,
'fetchDepositAddress': true,
'fetchDepositAddresses': undefined,
'fetchDepositAddressesByNetwork': true,
'fetchDeposits': true,
'fetchDepositWithdrawFee': 'emulated',
'fetchDepositWithdrawFees': true,
'fetchFundingHistory': true,
'fetchFundingRate': true,
'fetchFundingRateHistory': true,
'fetchFundingRates': undefined,
'fetchIndexOHLCV': true,
'fetchIsolatedBorrowRate': false,
'fetchIsolatedBorrowRates': false,
'fetchL2OrderBook': true,
'fetchLedger': undefined,
'fetchLedgerEntry': undefined,
'fetchLeverageTiers': true,
'fetchMarginMode': false,
'fetchMarketLeverageTiers': undefined,
'fetchMarkets': true,
'fetchMarkOHLCV': true,
'fetchMyTrades': true,
'fetchOHLCV': true,
'fetchOpenOrder': undefined,
'fetchOpenOrders': true,
'fetchOrder': true,
'fetchOrderBook': true,
'fetchOrderBooks': undefined,
'fetchOrders': true,
'fetchOrderTrades': true,
'fetchPosition': true,
'fetchPositionMode': true,
'fetchPositions': true,
'fetchPositionsRisk': undefined,
'fetchPremiumIndexOHLCV': false,
'fetchStatus': true,
'fetchTicker': true,
'fetchTickers': true,
'fetchTime': true,
'fetchTrades': true,
'fetchTradingFee': undefined,
'fetchTradingFees': true,
'fetchTradingLimits': undefined,
'fetchTransactionFee': 'emulated',
'fetchTransactionFees': true,
'fetchTransactions': undefined,
'fetchTransfer': true,
'fetchTransfers': true,
'fetchWithdrawal': undefined,
'fetchWithdrawals': true,
'reduceMargin': true,
'repayCrossMargin': false,
'repayIsolatedMargin': false,
'setLeverage': true,
'setMarginMode': undefined,
'setPositionMode': true,
'signIn': undefined,
'transfer': undefined,
'withdraw': true,
},
'urls': {
'logo': 'https://user-images.githubusercontent.com/1294454/137283979-8b2a818d-8633-461b-bfca-de89e8c446b2.jpg',
'api': {
'spot': {
'public': 'https://api.mexc.com',
'private': 'https://api.mexc.com',
},
'spot2': {
'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',
},
'broker': {
'private': 'https://api.mexc.com/api/v3/broker',
},
},
'www': 'https://www.mexc.com/',
'doc': [
'https://mexcdevelop.github.io/apidocs/spot_v3_en/',
'https://mexcdevelop.github.io/APIDoc/', // v1 & v2 : soon to be deprecated
],
'fees': [
'https://www.mexc.com/fee',
],
'referral': 'https://m.mexc.com/auth/signup?inviteCode=1FQ1G',
},
'api': {
'spot': {
'public': {
'get': {
'ping': 1,
'time': 1,
'exchangeInfo': 10,
'depth': 1,
'trades': 5,
'historicalTrades': 1,
'aggTrades': 1,
'klines': 1,
'avgPrice': 1,
'ticker/24hr': 1,
'ticker/price': 1,
'ticker/bookTicker': 1,
'etf/info': 1,
},
},
'private': {
'get': {
'order': 2,
'openOrders': 3,
'allOrders': 10,
'account': 10,
'myTrades': 10,
'sub-account/list': 1,
'sub-account/apiKey': 1,
'capital/config/getall': 10,
'capital/deposit/hisrec': 1,
'capital/withdraw/history': 1,
'capital/withdraw/address': 10,
'capital/deposit/address': 10,
'capital/transfer': 1,
'capital/transfer/tranId': 1,
'capital/transfer/internal': 1,
'capital/sub-account/universalTransfer': 1,
'capital/convert': 1,
'capital/convert/list': 1,
'margin/loan': 1,
'margin/allOrders': 1,
'margin/myTrades': 1,
'margin/openOrders': 1,
'margin/maxTransferable': 1,
'margin/priceIndex': 1,
'margin/order': 1,
'margin/isolated/account': 1,
'margin/maxBorrowable': 1,
'margin/repay': 1,
'margin/isolated/pair': 1,
'margin/forceLiquidationRec': 1,
'margin/isolatedMarginData': 1,
'margin/isolatedMarginTier': 1,
'rebate/taxQuery': 1,
'rebate/detail': 1,
'rebate/detail/kickback': 1,
'rebate/referCode': 1,
'rebate/affiliate/commission': 1,
'rebate/affiliate/withdraw': 1,
'rebate/affiliate/commission/detail': 1,
'mxDeduct/enable': 1,
'userDataStream': 1,
},
'post': {
'order': 1,
'order/test': 1,
'sub-account/virtualSubAccount': 1,
'sub-account/apiKey': 1,
'sub-account/futures': 1,
'sub-account/margin': 1,
'batchOrders': 10,
'capital/withdraw/apply': 1,
'capital/transfer': 1,
'capital/transfer/internal': 1,
'capital/deposit/address': 1,
'capital/sub-account/universalTransfer': 1,
'capital/convert': 10,
'mxDeduct/enable': 1,
'userDataStream': 1,
},
'put': {
'userDataStream': 1,
},
'delete': {
'order': 1,
'openOrders': 1,
'sub-account/apiKey': 1,
'margin/order': 1,
'margin/openOrders': 1,
'userDataStream': 1,
},
},
},
'contract': {
'public': {
'get': {
'ping': 2,
'detail': 100,
'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,
'position/leverage': 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,
},
},
},
'spot2': {
'public': {
'get': {
'market/symbols': 1,
'market/coin/list': 2,
'common/timestamp': 1,
'common/ping': 2,
'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,
'order/advanced/place_batch': 1,
'asset/withdraw': 2,
'asset/internal/transfer': 10,
},
'delete': {
'order/cancel': 1,
'order/cancel_by_symbol': 1,
'asset/withdraw': 2,
},
},
},
'broker': {
'private': {
'get': {
'sub-account/universalTransfer': 1,
'sub-account/list': 1,
'sub-account/apiKey': 1,
'capital/deposit/subAddress': 1,
'capital/deposit/subHisrec': 1,
'capital/deposit/subHisrec/getall': 1,
},
'post': {
'sub-account/virtualSubAccount': 1,
'sub-account/apiKey': 1,
'capital/deposit/subAddress': 1,
'capital/withdraw/apply': 1,
'sub-account/universalTransfer': 1,
'sub-account/futures': 1,
},
'delete': {
'sub-account/apiKey': 1,
},
},
},
},
'precisionMode': TICK_SIZE,
'timeframes': {
'1m': '1m',
'5m': '5m',
'15m': '15m',
'30m': '30m',
'1h': '1h',
'4h': '4h',
'8h': '8h',
'1d': '1d',
'1w': '1w',
'1M': '1M', // spot, swap
},
'fees': {
'trading': {
'tierBased': false,
'percentage': true,
'maker': this.parseNumber('0.002'),
'taker': this.parseNumber('0.002'),
},
},
'options': {
'createMarketBuyOrderRequiresPrice': true,
'unavailableContracts': {
'BTC/USDT:USDT': true,
'LTC/USDT:USDT': true,
'ETH/USDT:USDT': true,
},
'fetchMarkets': {
'types': {
'spot': true,
'swap': {
'linear': true,
'inverse': false,
},
},
},
'timeframes': {
'spot': {
'1m': '1m',
'5m': '5m',
'15m': '15m',
'30m': '30m',
'1h': '60m',
'4h': '4h',
'1d': '1d',
'1M': '1M',
},
'swap': {
'1m': 'Min1',
'5m': 'Min5',
'15m': 'Min15',
'30m': 'Min30',
'1h': 'Min60',
'4h': 'Hour4',
'8h': 'Hour8',
'1d': 'Day1',
'1w': 'Week1',
'1M': 'Month1',
},
},
'defaultType': 'spot',
'defaultNetwork': 'ETH',
'defaultNetworks': {
'ETH': 'ETH',
'USDT': 'TRC20',
},
'networks': {
'BTC': 'BTC',
'BCH': 'BCH',
'TRC20': 'Tron(TRC20)',
'ERC20': 'Ethereum(ERC20)',
'BEP20': 'BNBSmartChain(BEP20)',
'OPTIMISM': 'Optimism(OP)',
'SOL': 'Solana(SOL)',
'CRC20': 'CRONOS',
'ALGO': 'Algorand(ALGO)',
'XRP': 'XRP',
'MATIC': 'Polygon(MATIC)',
'AVAXX': 'AVAX_XCHAIN',
'AVAXC': 'AvalancheCChain(AVAXCCHAIN)',
'ARBONE': 'ArbitrumOne(ARB)',
'ARBNOVA': 'ARBNOVA',
'FTM': 'FTM',
'WAVES': 'WAVES',
'CHZ': 'Chiliz Chain(CHZ)',
'HRC20': 'HECO',
'TRC10': 'TRC10',
'DASH': 'DASH',
'LTC': 'LTC',
// 'DOGECOIN': [ 'DOGE', 'DOGECHAIN' ], // todo after unification
'XTZ': 'XTZ',
'OMNI': 'OMNI',
'APT': 'APTOS',
'ONT': 'ONT',
'BSV': 'BSV',
'OKC': 'OKT',
'CELO': 'CELO',
'KLAY': 'KLAY',
'BEP2': 'BEP2',
'EGLD': 'EGLD',
'EOS': 'EOS',
'ZIL': 'ZIL',
'ETHW': 'ETHW',
'IOTX': 'IOTX',
'IOTA': 'IOTA',
'SYS': 'SYS',
'XCH': 'CHIA',
'KMA': 'KMA',
'ONE': 'ONE',
'METIS': 'METIS',
'KAVA': 'KAVA',
'KDA': 'KDA',
'IOST': 'IOST',
'XEC': 'XEC',
'VET': 'VET',
'XLM': 'XLM',
'KSM': 'KSM',
'MOVR': 'MOVR',
'XMR': 'XMR',
'LAT': 'LAT',
'ETC': 'ETC',
// 'TLOS': 'TELOS', // todo
// 'TELOSCOIN': 'TLOS', // todo
'GLMR': 'GLMR',
'DOT': 'DOT',
'SC': 'SC',
'ICP': 'ICP',
'AOK': 'AOK',
'ZEC': 'ZEC',
'ACA': 'ACALA',
'ASTR': 'ASTAR',
'FIL': 'FIL',
'NEAR': 'NEAR',
'OSMO': 'OSMO',
'SDN': 'SDN',
'BITCI': 'BITCI',
'NEO': 'NEO',
'ADA': 'ADA',
'RVN': 'RVN',
'BNC': 'BNC',
'BNCDOT': 'BNCPOLKA',
'ETHF': 'ETF',
'STEEM': 'STEEM',
'OASYS': 'OASYS',
'BEAM': 'BEAM',
'VSYS': 'VSYS',
'OASIS': 'ROSE',
'AR': 'AR',
'AE': 'AE',
'QTUM': 'QTUM',
'ATOM': 'ATOM',
'HBAR': 'HBAR',
'CSPR': 'CSPR',
'WEMIX': 'WEMIX',
'SGB': 'SGB',
'XPR': 'PROTON',
'HYDRA': 'HYDRA',
'SCRT': 'SCRT',
'TOMO': 'TOMO',
'WAX': 'WAX',
'KAR': 'KAR',
'KILT': 'KILT',
'XDC': 'XDC',
'GRIN': 'GRIN',
'PLCU': 'PLCU',
'MINA': 'MINA',
'ABBC': 'ABBC',
'ZEN': 'ZEN',
'FLOW': 'FLOW',
'RSK': 'RBTC',
'DCR': 'DCR',
'HIVE': 'HIVE',
'XYM': 'XYM',
'CKB': 'CKB',
'XRD': 'XRD',
'XVG': 'XVG',
'BOBA': 'BOBA',
'AZERO': 'AZERO',
'ARK': 'ARK',
'NULS': 'NULS',
'POKT': 'POKT',
'NEO3': 'NEO3',
'FIO': 'FIO',
'MASS': 'MASS',
'AME': 'AME',
'REI': 'REI',
'IRIS': 'IRIS',
'ZTG': 'ZTG',
'EDG': 'EDG',
'FUSE': 'FUSE',
'EVER': 'EVER',
'FET': 'FET',
'CFX': 'CFX',
'NEBL': 'NEBL',
'STAR': 'STAR',
'NEM': 'NEM',
'BDX': 'BDX',
'TON': 'TONCOIN',
'NAS': 'NAS',
'QKC': 'QKC',
'BTM': 'BTM2',
'FSN': 'FSN',
// todo: uncomment below after concensus
// 'TERRACLASSIC': 'LUNC',
// 'TERRA': 'LUNA2',
// 'PHALA': 'Khala',
// 'NODLE': 'NODLE',
// 'KUJIRA': 'KUJI',
// 'HUAHUA': 'HUAHUA',
// 'FRUITS': 'FRTS',
// 'IOEX': 'IOEX',
// 'TOMAINFO': 'TON',
// 'BITCOINHD': 'BHD',
// 'CENNZ': 'CENNZ',
// 'WAYKICHAIN': 'WICC',
// 'EMERALD': 'EMERALD', // sits on top of OASIS
// 'CONTENTVALUENETWORK': 'CVNT',
// 'ORIGYN': 'OGY',
// 'KASPA': 'KASPA',
// 'CANTO': 'CANTO', // CANTOEVM
// 'DARWINIASMARTCHAIN': 'Darwinia Smart Chain',
// 'KEKCHAIN': 'KEKCHAIN',
// 'ZENITH': 'ZENITH',
// 'ECOCHAIN': 'ECOC',
// 'ELECTRAPROTOCOL': 'XEP',
// 'KULUPU': 'KLP',
// 'KINTSUGI': 'KINT',
// 'PLEX': 'PLEX',
// 'CONCODRIUM': 'CCD',
// 'REBUS': 'REBUS', // REBUSEVM is different
// 'BITKUB': 'KUB',
// 'BITCOINVAULT': 'BTCV',
// 'PROXIMAX': 'XPX',
// 'PAC': 'PAC',
// 'CHAINX': 'PCX',
// 'DRAC': 'DRAC',
// 'WHITECOIN': 'XWC',
// 'TECHPAY': 'TPC',
// 'GXCHAIN': 'GXC',
// 'CYPHERIUM': 'CPH',
// 'LBRY': 'LBC',
// 'TONGTONG': 'TTC',
// 'LEDGIS': 'LED',
// 'PMG': 'PMG',
// 'PROOFOFMEMES': 'POM',
// 'SENTINEL': 'DVPN',
// 'METER': 'MTRG',
// 'YAS': 'YAS',
// 'ULTRAIN': 'UGAS',
// 'PASTEL': 'PSL',
// 'KONSTELLATION': 'DARC',
// 'ANDUSCHAIN': 'DEB',
// 'FIRMACHAIN': 'FCT',
// 'HANDSHAKE': 'HNS',
// 'DANGNN': 'DGC',
// 'SERO': 'SERO',
// 'HPB': 'HPB',
// 'XDAI': 'XDAI',
// 'EXOSAMA': 'SAMA',
// 'DHEALTH': 'DHP',
// 'HUPAYX': 'HPX',
// 'GLEEC': 'GLEEC',
// 'FIBOS': 'FO',
// 'MDNA': 'DNA',
// 'HSHARE': 'HC',
// 'BYTZ': 'BYTZ',
// 'DRAKEN': 'DRK',
// 'LINE': 'LINE',
// 'MDUKEY': 'MDU',
// 'KOINOS': 'KOINOS',
// 'MEVERSE': 'MEVerse',
// 'POINT': 'POINT', // POINTEVM is different
// 'INDEXCHAIN': 'IDX',
// 'ULORD': 'UT',
// 'INTEGRITEE': 'TEER',
// 'XX': 'XX',
// 'CORTEX': 'CTXC',
// 'RIZON': 'ATOLO',
// 'VDIMENSION': 'VOLLAR',
// 'JUNO': 'JUNO',
// 'VEXANIUM': 'VEX',
// 'INTCHAIN': 'INT',
// 'METAMUI': 'MMUI',
// 'RCHAIN': 'REV',
// 'EVMOS': 'EVMOS', // EVMOSETH is different
// 'ZKSYNC': 'ZKSYNC',
// 'BITSHARES_OLD': 'BTS',
// 'BITSHARES': 'NBS',
// 'UMEE': 'UMEE',
// 'VNT': 'VNT',
// 'TURTLECOIN': 'TRTL',
// 'METAVERSE_ETP': 'ETP',
// 'NEWTON': 'NEW',
// // 'BAJUN': '',
// 'INTERLAY': 'INTR',
// 'LIGHTNINGBITCOIN': 'LBTC',
// 'FIRO': 'XZC',
// 'ALAYA': 'ATP',
// 'AXE': 'AXE',
// 'FNCY': 'FNCY',
// 'WITNET': 'WIT',
// 'FILECASH': 'FIC',
// 'ASSETMANTLE': 'MNTL',
// OKB <> OKT (for usdt it's exception) for OKC, PMEER, FLARE, STRD, ZEL, FUND, "NONE", CRING, FREETON, QTZ (probably unique network is meant), HT, BSC(RACAV1), BSC(RACAV2), AMBROSUS, BAJUN, NOM. their individual info is at https://www.mexc.com/api/platform/asset/spot/{COINNAME}
},
'recvWindow': 5 * 1000,
'maxTimeTillEnd': 90 * 86400 * 1000 - 1,
'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',
'STEPN': 'GMT',
'HERO': 'Step Hero',
'MIMO': 'Mimosa',
'PROS': 'Pros.Finance',
'SIN': 'Sin City Token',
'SOUL': 'Soul Swap',
},
'exceptions': {
'exact': {
// until mexc migrates fully to v3, it might be worth to note the version & market aside errors, not easily remove obsolete version's exceptions in future
'-1128': BadRequest,
'-2011': BadRequest,
'-1121': BadSymbol,
'10101': InsufficientFunds,
'2009': InvalidOrder,
'2011': BadRequest,
'30004': InsufficientFunds,
'33333': BadRequest,
'44444': BadRequest,
'1002': InvalidOrder,
'30019': BadRequest,
'30005': InvalidOrder,
'2003': InvalidOrder,
'2005': InsufficientFunds,
'400': BadRequest,
// '500': OnMaintenance, // {"code": 500,"message": "Under maintenance, please try again later","announcement": "https://www.mexc.com/support/articles/17827791510263"}
'600': BadRequest,
'70011': PermissionDenied,
'88004': InsufficientFunds,
'88009': ExchangeError,
'88013': InvalidOrder,
'88015': InsufficientFunds,
'700003': InvalidNonce,
'26': ExchangeError,
'602': AuthenticationError,
'10001': AuthenticationError,
'10007': BadSymbol,
'10015': BadRequest,
'10072': BadRequest,
'10073': BadRequest,
'10095': InvalidOrder,
'10096': InvalidOrder,
'10097': InvalidOrder,
'10098': InvalidOrder,
'10099': BadRequest,
'10100': BadRequest,
'10102': InvalidOrder,
'10103': ExchangeError,
'10200': BadRequest,
'10201': BadRequest,
'10202': BadRequest,
'10206': BadRequest,
'10211': BadRequest,
'10212': BadRequest,
'10216': ExchangeError,
'10219': ExchangeError,
'10222': BadRequest,
'10232': BadRequest,
'10259': ExchangeError,
'10265': ExchangeError,
'10268': BadRequest,
'20001': ExchangeError,
'20002': ExchangeError,
'22222': BadRequest,
'30000': ExchangeError,
'30001': InvalidOrder,
'30002': InvalidOrder,
'30003': InvalidOrder,
'30010': InvalidOrder,
'30014': InvalidOrder,
'30016': InvalidOrder,
'30018': AccountSuspended,
'30020': AuthenticationError,
'30021': BadRequest,
'30025': InvalidOrder,
'30026': BadRequest,
'30027': InvalidOrder,
'30028': InvalidOrder,
'30029': InvalidOrder,
'30032': InvalidOrder,
'30041': InvalidOrder,
'60005': ExchangeError,
'700001': AuthenticationError,
'700002': AuthenticationError,
'700004': BadRequest,
'700005': InvalidNonce,
'700006': BadRequest,
'700007': AuthenticationError,
'700008': BadRequest,
'730001': BadRequest,
'730002': BadRequest,
'730000': ExchangeError,
'730003': ExchangeError,
'730100': ExchangeError,
'730600': BadRequest,
'730601': BadRequest,
'730602': BadRequest,
'730700': BadRequest,
'730701': BadRequest,
'730702': BadRequest,
'730703': BadRequest,
'730704': BadRequest,
'730705': BadRequest,
'730706': BadRequest,
'730707': BadRequest,
'730101': BadRequest,
'140001': BadRequest,
'140002': AuthenticationError, // sub account is forbidden
},
'broad': {
'Order quantity error, please try to modify.': BadRequest,
'Combination of optional parameters invalid': BadRequest,
'api market order is disabled': BadRequest,
'Contract not allow place order!': InvalidOrder,
'Oversold': InvalidOrder,
'Insufficient position': InsufficientFunds,
'Insufficient balance!': InsufficientFunds,
'Bid price is great than max allow price': InvalidOrder,
'Invalid symbol.': BadSymbol,
'Param error!': BadRequest,
'maintenance': OnMaintenance, // {"code": 500,"message": "Under maintenance, please try again later","announcement": "https://www.mexc.com/support/articles/17827791510263"}
},
},
});
}
async fetchStatus(params = {}) {
/**
* @method
* @name mexc3#fetchStatus
* @description the latest known information on the availability of the exchange API
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [status structure]{@link https://docs.ccxt.com/#/?id=exchange-status-structure}
*/
const [marketType, query] = this.handleMarketTypeAndParams('fetchStatus', undefined, params);
let response = undefined;
let status = undefined;
let updated = undefined;
if (marketType === 'spot') {
response = await this.spotPublicGetPing(query);
//
// {}
//
const keys = Object.keys(response);
const length = keys.length;
status = length ? this.json(response) : 'ok';
}
else if (marketType === 'swap') {
response = await this.contractPublicGetPing(query);
//
// {"success":true,"code":"0","data":"1648124374985"}
//
status = this.safeValue(response, 'success') ? 'ok' : this.json(response);
updated = this.safeInteger(response, 'data');
}
return {
'status': status,
'updated': updated,
'url': undefined,
'eta': undefined,
'info': response,
};
}
async fetchTime(params = {}) {
/**
* @method
* @name mexc3#fetchTime
* @description fetches the current integer timestamp in milliseconds from the exchange server
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {int} the current integer timestamp in milliseconds from the exchange server
*/
const [marketType, query] = this.handleMarketTypeAndParams('fetchTime', undefined, params);
let response = undefined;
if (marketType === 'spot') {
response = await this.spotPublicGetTime(query);
//
// {"serverTime": "1647519277579"}
//
return this.safeInteger(response, 'serverTime');
}
else if (marketType === 'swap') {
response = await this.contractPublicGetPing(query);
//
// {"success":true,"code":"0","data":"1648124374985"}
//
return this.safeInteger(response, 'data');
}
return undefined;
}
async fetchCurrencies(params = {}) {
/**
* @method
* @name mexc3#fetchCurrencies
* @description fetches all available currencies on an exchange
* @see https://mexcdevelop.github.io/apidocs/spot_v3_en/#query-the-currency-information
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} an associative dictionary of currencies
*/
// this endpoint requires authentication
// while fetchCurrencies is a public API method by design
// therefore we check the keys here
// and fallback to generating the currencies from the markets
if (!this.checkRequiredCredentials(false)) {
return undefined;
}
const response = await this.spotPrivateGetCapitalConfigGetall(params);
//
// {
// "coin": "QANX",
// "name": "QANplatform",
// "networkList": [
// {
// "coin": "QANX",
// "depositDesc": null,
// "depositEnable": true,
// "minConfirm": "0",
// "name": "QANplatform",
// "network": "BEP20(BSC)",
// "withdrawEnable": false,
// "withdrawFee": "42.000000000000000000",
// "withdrawIntegerMultiple": null,
// "withdrawMax": "24000000.000000000000000000",
// "withdrawMin": "20.000000000000000000",
// "sameAddress": false,
// "contract": "0xAAA7A10a8ee237ea61E8AC46C50A8Db8bCC1baaa"
// },
// {
// "coin": "QANX",
// "depositDesc": null,
// "depositEnable": true,
// "minConfirm": "0",
// "name": "QANplatform",
// "network": "ERC20",
// "withdrawEnable": true,
// "withdrawFee": "2732.000000000000000000",
// "withdrawIntegerMultiple": null,
// "withdrawMax": "24000000.000000000000000000",
// "withdrawMin": "240.000000000000000000",
// "sameAddress": false,
// "contract": "0xAAA7A10a8ee237ea61E8AC46C50A8Db8bCC1baaa"
// }
// ]
// }
//
const result = {};
for (let i = 0; i < response.length; i++) {
const currency = response[i];
const id = this.safeString(currency, 'coin');
const code = this.safeCurrencyCode(id);
const name = this.safeString(currency, 'name');
let currencyActive = false;
let currencyFee = undefined;
let currencyWithdrawMin = undefined;
let currencyWithdrawMax = undefined;
let depositEnabled = false;
let withdrawEnabled = false;
const networks = {};
const chains = this.safeValue(currency, 'networkList', []);
for (let j = 0; j < chains.length; j++) {
const chain = chains[j];
const networkId = this.safeString(chain, 'network');
const network = this.safeNetwork(networkId);
const isDepositEnabled = this.safeValue(chain, 'depositEnable', false);
const isWithdrawEnabled = this.safeValue(chain, 'withdrawEnable', false);
const active = (isDepositEnabled && isWithdrawEnabled);
currencyActive = active || currencyActive;
const withdrawMin = this.safeString(chain, 'withdrawMin');
const withdrawMax = this.safeString(chain, 'withdrawMax');
currencyWithdrawMin = (currencyWithdrawMin === undefined) ? withdrawMin : currencyWithdrawMin;
currencyWithdrawMax = (currencyWithdrawMax === undefined) ? withdrawMax : currencyWithdrawMax;
const fee = this.safeNumber(chain, 'withdrawFee');
currencyFee = (currencyFee === undefined) ? fee : currencyFee;
if (Precise.stringGt(currencyWithdrawMin, withdrawMin)) {
currencyWithdrawMin = withdrawMin;
}
if (Precise.stringLt(currencyWithdrawMax, withdrawMax)) {
currencyWithdrawMax = withdrawMax;
}
if (isDepositEnabled) {
depositEnabled = true;
}
if (isWithdrawEnabled) {
withdrawEnabled = true;
}
networks[network] = {
'info': chain,
'id': networkId,
'network': network,
'active': active,
'deposit': isDepositEnabled,
'withdraw': isWithdrawEnabled,
'fee': fee,
'precision': undefined,
'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] = {
'info': currency,
'id': id,
'code': code,
'name': name,
'active': currencyActive,
'deposit': depositEnabled,
'withdraw': withdrawEnabled,
'fee': currencyFee,
'precision': undefined,
'limits': {
'amount': {
'min': undefined,
'max': undefined,
},
'withdraw': {
'min': currencyWithdrawMin,
'max': currencyWithdrawMax,
},
},
'networks': networks,
};
}
return result;
}
safeNetwork(networkId) {
if (networkId.indexOf('BSC') >= 0) {
return 'BEP20';
}
const parts = networkId.split(' ');
networkId = parts.join('');
networkId = networkId.replace('-20', '20');
const networksById = {
'Ethereum(ERC20)': 'ERC20',
'Algorand(ALGO)': 'ALGO',
'ArbitrumOne(ARB)': 'ARBONE',
'AvalancheCChain(AVAXCCHAIN)': 'AVAXC',
'BNBSmartChain(BEP20)': 'BEP20',
'Polygon(MATIC)': 'MATIC',
'Optimism(OP)': 'OPTIMISM',
'Solana(SOL)': 'SOL',
'Tron(TRC20)': 'TRC20',
};
return this.safeString(networksById, networkId, networkId);
}
async fetchMarkets(params = {}) {
/**
* @method
* @name mexc3#fetchMarkets
* @description retrieves data on all markets for mexc3
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object[]} an array of objects representing market data
*/
const spotMarket = await this.fetchSpotMarkets(params);
const swapMarket = await this.fetchSwapMarkets(params);
return this.arrayConcat(spotMarket, swapMarket);
}
async fetchSpotMarkets(params = {}) {
const response = await this.spotPublicGetExchangeInfo(params);
//
// {
// "timezone": "CST",
// "serverTime": 1647521860402,
// "rateLimits": [],
// "exchangeFilters": [],
// "symbols": [
// {
// "symbol": "OGNUSDT",
// "status": "ENABLED",
// "baseAsset": "OGN",
// "baseAssetPrecision": "2",
// "quoteAsset": "USDT",
// "quoteAssetPrecision": "4",
// "orderTypes": [
// "LIMIT",
// "LIMIT_MAKER"
// ],
// "baseCommissionPrecision": "2",
// "quoteCommissionPrecision": "4",
// "quoteOrderQtyMarketAllowed": false,
// "isSpotTradingAllowed": true,
// "isMarginTradingAllowed": true,
// "permissions": [
// "SPOT",
// "MARGIN"
// ],
// "filters": [],
// "baseSizePrecision": "0.01", // this turned out to be a minimum base amount for order
// "maxQuoteAmount": "5000000",
// "makerCommission": "0.002",
// "takerCommission": "0.002"
// "quoteAmountPrecision": "5", // this turned out to be a minimum cost amount for order
// "quotePrecision": "4", // deprecated in favor of 'quoteAssetPrecision' ( https://dev.binance.vision/t/what-is-the-difference-between-quoteprecision-and-quoteassetprecision/4333 )
// // note, "icebergAllowed" & "ocoAllowed" fields were recently removed
// },
// ]
// }
//
// Notes:
// - 'quoteAssetPrecision' & 'baseAssetPrecision' are not currency's real blockchain precision (to view currency's actual individual precision, refer to fetchCurrencies() method).
//
const data = this.safeValue(response, 'symbols', []);
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, 'baseAsset');
const quoteId = this.safeString(market, 'quoteAsset');
const base = this.safeCurrencyCode(baseId);
const quote = this.safeCurrencyCode(quoteId);
const status = this.safeString(market, 'status');
const isSpotTradingAllowed = this.safeValue(market, 'isSpotTradingAllowed');
let active = false;
if ((status === 'ENABLED') && (isSpotTradingAllowed)) {
active = true;
}
const isMarginTradingAllowed = this.safeValue(market, 'isMarginTradingAllowed');
const makerCommission = this.safeNumber(market, 'makerCommission');
const takerCommission = this.safeNumber(market, 'takerCommission');
const maxQuoteAmount = this.safeNumber(market, 'maxQuoteAmount');
result.push({
'id': id,
'symbol': base + '/' + quote,
'base': base,
'quote': quote,
'settle': undefined,
'baseId': baseId,
'quoteId': quoteId,
'settleId': undefined,
'type': 'spot',
'spot': true,
'margin': isMarginTradingAllowed,
'swap': false,
'future': false,
'option': false,
'active': active,
'contract': false,
'linear': undefined,
'inverse': undefined,
'taker': takerCommission,
'maker': makerCommission,
'contractSize': undefined,
'expiry': undefined,
'expiryDatetime': undefined,
'strike': undefined,
'optionType': undefined,
'precision': {
'amount': thi