ccxt
Version:
1,118 lines (1,115 loc) • 145 kB
JavaScript
'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,