UNPKG

@proton/ccxt

Version:

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

1,128 lines (1,126 loc) 135 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 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': undefined, 'future': false, 'option': undefined, 'borrowMargin': true, 'cancelAllOrders': true, 'cancelOrder': true, 'cancelOrders': false, 'createOrder': true, 'createPostOnlyOrder': true, 'createStopLimitOrder': false, 'createStopMarketOrder': false, 'createStopOrder': false, 'fetchBalance': true, 'fetchBorrowInterest': true, 'fetchBorrowRate': true, 'fetchBorrowRateHistories': false, 'fetchBorrowRateHistory': false, 'fetchBorrowRates': true, 'fetchCanceledOrders': true, 'fetchClosedOrders': true, 'fetchCurrencies': true, 'fetchDeposit': true, 'fetchDepositAddress': true, 'fetchDepositAddresses': false, 'fetchDepositAddressesByNetwork': false, 'fetchDeposits': true, 'fetchDepositWithdrawFee': true, 'fetchDepositWithdrawFees': false, 'fetchFundingHistory': undefined, 'fetchMarginMode': false, 'fetchMarkets': true, 'fetchMyTrades': true, 'fetchOHLCV': true, 'fetchOpenOrders': true, 'fetchOrder': true, 'fetchOrderBook': true, 'fetchOrders': false, 'fetchOrderTrades': true, 'fetchPositionMode': false, 'fetchStatus': true, 'fetchTicker': true, 'fetchTickers': true, 'fetchTime': true, 'fetchTrades': true, 'fetchTradingFee': true, 'fetchTradingFees': false, 'fetchTransactionFee': true, 'fetchTransactionFees': false, 'fetchTransfer': false, 'fetchTransfers': false, 'fetchWithdrawAddressesByNetwork': false, 'fetchWithdrawal': true, 'fetchWithdrawals': true, 'reduceMargin': false, 'repayMargin': true, 'setLeverage': false, '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/v1/ticker': 5, 'spot/v2/ticker': 5, 'spot/v1/steps': 30, 'spot/v1/symbols/kline': 5, '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': 5, '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 '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': 1, 'spot/v1/margin/isolated/account': 6, 'spot/v1/trade_fee': 6, 'spot/v1/user_fee': 6, // contract 'contract/private/assets-detail': 5, 'contract/private/order': 2, 'contract/private/order-history': 10, 'contract/private/position': 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 '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, // 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': 6, 'spot/v1/margin/isolated/repay': 6, 'spot/v1/margin/isolated/transfer': 6, // contract 'contract/private/trades': 10, }, }, }, '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, // 403, Your account has not yet completed the kyc advanced certification, please complete first }, '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': { 'networks': { 'TRX': 'TRC20', 'ETH': 'ERC20', }, 'defaultNetworks': { 'USDT': 'ERC20', }, 'defaultType': 'spot', 'fetchBalance': { 'type': 'spot', // 'spot', 'swap', 'account' }, 'accountsByType': { 'spot': 'spot', }, 'createMarketBuyOrderRequiresPrice': true, }, }); } 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 bitmart 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 bitmart 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, }, }, '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, }, }, '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 bitmart 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 * @description *DEPRECATED* please use fetchDepositWithdrawFee instead * @param {string} code unified currency code * @param {object} params extra parameters specific to the bitmart 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 bitmart 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, 'best_bid_size'), 'ask': this.safeString(ticker, 'best_ask'), 'askVolume': this.safeString(ticker, 'best_ask_size'), 'vwap': undefined, 'open': this.safeString(ticker, 'open_24h'), 'close': last, 'last': last, 'previousClose': undefined, 'change': undefined, 'percentage': percentage, 'average': average, 'baseVolume': baseVolume, 'quoteVolume': quoteVolume, 'info': ticker, }, market); } async fetchTicker(symbol, params = {}) { /** * @method * @name bitmart#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 bitmart 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 = {}; let method = undefined; if (market['swap']) { method = 'publicGetContractV1Tickers'; request['contract_symbol'] = market['id']; } else if (market['spot']) { method = 'publicGetSpotV1Ticker'; request['symbol'] = market['id']; } const response = await this[method](this.extend(request, params)); // // spot // // { // "message":"OK", // "code":1000, // "trace":"6aa5b923-2f57-46e3-876d-feca190e0b82", // "data":{ // "tickers":[ // { // "symbol":"ETH_BTC", // "last_price":"0.036037", // "quote_volume_24h":"4380.6660000000", // "base_volume_24h":"159.3582006712", // "high_24h":"0.036972", // "low_24h":"0.035524", // "open_24h":"0.036561", // "close_24h":"0.036037", // "best_ask":"0.036077", // "best_ask_size":"9.9500", // "best_bid":"0.035983", // "best_bid_size":"4.2792", // "fluctuation":"-0.0143", // "url":"https://www.bitmart.com/trade?symbol=ETH_BTC" // } // ] // } // } // // swap // // { // "message":"OK", // "code":1000, // "trace":"4a0ebceb-d3f7-45a3-8feb-f61e230e24cd", // "data":{ // "tickers":[ // { // "contract_symbol":"DOGEUSDT", // "last_price":"0.130180", // "index_price":"0.13028635", // "last_funding_rate":"0.00002025", // "price_change_percent_24h":"-2.326", // "volume_24h":"116789313.01797258", // "url":"https://futures.bitmart.com/en?symbol=DOGEUSDT", // "high_price":"0.134520", // "low_price":"0.128570", // "legal_coin_price":"0.13017401" // } // ] // } // } // const data = this.safeValue(response, 'data', {}); const tickers = this.safeValue(data, 'tickers', []); // fails in naming for contract tickers 'contract_symbol' let tickersById = undefined; if (market['spot']) { tickersById = this.indexBy(tickers, 'symbol'); } else if (market['swap']) { tickersById = this.indexBy(tickers, 'contract_symbol'); } const ticker = this.safeValue(tickersById, market['id']); return this.parseTicker(ticker, market); } async fetchTickers(symbols = undefined, params = {}) { /** * @method * @name bitmart#fetchTickers * @description fetches price tickers for multiple markets, statistical calculations with the information calculated over the past 24 hours each market * @see https://developer-pro.bitmart.com/en/spot/#get-ticker-of-all-pairs-v2 * @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 bitmart api endpoint * @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure} */ await this.loadMarkets(); symbols = this.marketSymbols(symbols); let type = undefined; let market = undefined; if (symbols !== undefined) { const symbol = this.safeValue(symbols, 0); market = this.market(symbol); } [type, params] = this.handleMarketTypeAndParams('fetchTickers', market, params); const method = this.getSupportedMapping(type, { 'spot': 'publicGetSpotV2Ticker', 'swap': 'publicGetContractV1Tickers', }); const response = await this[method](params); const data = this.safeValue(response, 'data', {}); const tickers = this.safeValue(data, 'tickers', []); const result = {}; for (let i = 0; i < tickers.length; i++) { const ticker = this.parseTicker(tickers[i]); const symbol = ticker['symbol']; result[symbol] = ticker; } return this.filterByArray(result, 'symbol', symbols); } async fetchOrderBook(symbol, limit = undefined, params = {}) { /** * @method * @name bitmart#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 bitmart 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); if (!market['spot']) { throw new errors.NotSupported(this.id + ' fetchOrderBook() does not support ' + market['type'] + ' markets, only spot markets are accepted'); } const request = { 'symbol': market['id'], }; if (limit !== undefined) { request['size'] = limit; // default 50, max 200 } // request['precision'] = 4; // optional price precision / depth level whose range is defined in symbol details const response = await this.publicGetSpotV1SymbolsBook(this.extend(request, params)); // // spot // // { // "message":"OK", // "code":1000, // "trace":"8254f8fc-431d-404f-ad9a-e716339f66c7", // "data":{ // "buys":[ // {"amount":"4.7091","total":"4.71","price":"0.034047","count":"1"}, // {"amount":"5.7439","total":"10.45","price":"0.034039","count":"1"}, // {"amount":"2.5249","total":"12.98","price":"0.032937","count":"1"}, // ], // "sells":[ // {"amount":"41.4365","total":"41.44","price":"0.034174","count":"1"}, // {"amount":"4.2317","total":"45.67","price":"0.034183","count":"1"}, // {"amount":"0.3000","total":"45.97","price":"0.034240","count":"1"}, // ] // } // } // const data = this.safeValue(response, 'data', {}); const timestamp = this.safeInteger(data, 'timestamp'); return this.parseOrderBook(data, symbol, timestamp, 'buys', 'sells', 'price', 'amount'); } parseTrade(trade, market = undefined) { // // public fetchTrades spot ( amount = count * price ) // // { // "amount": "818.94", // "order_time": "1637601839035", // ETH/USDT // "price": "4221.99", // "count": "0.19397", // "type": "buy" // } // // private fetchMyTrades spot // // { // "detail_id":256348632, // "order_id":2147484350, // "symbol":"BTC_USDT", // "create_time":1590462303000, // "side":"buy", // "fees":"0.00001350", // "fee_coin_name":"BTC", // "notional":"88.00000000", // "price_avg":"8800.00", // "size":"0.01000", // "exec_type":"M" // } // const id = this.safeString(trade, 'detail_id'); const timestamp = this.safeInteger2(trade, 'order_time', 'create_time'); const type = undefined; const side = this.safeStringLower2(trade, 'type', 'side'); let takerOrMaker = undefined; const execType = this.safeString(trade, 'exec_type'); if (execType !== undefined) { takerOrMaker = (execType === 'M') ? 'maker' : 'taker'; } let priceString = this.safeString(trade, 'price'); priceString = this.safeString(trade, 'price_avg', priceString); let amountString = this.safeString(trade, 'count'); amountString = this.safeString(trade, 'size', amountString); const costString = this.safeString2(trade, 'amount', 'notional'); const orderId = this.safeString(trade, 'order_id'); const marketId = this.safeString(trade, 'sy