UNPKG

@jalmonter/ccxt

Version:

A JavaScript / TypeScript / Python / C# / PHP cryptocurrency trading library with support for 130+ exchanges

1,109 lines (1,107 loc) 192 kB
'use strict'; var bitmart$1 = require('./abstract/bitmart.js'); var errors = require('./base/errors.js'); var Precise = require('./base/Precise.js'); var number = require('./base/functions/number.js'); var sha256 = require('./static_dependencies/noble-hashes/sha256.js'); // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- /** * @class bitmart * @augments Exchange */ class bitmart extends bitmart$1 { describe() { return this.deepExtend(super.describe(), { 'id': 'bitmart', 'name': 'BitMart', 'countries': ['US', 'CN', 'HK', 'KR'], // 150 per 5 seconds = 30 per second // rateLimit = 1000ms / 30 ~= 33.334 'rateLimit': 33.34, 'version': 'v2', 'certified': true, 'pro': true, 'has': { 'CORS': undefined, 'spot': true, 'margin': true, 'swap': true, 'future': false, 'option': false, 'borrowCrossMargin': false, 'borrowIsolatedMargin': true, 'cancelAllOrders': true, 'cancelOrder': true, 'cancelOrders': false, 'createMarketBuyOrderWithCost': true, 'createMarketOrderWithCost': false, 'createMarketSellOrderWithCost': false, 'createOrder': true, 'createPostOnlyOrder': true, 'createStopLimitOrder': false, 'createStopMarketOrder': false, 'createStopOrder': false, 'fetchBalance': true, 'fetchBorrowInterest': true, 'fetchBorrowRateHistories': false, 'fetchBorrowRateHistory': false, 'fetchCanceledOrders': true, 'fetchClosedOrders': true, 'fetchCrossBorrowRate': false, 'fetchCrossBorrowRates': false, 'fetchCurrencies': true, 'fetchDeposit': true, 'fetchDepositAddress': true, 'fetchDepositAddresses': false, 'fetchDepositAddressesByNetwork': false, 'fetchDeposits': true, 'fetchDepositWithdrawFee': true, 'fetchDepositWithdrawFees': false, 'fetchFundingHistory': undefined, 'fetchFundingRate': true, 'fetchFundingRateHistory': false, 'fetchFundingRates': false, 'fetchIsolatedBorrowRate': true, 'fetchIsolatedBorrowRates': true, 'fetchLiquidations': false, 'fetchMarginMode': false, 'fetchMarkets': true, 'fetchMyLiquidations': true, 'fetchMyTrades': true, 'fetchOHLCV': true, 'fetchOpenInterest': true, 'fetchOpenInterestHistory': false, 'fetchOpenOrders': true, 'fetchOrder': true, 'fetchOrderBook': true, 'fetchOrders': false, 'fetchOrderTrades': true, 'fetchPosition': true, 'fetchPositionMode': false, 'fetchPositions': true, 'fetchStatus': true, 'fetchTicker': true, 'fetchTickers': true, 'fetchTime': true, 'fetchTrades': true, 'fetchTradingFee': true, 'fetchTradingFees': false, 'fetchTransactionFee': true, 'fetchTransactionFees': false, 'fetchTransfer': false, 'fetchTransfers': true, 'fetchWithdrawAddressesByNetwork': false, 'fetchWithdrawal': true, 'fetchWithdrawals': true, 'reduceMargin': false, 'repayCrossMargin': false, 'repayIsolatedMargin': true, 'setLeverage': true, 'setMarginMode': false, 'transfer': true, 'withdraw': true, }, 'hostname': 'bitmart.com', 'urls': { 'logo': 'https://user-images.githubusercontent.com/1294454/129991357-8f47464b-d0f4-41d6-8a82-34122f0d1398.jpg', 'api': { 'rest': 'https://api-cloud.{hostname}', // bitmart.info for Hong Kong users }, 'www': 'https://www.bitmart.com/', 'doc': 'https://developer-pro.bitmart.com/', 'referral': { 'url': 'http://www.bitmart.com/?r=rQCFLh', 'discount': 0.3, }, 'fees': 'https://www.bitmart.com/fee/en', }, 'requiredCredentials': { 'apiKey': true, 'secret': true, 'uid': true, }, 'api': { 'public': { 'get': { 'system/time': 3, 'system/service': 3, // spot markets 'spot/v1/currencies': 7.5, 'spot/v1/symbols': 7.5, 'spot/v1/symbols/details': 5, 'spot/quotation/v3/tickers': 6, 'spot/quotation/v3/ticker': 4, 'spot/quotation/v3/lite-klines': 5, 'spot/quotation/v3/klines': 7, 'spot/quotation/v3/books': 4, 'spot/quotation/v3/trades': 4, 'spot/v1/ticker': 5, 'spot/v2/ticker': 30, 'spot/v1/ticker_detail': 5, 'spot/v1/steps': 30, 'spot/v1/symbols/kline': 6, 'spot/v1/symbols/book': 5, 'spot/v1/symbols/trades': 5, // contract markets 'contract/v1/tickers': 15, 'contract/public/details': 5, 'contract/public/depth': 5, 'contract/public/open-interest': 30, 'contract/public/funding-rate': 30, 'contract/public/kline': 6, 'account/v1/currencies': 30, }, }, 'private': { 'get': { // sub-account 'account/sub-account/v1/transfer-list': 7.5, 'account/sub-account/v1/transfer-history': 7.5, 'account/sub-account/main/v1/wallet': 5, 'account/sub-account/main/v1/subaccount-list': 7.5, 'account/contract/sub-account/main/v1/wallet': 5, 'account/contract/sub-account/main/v1/transfer-list': 7.5, 'account/contract/sub-account/v1/transfer-history': 7.5, // account 'account/v1/wallet': 5, 'account/v1/currencies': 30, 'spot/v1/wallet': 5, 'account/v1/deposit/address': 30, 'account/v1/withdraw/charge': 32, 'account/v2/deposit-withdraw/history': 7.5, 'account/v1/deposit-withdraw/detail': 7.5, // order 'spot/v1/order_detail': 1, 'spot/v2/orders': 5, 'spot/v1/trades': 5, // newer order endpoint 'spot/v2/trades': 5, 'spot/v3/orders': 5, 'spot/v2/order_detail': 1, // margin 'spot/v1/margin/isolated/borrow_record': 1, 'spot/v1/margin/isolated/repay_record': 1, 'spot/v1/margin/isolated/pairs': 30, 'spot/v1/margin/isolated/account': 5, 'spot/v1/trade_fee': 30, 'spot/v1/user_fee': 30, // broker 'spot/v1/broker/rebate': 1, // contract 'contract/private/assets-detail': 5, 'contract/private/order': 1.2, 'contract/private/order-history': 10, 'contract/private/position': 10, 'contract/private/get-open-orders': 1.2, 'contract/private/trades': 10, }, 'post': { // sub-account endpoints 'account/sub-account/main/v1/sub-to-main': 30, 'account/sub-account/sub/v1/sub-to-main': 30, 'account/sub-account/main/v1/main-to-sub': 30, 'account/sub-account/sub/v1/sub-to-sub': 30, 'account/sub-account/main/v1/sub-to-sub': 30, 'account/contract/sub-account/main/v1/sub-to-main': 7.5, 'account/contract/sub-account/main/v1/main-to-sub': 7.5, 'account/contract/sub-account/sub/v1/sub-to-main': 7.5, // account 'account/v1/withdraw/apply': 7.5, // transaction and trading 'spot/v1/submit_order': 1, 'spot/v1/batch_orders': 1, 'spot/v2/cancel_order': 1, 'spot/v1/cancel_orders': 15, 'spot/v4/query/order': 1, 'spot/v4/query/client-order': 1, 'spot/v4/query/open-orders': 5, 'spot/v4/query/history-orders': 5, 'spot/v4/query/trades': 5, 'spot/v4/query/order-trades': 5, // newer endpoint 'spot/v3/cancel_order': 1, 'spot/v2/batch_orders': 1, 'spot/v2/submit_order': 1, // margin 'spot/v1/margin/submit_order': 1, 'spot/v1/margin/isolated/borrow': 30, 'spot/v1/margin/isolated/repay': 30, 'spot/v1/margin/isolated/transfer': 30, // contract 'account/v1/transfer-contract-list': 60, 'account/v1/transfer-contract': 60, 'contract/private/submit-order': 2.5, 'contract/private/cancel-order': 1.5, 'contract/private/cancel-orders': 30, 'contract/private/submit-plan-order': 2.5, 'contract/private/cancel-plan-order': 1.5, 'contract/private/submit-leverage': 2.5, }, }, }, 'timeframes': { '1m': 1, '3m': 3, '5m': 5, '15m': 15, '30m': 30, '45m': 45, '1h': 60, '2h': 120, '3h': 180, '4h': 240, '1d': 1440, '1w': 10080, '1M': 43200, }, 'fees': { 'trading': { 'tierBased': true, 'percentage': true, 'taker': this.parseNumber('0.0025'), 'maker': this.parseNumber('0.0025'), 'tiers': { 'taker': [ [this.parseNumber('0'), this.parseNumber('0.0020')], [this.parseNumber('10'), this.parseNumber('0.18')], [this.parseNumber('50'), this.parseNumber('0.0016')], [this.parseNumber('250'), this.parseNumber('0.0014')], [this.parseNumber('1000'), this.parseNumber('0.0012')], [this.parseNumber('5000'), this.parseNumber('0.0010')], [this.parseNumber('25000'), this.parseNumber('0.0008')], [this.parseNumber('50000'), this.parseNumber('0.0006')], ], 'maker': [ [this.parseNumber('0'), this.parseNumber('0.001')], [this.parseNumber('10'), this.parseNumber('0.0009')], [this.parseNumber('50'), this.parseNumber('0.0008')], [this.parseNumber('250'), this.parseNumber('0.0007')], [this.parseNumber('1000'), this.parseNumber('0.0006')], [this.parseNumber('5000'), this.parseNumber('0.0005')], [this.parseNumber('25000'), this.parseNumber('0.0004')], [this.parseNumber('50000'), this.parseNumber('0.0003')], ], }, }, }, 'precisionMode': number.TICK_SIZE, 'exceptions': { 'exact': { // general errors '30000': errors.ExchangeError, '30001': errors.AuthenticationError, '30002': errors.AuthenticationError, '30003': errors.AccountSuspended, '30004': errors.AuthenticationError, '30005': errors.AuthenticationError, '30006': errors.AuthenticationError, '30007': errors.AuthenticationError, '30008': errors.AuthenticationError, '30010': errors.PermissionDenied, '30011': errors.AuthenticationError, '30012': errors.AuthenticationError, '30013': errors.RateLimitExceeded, '30014': errors.ExchangeNotAvailable, // funding account errors '60000': errors.BadRequest, '60001': errors.BadRequest, '60002': errors.BadRequest, '60003': errors.ExchangeError, '60004': errors.ExchangeError, '60005': errors.ExchangeError, '60006': errors.ExchangeError, '60007': errors.InvalidAddress, '60008': errors.InsufficientFunds, '60009': errors.ExchangeError, '60010': errors.ExchangeError, '60011': errors.InvalidAddress, '60012': errors.ExchangeError, '60020': errors.PermissionDenied, '60021': errors.PermissionDenied, '60022': errors.PermissionDenied, '60030': errors.BadRequest, '60031': errors.BadRequest, '60050': errors.ExchangeError, '60051': errors.ExchangeError, '61001': errors.InsufficientFunds, '61003': errors.BadRequest, // spot errors '50000': errors.BadRequest, '50001': errors.BadSymbol, '50002': errors.BadRequest, '50003': errors.BadRequest, '50004': errors.BadRequest, '50005': errors.OrderNotFound, '50006': errors.InvalidOrder, '50007': errors.InvalidOrder, '50008': errors.InvalidOrder, '50009': errors.InvalidOrder, '50010': errors.InvalidOrder, '50011': errors.InvalidOrder, '50012': errors.InvalidOrder, '50013': errors.InvalidOrder, '50014': errors.BadRequest, '50015': errors.BadRequest, '50016': errors.BadRequest, '50017': errors.BadRequest, '50018': errors.BadRequest, '50019': errors.BadRequest, '51004': errors.InsufficientFunds, // '50019': ExchangeError, // 400, Invalid status. validate status is [1=Failed, 2=Success, 3=Frozen Failed, 4=Frozen Success, 5=Partially Filled, 6=Fully Fulled, 7=Canceling, 8=Canceled '50020': errors.InsufficientFunds, '50021': errors.BadRequest, '50022': errors.ExchangeNotAvailable, '50023': errors.BadSymbol, '50029': errors.InvalidOrder, '50030': errors.InvalidOrder, '50032': errors.OrderNotFound, // below Error codes used interchangeably for both failed postOnly and IOC orders depending on market price and order side '50035': errors.InvalidOrder, '50034': errors.InvalidOrder, '51011': errors.InvalidOrder, '53000': errors.AccountSuspended, '53001': errors.AccountSuspended, '57001': errors.BadRequest, '58001': errors.BadRequest, '59001': errors.ExchangeError, '59002': errors.ExchangeError, // contract errors '40001': errors.ExchangeError, '40002': errors.ExchangeError, '40003': errors.ExchangeError, '40004': errors.ExchangeError, '40005': errors.ExchangeError, '40006': errors.PermissionDenied, '40007': errors.BadRequest, '40008': errors.InvalidNonce, '40009': errors.BadRequest, '40010': errors.BadRequest, '40011': errors.BadRequest, '40012': errors.ExchangeError, '40013': errors.ExchangeError, '40014': errors.BadSymbol, '40015': errors.BadSymbol, '40016': errors.InvalidOrder, '40017': errors.InvalidOrder, '40018': errors.InvalidOrder, '40019': errors.ExchangeError, '40020': errors.InvalidOrder, '40021': errors.ExchangeError, '40022': errors.ExchangeError, '40023': errors.ExchangeError, '40024': errors.ExchangeError, '40025': errors.ExchangeError, '40026': errors.ExchangeError, '40027': errors.InsufficientFunds, '40028': errors.PermissionDenied, '40029': errors.InvalidOrder, '40030': errors.InvalidOrder, '40031': errors.InvalidOrder, '40032': errors.InvalidOrder, '40033': errors.InvalidOrder, '40034': errors.BadSymbol, '53002': errors.PermissionDenied, '53003': errors.PermissionDenied, '53005': errors.PermissionDenied, '53006': errors.PermissionDenied, '53007': errors.PermissionDenied, '53008': errors.PermissionDenied, '53009': errors.PermissionDenied, '53010': errors.PermissionDenied, // 403 This account is restricted from borrowing }, 'broad': {}, }, 'commonCurrencies': { '$GM': 'GOLDMINER', '$HERO': 'Step Hero', '$PAC': 'PAC', 'BP': 'BEYOND', 'GDT': 'Gorilla Diamond', 'GLD': 'Goldario', 'MVP': 'MVP Coin', 'TRU': 'Truebit', // conflict with TrueFi }, 'options': { 'defaultNetwork': 'ERC20', 'defaultNetworks': { 'USDT': 'ERC20', }, 'networks': { 'ERC20': 'ERC20', 'BTC': 'BTC', 'TRC20': 'TRC20', // todo: should be TRX after unification // 'TRC20': [ 'TRC20', 'trc20', 'TRON' ], // todo: after unification i.e. TRON is returned from fetchDepositAddress // 'ERC20': [ 'ERC20', 'ERC-20', 'ERC20 ' ], // todo: after unification 'OMNI': 'OMNI', 'XLM': 'XLM', 'EOS': 'EOS', 'NEO': 'NEO', 'BTM': 'BTM', 'BCH': 'BCH', 'LTC': 'LTC', 'BSV': 'BSV', 'XRP': 'XRP', // 'VECHAIN': [ 'VET', 'Vechain' ], // todo: after unification 'PLEX': 'PLEX', 'XCH': 'XCH', // 'AVALANCHE_C': [ 'AVAX', 'AVAX-C' ], // todo: after unification 'NEAR': 'NEAR', 'FIO': 'FIO', 'SCRT': 'SCRT', 'IOTX': 'IOTX', 'SOL': 'SOL', 'ALGO': 'ALGO', 'ATOM': 'ATOM', 'DOT': 'DOT', 'ADA': 'ADA', 'DOGE': 'DOGE', 'XYM': 'XYM', 'GLMR': 'GLMR', 'MOVR': 'MOVR', 'ZIL': 'ZIL', 'INJ': 'INJ', 'KSM': 'KSM', 'ZEC': 'ZEC', 'NAS': 'NAS', // 'POLYGON': [ 'MATIC', 'Polygon', 'POLYGON' ], // todo: after unification 'HRC20': 'HECO', 'XDC': 'XDC', 'ONE': 'ONE', 'LAT': 'LAT', 'CSPR': 'Casper', 'ICP': 'Computer', 'XTZ': 'XTZ', 'MINA': 'MINA', // 'BEP20': [ 'BEP20', 'BSC_BNB', 'bep20' ], // todo: after unification 'THETA': 'THETA', 'AKT': 'AKT', 'AR': 'AR', 'CELO': 'CELO', 'FIL': 'FIL', 'NULS': 'NULS', 'ETC': 'ETC', 'DASH': 'DASH', 'DGB': 'DGB', 'BEP2': 'BEP2', 'GRIN': 'GRIN', 'WAVES': 'WAVES', 'ABBC': 'ABBC', 'ACA': 'ACA', 'QTUM': 'QTUM', 'PAC': 'PAC', // 'TERRACLASSIC': 'LUNC', // TBD // 'TERRA': 'Terra', // TBD // 'HEDERA': [ 'HBAR', 'Hedera', 'Hedera Mainnet' ], // todo: after unification 'TLOS': 'TLOS', 'KARDIA': 'KardiaChain', 'FUSE': 'FUSE', 'TRC10': 'TRC10', 'FIRO': 'FIRO', 'FTM': 'Fantom', // 'KLAYTN': [ 'klaytn', 'KLAY', 'Klaytn' ], // todo: after unification // 'ELROND': [ 'EGLD', 'Elrond eGold', 'MultiversX' ], // todo: after unification 'EVER': 'EVER', 'KAVA': 'KAVA', 'HYDRA': 'HYDRA', 'PLCU': 'PLCU', 'BRISE': 'BRISE', // 'CRC20': [ 'CRO', 'CRO_Chain' ], // todo: after unification // 'CONFLUX': [ 'CFX eSpace', 'CFX' ], // todo: after unification 'OPTIMISM': 'OPTIMISM', 'REEF': 'REEF', 'SYS': 'SYS', 'VITE': 'VITE', 'STX': 'STX', 'SXP': 'SXP', 'BITCI': 'BITCI', // 'ARBITRUM': [ 'ARBI', 'Arbitrum' ], // todo: after unification 'XRD': 'XRD', 'ASTR': 'ASTAR', 'ZEN': 'HORIZEN', 'LTO': 'LTO', 'ETHW': 'ETHW', 'ETHF': 'ETHF', 'IOST': 'IOST', // 'CHILIZ': [ 'CHZ', 'CHILIZ' ], // todo: after unification 'APT': 'APT', // 'FLOW': [ 'FLOW', 'Flow' ], // todo: after unification 'ONT': 'ONT', 'EVMOS': 'EVMOS', 'XMR': 'XMR', 'OASYS': 'OAS', 'OSMO': 'OSMO', 'OMAX': 'OMAX Chain', 'DESO': 'DESO', 'BFIC': 'BFIC', 'OHO': 'OHO', 'CS': 'CS', 'CHEQ': 'CHEQ', 'NODL': 'NODL', 'NEM': 'XEM', 'FRA': 'FRA', 'ERGO': 'ERG', // todo: below will be uncommented after unification // 'BITCOINHD': 'BHD', // 'CRUST': 'CRU', // 'MINTME': 'MINTME', // 'ZENITH': 'ZENITH', // 'ZENIQ': 'ZENIQ', // "ZEN-20" is different // 'BITCOINVAULT': 'BTCV', // 'MOBILECOIN': 'MBX', // 'PINETWORK': 'PI', // 'PI': 'PI', // 'REBUS': 'REBUS', // 'XODEX': 'XODEX', // 'ULTRONGLOW': 'UTG' // 'QIBLOCKCHAIN': 'QIE', // 'XIDEN': 'XDEN', // 'PHAETON': 'PHAE', // 'REDLIGHT': 'REDLC', // 'VERITISE': 'VTS', // 'VERIBLOCK': 'VBK', // 'RAMESTTA': 'RAMA', // 'BITICA': 'BDCC', // 'CROWNSOVEREIGN': 'CSOV', // 'DRAC': 'DRC20', // 'QCHAIN': 'QDT', // 'KINGARU': 'KRU', // 'PROOFOFMEMES': 'POM', // 'CUBE': 'CUBE', // 'CADUCEUS': 'CMP', // 'VEIL': 'VEIL', // 'ENERGYWEB': 'EWT', // 'CYPHERIUM': 'CPH', // 'LBRY': 'LBC', // 'ETHERCOIN': 'ETE', // undetermined chains: // LEX (for LexThum), TAYCAN (for TRICE), SFL (probably TAYCAN), OMNIA (for APEX), NAC (for NAC), KAG (Kinesis), CEM (crypto emergency), XVM (for Venidium), NEVM (for NEVM), IGT20 (for IGNITE), FILM (FILMCredits), CC (CloudCoin), MERGE (MERGE), LTNM (Bitcoin latinum), PLUGCN ( PlugChain), DINGO (dingo), LED (LEDGIS), AVAT (AVAT), VSOL (Vsolidus), EPIC (EPIC cash), NFC (netflowcoin), mrx (Metrix Coin), Idena (idena network), PKT (PKT Cash), BondDex (BondDex), XBN (XBN), KALAM (Kalamint), REV (RChain), KRC20 (MyDeFiPet), ARC20 (Hurricane Token), GMD (Coop network), BERS (Berith), ZEBI (Zebi), BRC (Baer Chain), DAPS (DAPS Coin), APL (Gold Secured Currency), NDAU (NDAU), WICC (WICC), UPG (Unipay God), TSL (TreasureSL), MXW (Maxonrow), CLC (Cifculation), SMH (SMH Coin), XIN (CPCoin), RDD (ReddCoin), OK (Okcash), KAR (KAR), CCX (ConcealNetwork), }, 'defaultType': 'spot', 'fetchBalance': { 'type': 'spot', // 'spot', 'swap', 'account' }, 'accountsByType': { 'spot': 'spot', 'swap': 'swap', }, 'createMarketBuyOrderRequiresPrice': true, 'brokerId': 'CCXTxBitmart000', }, }); } async fetchTime(params = {}) { /** * @method * @name bitmart#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 response = await this.publicGetSystemTime(params); // // { // "message":"OK", // "code":1000, // "trace":"c4e5e5b7-fe9f-4191-89f7-53f6c5bf9030", // "data":{ // "server_time":1599843709578 // } // } // const data = this.safeValue(response, 'data', {}); return this.safeInteger(data, 'server_time'); } async fetchStatus(params = {}) { /** * @method * @name bitmart#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 options = this.safeValue(this.options, 'fetchStatus', {}); const defaultType = this.safeString(this.options, 'defaultType'); let type = this.safeString(options, 'type', defaultType); type = this.safeString(params, 'type', type); params = this.omit(params, 'type'); const response = await this.publicGetSystemService(params); // // { // "message": "OK", // "code": 1000, // "trace": "1d3f28b0-763e-4f78-90c4-5e3ad19dc595", // "data": { // "service": [ // { // "title": "Spot API Stop", // "service_type": "spot", // "status": 2, // "start_time": 1648639069125, // "end_time": 1648639069125 // }, // { // "title": "Contract API Stop", // "service_type": "contract", // "status": 2, // "start_time": 1648639069125, // "end_time": 1648639069125 // } // ] // } // } // const data = this.safeValue(response, 'data', {}); const services = this.safeValue(data, 'service', []); const servicesByType = this.indexBy(services, 'service_type'); if (type === 'swap') { type = 'contract'; } const service = this.safeValue(servicesByType, type); let status = undefined; let eta = undefined; if (service !== undefined) { const statusCode = this.safeInteger(service, 'status'); if (statusCode === 2) { status = 'ok'; } else { status = 'maintenance'; eta = this.safeInteger(service, 'end_time'); } } return { 'status': status, 'updated': undefined, 'eta': eta, 'url': undefined, 'info': response, }; } async fetchSpotMarkets(params = {}) { const response = await this.publicGetSpotV1SymbolsDetails(params); // // { // "message":"OK", // "code":1000, // "trace":"a67c9146-086d-4d3f-9897-5636a9bb26e1", // "data":{ // "symbols":[ // { // "symbol": "BTC_USDT", // "symbol_id": 53, // "base_currency": "BTC", // "quote_currency": "USDT", // "base_min_size": "0.000010000000000000000000000000", // "base_max_size": "100000000.000000000000000000000000000000", // "price_min_precision": -1, // "price_max_precision": 2, // "quote_increment": "0.00001", // Api docs says "The minimum order quantity is also the minimum order quantity increment", however I think they mistakenly use the term 'order quantity' // "expiration": "NA", // "min_buy_amount": "5.000000000000000000000000000000", // "min_sell_amount": "5.000000000000000000000000000000", // "trade_status": "trading" // }, // ] // } // } // const data = this.safeValue(response, 'data', {}); const symbols = this.safeValue(data, 'symbols', []); const result = []; for (let i = 0; i < symbols.length; i++) { const market = symbols[i]; const id = this.safeString(market, 'symbol'); const numericId = this.safeInteger(market, 'symbol_id'); const baseId = this.safeString(market, 'base_currency'); const quoteId = this.safeString(market, 'quote_currency'); const base = this.safeCurrencyCode(baseId); const quote = this.safeCurrencyCode(quoteId); const symbol = base + '/' + quote; const minBuyCost = this.safeString(market, 'min_buy_amount'); const minSellCost = this.safeString(market, 'min_sell_amount'); const minCost = Precise["default"].stringMax(minBuyCost, minSellCost); const baseMinSize = this.safeNumber(market, 'base_min_size'); result.push({ 'id': id, 'numericId': numericId, 'symbol': symbol, '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': true, 'contract': false, 'linear': undefined, 'inverse': undefined, 'contractSize': undefined, 'expiry': undefined, 'expiryDatetime': undefined, 'strike': undefined, 'optionType': undefined, 'precision': { 'amount': baseMinSize, 'price': this.parseNumber(this.parsePrecision(this.safeString(market, 'price_max_precision'))), }, 'limits': { 'leverage': { 'min': undefined, 'max': undefined, }, 'amount': { 'min': baseMinSize, 'max': this.safeNumber(market, 'base_max_size'), }, 'price': { 'min': undefined, 'max': undefined, }, 'cost': { 'min': this.parseNumber(minCost), 'max': undefined, }, }, 'created': undefined, 'info': market, }); } return result; } async fetchContractMarkets(params = {}) { const response = await this.publicGetContractPublicDetails(params); // // { // "code": 1000, // "message": "Ok", // "trace": "9b92a999-9463-4c96-91a4-93ad1cad0d72", // "data": { // "symbols": [{ // "symbol": "BTCUSDT", // "product_type": 1, // "open_timestamp": 1594080000, // "expire_timestamp": 0, // "settle_timestamp": 0, // "base_currency": "BTC", // "quote_currency": "USDT", // "last_price": "23920", // "volume_24h": "18969368", // "turnover_24h": "458933659.7858", // "index_price": "23945.25191635", // "index_name": "BTCUSDT", // "contract_size": "0.001", // "min_leverage": "1", // "max_leverage": "100", // "price_precision": "0.1", // "vol_precision": "1", // "max_volume": "500000", // "min_volume": "1" // }, // ... // ] // } // } // const data = this.safeValue(response, 'data', {}); const symbols = this.safeValue(data, 'symbols', []); const result = []; for (let i = 0; i < symbols.length; i++) { const market = symbols[i]; const id = this.safeString(market, 'symbol'); const baseId = this.safeString(market, 'base_currency'); const quoteId = this.safeString(market, 'quote_currency'); const base = this.safeCurrencyCode(baseId); const quote = this.safeCurrencyCode(quoteId); const settleId = 'USDT'; // this is bitmart's ID for usdt const settle = this.safeCurrencyCode(settleId); const symbol = base + '/' + quote + ':' + settle; const productType = this.safeInteger(market, 'product_type'); const isSwap = (productType === 1); const isFutures = (productType === 2); let expiry = this.safeInteger(market, 'expire_timestamp'); if (!isFutures && (expiry === 0)) { expiry = undefined; } result.push({ 'id': id, 'numericId': undefined, 'symbol': symbol, 'base': base, 'quote': quote, 'settle': settle, 'baseId': baseId, 'quoteId': quoteId, 'settleId': settleId, 'type': isSwap ? 'swap' : 'future', 'spot': false, 'margin': false, 'swap': isSwap, 'future': isFutures, 'option': false, 'active': true, 'contract': true, 'linear': true, 'inverse': false, 'contractSize': this.safeNumber(market, 'contract_size'), 'expiry': expiry, 'expiryDatetime': this.iso8601(expiry), 'strike': undefined, 'optionType': undefined, 'precision': { 'amount': this.safeNumber(market, 'vol_precision'), 'price': this.safeNumber(market, 'price_precision'), }, 'limits': { 'leverage': { 'min': this.safeNumber(market, 'min_leverage'), 'max': this.safeNumber(market, 'max_leverage'), }, 'amount': { 'min': this.safeNumber(market, 'min_volume'), 'max': this.safeNumber(market, 'max_volume'), }, 'price': { 'min': undefined, 'max': undefined, }, 'cost': { 'min': undefined, 'max': undefined, }, }, 'created': this.safeInteger(market, 'open_timestamp'), 'info': market, }); } return result; } async fetchMarkets(params = {}) { /** * @method * @name bitmart#fetchMarkets * @description retrieves data on all markets for bitmart * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object[]} an array of objects representing market data */ const spot = await this.fetchSpotMarkets(params); const contract = await this.fetchContractMarkets(params); return this.arrayConcat(spot, contract); } async fetchCurrencies(params = {}) { /** * @method * @name bitmart#fetchCurrencies * @description fetches all available currencies on an exchange * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} an associative dictionary of currencies */ const response = await this.publicGetSpotV1Currencies(params); // // { // "message":"OK", // "code":1000, // "trace":"8c768b3c-025f-413f-bec5-6d6411d46883", // "data":{ // "currencies":[ // {"currency":"MATIC","name":"Matic Network","withdraw_enabled":true,"deposit_enabled":true}, // {"currency":"KTN","name":"Kasoutuuka News","withdraw_enabled":true,"deposit_enabled":false}, // {"currency":"BRT","name":"Berith","withdraw_enabled":true,"deposit_enabled":true}, // ] // } // } // const data = this.safeValue(response, 'data', {}); const currencies = this.safeValue(data, 'currencies', []); const result = {}; for (let i = 0; i < currencies.length; i++) { const currency = currencies[i]; const id = this.safeString(currency, 'id'); const code = this.safeCurrencyCode(id); const name = this.safeString(currency, 'name'); const withdrawEnabled = this.safeValue(currency, 'withdraw_enabled'); const depositEnabled = this.safeValue(currency, 'deposit_enabled'); const active = withdrawEnabled && depositEnabled; result[code] = { 'id': id, 'code': code, 'name': name, 'info': currency, 'active': active, 'deposit': depositEnabled, 'withdraw': withdrawEnabled, 'fee': undefined, 'precision': undefined, 'limits': { 'amount': { 'min': undefined, 'max': undefined }, 'withdraw': { 'min': undefined, 'max': undefined }, }, }; } return result; } async fetchTransactionFee(code, params = {}) { /** * @method * @name bitmart#fetchTransactionFee * @deprecated * @description please use fetchDepositWithdrawFee instead * @param {string} code unified currency code * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a [fee structure]{@link https://docs.ccxt.com/#/?id=fee-structure} */ await this.loadMarkets(); const currency = this.currency(code); const request = { 'currency': currency['id'], }; const response = await this.privateGetAccountV1WithdrawCharge(this.extend(request, params)); // // { // "message": "OK", // "code": "1000", // "trace": "3ecc0adf-91bd-4de7-aca1-886c1122f54f", // "data": { // "today_available_withdraw_BTC": "100.0000", // "min_withdraw": "0.005", // "withdraw_precision": "8", // "withdraw_fee": "0.000500000000000000000000000000" // } // } // const data = response['data']; const withdrawFees = {}; withdrawFees[code] = this.safeNumber(data, 'withdraw_fee'); return { 'info': response, 'withdraw': withdrawFees, 'deposit': {}, }; } parseDepositWithdrawFee(fee, currency = undefined) { // // { // "today_available_withdraw_BTC": "100.0000", // "min_withdraw": "0.005", // "withdraw_precision": "8", // "withdraw_fee": "0.000500000000000000000000000000" // } // return { 'info': fee, 'withdraw': { 'fee': this.safeNumber(fee, 'withdraw_fee'), 'percentage': undefined, }, 'deposit': { 'fee': undefined, 'percentage': undefined, }, 'networks': {}, }; } async fetchDepositWithdrawFee(code, params = {}) { /** * @method * @name bitmart#fetchDepositWithdrawFee * @description fetch the fee for deposits and withdrawals * @param {string} code unified currency code * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a [fee structure]{@link https://docs.ccxt.com/#/?id=fee-structure} */ await this.loadMarkets(); const currency = this.currency(code); const request = { 'currency': currency['id'], }; const response = await this.privateGetAccountV1WithdrawCharge(this.extend(request, params)); // // { // "message": "OK", // "code": "1000", // "trace": "3ecc0adf-91bd-4de7-aca1-886c1122f54f", // "data": { // "today_available_withdraw_BTC": "100.0000", // "min_withdraw": "0.005", // "withdraw_precision": "8", // "withdraw_fee": "0.000500000000000000000000000000" // } // } // const data = response['data']; return this.parseDepositWithdrawFee(data); } parseTicker(ticker, market = undefined) { // // spot // // { // "symbol": "SOLAR_USDT", // "last_price": "0.020342", // "quote_volume_24h": "56817.811802", // "base_volume_24h": "2172060", // "high_24h": "0.256000", // "low_24h": "0.016980", // "open_24h": "0.022309", // "close_24h": "0.020342", // "best_ask": "0.020389", // "best_ask_size": "339.000000000000000000000000000000", // "best_bid": "0.020342", // "best_bid_size": "3369.000000000000000000000000000000", // "fluctuation": "-0.0882", // "url": "https://www.bitmart.com/trade?symbol=SOLAR_USDT", // "timestamp": 1667403439367 // } // // swap // // { // "contract_symbol":"DOGEUSDT", // "last_price":"0.130340", // "index_price":"0.13048245", // "last_funding_rate":"0.00002287", // "price_change_percent_24h":"-2.074", // "volume_24h":"113705028.59482228", // "url":"https://futures.bitmart.com/en?symbol=DOGEUSDT", // "high_price":"0.134520", // "low_price":"0.128570", // "legal_coin_price":"0.1302699" // } // const timestamp = this.safeInteger(ticker, 'timestamp', this.milliseconds()); const marketId = this.safeString2(ticker, 'symbol', 'contract_symbol'); market = this.safeMarket(marketId, market); const symbol = market['symbol']; const last = this.safeString2(ticker, 'close_24h', 'last_price'); let percentage = this.safeString(ticker, 'price_change_percent_24h'); if (percentage === undefined) { const percentageRaw = this.safeString(ticker, 'fluctuation'); if ((percentageRaw !== undefined) && (percentageRaw !== '0')) { // a few tickers show strictly '0' in fluctuation field const direction = percentageRaw[0]; percentage = direction + Precise["default"].stringMul(percentageRaw.replace(direction, ''), '100'); } else if (percentageRaw === '0') { percentage = '0'; } } const baseVolume = this.safeString(ticker, 'base_volume_24h'); let quoteVolume = this.safeString(ticker, 'quote_volume_24h'); quoteVolume = this.safeString(ticker, 'volume_24h', quoteVolume); const average = this.safeString2(ticker, 'avg_price', 'index_price'); const high = this.safeString2(ticker, 'high_24h', 'high_price'); const low = this.safeString2(ticker, 'low_24h', 'low_price'); return this.safeTicker({ 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601(timestamp), 'high': high, 'low': low, 'bid': this.safeString(ticker, 'best_bid'), 'bidVolume': this.safeString(ticker, 'b