ccxt
Version:
1,109 lines (1,106 loc) • 252 kB
JavaScript
// ----------------------------------------------------------------------------
// 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
// EDIT THE CORRESPONDENT .ts FILE INSTEAD
// ---------------------------------------------------------------------------
import Exchange from './abstract/bitmart.js';
import { AuthenticationError, ExchangeNotAvailable, OnMaintenance, AccountSuspended, PermissionDenied, RateLimitExceeded, InvalidNonce, InvalidAddress, ArgumentsRequired, ExchangeError, InvalidOrder, InsufficientFunds, BadRequest, OrderNotFound, BadSymbol, NotSupported, NetworkError } from './base/errors.js';
import { Precise } from './base/Precise.js';
import { TICK_SIZE, TRUNCATE } from './base/functions/number.js';
import { sha256 } from './static_dependencies/noble-hashes/sha256.js';
// ---------------------------------------------------------------------------
/**
* @class bitmart
* @augments Exchange
*/
export default class bitmart extends Exchange {
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': true,
'createMarketBuyOrderWithCost': true,
'createMarketOrderWithCost': false,
'createMarketSellOrderWithCost': false,
'createOrder': true,
'createOrders': true,
'createPostOnlyOrder': true,
'createReduceOnlyOrder': true,
'createStopLimitOrder': false,
'createStopMarketOrder': false,
'createStopOrder': false,
'createTrailingPercentOrder': true,
'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': true,
'fetchFundingRate': true,
'fetchFundingRateHistory': false,
'fetchFundingRates': false,
'fetchIsolatedBorrowRate': true,
'fetchIsolatedBorrowRates': true,
'fetchLedger': true,
'fetchLiquidations': false,
'fetchMarginMode': false,
'fetchMarkets': true,
'fetchMarkOHLCV': true,
'fetchMyLiquidations': true,
'fetchMyTrades': true,
'fetchOHLCV': true,
'fetchOpenInterest': true,
'fetchOpenInterestHistory': false,
'fetchOpenOrders': true,
'fetchOrder': true,
'fetchOrderBook': true,
'fetchOrders': false,
'fetchOrderTrades': true,
'fetchPosition': true,
'fetchPositionMode': true,
'fetchPositions': true,
'fetchStatus': true,
'fetchTicker': true,
'fetchTickers': true,
'fetchTime': true,
'fetchTrades': true,
'fetchTradingFee': true,
'fetchTradingFees': false,
'fetchTransactionFee': true,
'fetchTransactionFees': false,
'fetchTransfer': false,
'fetchTransfers': true,
'fetchWithdrawAddresses': true,
'fetchWithdrawAddressesByNetwork': false,
'fetchWithdrawal': true,
'fetchWithdrawals': true,
'reduceMargin': false,
'repayCrossMargin': false,
'repayIsolatedMargin': true,
'setLeverage': true,
'setMarginMode': false,
'setPositionMode': true,
'transfer': true,
'withdraw': true,
},
'hostname': 'bitmart.com',
'urls': {
'logo': 'https://github.com/user-attachments/assets/0623e9c4-f50e-48c9-82bd-65c3908c3a14',
'api': {
'spot': 'https://api-cloud.{hostname}',
'swap': 'https://api-cloud-v2.{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/funding-rate-history': 30,
'contract/public/kline': 6,
'account/v1/currencies': 30,
'contract/public/markprice-kline': 5, // 6 times per 1 second
},
},
'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,
'account/v1/withdraw/address/list': 30,
// order
'spot/v1/order_detail': 1,
'spot/v2/orders': 5,
'spot/v1/trades': 5,
// newer order endpoint
'spot/v2/trades': 4,
'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/position-v2': 10,
'contract/private/get-open-orders': 1.2,
'contract/private/current-plan-order': 1.2,
'contract/private/trades': 10,
'contract/private/position-risk': 10,
'contract/private/affilate/rebate-list': 10,
'contract/private/affilate/trade-list': 10,
'contract/private/transaction-history': 10,
'contract/private/get-position-mode': 1,
},
'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,
'spot/v4/cancel_orders': 3,
'spot/v4/cancel_all': 90,
'spot/v4/batch_orders': 3,
// newer endpoint
'spot/v3/cancel_order': 1,
'spot/v2/batch_orders': 1,
'spot/v2/submit_order': 1,
// margin
'spot/v1/margin/submit_order': 1.5,
'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,
'contract/private/submit-tp-sl-order': 2.5,
'contract/private/modify-plan-order': 2.5,
'contract/private/modify-preset-plan-order': 2.5,
'contract/private/modify-limit-order': 2.5,
'contract/private/modify-tp-sl-order': 2.5,
'contract/private/submit-trail-order': 2.5,
'contract/private/cancel-trail-order': 1.5,
'contract/private/set-position-mode': 1,
},
},
},
'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.0040'),
'maker': this.parseNumber('0.0035'),
'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': TICK_SIZE,
'exceptions': {
'exact': {
// general errors
'30000': ExchangeError,
'30001': AuthenticationError,
'30002': AuthenticationError,
'30003': AccountSuspended,
'30004': AuthenticationError,
'30005': AuthenticationError,
'30006': AuthenticationError,
'30007': AuthenticationError,
'30008': AuthenticationError,
'30010': PermissionDenied,
'30011': AuthenticationError,
'30012': AuthenticationError,
'30013': RateLimitExceeded,
'30014': ExchangeNotAvailable,
'30016': OnMaintenance,
'30017': RateLimitExceeded,
'30018': BadRequest,
'30019': PermissionDenied,
// funding account & sub account errors
'60000': BadRequest,
'60001': BadRequest,
'60002': BadRequest,
'60003': ExchangeError,
'60004': ExchangeError,
'60005': ExchangeError,
'60006': ExchangeError,
'60007': InvalidAddress,
'60008': InsufficientFunds,
'60009': ExchangeError,
'60010': ExchangeError,
'60011': InvalidAddress,
'60012': ExchangeError,
'60020': PermissionDenied,
'60021': PermissionDenied,
'60022': PermissionDenied,
'60026': PermissionDenied,
'60027': PermissionDenied,
'60028': AccountSuspended,
'60029': AccountSuspended,
'60030': BadRequest,
'60031': BadRequest,
'60050': ExchangeError,
'60051': ExchangeError,
'61001': InsufficientFunds,
'61003': BadRequest,
'61004': BadRequest,
'61005': BadRequest,
'61006': NotSupported,
'61007': ExchangeError,
'61008': ExchangeError,
// spot public errors
'70000': ExchangeError,
'70001': BadRequest,
'70002': BadSymbol,
'70003': NetworkError,
'71001': BadRequest,
'71002': BadRequest,
'71003': BadRequest,
'71004': BadRequest,
'71005': BadRequest,
// spot & margin errors
'50000': BadRequest,
'50001': BadSymbol,
'50002': BadRequest,
'50003': BadRequest,
'50004': BadRequest,
'50005': OrderNotFound,
'50006': InvalidOrder,
'50007': InvalidOrder,
'50008': InvalidOrder,
'50009': InvalidOrder,
'50010': InvalidOrder,
'50011': InvalidOrder,
'50012': InvalidOrder,
'50013': InvalidOrder,
'50014': BadRequest,
'50015': BadRequest,
'50016': BadRequest,
'50017': BadRequest,
'50018': BadRequest,
'50019': ExchangeError,
'50020': InsufficientFunds,
'50021': BadRequest,
'50022': ExchangeNotAvailable,
'50023': BadSymbol,
'50024': BadRequest,
'50025': BadRequest,
'50026': BadRequest,
'50027': BadRequest,
'50028': BadRequest,
'50029': InvalidOrder,
'50030': OrderNotFound,
'50031': OrderNotFound,
'50032': OrderNotFound,
'50033': InvalidOrder,
// below Error codes used interchangeably for both failed postOnly and IOC orders depending on market price and order side
'50034': InvalidOrder,
'50035': InvalidOrder,
'50036': ExchangeError,
'50037': BadRequest,
'50038': BadRequest,
'50039': BadRequest,
'50040': BadSymbol,
'50041': ExchangeError,
'50042': BadRequest,
'51000': BadSymbol,
'51001': ExchangeError,
'51002': ExchangeError,
'51003': ExchangeError,
'51004': InsufficientFunds,
'51005': InvalidOrder,
'51006': InvalidOrder,
'51007': BadRequest,
'51008': ExchangeError,
'51009': InvalidOrder,
'51010': InvalidOrder,
'51011': InvalidOrder,
'51012': InvalidOrder,
'51013': InvalidOrder,
'51014': InvalidOrder,
'51015': InvalidOrder,
'52000': BadRequest,
'52001': BadRequest,
'52002': BadRequest,
'52003': BadRequest,
'52004': BadRequest,
'53000': AccountSuspended,
'53001': AccountSuspended,
'53002': PermissionDenied,
'53003': PermissionDenied,
'53005': PermissionDenied,
'53006': PermissionDenied,
'53007': PermissionDenied,
'53008': PermissionDenied,
'53009': PermissionDenied,
'53010': PermissionDenied,
'57001': BadRequest,
'58001': BadRequest,
'59001': ExchangeError,
'59002': ExchangeError,
'59003': ExchangeError,
'59004': ExchangeError,
'59005': PermissionDenied,
'59006': ExchangeError,
'59007': ExchangeError,
'59008': ExchangeError,
'59009': ExchangeError,
'59010': InsufficientFunds,
'59011': ExchangeError,
// contract errors
'40001': ExchangeError,
'40002': ExchangeError,
'40003': ExchangeError,
'40004': ExchangeError,
'40005': ExchangeError,
'40006': PermissionDenied,
'40007': BadRequest,
'40008': InvalidNonce,
'40009': BadRequest,
'40010': BadRequest,
'40011': BadRequest,
'40012': ExchangeError,
'40013': ExchangeError,
'40014': BadSymbol,
'40015': BadSymbol,
'40016': InvalidOrder,
'40017': InvalidOrder,
'40018': InvalidOrder,
'40019': ExchangeError,
'40020': InvalidOrder,
'40021': ExchangeError,
'40022': ExchangeError,
'40023': ExchangeError,
'40024': ExchangeError,
'40025': ExchangeError,
'40026': ExchangeError,
'40027': InsufficientFunds,
'40028': PermissionDenied,
'40029': InvalidOrder,
'40030': InvalidOrder,
'40031': InvalidOrder,
'40032': InvalidOrder,
'40033': InvalidOrder,
'40034': BadSymbol,
'40035': OrderNotFound,
'40036': InvalidOrder,
'40037': OrderNotFound,
'40038': BadRequest,
'40039': BadRequest,
'40040': InvalidOrder,
'40041': InvalidOrder,
'40042': InvalidOrder,
'40043': InvalidOrder,
'40044': InvalidOrder,
'40045': InvalidOrder,
'40046': PermissionDenied,
'40047': PermissionDenied,
'40048': InvalidOrder,
'40049': InvalidOrder,
'40050': InvalidOrder, // 403, Client OrderId duplicated with existing orders
},
'broad': {
'You contract account available balance not enough': InsufficientFunds,
'you contract account available balance not enough': InsufficientFunds,
},
},
'commonCurrencies': {
'$GM': 'GOLDMINER',
'$HERO': 'Step Hero',
'$PAC': 'PAC',
'BP': 'BEYOND',
'GDT': 'Gorilla Diamond',
'GLD': 'Goldario',
'MVP': 'MVP Coin',
'TRU': 'Truebit', // conflict with TrueFi
},
'options': {
'defaultNetworks': {
'USDT': 'TRC20',
'BTC': 'BTC',
'ETH': 'ERC20',
},
'timeDifference': 0,
'adjustForTimeDifference': false,
'networks': {
'ERC20': 'ERC20',
'SOL': 'SOL',
'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',
'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',
'HRC20': 'HECO',
'XDC': 'XDC',
'ONE': 'ONE',
'LAT': 'LAT',
'CSPR': 'Casper',
'ICP': 'Computer',
'XTZ': 'XTZ',
'MINA': 'MINA',
'BEP20': 'BSC_BNB',
'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),
},
'networksById': {
'ETH': 'ERC20',
'Ethereum': 'ERC20',
'USDT': 'OMNI',
'Bitcoin': 'BTC',
},
'defaultType': 'spot',
'fetchBalance': {
'type': 'spot', // 'spot', 'swap', 'account'
},
'accountsByType': {
'spot': 'spot',
'swap': 'swap',
},
'createMarketBuyOrderRequiresPrice': true,
'brokerId': 'CCXTxBitmart000',
},
'features': {
'default': {
'sandbox': false,
'createOrder': {
'marginMode': true,
'triggerPrice': false,
'triggerPriceType': undefined,
'triggerDirection': false,
'stopLossPrice': false,
'takeProfitPrice': false,
'attachedStopLossTakeProfit': undefined,
'timeInForce': {
'IOC': true,
'FOK': false,
'PO': true,
'GTD': false,
},
'hedged': false,
'trailing': false,
'marketBuyRequiresPrice': false,
'marketBuyByCost': true,
'leverage': true,
'selfTradePrevention': false,
'iceberg': false,
},
'createOrders': {
'max': 10,
},
'fetchMyTrades': {
'marginMode': true,
'limit': 200,
'daysBack': undefined,
'untilDays': 99999,
'symbolRequired': false,
},
'fetchOrder': {
'marginMode': false,
'trigger': false,
'trailing': false,
'symbolRequired': false,
},
'fetchOpenOrders': {
'marginMode': true,
'limit': 200,
'trigger': false,
'trailing': false,
'symbolRequired': false,
},
'fetchOrders': undefined,
'fetchClosedOrders': {
'marginMode': true,
'limit': 200,
'daysBack': undefined,
'daysBackCanceled': undefined,
'untilDays': undefined,
'trigger': false,
'trailing': false,
'symbolRequired': false,
},
'fetchOHLCV': {
'limit': 1000, // variable timespans for recent endpoint, 200 for historical
},
},
'forDerivatives': {
'extends': 'default',
'createOrder': {
'marginMode': true,
'triggerPrice': true,
'triggerPriceType': {
'last': true,
'mark': true,
'index': false,
},
'triggerDirection': true,
'stopLossPrice': true,
'takeProfitPrice': true,
'attachedStopLossTakeProfit': {
'triggerPriceType': {
'last': true,
'mark': true,
'index': false,
},
'price': false,
},
'timeInForce': {
'IOC': true,
'FOK': true,
'PO': true,
'GTD': false,
},
'hedged': false,
'trailing': true,
'marketBuyRequiresPrice': true,
'marketBuyByCost': true,
// exchange-supported features
// 'selfTradePrevention': true,
// 'twap': false,
// 'iceberg': false,
// 'oco': false,
},
'fetchMyTrades': {
'marginMode': true,
'limit': undefined,
'daysBack': undefined,
'untilDays': 99999,
},
'fetchOrder': {
'marginMode': false,
'trigger': false,
'trailing': true,
},
'fetchOpenOrders': {
'marginMode': false,
'limit': 100,
'trigger': true,
'trailing': false,
},
'fetchClosedOrders': {
'marginMode': true,
'limit': 200,
'daysBack': undefined,
'daysBackCanceled': undefined,
'untilDays': undefined,
'trigger': false,
'trailing': false,
},
'fetchOHLCV': {
'limit': 500,
},
},
'spot': {
'extends': 'default',
},
'swap': {
'linear': {
'extends': 'forDerivatives',
},
'inverse': {
'extends': 'forDerivatives',
},
},
'future': {
'linear': undefined,
'inverse': undefined,
},
},
});
}
/**
* @method
* @name bitmart#fetchTime
* @description fetches the current integer timestamp in milliseconds from the exchange server
* @see https://developer-pro.bitmart.com/en/spot/#get-system-time
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {int} the current integer timestamp in milliseconds from the exchange server
*/
async fetchTime(params = {}) {
const response = await this.publicGetSystemTime(params);
//
// {
// "message":"OK",
// "code":1000,
// "trace":"c4e5e5b7-fe9f-4191-89f7-53f6c5bf9030",
// "data":{
// "server_time":1599843709578
// }
// }
//
const data = this.safeDict(response, 'data', {});
return this.safeInteger(data, 'server_time');
}
/**
* @method
* @name bitmart#fetchStatus
* @description the latest known information on the availability of the exchange API
* @see https://developer-pro.bitmart.com/en/spot/#get-system-service-status
* @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}
*/
async fetchStatus(params = {}) {
const options = this.safeDict(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.safeDict(response, 'data', {});
const services = this.safeList(data, 'service', []);
const servicesByType = this.indexBy(services, 'service_type');
if (type === 'swap') {
type = 'contract';
}
const service = this.safeString(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.safeDict(response, 'data', {});
const symbols = this.safeList(data, 'symbols', []);
const result = [];
const fees = this.fees['trading'];
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.stringMax(minBuyCost, minSellCost);
const baseMinSize = this.safeNumber(market, 'base_min_size');
result.push(this.safeMarketStructure({
'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,
'maker': fees['maker'],
'taker': fees['taker'],
'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",
// "data": {
// "symbols": [
// {
// "symbol": "BTCUSDT",
// "product_type": 1,
// "open_timestamp": 1645977600000,
// "expire_timestamp": 0,
// "settle_timestamp": 0,
// "base_currency": "BTC",
// "quote_currency": "USDT",
// "last_price": "63547.4",
// "volume_24h": "110938430",
// "turnover_24h": "7004836342.6944",
// "index_price": "63587.85404255",
// "index_name": "BTCUSDT",
// "contract_size": "0.001",
// "min_leverage": "1",
// "max_leverage": "100",
// "price_precision": "0.1",
// "vol_precision": "1",
// "max_volume": "1000000",
// "min_volume": "1",
// "funding_rate": "0.0000801",
// "expected_funding_rate": "-0.0000035",
// "open_interest": "278214",
// "open_interest_value": "17555316.9355496",
// "high_24h": "64109.4",
// "low_24h": "61857.6",
// "change_24h": "0.0239264900886327",
// "funding_time": 1726819200000
// },
// ]
// }
// }
//
const data = this.safeDict(response, 'data', {});
const symbols = this.safeList(data, 'symbols', []);
const result = [];
const fees = this.fees['trading'];
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