UNPKG

remsed

Version:

A JavaScript cryptocurrency trading library with support for fairdesk.com

1,169 lines (1,166 loc) 165 kB
// ---------------------------------------------------------------------------- // 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 './base/Exchange.js'; import { ExchangeError, ExchangeNotAvailable, OnMaintenance, ArgumentsRequired, BadRequest, AccountSuspended, InvalidAddress, PermissionDenied, DDoSProtection, InsufficientFunds, InvalidNonce, CancelPending, InvalidOrder, OrderNotFound, AuthenticationError, RequestTimeout, NotSupported, BadSymbol, RateLimitExceeded } from './base/errors.js'; import { Precise } from './base/Precise.js'; import { TICK_SIZE } from './base/functions/number.js'; // --------------------------------------------------------------------------- export default class okcoin extends Exchange { describe() { return this.deepExtend(super.describe(), { 'id': 'okcoin', 'name': 'OKCoin', 'countries': ['CN', 'US'], 'version': 'v3', // 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': undefined, 'future': true, 'option': undefined, 'cancelOrder': true, 'createOrder': true, 'fetchBalance': true, 'fetchClosedOrders': true, 'fetchCurrencies': true, 'fetchDepositAddress': true, 'fetchDeposits': true, 'fetchLedger': true, 'fetchMarkets': true, 'fetchMyTrades': true, 'fetchOHLCV': true, 'fetchOpenOrders': true, 'fetchOrder': true, 'fetchOrderBook': true, 'fetchOrders': undefined, 'fetchOrderTrades': true, 'fetchPosition': true, 'fetchPositions': true, 'fetchTicker': true, 'fetchTickers': true, 'fetchTime': true, 'fetchTrades': true, 'fetchTransactions': undefined, 'fetchWithdrawals': true, 'transfer': true, 'withdraw': true, }, 'timeframes': { '1m': '60', '3m': '180', '5m': '300', '15m': '900', '30m': '1800', '1h': '3600', '2h': '7200', '4h': '14400', '6h': '21600', '12h': '43200', '1d': '86400', '1w': '604800', '1M': '2678400', '3M': '8035200', '6M': '16070400', '1y': '31536000', }, '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': { 'general': { 'get': { 'time': 8.3334, }, }, 'account': { 'get': { 'wallet': 8.3334, 'sub-account': 1000, 'asset-valuation': 1000, 'wallet/{currency}': 8.3334, 'withdrawal/history': 8.3334, 'withdrawal/history/{currency}': 8.3334, 'ledger': 5, 'deposit/address': 8.3334, 'deposit/history': 8.3334, 'deposit/history/{currency}': 8.3334, 'currencies': 8.3334, 'withdrawal/fee': 8.3334, 'deposit-lightning': 50, 'withdrawal-lightning': 50, 'fiat/deposit/detail': 5, 'fiat/deposit/details': 8.3334, 'fiat/withdraw/detail': 5, 'fiat/withdraw/details': 8.3334, 'fiat/channel': 8.3334, }, 'post': { 'transfer': 100, 'withdrawal': 8.3334, 'fiat/cancel_deposit': 1, 'fiat/deposit': 8.3334, 'fiat/withdraw': 8.3334, 'fiat/cancel_withdrawal': 1, }, }, // TODO fix signing issue in sign () // all other endpoints of the format // api/account/v3/wallet // otc endpoints actually of the format: (exchanged places) // api/v3/otc/rfq/instruments 'otc': { 'get': { 'rfq/instruments': 50, 'rfq/trade': 50, 'rfq/history': 50, }, 'post': { 'rfq/quote': 50, 'rfq/trade': 50, }, }, // TODO fix signing issue as above 'users': { 'get': { 'subaccount-info': 20, 'account-info': 20, 'subaccount/apikey': 20, }, 'post': { 'create-subaccount': 5, 'delete-subaccount': 5, 'subaccount/apikey': 50, 'subacount/delete-apikey': 20, 'subacount/modify-apikey': 20, }, }, 'earning': { 'get': { 'offers': 5, 'orders': 5, 'positions': 8.3334, }, 'post': { 'purchase': 5, 'redeem': 5, 'cancel': 5, }, }, 'spot': { 'get': { 'accounts': 5, 'accounts/{currency}': 5, 'accounts/{currency}/ledger': 5, 'orders': 10, 'orders_pending': 5, 'orders/{order_id}': 5, 'orders/{client_oid}': 5, 'trade_fee': 5, 'fills': 10, 'algo': 5, // public 'instruments': 5, 'instruments/{instrument_id}/book': 5, 'instruments/ticker': 5, 'instruments/{instrument_id}/ticker': 5, 'instruments/{instrument_id}/trades': 5, 'instruments/{instrument_id}/candles': 5, }, 'post': { 'order_algo': 2.5, 'orders': 1, 'batch_orders': 2, 'cancel_orders/{order_id}': 1, 'cancel_orders/{client_oid}': 1, 'cancel_batch_algos': 5, 'cancel_batch_orders': 5, 'amend_order/{instrument_id}': 2.5, 'amend_batch_orders': 5, }, }, 'margin': { // Margin trading closed down on February 21, 2022 'get': { 'accounts': 5, 'accounts/{instrument_id}': 5, 'accounts/{instrument_id}/ledger': 5, 'accounts/availability': 5, 'accounts/{instrument_id}/availability': 5, 'accounts/borrowed': 5, 'accounts/{instrument_id}/borrowed': 5, 'orders': 10, 'accounts/{instrument_id}/leverage': 1, 'orders/{order_id}': 5, 'orders/{client_oid}': 5, 'orders_pending': 5, 'fills': 10, // public 'instruments/{instrument_id}/mark_price': 5, }, 'post': { 'accounts/borrow': 1, 'accounts/repayment': 1, 'orders': 1, 'batch_orders': 2, 'cancel_orders': 1, 'cancel_orders/{order_id}': 1, 'cancel_orders/{client_oid}': 1, 'cancel_batch_orders': 2, 'amend_order/{instrument_id}': 2.5, 'amend_batch_orders': 5, 'accounts/{instrument_id}/leverage': 1, }, }, 'system': { 'get': { 'status': 250, }, }, 'market': { 'get': { 'oracle': 250, }, }, 'futures': { 'get': [ 'position', '{instrument_id}/position', 'accounts', 'accounts/{underlying}', 'accounts/{underlying}/leverage', 'accounts/{underlying}/ledger', 'order_algo/{instrument_id}', 'orders/{instrument_id}', 'orders/{instrument_id}/{order_id}', 'orders/{instrument_id}/{client_oid}', 'fills', 'trade_fee', 'accounts/{instrument_id}/holds', 'order_algo/{instrument_id}', // public 'instruments', 'instruments/{instrument_id}/book', 'instruments/ticker', 'instruments/{instrument_id}/ticker', 'instruments/{instrument_id}/trades', 'instruments/{instrument_id}/candles', 'instruments/{instrument_id}/history/candles', 'instruments/{instrument_id}/index', 'rate', 'instruments/{instrument_id}/estimated_price', 'instruments/{instrument_id}/open_interest', 'instruments/{instrument_id}/price_limit', 'instruments/{instrument_id}/mark_price', 'instruments/{instrument_id}/liquidation', ], 'post': [ 'accounts/{underlying}/leverage', 'order', 'amend_order/{instrument_id}', 'orders', 'cancel_order/{instrument_id}/{order_id}', 'cancel_order/{instrument_id}/{client_oid}', 'cancel_batch_orders/{instrument_id}', 'accounts/margin_mode', 'close_position', 'cancel_all', 'order_algo', 'cancel_algos', ], }, 'swap': { 'get': [ 'position', '{instrument_id}/position', 'accounts', '{instrument_id}/accounts', 'accounts/{instrument_id}/settings', 'accounts/{instrument_id}/ledger', 'orders/{instrument_id}', 'orders/{instrument_id}/{order_id}', 'orders/{instrument_id}/{client_oid}', 'fills', 'accounts/{instrument_id}/holds', 'trade_fee', 'order_algo/{instrument_id}', // public 'instruments', 'instruments/{instrument_id}/depth', 'instruments/ticker', 'instruments/{instrument_id}/ticker', 'instruments/{instrument_id}/trades', 'instruments/{instrument_id}/candles', 'instruments/{instrument_id}/history/candles', 'instruments/{instrument_id}/index', 'rate', 'instruments/{instrument_id}/open_interest', 'instruments/{instrument_id}/price_limit', 'instruments/{instrument_id}/liquidation', 'instruments/{instrument_id}/funding_time', 'instruments/{instrument_id}/mark_price', 'instruments/{instrument_id}/historical_funding_rate', ], 'post': [ 'accounts/{instrument_id}/leverage', 'order', 'amend_order/{instrument_id}', 'orders', 'cancel_order/{instrument_id}/{order_id}', 'cancel_order/{instrument_id}/{client_oid}', 'cancel_batch_orders/{instrument_id}', 'order_algo', 'cancel_algos', 'close_position', 'cancel_all', 'order_algo', 'cancel_algos', ], }, 'option': { 'get': [ 'accounts', 'position', '{underlying}/position', 'accounts/{underlying}', 'orders/{underlying}', 'fills/{underlying}', 'accounts/{underlying}/ledger', 'trade_fee', 'orders/{underlying}/{order_id}', 'orders/{underlying}/{client_oid}', // public 'underlying', 'instruments/{underlying}', 'instruments/{underlying}/summary', 'instruments/{underlying}/summary/{instrument_id}', 'instruments/{instrument_id}/book', 'instruments/{instrument_id}/trades', 'instruments/{instrument_id}/ticker', 'instruments/{instrument_id}/candles', ], 'post': [ 'order', 'orders', 'cancel_order/{underlying}/{order_id}', 'cancel_order/{underlying}/{client_oid}', 'cancel_batch_orders/{underlying}', 'amend_order/{underlying}', 'amend_batch_orders/{underlying}', ], }, 'information': { 'get': [ '{currency}/long_short_ratio', '{currency}/volume', '{currency}/taker', '{currency}/sentiment', '{currency}/margin', ], }, 'index': { 'get': [ '{instrument_id}/constituents', ], }, }, 'fees': { 'trading': { 'taker': 0.002, 'maker': 0.001, }, 'spot': { 'taker': 0.0015, 'maker': 0.0010, }, }, 'requiredCredentials': { 'apiKey': true, 'secret': true, 'password': true, }, 'exceptions': { // http error codes // 400 Bad Request — Invalid request format // 401 Unauthorized — Invalid API Key // 403 Forbidden — You do not have access to the requested resource // 404 Not Found // 429 Client Error: Too Many Requests for url // 500 Internal Server Error — We had a problem with our server 'exact': { '1': ExchangeError, // undocumented 'failure to get a peer from the ring-balancer': ExchangeNotAvailable, 'Server is busy, please try again.': ExchangeNotAvailable, 'An unexpected error occurred': ExchangeError, 'System error': ExchangeError, '4010': PermissionDenied, // common // '0': ExchangeError, // 200 successful,when the order placement / cancellation / operation is successful '4001': ExchangeError, '4002': ExchangeError, // -------------------------------------------------------- '30001': AuthenticationError, '30002': AuthenticationError, '30003': AuthenticationError, '30004': AuthenticationError, '30005': InvalidNonce, '30006': AuthenticationError, '30007': BadRequest, '30008': RequestTimeout, '30009': ExchangeError, '30010': AuthenticationError, '30011': PermissionDenied, '30012': AuthenticationError, '30013': AuthenticationError, '30014': DDoSProtection, '30015': AuthenticationError, '30016': ExchangeError, '30017': ExchangeError, '30018': ExchangeError, '30019': ExchangeNotAvailable, '30020': BadRequest, '30021': BadRequest, '30022': PermissionDenied, '30023': BadRequest, '30024': BadSymbol, '30025': BadRequest, '30026': DDoSProtection, '30027': AuthenticationError, '30028': PermissionDenied, '30029': AccountSuspended, '30030': ExchangeNotAvailable, '30031': BadRequest, '30032': BadSymbol, '30033': BadRequest, '30034': ExchangeError, '30035': ExchangeError, '30036': ExchangeError, '30037': ExchangeNotAvailable, // '30038': AuthenticationError, // { "code": 30038, "message": "user does not exist" } '30038': OnMaintenance, '30044': RequestTimeout, // futures '32001': AccountSuspended, '32002': PermissionDenied, '32003': CancelPending, '32004': ExchangeError, '32005': InvalidOrder, '32006': InvalidOrder, '32007': InvalidOrder, '32008': InvalidOrder, '32009': InvalidOrder, '32010': ExchangeError, '32011': ExchangeError, '32012': ExchangeError, '32013': ExchangeError, '32014': ExchangeError, '32015': ExchangeError, '32016': ExchangeError, '32017': ExchangeError, '32018': ExchangeError, '32019': ExchangeError, '32020': ExchangeError, '32021': ExchangeError, '32022': ExchangeError, '32023': ExchangeError, '32024': ExchangeError, '32025': ExchangeError, '32026': ExchangeError, '32027': ExchangeError, '32028': ExchangeError, '32029': ExchangeError, '32030': InvalidOrder, '32031': ArgumentsRequired, '32038': AuthenticationError, '32040': ExchangeError, '32044': ExchangeError, '32045': ExchangeError, '32046': ExchangeError, '32047': ExchangeError, '32048': InvalidOrder, '32049': ExchangeError, '32050': InvalidOrder, '32051': InvalidOrder, '32052': ExchangeError, '32053': ExchangeError, '32057': ExchangeError, '32054': ExchangeError, '32055': InvalidOrder, '32056': ExchangeError, '32058': ExchangeError, '32059': InvalidOrder, '32060': InvalidOrder, '32061': InvalidOrder, '32062': InvalidOrder, '32063': InvalidOrder, '32064': ExchangeError, '32065': ExchangeError, '32066': ExchangeError, '32067': ExchangeError, '32068': ExchangeError, '32069': ExchangeError, '32070': ExchangeError, '32071': ExchangeError, '32072': ExchangeError, '32073': ExchangeError, '32074': ExchangeError, '32075': ExchangeError, '32076': ExchangeError, '32077': ExchangeError, '32078': ExchangeError, '32079': ExchangeError, '32080': ExchangeError, '32083': ExchangeError, // token and margin trading '33001': PermissionDenied, '33002': AccountSuspended, '33003': InsufficientFunds, '33004': ExchangeError, '33005': ExchangeError, '33006': ExchangeError, '33007': ExchangeError, '33008': InsufficientFunds, '33009': ExchangeError, '33010': ExchangeError, '33011': ExchangeError, '33012': ExchangeError, '33013': InvalidOrder, '33014': OrderNotFound, '33015': InvalidOrder, '33016': ExchangeError, '33017': InsufficientFunds, '33018': ExchangeError, '33020': ExchangeError, '33021': BadRequest, '33022': InvalidOrder, '33023': ExchangeError, '33024': InvalidOrder, '33025': InvalidOrder, '33026': ExchangeError, '33027': InvalidOrder, '33028': InvalidOrder, '33029': InvalidOrder, '33034': ExchangeError, '33035': ExchangeError, '33036': ExchangeError, '33037': ExchangeError, '33038': ExchangeError, '33039': ExchangeError, '33040': ExchangeError, '33041': ExchangeError, '33042': ExchangeError, '33043': ExchangeError, '33044': ExchangeError, '33045': ExchangeError, '33046': ExchangeError, '33047': ExchangeError, '33048': ExchangeError, '33049': ExchangeError, '33050': ExchangeError, '33051': ExchangeError, '33059': BadRequest, '33060': BadRequest, '33061': ExchangeError, '33062': ExchangeError, '33063': ExchangeError, '33064': ExchangeError, '33065': ExchangeError, '33085': InvalidOrder, // account '21009': ExchangeError, '34001': PermissionDenied, '34002': InvalidAddress, '34003': ExchangeError, '34004': ExchangeError, '34005': ExchangeError, '34006': ExchangeError, '34007': ExchangeError, '34008': InsufficientFunds, '34009': ExchangeError, '34010': ExchangeError, '34011': ExchangeError, '34012': ExchangeError, '34013': ExchangeError, '34014': ExchangeError, '34015': ExchangeError, '34016': PermissionDenied, '34017': AccountSuspended, '34018': AuthenticationError, '34019': PermissionDenied, '34020': PermissionDenied, '34021': InvalidAddress, '34022': ExchangeError, '34023': PermissionDenied, '34026': RateLimitExceeded, '34036': ExchangeError, '34037': ExchangeError, '34038': ExchangeError, '34039': ExchangeError, // swap '35001': ExchangeError, '35002': ExchangeError, '35003': ExchangeError, '35004': ExchangeError, '35005': AuthenticationError, '35008': InvalidOrder, '35010': InvalidOrder, '35012': InvalidOrder, '35014': InvalidOrder, '35015': InvalidOrder, '35017': ExchangeError, '35019': InvalidOrder, '35020': InvalidOrder, '35021': InvalidOrder, '35022': BadRequest, '35024': BadRequest, '35025': InsufficientFunds, '35026': BadRequest, '35029': OrderNotFound, '35030': InvalidOrder, '35031': InvalidOrder, '35032': ExchangeError, '35037': ExchangeError, '35039': InsufficientFunds, '35040': InvalidOrder, '35044': ExchangeError, '35046': InsufficientFunds, '35047': InsufficientFunds, '35048': ExchangeError, '35049': InvalidOrder, '35050': InvalidOrder, '35052': InsufficientFunds, '35053': ExchangeError, '35055': InsufficientFunds, '35057': ExchangeError, '35058': ExchangeError, '35059': BadRequest, '35060': BadRequest, '35061': BadRequest, '35062': InvalidOrder, '35063': InvalidOrder, '35064': InvalidOrder, '35066': InvalidOrder, '35067': InvalidOrder, '35068': InvalidOrder, '35069': InvalidOrder, '35070': InvalidOrder, '35071': InvalidOrder, '35072': InvalidOrder, '35073': InvalidOrder, '35074': InvalidOrder, '35075': InvalidOrder, '35076': InvalidOrder, '35077': InvalidOrder, '35078': InvalidOrder, '35079': InvalidOrder, '35080': InvalidOrder, '35081': InvalidOrder, '35082': InvalidOrder, '35083': InvalidOrder, '35084': InvalidOrder, '35085': InvalidOrder, '35086': InvalidOrder, '35087': InvalidOrder, '35088': InvalidOrder, '35089': InvalidOrder, '35090': ExchangeError, '35091': ExchangeError, '35092': ExchangeError, '35093': ExchangeError, '35094': ExchangeError, '35095': BadRequest, '35096': ExchangeError, '35097': ExchangeError, '35098': ExchangeError, '35099': ExchangeError, '35102': RateLimitExceeded, // option '36001': BadRequest, '36002': BadRequest, '36005': ExchangeError, '36101': AuthenticationError, '36102': PermissionDenied, '36103': PermissionDenied, '36104': PermissionDenied, '36105': PermissionDenied, '36106': PermissionDenied, '36107': PermissionDenied, '36108': InsufficientFunds, '36109': PermissionDenied, '36201': PermissionDenied, '36202': PermissionDenied, '36203': InvalidOrder, '36204': ExchangeError, '36205': BadRequest, '36206': BadRequest, '36207': InvalidOrder, '36208': InvalidOrder, '36209': InvalidOrder, '36210': InvalidOrder, '36211': InvalidOrder, '36212': InvalidOrder, '36213': InvalidOrder, '36214': ExchangeError, '36216': OrderNotFound, '36217': InvalidOrder, '36218': InvalidOrder, '36219': InvalidOrder, '36220': InvalidOrder, '36221': InvalidOrder, '36222': InvalidOrder, '36223': InvalidOrder, '36224': InvalidOrder, '36225': InvalidOrder, '36226': InvalidOrder, '36227': InvalidOrder, '36228': InvalidOrder, '36229': InvalidOrder, '36230': InvalidOrder, // Exceeding max position limit for underlying. }, 'broad': {}, }, 'precisionMode': TICK_SIZE, 'options': { 'fetchOHLCV': { 'type': 'Candles', // Candles or HistoryCandles }, 'createMarketBuyOrderRequiresPrice': true, 'fetchMarkets': ['spot'], 'defaultType': 'spot', 'accountsByType': { 'spot': '1', 'funding': '6', 'main': '6', }, 'accountsById': { '1': 'spot', '6': 'funding', }, 'auth': { 'time': 'public', 'currencies': 'private', 'instruments': 'public', 'rate': 'public', '{instrument_id}/constituents': 'public', }, 'warnOnFetchCurrenciesWithoutAuthorization': false, }, '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 }, }); } async fetchTime(params = {}) { /** * @method * @name okcoin#fetchTime * @description fetches the current integer timestamp in milliseconds from the exchange server * @param {object} params extra parameters specific to the okcoin api endpoint * @returns {int} the current integer timestamp in milliseconds from the exchange server */ const response = await this.generalGetTime(params); // // { // "iso": "2015-01-07T23:47:25.201Z", // "epoch": 1420674445.201 // } // return this.parse8601(this.safeString(response, 'iso')); } async fetchMarkets(params = {}) { /** * @method * @name okcoin#fetchMarkets * @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 */ const types = this.safeValue(this.options, 'fetchMarkets'); let result = []; for (let i = 0; i < types.length; i++) { const markets = await this.fetchMarketsByType(types[i], params); result = this.arrayConcat(result, markets); } return result; } parseMarkets(markets) { const result = []; for (let i = 0; i < markets.length; i++) { result.push(this.parseMarket(markets[i])); } return result; } 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" // } // // futures markets // // { // instrument_id: "XRP-USD-200320", // underlying_index: "XRP", // quote_currency: "USD", // tick_size: "0.0001", // contract_val: "10", // listing: "2020-03-06", // delivery: "2020-03-20", // trade_increment: "1", // alias: "this_week", // underlying: "XRP-USD", // base_currency: "XRP", // settlement_currency: "XRP", // is_inverse: "true", // contract_val_currency: "USD", // } // // swap markets // // { // instrument_id: "BSV-USD-SWAP", // underlying_index: "BSV", // quote_currency: "USD", // coin: "BSV", // contract_val: "10", // listing: "2018-12-21T07:53:47.000Z", // delivery: "2020-03-14T08:00:00.000Z", // size_increment: "1", // tick_size: "0.01", // base_currency: "BSV", // underlying: "BSV-USD", // settlement_currency: "BSV", // is_inverse: "true", // contract_val_currency: "USD" // } // // options markets // // { // instrument_id: 'BTC-USD-200327-4000-C', // underlying: 'BTC-USD', // settlement_currency: 'BTC', // contract_val: '0.1000', // option_type: 'C', // strike: '4000', // tick_size: '0.0005', // lot_size: '1.0000', // listing: '2019-12-25T08:30:36.302Z', // delivery: '2020-03-27T08:00:00.000Z', // state: '2', // trading_start_time: '2019-12-25T08:30:36.302Z', // timestamp: '2020-03-13T08:05:09.456Z', // } // const id = this.safeString(market, 'instrument_id'); let optionType = this.safeValue(market, 'option_type'); const contractVal = this.safeNumber(market, 'contract_val'); const contract = contractVal !== undefined; const futuresAlias = this.safeString(market, 'alias'); let marketType = 'spot'; const spot = !contract; const option = (optionType !== undefined); const future = !option && (futuresAlias !== undefined); const swap = contract && !future && !option; let baseId = this.safeString(market, 'base_currency'); let quoteId = this.safeString(market, 'quote_currency'); const settleId = this.safeString(market, 'settlement_currency'); if (option) { const underlying = this.safeString(market, 'underlying'); const parts = underlying.split('-'); baseId = this.safeString(parts, 0); quoteId = this.safeString(parts, 1); marketType = 'option'; } else if (future) { baseId = this.safeString(market, 'underlying_index'); marketType = 'futures'; } else if (swap) { marketType = 'swap'; } const base = this.safeCurrencyCode(baseId); const quote = this.safeCurrencyCode(quoteId); const settle = this.safeCurrencyCode(settleId); let symbol = base + '/' + quote; let expiryDatetime = this.safeString(market, 'delivery'); let expiry = undefined; const strike = this.safeValue(market, 'strike'); if (contract) { symbol = symbol + ':' + settle; if (future || option) { if (future) { expiryDatetime += 'T00:00:00Z'; } expiry = this.parse8601(expiryDatetime); symbol = symbol + '-' + this.yymmdd(expiry); if (option) { symbol = symbol + ':' + strike + ':' + optionType; optionType = (optionType === 'C') ? 'call' : 'put'; } } } const lotSize = this.safeNumber2(market, 'lot_size', 'trade_increment'); const minPrice = this.safeString(market, 'tick_size'); const minAmountString = this.safeString2(market, 'min_size', 'base_min_size'); const minAmount = this.parseNumber(minAmountString); let minCost = undefined; if ((minAmount !== undefined) && (minPrice !== undefined)) { minCost = this.parseNumber(Precise.stringMul(minPrice, minAmountString)); } const fees = this.safeValue2(this.fees, marketType, 'trading', {}); const maxLeverageString = this.safeString(market, 'max_leverage', '1'); const maxLeverage = this.parseNumber(Precise.stringMax(maxLeverageString, '1')); const precisionPrice = this.parseNumber(minPrice); return this.extend(fees, { 'id': id, 'symbol': symbol, 'base': base, 'quote': quote, 'settle': settle, 'baseId': baseId, 'quoteId': quoteId, 'settleId': settleId, 'type': marketType, 'spot': spot, 'margin': false, 'swap': swap, 'future': future, 'futures': future, 'option': option, 'active': true, 'contract': contract, 'linear': contract ? (quote === settle) : undefined, 'inverse': contract ? (base === settle) : undefined, 'contractSize': contractVal, 'expiry': expiry, 'expiryDatetime': this.iso8601(expiry), 'strike': strike, 'optionType': optionType, 'precision': { 'amount': this.safeNumber(market, 'size_increment', lotSize), 'price': precisionPrice, }, 'limits': { 'leverage': { 'min': this.parseNumber('1'), 'max': this.parseNumber(maxLeverage), }, 'amount': { 'min': minAmount, 'max': undefined, }, 'price': { 'min': precisionPrice, 'max': undefined, }, 'cost': { 'min': minCost, 'max': undefined, }, }, 'info': market, }); } async fetchMarketsByType(type, params = {}) { if (type === 'option') { const underlying = await this.optionGetUnderlying(params); let result = []; for (let i = 0; i < underlying.length; i++) { const response = await this.optionGetInstrumentsUnderlying({ 'underlying': underlying[i], }); // // options markets // // [ // { // instrument_id: 'BTC-USD-200327-4000-C', // underlying: 'BTC-USD', // settlement_currency: 'BTC', // contract_val: '0.1000', // option_type: 'C', // strike: '4000', // tick_size: '0.0005', // lot_size: '1.0000', // listing: '2019-12-25T08:30:36.302Z', // delivery: '2020-03-27T08:00:00.000Z', // state: '2', // trading_start_time: '2019-12-25T08:30:36.302Z', // timestamp: '2020-03-13T08:05:09.456Z', // }, // ] // result = this.arrayConcat(result, response); } return this.parseMarkets(result); } else if ((type === 'spot') || (type === 'futures') || (type === 'swap')) { const method = type + 'GetInstruments'; const response = await this[method](params); // // spot markets // // [ // { // base_currency: "EOS", // instrument_id: "EOS-OKB", // min_size: "0.01", // quote_currency: "OKB", // size_increment: "0.000001", // tick_size: "0.0001" // } // ] // // futures markets // // [ // { // instrument_id: "XRP-USD-200320", // underlying_index: "XRP", // quote_currency: "USD", // tick_size: "0.0001", // contract_val: "10", // listing: "2020-03-06", // delivery: "2020-03-20", // trade_increment: "1", // alias: "this_week", // underlying: "XRP-USD", // base_currency: "XRP", // settlement_currency: "XRP", // is_inverse: "true", // contract_val_currency: "USD", // } // ] // // swap markets // // [ // { // instrument_id: "BSV-USD-SWAP", // underlying_index: "BSV", // quote_currency: "USD", // coin: "BSV", // contract_val: "10", // listing: "2018-12-21T07:53:47.000Z", // delivery: "2020-03-14T08:00:00.000Z", // size_increment: "1", // tick_size: "0.01", // base_currency: "BSV", // underlying: "BSV-USD", // settlement_currency: "BSV", // is_inverse: "true", // contract_val_currency: "USD" // } // ] // return this.parseMarkets(response); } else { throw new NotSupported(this.id + ' fetchMarketsByType() does not support market type ' + type); } } async fetchCurrencies(params = {}) { /** * @method * @name okcoin#fetchCurrencies * @description fetches all available currencies on an exchange * @param {object} params extra parameters specific to the okcoin api endpoint * @returns {object} an associative dictionary of currencies */ // despite that their docs say these endpoints are public: // https://www.okex.com/api/account/v3/withdrawal/fee // https://www.okex.com/api/account/v3/currencies // it will still reply with { "code":30001, "message": "OK-ACCESS-KEY header is required" } // if you attempt to access it without authentication if (!this.checkRequiredCredentials(false)) { if (this.options['warnOnFetchCurrenciesWithoutAuthorization']) { throw new 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.accountGetCurrencies(params); // // [ // { // name: '', // currency: 'BTC', // can_withdraw: '1', // can_deposit: '1', // min_withdrawal: '0.0100000000000000' // }, // ] // const result = {}; for (let i = 0; i < response.length; i++) { const currency = response[i]; const id = this.safeString(currency, 'currency'); const code = this.safeCurrencyCode(id); const name = this.safeString(currency, 'name'); const canDeposit = this.safeInteger(currency, 'can_deposit'); const canWithdraw = this.safeInteger(currency, 'can_withdraw'); const depositEnabled = (canDeposit === 1); const withdrawEnabled = (canWithdraw === 1); const active = (canDeposit && canWithdraw) ? true : false; result[code] = { 'id': id, 'code': code, 'info': currency, 'type': undefined, 'name': name, 'active': active, 'deposit': depositEnabled, 'withdraw': withdrawEnabled, 'fee': undefined, 'precision': this.parseNumber('1e-8'), 'limits': { 'amount': { 'min': undefined, 'max': undefined }, 'withdraw': { 'min': this.safeNumber(currency, 'min_withdrawal'), 'max': undefined, }, }, }; } return result; } } async fetchOrderBook(symbol, limit = undefined, params = {}) { /** * @method