UNPKG

ccxt

Version:

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

1,118 lines (1,115 loc) • 145 kB
'use strict'; var okcoin$1 = require('./abstract/okcoin.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 okcoin * @augments Exchange */ class okcoin extends okcoin$1 { describe() { return this.deepExtend(super.describe(), { 'id': 'okcoin', 'name': 'OKCoin', 'countries': ['CN', 'US'], 'version': 'v5', // cheapest endpoint is 100 requests per 2 seconds // 50 requests per second => 1000 / 50 = 20ms 'rateLimit': 20, 'pro': true, 'has': { 'CORS': undefined, 'spot': true, 'margin': false, 'swap': false, 'future': true, 'option': undefined, 'cancelOrder': true, 'createMarketBuyOrderWithCost': true, 'createMarketOrderWithCost': false, 'createMarketSellOrderWithCost': false, 'createOrder': true, 'createStopOrder': true, 'createTriggerOrder': true, 'fetchBalance': true, 'fetchBorrowInterest': false, 'fetchBorrowRate': false, 'fetchBorrowRateHistories': false, 'fetchBorrowRateHistory': false, 'fetchBorrowRates': false, 'fetchBorrowRatesPerSymbol': false, 'fetchClosedOrders': true, 'fetchCurrencies': true, 'fetchDepositAddress': true, 'fetchDepositAddresses': false, 'fetchDepositAddressesByNetwork': false, 'fetchDeposits': true, 'fetchFundingHistory': false, 'fetchFundingRate': false, 'fetchFundingRateHistory': false, 'fetchFundingRates': false, 'fetchLedger': true, 'fetchMarkets': true, 'fetchMyTrades': true, 'fetchOHLCV': true, 'fetchOpenOrders': true, 'fetchOrder': true, 'fetchOrderBook': true, 'fetchOrders': undefined, 'fetchOrderTrades': true, 'fetchPosition': false, 'fetchPositions': false, 'fetchTicker': true, 'fetchTickers': true, 'fetchTime': true, 'fetchTrades': true, 'fetchTransactions': undefined, 'fetchWithdrawals': true, 'reduceMargin': false, 'repayCrossMargin': false, 'repayIsolatedMargin': false, 'setMargin': false, 'transfer': true, 'withdraw': true, }, 'timeframes': { '1m': '1m', '3m': '3m', '5m': '5m', '15m': '15m', '30m': '30m', '1h': '1H', '2h': '2H', '4h': '4H', '6h': '6H', '12h': '12H', '1d': '1D', '1w': '1W', '1M': '1M', '3M': '3M', }, 'hostname': 'okcoin.com', 'urls': { 'logo': 'https://user-images.githubusercontent.com/51840849/87295551-102fbf00-c50e-11ea-90a9-462eebba5829.jpg', 'api': { 'rest': 'https://www.{hostname}', }, 'www': 'https://www.okcoin.com', 'doc': 'https://www.okcoin.com/docs/en/', 'fees': 'https://www.okcoin.com/coin-fees', 'referral': 'https://www.okcoin.com/account/register?flag=activity&channelId=600001513', 'test': { 'rest': 'https://testnet.okex.com', }, }, 'api': { 'public': { 'get': { 'market/tickers': 1, 'market/ticker': 1, 'market/books': 1 / 2, 'market/candles': 1 / 2, 'market/history-candles': 1 / 2, 'market/trades': 1 / 5, 'market/history-trades': 2, 'market/platform-24-volume': 10, 'market/open-oracle': 50, 'market/exchange-rate': 20, 'public/instruments': 1, 'public/time': 2, }, }, 'private': { 'get': { // trade 'trade/order': 1 / 3, 'trade/orders-pending': 1 / 3, 'trade/orders-history': 1 / 2, 'trade/orders-history-archive': 1 / 2, 'trade/fills': 1 / 3, 'trade/fills-history': 2.2, 'trade/fills-archive': 2, 'trade/order-algo': 1, 'trade/orders-algo-pending': 1, 'trade/orders-algo-history': 1, // rfq 'otc/rfq/trade': 4, 'otc/rfq/history': 4, // account 'account/balance': 2, 'account/bills': 5 / 3, 'account/bills-archive': 5 / 3, 'account/config': 4, 'account/max-size': 4, 'account/max-avail-size': 4, 'account/trade-fee': 4, 'account/max-withdrawal': 4, // funding or assets 'asset/currencies': 5 / 3, 'asset/balances': 5 / 3, 'asset/asset-valuation': 10, 'asset/transfer-state': 10, 'asset/bills': 5 / 3, 'asset/deposit-lightning': 5, 'asset/deposit-address': 5 / 3, 'asset/deposit-history': 5 / 3, 'asset/withdrawal-history': 5 / 3, 'asset/deposit-withdraw-status': 20, // fiat 'fiat/deposit-history': 5 / 3, 'fiat-withdraw-history': 5 / 3, 'fiat-channel': 5 / 3, // sub-account 'users/subaccount/list': 10, 'users/subaccount/apiKey': 10, 'account/subaccount/balances': 10, 'asset/subaccount/balances': 10, 'asset/subaccount/bills': 10, }, 'post': { // trade 'trade/order': 1 / 3, 'trade/batch-orders': 1 / 15, 'trade/cancel-order': 1 / 3, 'trade/cancel-batch-orders': 1 / 15, 'trade/amend-order': 1 / 3, 'trade/amend-batch-orders': 1 / 150, 'trade/order-algo': 1, 'trade/cancel-algos': 1, 'trade/cancel-advance-algos': 1, // rfq 'otc/rfq/quote': 4, 'otc/rfq/trade': 4, // funding 'asset/transfer': 4, 'asset/withdrawal': 4, 'asset/withdrawal-lightning': 4, 'asset/withdrawal-cancel': 4, // fiat 'fiat/deposit': 5 / 3, 'fiat/cancel-deposit': 5 / 3, 'fiat/withdrawal': 5 / 3, 'fiat/cancel-withdrawal': 5 / 3, // sub-account 'asset/subaccount/transfer': 10, }, }, }, 'features': { 'spot': { 'sandbox': false, 'createOrder': { 'marginMode': true, 'triggerPrice': true, 'triggerDirection': true, 'triggerPriceType': { 'last': true, 'mark': false, 'index': false, }, 'stopLossPrice': true, 'takeProfitPrice': true, 'attachedStopLossTakeProfit': { 'triggerPriceType': { 'last': true, 'mark': false, 'index': false, }, 'price': true, }, 'timeInForce': { 'IOC': true, 'FOK': true, 'PO': true, 'GTD': false, }, 'hedged': false, 'trailing': true, 'leverage': false, 'marketBuyByCost': true, 'marketBuyRequiresPrice': true, 'selfTradePrevention': false, 'iceberg': true, // todo }, 'createOrders': undefined, 'fetchMyTrades': { 'marginMode': false, 'limit': 100, 'daysBack': 90, 'untilDays': 90, 'symbolRequired': false, }, 'fetchOrder': { 'marginMode': false, 'trigger': true, 'trailing': true, 'symbolRequired': true, }, 'fetchOpenOrders': { 'marginMode': false, 'limit': 100, 'trigger': true, 'trailing': true, 'symbolRequired': false, }, 'fetchOrders': undefined, 'fetchClosedOrders': { 'marginMode': false, 'limit': 100, 'daysBack': 90, 'daysBackCanceled': 1 / 12, 'untilDays': 90, 'trigger': true, 'trailing': true, 'symbolRequired': false, }, 'fetchOHLCV': { 'limit': 100, // 300 is only possible for 'recent' 1440 candles, which does not make much sense }, }, 'swap': { 'linear': undefined, 'inverse': undefined, }, 'future': { 'linear': undefined, 'inverse': undefined, }, }, 'fees': { 'trading': { 'taker': 0.002, 'maker': 0.001, }, 'spot': { 'taker': 0.0015, 'maker': 0.0010, }, }, 'requiredCredentials': { 'apiKey': true, 'secret': true, 'password': true, }, 'exceptions': { 'exact': { // Public error codes from 50000-53999 // General Class '1': errors.ExchangeError, '2': errors.ExchangeError, '50000': errors.BadRequest, '50001': errors.OnMaintenance, '50002': errors.BadRequest, '50004': errors.RequestTimeout, '50005': errors.ExchangeNotAvailable, '50006': errors.BadRequest, '50007': errors.AccountSuspended, '50008': errors.AuthenticationError, '50009': errors.AccountSuspended, '50010': errors.ExchangeError, '50011': errors.RateLimitExceeded, '50012': errors.ExchangeError, '50013': errors.ExchangeNotAvailable, '50014': errors.BadRequest, '50015': errors.ExchangeError, '50016': errors.ExchangeError, '50017': errors.ExchangeError, '50018': errors.ExchangeError, '50019': errors.ExchangeError, '50020': errors.ExchangeError, '50021': errors.ExchangeError, '50022': errors.ExchangeError, '50023': errors.ExchangeError, '50024': errors.BadRequest, '50025': errors.ExchangeError, '50026': errors.ExchangeNotAvailable, '50027': errors.PermissionDenied, '50028': errors.ExchangeError, '50029': errors.ExchangeError, '50030': errors.PermissionDenied, '50032': errors.AccountSuspended, '50033': errors.AccountSuspended, '50035': errors.BadRequest, '50036': errors.BadRequest, '50037': errors.BadRequest, '50038': errors.ExchangeError, '50039': errors.ExchangeError, '50041': errors.ExchangeError, '50044': errors.BadRequest, // API Class '50100': errors.ExchangeError, '50101': errors.AuthenticationError, '50102': errors.InvalidNonce, '50103': errors.AuthenticationError, '50104': errors.AuthenticationError, '50105': errors.AuthenticationError, '50106': errors.AuthenticationError, '50107': errors.AuthenticationError, '50108': errors.ExchangeError, '50109': errors.ExchangeError, '50110': errors.PermissionDenied, '50111': errors.AuthenticationError, '50112': errors.AuthenticationError, '50113': errors.AuthenticationError, '50114': errors.AuthenticationError, '50115': errors.BadRequest, // Trade Class '51000': errors.BadRequest, '51001': errors.BadSymbol, '51002': errors.BadSymbol, '51003': errors.BadRequest, '51004': errors.InvalidOrder, '51005': errors.InvalidOrder, '51006': errors.InvalidOrder, '51007': errors.InvalidOrder, '51008': errors.InsufficientFunds, '51009': errors.AccountSuspended, '51010': errors.AccountNotEnabled, '51011': errors.InvalidOrder, '51012': errors.BadSymbol, '51014': errors.BadSymbol, '51015': errors.BadSymbol, '51016': errors.InvalidOrder, '51017': errors.ExchangeError, '51018': errors.ExchangeError, '51019': errors.ExchangeError, '51020': errors.InvalidOrder, '51023': errors.ExchangeError, '51024': errors.AccountSuspended, '51025': errors.ExchangeError, '51026': errors.BadSymbol, '51030': errors.InvalidOrder, '51031': errors.InvalidOrder, '51032': errors.InvalidOrder, '51033': errors.InvalidOrder, '51037': errors.InvalidOrder, '51038': errors.InvalidOrder, '51044': errors.InvalidOrder, '51046': errors.InvalidOrder, '51047': errors.InvalidOrder, '51048': errors.InvalidOrder, '51049': errors.InvalidOrder, '51050': errors.InvalidOrder, '51051': errors.InvalidOrder, '51052': errors.InvalidOrder, '51053': errors.InvalidOrder, '51054': errors.BadRequest, '51056': errors.InvalidOrder, '51058': errors.InvalidOrder, '51059': errors.InvalidOrder, '51100': errors.InvalidOrder, '51102': errors.InvalidOrder, '51103': errors.InvalidOrder, '51108': errors.InvalidOrder, '51109': errors.InvalidOrder, '51110': errors.InvalidOrder, '51111': errors.BadRequest, '51112': errors.InvalidOrder, '51113': errors.RateLimitExceeded, '51115': errors.InvalidOrder, '51116': errors.InvalidOrder, '51117': errors.InvalidOrder, '51118': errors.InvalidOrder, '51119': errors.InsufficientFunds, '51120': errors.InvalidOrder, '51121': errors.InvalidOrder, '51122': errors.InvalidOrder, '51124': errors.InvalidOrder, '51125': errors.InvalidOrder, '51126': errors.InvalidOrder, '51127': errors.InsufficientFunds, '51128': errors.InvalidOrder, '51129': errors.InvalidOrder, '51130': errors.BadSymbol, '51131': errors.InsufficientFunds, '51132': errors.InvalidOrder, '51133': errors.InvalidOrder, '51134': errors.InvalidOrder, '51135': errors.InvalidOrder, '51136': errors.InvalidOrder, '51137': errors.InvalidOrder, '51138': errors.InvalidOrder, '51139': errors.InvalidOrder, '51156': errors.BadRequest, '51159': errors.BadRequest, '51162': errors.InvalidOrder, '51163': errors.InvalidOrder, '51166': errors.InvalidOrder, '51174': errors.InvalidOrder, '51201': errors.InvalidOrder, '51202': errors.InvalidOrder, '51203': errors.InvalidOrder, '51204': errors.InvalidOrder, '51205': errors.InvalidOrder, '51250': errors.InvalidOrder, '51251': errors.InvalidOrder, '51252': errors.InvalidOrder, '51253': errors.InvalidOrder, '51254': errors.InvalidOrder, '51255': errors.InvalidOrder, '51256': errors.InvalidOrder, '51257': errors.InvalidOrder, '51258': errors.InvalidOrder, '51259': errors.InvalidOrder, '51260': errors.InvalidOrder, '51261': errors.InvalidOrder, '51262': errors.InvalidOrder, '51263': errors.InvalidOrder, '51264': errors.InvalidOrder, '51265': errors.InvalidOrder, '51267': errors.InvalidOrder, '51268': errors.InvalidOrder, '51269': errors.InvalidOrder, '51270': errors.InvalidOrder, '51271': errors.InvalidOrder, '51272': errors.InvalidOrder, '51273': errors.InvalidOrder, '51274': errors.InvalidOrder, '51275': errors.InvalidOrder, '51276': errors.InvalidOrder, '51277': errors.InvalidOrder, '51278': errors.InvalidOrder, '51279': errors.InvalidOrder, '51280': errors.InvalidOrder, '51321': errors.InvalidOrder, '51322': errors.InvalidOrder, '51323': errors.BadRequest, '51324': errors.BadRequest, '51325': errors.InvalidOrder, '51327': errors.InvalidOrder, '51328': errors.InvalidOrder, '51329': errors.InvalidOrder, '51330': errors.InvalidOrder, '51400': errors.OrderNotFound, '51401': errors.OrderNotFound, '51402': errors.OrderNotFound, '51403': errors.InvalidOrder, '51404': errors.InvalidOrder, '51405': errors.ExchangeError, '51406': errors.ExchangeError, '51407': errors.BadRequest, '51408': errors.ExchangeError, '51409': errors.ExchangeError, '51410': errors.CancelPending, '51500': errors.ExchangeError, '51501': errors.ExchangeError, '51502': errors.InsufficientFunds, '51503': errors.ExchangeError, '51506': errors.ExchangeError, '51508': errors.ExchangeError, '51509': errors.ExchangeError, '51510': errors.ExchangeError, '51511': errors.ExchangeError, '51600': errors.ExchangeError, '51601': errors.ExchangeError, '51602': errors.ExchangeError, '51603': errors.OrderNotFound, '51732': errors.AuthenticationError, '51733': errors.AuthenticationError, '51734': errors.AuthenticationError, '51735': errors.ExchangeError, '51736': errors.InsufficientFunds, // Data class '52000': errors.ExchangeError, // SPOT/MARGIN error codes 54000-54999 '54000': errors.ExchangeError, '54001': errors.ExchangeError, // FUNDING error codes 58000-58999 '58000': errors.ExchangeError, '58001': errors.AuthenticationError, '58002': errors.PermissionDenied, '58003': errors.ExchangeError, '58004': errors.AccountSuspended, '58005': errors.ExchangeError, '58006': errors.ExchangeError, '58007': errors.ExchangeError, '58100': errors.ExchangeError, '58101': errors.AccountSuspended, '58102': errors.RateLimitExceeded, '58103': errors.ExchangeError, '58104': errors.ExchangeError, '58105': errors.ExchangeError, '58106': errors.ExchangeError, '58107': errors.ExchangeError, '58108': errors.ExchangeError, '58109': errors.ExchangeError, '58110': errors.ExchangeError, '58111': errors.ExchangeError, '58112': errors.ExchangeError, '58114': errors.ExchangeError, '58115': errors.ExchangeError, '58116': errors.ExchangeError, '58117': errors.ExchangeError, '58125': errors.BadRequest, '58126': errors.BadRequest, '58127': errors.BadRequest, '58128': errors.BadRequest, '58200': errors.ExchangeError, '58201': errors.ExchangeError, '58202': errors.ExchangeError, '58203': errors.InvalidAddress, '58204': errors.AccountSuspended, '58205': errors.ExchangeError, '58206': errors.ExchangeError, '58207': errors.InvalidAddress, '58208': errors.ExchangeError, '58209': errors.ExchangeError, '58210': errors.ExchangeError, '58211': errors.ExchangeError, '58212': errors.ExchangeError, '58213': errors.AuthenticationError, '58221': errors.BadRequest, '58222': errors.BadRequest, '58224': errors.BadRequest, '58227': errors.BadRequest, '58228': errors.BadRequest, '58229': errors.InsufficientFunds, '58300': errors.ExchangeError, '58350': errors.InsufficientFunds, // Account error codes 59000-59999 '59000': errors.ExchangeError, '59001': errors.ExchangeError, '59100': errors.ExchangeError, '59101': errors.ExchangeError, '59102': errors.ExchangeError, '59103': errors.InsufficientFunds, '59104': errors.ExchangeError, '59105': errors.ExchangeError, '59106': errors.ExchangeError, '59107': errors.ExchangeError, '59108': errors.InsufficientFunds, '59109': errors.ExchangeError, '59128': errors.InvalidOrder, '59200': errors.InsufficientFunds, '59201': errors.InsufficientFunds, '59216': errors.BadRequest, '59300': errors.ExchangeError, '59301': errors.ExchangeError, '59313': errors.ExchangeError, '59401': errors.ExchangeError, '59500': errors.ExchangeError, '59501': errors.ExchangeError, '59502': errors.ExchangeError, '59503': errors.ExchangeError, '59504': errors.ExchangeError, '59505': errors.ExchangeError, '59506': errors.ExchangeError, '59507': errors.ExchangeError, '59508': errors.AccountSuspended, // WebSocket error Codes from 60000-63999 '60001': errors.AuthenticationError, '60002': errors.AuthenticationError, '60003': errors.AuthenticationError, '60004': errors.AuthenticationError, '60005': errors.AuthenticationError, '60006': errors.InvalidNonce, '60007': errors.AuthenticationError, '60008': errors.AuthenticationError, '60009': errors.AuthenticationError, '60010': errors.AuthenticationError, '60011': errors.AuthenticationError, '60012': errors.BadRequest, '60013': errors.BadRequest, '60014': errors.RateLimitExceeded, '60015': errors.NetworkError, '60016': errors.ExchangeNotAvailable, '60017': errors.BadRequest, '60018': errors.BadRequest, '60019': errors.BadRequest, '63999': errors.ExchangeError, '70010': errors.BadRequest, '70013': errors.BadRequest, '70016': errors.BadRequest, // Please specify your instrument settings for at least one instType. }, 'broad': { 'Internal Server Error': errors.ExchangeNotAvailable, 'server error': errors.ExchangeNotAvailable, // {"code":500,"data":{},"detailMsg":"","error_code":"500","error_message":"server error 1236805249","msg":"server error 1236805249"} }, }, 'precisionMode': number.TICK_SIZE, 'options': { 'fetchOHLCV': { 'type': 'Candles', // Candles or HistoryCandles }, 'createMarketBuyOrderRequiresPrice': true, 'fetchMarkets': ['spot'], 'defaultType': 'spot', 'accountsByType': { 'classic': '1', 'spot': '1', 'funding': '6', 'main': '6', 'unified': '18', }, 'accountsById': { '1': 'spot', '6': 'funding', '18': 'unified', }, 'auth': { 'time': 'public', 'currencies': 'private', 'instruments': 'public', 'rate': 'public', '{instrument_id}/constituents': 'public', }, 'warnOnFetchCurrenciesWithoutAuthorization': false, 'defaultNetwork': 'ERC20', 'networks': { 'ERC20': 'Ethereum', 'BTC': 'Bitcoin', 'OMNI': 'Omni', 'TRC20': 'TRON', }, }, 'commonCurrencies': { // OKEX refers to ERC20 version of Aeternity (AEToken) 'AE': 'AET', 'BOX': 'DefiBox', 'HOT': 'Hydro Protocol', 'HSR': 'HC', 'MAG': 'Maggie', 'SBTC': 'Super Bitcoin', 'TRADE': 'Unitrade', 'YOYO': 'YOYOW', 'WIN': 'WinToken', // https://github.com/ccxt/ccxt/issues/5701 }, }); } /** * @method * @name okcoin#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 */ async fetchTime(params = {}) { const response = await this.publicGetPublicTime(params); // // { // "code": "0", // "data": // [ // { // "ts": "1737379360033" // } // ], // "msg": "" // } // const data = this.safeList(response, 'data'); const timestamp = this.safeDict(data, 0); return this.safeInteger(timestamp, 'ts'); } /** * @method * @name okcoin#fetchMarkets * @see https://www.okcoin.com/docs-v5/en/#rest-api-public-data-get-instruments * @description retrieves data on all markets for okcoin * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object[]} an array of objects representing market data */ async fetchMarkets(params = {}) { const request = { 'instType': 'SPOT', }; const response = await this.publicGetPublicInstruments(this.extend(request, params)); const markets = this.safeValue(response, 'data', []); return this.parseMarkets(markets); } parseMarket(market) { // // spot markets // // { // "base_currency": "EOS", // "instrument_id": "EOS-OKB", // "min_size": "0.01", // "quote_currency": "OKB", // "size_increment": "0.000001", // "tick_size": "0.0001" // } // const id = this.safeString(market, 'instId'); let type = this.safeStringLower(market, 'instType'); if (type === 'futures') { type = 'future'; } const spot = (type === 'spot'); const future = (type === 'future'); const swap = (type === 'swap'); const option = (type === 'option'); const contract = swap || future || option; const baseId = this.safeString(market, 'baseCcy'); const quoteId = this.safeString(market, 'quoteCcy'); const base = this.safeCurrencyCode(baseId); const quote = this.safeCurrencyCode(quoteId); const symbol = base + '/' + quote; const tickSize = this.safeString(market, 'tickSz'); const fees = this.safeValue2(this.fees, type, 'trading', {}); let maxLeverage = this.safeString(market, 'lever', '1'); maxLeverage = Precise["default"].stringMax(maxLeverage, '1'); const maxSpotCost = this.safeNumber(market, 'maxMktSz'); return this.extend(fees, { 'id': id, 'symbol': symbol, 'base': base, 'quote': quote, 'settle': undefined, 'baseId': baseId, 'quoteId': quoteId, 'settleId': undefined, 'type': type, 'spot': spot, 'margin': spot && (Precise["default"].stringGt(maxLeverage, '1')), 'swap': false, 'future': false, 'option': false, 'active': true, 'contract': false, 'linear': undefined, 'inverse': undefined, 'contractSize': contract ? this.safeNumber(market, 'ctVal') : undefined, 'expiry': undefined, 'expiryDatetime': undefined, 'strike': undefined, 'optionType': undefined, 'created': this.safeInteger(market, 'listTime'), 'precision': { 'amount': this.safeNumber(market, 'lotSz'), 'price': this.parseNumber(tickSize), }, 'limits': { 'leverage': { 'min': this.parseNumber('1'), 'max': this.parseNumber(maxLeverage), }, 'amount': { 'min': this.safeNumber(market, 'minSz'), 'max': undefined, }, 'price': { 'min': undefined, 'max': undefined, }, 'cost': { 'min': undefined, 'max': contract ? undefined : maxSpotCost, }, }, 'info': market, }); } /** * @method * @name okcoin#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 */ async fetchCurrencies(params = {}) { if (!this.checkRequiredCredentials(false)) { if (this.options['warnOnFetchCurrenciesWithoutAuthorization']) { throw new errors.ExchangeError(this.id + ' fetchCurrencies() is a private API endpoint that requires authentication with API keys. Set the API keys on the exchange instance or exchange.options["warnOnFetchCurrenciesWithoutAuthorization"] = false to suppress this warning message.'); } return undefined; } else { const response = await this.privateGetAssetCurrencies(params); const data = this.safeValue(response, 'data', []); const result = {}; const dataByCurrencyId = this.groupBy(data, 'ccy'); const currencyIds = Object.keys(dataByCurrencyId); for (let i = 0; i < currencyIds.length; i++) { const currencyId = currencyIds[i]; const currency = this.safeCurrency(currencyId); const code = currency['code']; const chains = dataByCurrencyId[currencyId]; const networks = {}; let currencyActive = false; let depositEnabled = false; let withdrawEnabled = false; let maxPrecision = undefined; for (let j = 0; j < chains.length; j++) { const chain = chains[j]; const canDeposit = this.safeValue(chain, 'canDep'); depositEnabled = (canDeposit) ? canDeposit : depositEnabled; const canWithdraw = this.safeValue(chain, 'canWd'); withdrawEnabled = (canWithdraw) ? canWithdraw : withdrawEnabled; const canInternal = this.safeValue(chain, 'canInternal'); const active = (canDeposit && canWithdraw && canInternal) ? true : false; currencyActive = (active) ? active : currencyActive; const networkId = this.safeString(chain, 'chain'); if ((networkId !== undefined) && (networkId.indexOf('-') >= 0)) { const parts = networkId.split('-'); const chainPart = this.safeString(parts, 1, networkId); const networkCode = this.networkIdToCode(chainPart); const precision = this.parsePrecision(this.safeString(chain, 'wdTickSz')); if (maxPrecision === undefined) { maxPrecision = precision; } else { maxPrecision = Precise["default"].stringMin(maxPrecision, precision); } networks[networkCode] = { 'id': networkId, 'network': networkCode, 'active': active, 'deposit': canDeposit, 'withdraw': canWithdraw, 'fee': this.safeNumber(chain, 'minFee'), 'precision': this.parseNumber(precision), 'limits': { 'withdraw': { 'min': this.safeNumber(chain, 'minWd'), 'max': this.safeNumber(chain, 'maxWd'), }, }, 'info': chain, }; } } const firstChain = this.safeValue(chains, 0); result[code] = { 'info': chains, 'code': code, 'id': currencyId, 'name': this.safeString(firstChain, 'name'), 'active': currencyActive, 'deposit': depositEnabled, 'withdraw': withdrawEnabled, 'fee': undefined, 'precision': this.parseNumber(maxPrecision), 'limits': { 'amount': { 'min': undefined, 'max': undefined, }, }, 'networks': networks, }; } return result; } } /** * @method * @name okcoin#fetchOrderBook * @see https://www.okcoin.com/docs-v5/en/#rest-api-market-data-get-order-book * @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} [limit] the maximum amount of order book entries to return * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols */ async fetchOrderBook(symbol, limit = undefined, params = {}) { await this.loadMarkets(); const market = this.market(symbol); const request = { 'instId': market['id'], }; limit = (limit === undefined) ? 20 : limit; if (limit !== undefined) { request['sz'] = limit; // max 400 } const response = await this.publicGetMarketBooks(this.extend(request, params)); // // { // "code": "0", // "msg": "", // "data": [ // { // "asks": [ // ["0.07228","4.211619","0","2"], // price, amount, liquidated orders, total open orders // ["0.0723","299.880364","0","2"], // ["0.07231","3.72832","0","1"], // ], // "bids": [ // ["0.07221","18.5","0","1"], // ["0.0722","18.5","0","1"], // ["0.07219","0.505407","0","1"], // ], // "ts": "1621438475342" // } // ] // } // const data = this.safeValue(response, 'data', []); const first = this.safeValue(data, 0, {}); const timestamp = this.safeInteger(first, 'ts'); return this.parseOrderBook(first, symbol, timestamp); } parseTicker(ticker, market = undefined) { // // { // "instType": "SPOT", // "instId": "ETH-BTC", // "last": "0.07319", // "lastSz": "0.044378", // "askPx": "0.07322", // "askSz": "4.2", // "bidPx": "0.0732", // "bidSz": "6.050058", // "open24h": "0.07801", // "high24h": "0.07975", // "low24h": "0.06019", // "volCcy24h": "11788.887619", // "vol24h": "167493.829229", // "ts": "1621440583784", // "sodUtc0": "0.07872", // "sodUtc8": "0.07345" // } // const timestamp = this.safeInteger(ticker, 'ts'); const marketId = this.safeString(ticker, 'instId'); market = this.safeMarket(marketId, market, '-'); const symbol = market['symbol']; const last = this.safeString(ticker, 'last'); const open = this.safeString(ticker, 'open24h'); const spot = this.safeBool(market, 'spot', false); const quoteVolume = spot ? this.safeString(ticker, 'volCcy24h') : undefined; const baseVolume = this.safeString(ticker, 'vol24h'); const high = this.safeString(ticker, 'high24h'); const low = this.safeString(ticker, 'low24h'); return this.safeTicker({ 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601(timestamp), 'high': high, 'low': low, 'bid': this.safeString(ticker, 'bidPx'), 'bidVolume': this.safeString(ticker, 'bidSz'), 'ask': this.safeString(ticker, 'askPx'), 'askVolume': this.safeString(ticker, 'askSz'), 'vwap': undefined, 'open': open, 'close': last, 'last': last, 'previousClose': undefined, 'change': undefined, 'percentage': undefined, 'average': undefined, 'baseVolume': baseVolume, 'quoteVolume': quoteVolume, 'info': ticker, }, market); } /** * @method * @name okcoin#fetchTicker * @see https://www.okcoin.com/docs-v5/en/#rest-api-market-data-get-ticker * @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 exchange API endpoint * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure} */ async fetchTicker(symbol, params = {}) { await this.loadMarkets(); const market = this.market(symbol); const request = { 'instId': market['id'], }; const response = await this.publicGetMarketTicker(this.extend(request, params)); const data = this.safeValue(response, 'data', []); const first = this.safeValue(data, 0, {}); // // { // "code": "0", // "msg": "", // "data": [ // { // "instType": "SPOT", // "instId": "ETH-BTC", // "last": "0.07319", // "lastSz": "0.044378", // "askPx": "0.07322", // "askSz": "4.2", // "bidPx": "0.0732", // "bidSz": "6.050058", // "open24h": "0.07801", // "high24h": "0.07975", // "low24h": "0.06019", // "volCcy24h": "11788.887619", // "vol24h": "167493.829229", // "ts": "1621440583784", // "sodUtc0": "0.07872", // "sodUtc8": "0.07345" // } // ] // } // return this.parseTicker(first, market); } /** * @method * @name okcoin#fetchTickers * @see https://www.okcoin.com/docs-v5/en/#rest-api-market-data-get-tickers * @description fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market * @param {string[]|undefined} symbols unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure} */ async fetchTickers(symbols = undefined, params = {}) { symbols = this.marketSymbols(symbols); const request = { 'instType': 'SPOT', }; const response = await this.publicGetMarketTickers(this.extend(request, params)); const data = this.safeList(response, 'data', []); return this.parseTickers(data, symbols, params); } parseTrade(trade, market = undefined) { // // public fetchTrades // // { // "instId": "ETH-BTC", // "side": "sell", // "sz": "0.119501", // "px": "0.07065", // "tradeId": "15826757", // "ts": "1621446178316" // } // // private fetchMyTrades // // { // "side": "buy", // "fillSz": "0.007533", // "fillPx": "2654.98", // "fee": "-0.000007533", // "ordId": "317321390244397056", // "instType": "SPOT", // "instId": "ETH-USDT", // "clOrdId": "", // "posSide": "net", // "billId": "317321390265368576", // "tag": "0", // "execType": "T", // "tradeId": "107601752", // "feeCcy": "ETH", // "ts": "1621927314985" // } // const id = this.safeString(trade, 'tradeId'); const marketId = this.safeString(trade, 'instId'); market = this.safeMarket(marketId, market, '-'); const symbol = market['symbol']; const timestamp = this.safeInteger(trade, 'ts'); const price = this.safeString2(trade, 'fillPx', 'px'); const amount = this.safeString2(trade, 'fillSz', 'sz'); const side = this.safeString(trade, 'side'); const orderId = this.safeString(trade, 'ordId'); const feeCostString = this.safeString(trade, 'fee'); let fee = undefined; if (feeCostString !== undefined) { const feeCostSigned = Precise["default"].stringNeg(feeCostString); const feeCurrencyId = this.safeString(trade, 'feeCcy'); const feeCurrencyCode = this.safeCurrencyCode(feeCurrencyId); fee = { 'cost': feeCostSigned, 'currency': feeCurrencyCode,