UNPKG

ccxt-look

Version:

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

827 lines (815 loc) 214 kB
'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ExchangeNotAvailable, OnMaintenance, ArgumentsRequired, BadRequest, AccountSuspended, InvalidAddress, PermissionDenied, InsufficientFunds, InvalidNonce, InvalidOrder, OrderNotFound, AuthenticationError, RequestTimeout, BadSymbol, RateLimitExceeded, NetworkError, CancelPending, NotSupported, AccountNotEnabled } = require ('./base/errors'); const { TICK_SIZE, TRUNCATE } = require ('./base/functions/number'); const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- module.exports = class okx extends Exchange { describe () { return this.deepExtend (super.describe (), { 'id': 'okx', 'name': 'OKX', 'countries': [ 'CN', 'US' ], 'version': 'v5', 'rateLimit': 100, 'pro': true, 'certified': true, 'has': { 'CORS': undefined, 'spot': true, 'margin': true, 'swap': true, 'future': true, 'option': undefined, 'addMargin': true, 'cancelAllOrders': undefined, 'cancelOrder': true, 'cancelOrders': true, 'createDepositAddress': undefined, 'createOrder': true, 'createReduceOnlyOrder': undefined, 'createStopLimitOrder': true, 'createStopMarketOrder': true, 'createStopOrder': true, 'fetchAccounts': true, 'fetchBalance': true, 'fetchBidsAsks': undefined, 'fetchBorrowRate': true, 'fetchBorrowRateHistories': true, 'fetchBorrowRateHistory': true, 'fetchBorrowRates': true, 'fetchBorrowRatesPerSymbol': false, 'fetchCanceledOrders': true, 'fetchClosedOrder': undefined, 'fetchClosedOrders': true, 'fetchCurrencies': true, 'fetchDeposit': undefined, 'fetchDepositAddress': true, 'fetchDepositAddresses': undefined, 'fetchDepositAddressesByNetwork': true, 'fetchDeposits': true, 'fetchFundingFee': undefined, 'fetchFundingFees': undefined, 'fetchFundingHistory': true, 'fetchFundingRate': true, 'fetchFundingRateHistory': true, 'fetchFundingRates': false, 'fetchIndexOHLCV': true, 'fetchL3OrderBook': undefined, 'fetchLedger': true, 'fetchLedgerEntry': undefined, 'fetchLeverage': true, 'fetchLeverageTiers': false, 'fetchMarketLeverageTiers': true, 'fetchMarkets': true, 'fetchMarkOHLCV': true, 'fetchMyBuys': undefined, 'fetchMySells': undefined, 'fetchMyTrades': true, 'fetchOHLCV': true, 'fetchOpenOrder': undefined, 'fetchOpenOrders': true, 'fetchOrder': true, 'fetchOrderBook': true, 'fetchOrderBooks': undefined, 'fetchOrders': undefined, 'fetchOrderTrades': true, 'fetchPosition': true, 'fetchPositions': true, 'fetchPositionsRisk': false, 'fetchPremiumIndexOHLCV': false, 'fetchStatus': true, 'fetchTicker': true, 'fetchTickers': true, 'fetchTime': true, 'fetchTrades': true, 'fetchTradingFee': true, 'fetchTradingFees': undefined, 'fetchTradingLimits': undefined, 'fetchTransactions': undefined, 'fetchTransfer': true, 'fetchTransfers': false, 'fetchWithdrawal': undefined, 'fetchWithdrawals': true, 'fetchWithdrawalWhitelist': undefined, 'reduceMargin': true, 'setLeverage': true, 'setMarginMode': true, 'setPositionMode': true, 'signIn': undefined, 'transfer': true, 'withdraw': true, }, 'timeframes': { '1m': '1m', '3m': '3m', '5m': '5m', '15m': '15m', '30m': '30m', '1h': '1H', '2h': '2H', '4h': '4H', '6h': '6Hutc', '12h': '12Hutc', '1d': '1Dutc', '1w': '1Wutc', '1M': '1Mutc', '3M': '3Mutc', '6M': '6Mutc', '1y': '1Yutc', }, 'hostname': 'www.okx.com', // or aws.okx.com 'urls': { 'logo': 'https://user-images.githubusercontent.com/1294454/152485636-38b19e4a-bece-4dec-979a-5982859ffc04.jpg', 'api': { 'rest': 'https://{hostname}', }, 'www': 'https://www.okx.com', 'doc': 'https://www.okx.com/docs-v5/en/', 'fees': 'https://www.okx.com/pages/products/fees.html', 'referral': 'https://www.okx.com/join/1888677', 'test': { 'rest': 'https://{hostname}', }, }, 'api': { 'public': { 'get': { 'market/tickers': 1, 'market/ticker': 1, 'market/index-tickers': 1, 'market/books': 1, 'market/candles': 1, 'market/history-candles': 1, 'market/index-candles': 1, 'market/mark-price-candles': 1, 'market/trades': 1, 'market/platform-24-volume': 10, 'market/open-oracle': 100, 'market/index-components': 1, // 'market/oracle', 'public/instruments': 1, 'public/delivery-exercise-history': 0.5, 'public/open-interest': 1, 'public/funding-rate': 1, 'public/funding-rate-history': 1, 'public/price-limit': 1, 'public/opt-summary': 1, 'public/estimated-price': 2, 'public/discount-rate-interest-free-quota': 10, 'public/time': 2, 'public/liquidation-orders': 0.5, 'public/mark-price': 2, // 'public/tier', 'public/position-tiers': 2, 'public/underlying': 1, 'public/interest-rate-loan-quota': 10, 'public/vip-interest-rate-loan-quota': 10, 'rubik/stat/trading-data/support-coin': 4, 'rubik/stat/taker-volume': 4, 'rubik/stat/margin/loan-ratio': 4, // long/short 'rubik/stat/contracts/long-short-account-ratio': 4, 'rubik/stat/contracts/open-interest-volume': 4, 'rubik/stat/option/open-interest-volume': 4, // put/call 'rubik/stat/option/open-interest-volume-ratio': 4, 'rubik/stat/option/open-interest-volume-expiry': 4, 'rubik/stat/option/open-interest-volume-strike': 4, 'rubik/stat/option/taker-block-volume': 4, 'system/status': 100, 'asset/lending-rate-summary': 5 / 3, 'asset/lending-rate-history': 5 / 3, 'market/exchange-rate': 20, }, }, 'private': { 'get': { 'account/account-position-risk': 2, 'account/balance': 2, 'account/positions': 2, 'account/bills': 5 / 3, 'account/bills-archive': 5 / 3, 'account/config': 4, 'account/max-size': 1, 'account/max-avail-size': 1, 'account/leverage-info': 1, 'account/max-loan': 1, 'account/trade-fee': 4, 'account/interest-accrued': 4, 'account/interest-rate': 4, 'account/max-withdrawal': 1, 'account/risk-state': 2, 'account/borrow-repay-history': 4, 'account/interest-limits': 4, 'asset/asset-valuation': 1 / 5, 'asset/deposit-address': 5 / 3, 'asset/balances': 5 / 3, 'asset/transfer-state': 10, 'asset/deposit-history': 5 / 3, 'asset/withdrawal-history': 5 / 3, 'asset/currencies': 5 / 3, 'asset/bills': 5 / 3, 'asset/piggy-balance': 5 / 3, 'asset/deposit-lightning': 5, 'asset/lending-history': 5 / 3, 'asset/saving-balance': 5 / 3, 'trade/order': 1 / 3, 'trade/orders-pending': 1, 'trade/orders-history': 0.5, 'trade/orders-history-archive': 1, 'trade/fills': 1 / 3, 'trade/fills-history': 2, 'trade/orders-algo-pending': 1, 'trade/orders-algo-history': 1, 'account/subaccount/balances': 10, 'asset/subaccount/bills': 5 / 3, 'users/subaccount/list': 10, 'users/subaccount/apikey': 10, 'users/entrust-subaccount-list': 10, // broker 'broker/nd/info': 10, 'broker/nd/subaccount-info': 10, 'asset/broker/nd/subaccount-deposit-address': 4, 'asset/broker/nd/subaccount-deposit-history': 4, 'broker/nd/rebate-daily': 1, // convert 'asset/convert/currencies': 5 / 3, 'asset/convert/currency-pair': 5 / 3, 'asset/convert/estimate-quote': 5, 'asset/convert/trade': 5, 'asset/convert/history': 5 / 3, // options 'account/greeks': 2, }, 'post': { 'account/set-position-mode': 4, 'account/set-leverage': 1, 'account/position/margin-balance': 1, 'account/set-greeks': 4, 'account/set-isolated-mode': 4, 'account/simulated_margin': 10, 'account/borrow-repay': 5 / 3, 'asset/transfer': 10, 'asset/withdrawal': 5 / 3, 'asset/purchase_redempt': 5 / 3, 'asset/withdrawal-lightning': 5, 'asset/set-lending-rate': 5 / 3, '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 / 3, 'trade/close-position': 1, 'trade/order-algo': 1, 'trade/cancel-algos': 1, 'trade/cancel-advance-algos': 1, 'users/subaccount/delete-apikey': 10, 'users/subaccount/modify-apikey': 10, 'users/subaccount/apikey': 10, 'asset/subaccount/transfer': 10, // broker 'broker/nd/create-subaccount': 10, 'broker/nd/delete-subaccount': 10, 'broker/nd/set-subaccount-level': 4, 'broker/nd/set-subaccount-fee-rate': 4, 'asset/broker/nd/subaccount-deposit-address': 4, }, }, }, 'fees': { 'trading': { 'taker': this.parseNumber ('0.0015'), 'maker': this.parseNumber ('0.0010'), }, 'spot': { 'taker': this.parseNumber ('0.0015'), 'maker': this.parseNumber ('0.0010'), }, 'future': { 'taker': this.parseNumber ('0.0005'), 'maker': this.parseNumber ('0.0002'), }, 'swap': { 'taker': this.parseNumber ('0.00050'), 'maker': this.parseNumber ('0.00020'), }, }, 'requiredCredentials': { 'apiKey': true, 'secret': true, 'password': true, }, 'exceptions': { 'exact': { // Public error codes from 50000-53999 // General Class '1': ExchangeError, // Operation failed '2': ExchangeError, // Bulk operation partially succeeded '50000': BadRequest, // Body can not be empty '50001': OnMaintenance, // Matching engine upgrading. Please try again later '50002': BadRequest, // Json data format error '50004': RequestTimeout, // Endpoint request timeout (does not indicate success or failure of order, please check order status) '50005': ExchangeNotAvailable, // API is offline or unavailable '50006': BadRequest, // Invalid Content_Type, please use "application/json" format '50007': AccountSuspended, // Account blocked '50008': AuthenticationError, // User does not exist '50009': AccountSuspended, // Account is suspended due to ongoing liquidation '50010': ExchangeError, // User ID can not be empty '50011': RateLimitExceeded, // Request too frequent '50012': ExchangeError, // Account status invalid '50013': ExchangeNotAvailable, // System is busy, please try again later '50014': BadRequest, // Parameter {0} can not be empty '50015': ExchangeError, // Either parameter {0} or {1} is required '50016': ExchangeError, // Parameter {0} does not match parameter {1} '50017': ExchangeError, // The position is frozen due to ADL. Operation restricted '50018': ExchangeError, // Currency {0} is frozen due to ADL. Operation restricted '50019': ExchangeError, // The account is frozen due to ADL. Operation restricted '50020': ExchangeError, // The position is frozen due to liquidation. Operation restricted '50021': ExchangeError, // Currency {0} is frozen due to liquidation. Operation restricted '50022': ExchangeError, // The account is frozen due to liquidation. Operation restricted '50023': ExchangeError, // Funding fee frozen. Operation restricted '50024': BadRequest, // Parameter {0} and {1} can not exist at the same time '50025': ExchangeError, // Parameter {0} count exceeds the limit {1} '50026': ExchangeError, // System error '50027': PermissionDenied, // The account is restricted from trading '50028': ExchangeError, // Unable to take the order, please reach out to support center for details // API Class '50100': ExchangeError, // API frozen, please contact customer service '50101': AuthenticationError, // Broker id of APIKey does not match current environment '50102': InvalidNonce, // Timestamp request expired '50103': AuthenticationError, // Request header "OK_ACCESS_KEY" can not be empty '50104': AuthenticationError, // Request header "OK_ACCESS_PASSPHRASE" can not be empty '50105': AuthenticationError, // Request header "OK_ACCESS_PASSPHRASE" incorrect '50106': AuthenticationError, // Request header "OK_ACCESS_SIGN" can not be empty '50107': AuthenticationError, // Request header "OK_ACCESS_TIMESTAMP" can not be empty '50108': ExchangeError, // Exchange ID does not exist '50109': ExchangeError, // Exchange domain does not exist '50110': PermissionDenied, // Invalid IP '50111': AuthenticationError, // Invalid OK_ACCESS_KEY '50112': AuthenticationError, // Invalid OK_ACCESS_TIMESTAMP '50113': AuthenticationError, // Invalid signature '50114': AuthenticationError, // Invalid authorization '50115': BadRequest, // Invalid request method // Trade Class '51000': BadRequest, // Parameter {0} error '51001': BadSymbol, // Instrument ID does not exist '51002': BadSymbol, // Instrument ID does not match underlying index '51003': BadRequest, // Either client order ID or order ID is required '51004': InvalidOrder, // Order amount exceeds current tier limit '51005': InvalidOrder, // Order amount exceeds the limit '51006': InvalidOrder, // Order price out of the limit '51007': InvalidOrder, // Order placement failed. Order amount should be at least 1 contract (showing up when placing an order with less than 1 contract) '51008': InsufficientFunds, // Order placement failed due to insufficient balance '51009': AccountSuspended, // Order placement function is blocked by the platform '51010': AccountNotEnabled, // Account level too low {"code":"1","data":[{"clOrdId":"uJrfGFth9F","ordId":"","sCode":"51010","sMsg":"The current account mode does not support this API interface. ","tag":""}],"msg":"Operation failed."} '51011': InvalidOrder, // Duplicated order ID '51012': BadSymbol, // Token does not exist '51014': BadSymbol, // Index does not exist '51015': BadSymbol, // Instrument ID does not match instrument type '51016': InvalidOrder, // Duplicated client order ID '51017': ExchangeError, // Borrow amount exceeds the limit '51018': ExchangeError, // User with option account can not hold net short positions '51019': ExchangeError, // No net long positions can be held under isolated margin mode in options '51020': InvalidOrder, // Order amount should be greater than the min available amount '51021': BadSymbol, // Contract to be listed '51022': BadSymbol, // Contract suspended '51023': ExchangeError, // Position does not exist '51024': AccountSuspended, // Unified accountblocked '51025': ExchangeError, // Order count exceeds the limit '51026': BadSymbol, // Instrument type does not match underlying index '51027': BadSymbol, // Contract expired '51028': BadSymbol, // Contract under delivery '51029': BadSymbol, // Contract is being settled '51030': BadSymbol, // Funding fee is being settled '51031': InvalidOrder, // This order price is not within the closing price range '51100': InvalidOrder, // Trading amount does not meet the min tradable amount '51101': InvalidOrder, // Entered amount exceeds the max pending order amount (Cont) per transaction '51102': InvalidOrder, // Entered amount exceeds the max pending count '51103': InvalidOrder, // Entered amount exceeds the max pending order count of the underlying asset '51104': InvalidOrder, // Entered amount exceeds the max pending order amount (Cont) of the underlying asset '51105': InvalidOrder, // Entered amount exceeds the max order amount (Cont) of the contract '51106': InvalidOrder, // Entered amount exceeds the max order amount (Cont) of the underlying asset '51107': InvalidOrder, // Entered amount exceeds the max holding amount (Cont) '51108': InvalidOrder, // Positions exceed the limit for closing out with the market price '51109': InvalidOrder, // No available offer '51110': InvalidOrder, // You can only place a limit order after Call Auction has started '51111': BadRequest, // Maximum {0} orders can be placed in bulk '51112': InvalidOrder, // Close order size exceeds your available size '51113': RateLimitExceeded, // Market-price liquidation requests too frequent '51115': InvalidOrder, // Cancel all pending close-orders before liquidation '51116': InvalidOrder, // Order price or trigger price exceeds {0} '51117': InvalidOrder, // Pending close-orders count exceeds limit '51118': InvalidOrder, // Total amount should exceed the min amount per order '51119': InsufficientFunds, // Order placement failed due to insufficient balance '51120': InvalidOrder, // Order quantity is less than {0}, please try again '51121': InvalidOrder, // Order count should be the integer multiples of the lot size '51122': InvalidOrder, // Order price should be higher than the min price {0} '51124': InvalidOrder, // You can only place limit orders during call auction '51125': InvalidOrder, // Currently there are reduce + reverse position pending orders in margin trading. Please cancel all reduce + reverse position pending orders and continue '51126': InvalidOrder, // Currently there are reduce only pending orders in margin trading.Please cancel all reduce only pending orders and continue '51127': InsufficientFunds, // Available balance is 0 '51128': InvalidOrder, // Multi-currency margin account can not do cross-margin trading '51129': InvalidOrder, // The value of the position and buy order has reached the position limit, and no further buying is allowed '51130': BadSymbol, // Fixed margin currency error '51131': InsufficientFunds, // Insufficient balance '51132': InvalidOrder, // Your position amount is negative and less than the minimum trading amount '51133': InvalidOrder, // Reduce-only feature is unavailable for the spot transactions by multi-currency margin account '51134': InvalidOrder, // Closing failed. Please check your holdings and pending orders '51135': InvalidOrder, // Your closing price has triggered the limit price, and the max buy price is {0} '51136': InvalidOrder, // Your closing price has triggered the limit price, and the min sell price is {0} '51137': InvalidOrder, // Your opening price has triggered the limit price, and the max buy price is {0} '51138': InvalidOrder, // Your opening price has triggered the limit price, and the min sell price is {0} '51139': InvalidOrder, // Reduce-only feature is unavailable for the spot transactions by simple account '51201': InvalidOrder, // Value of per market order cannot exceed 100,000 USDT '51202': InvalidOrder, // Market - order amount exceeds the max amount '51203': InvalidOrder, // Order amount exceeds the limit {0} '51204': InvalidOrder, // The price for the limit order can not be empty '51205': InvalidOrder, // Reduce-Only is not available '51250': InvalidOrder, // Algo order price is out of the available range '51251': InvalidOrder, // Algo order type error (when user place an iceberg order) '51252': InvalidOrder, // Algo order price is out of the available range '51253': InvalidOrder, // Average amount exceeds the limit of per iceberg order '51254': InvalidOrder, // Iceberg average amount error (when user place an iceberg order) '51255': InvalidOrder, // Limit of per iceberg order: Total amount/1000 < x <= Total amount '51256': InvalidOrder, // Iceberg order price variance error '51257': InvalidOrder, // Trail order callback rate error '51258': InvalidOrder, // Trail - order placement failed. The trigger price of a sell order should be higher than the last transaction price '51259': InvalidOrder, // Trail - order placement failed. The trigger price of a buy order should be lower than the last transaction price '51260': InvalidOrder, // Maximum {0} pending trail - orders can be held at the same time '51261': InvalidOrder, // Each user can hold up to {0} pending stop - orders at the same time '51262': InvalidOrder, // Maximum {0} pending iceberg orders can be held at the same time '51263': InvalidOrder, // Maximum {0} pending time-weighted orders can be held at the same time '51264': InvalidOrder, // Average amount exceeds the limit of per time-weighted order '51265': InvalidOrder, // Time-weighted order limit error '51267': InvalidOrder, // Time-weighted order strategy initiative rate error '51268': InvalidOrder, // Time-weighted order strategy initiative range error '51269': InvalidOrder, // Time-weighted order interval error, the interval should be {0}<= x<={1} '51270': InvalidOrder, // The limit of time-weighted order price variance is 0 < x <= 1% '51271': InvalidOrder, // Sweep ratio should be 0 < x <= 100% '51272': InvalidOrder, // Price variance should be 0 < x <= 1% '51273': InvalidOrder, // Total amount should be more than {0} '51274': InvalidOrder, // Total quantity of time-weighted order must be larger than single order limit '51275': InvalidOrder, // The amount of single stop-market order can not exceed the upper limit '51276': InvalidOrder, // Stop - Market orders cannot specify a price '51277': InvalidOrder, // TP trigger price can not be higher than the last price '51278': InvalidOrder, // SL trigger price can not be lower than the last price '51279': InvalidOrder, // TP trigger price can not be lower than the last price '51280': InvalidOrder, // SL trigger price can not be higher than the last price '51400': OrderNotFound, // Cancellation failed as the order does not exist '51401': OrderNotFound, // Cancellation failed as the order is already canceled '51402': OrderNotFound, // Cancellation failed as the order is already completed '51403': InvalidOrder, // Cancellation failed as the order type does not support cancellation '51404': InvalidOrder, // Order cancellation unavailable during the second phase of call auction '51405': ExchangeError, // Cancellation failed as you do not have any pending orders '51406': ExchangeError, // Canceled - order count exceeds the limit {0} '51407': BadRequest, // Either order ID or client order ID is required '51408': ExchangeError, // Pair ID or name does not match the order info '51409': ExchangeError, // Either pair ID or pair name ID is required '51410': CancelPending, // Cancellation failed as the order is already under cancelling status '51500': ExchangeError, // Either order price or amount is required '51501': ExchangeError, // Maximum {0} orders can be modified '51502': InsufficientFunds, // Order modification failed for insufficient margin '51503': ExchangeError, // Order modification failed as the order does not exist '51506': ExchangeError, // Order modification unavailable for the order type '51508': ExchangeError, // Orders are not allowed to be modified during the call auction '51509': ExchangeError, // Modification failed as the order has been canceled '51510': ExchangeError, // Modification failed as the order has been completed '51511': ExchangeError, // Modification failed as the order price did not meet the requirement for Post Only '51600': ExchangeError, // Status not found '51601': ExchangeError, // Order status and order ID cannot exist at the same time '51602': ExchangeError, // Either order status or order ID is required '51603': OrderNotFound, // Order does not exist // Data class '52000': ExchangeError, // No updates // SPOT/MARGIN error codes 54000-54999 '54000': ExchangeError, // Margin transactions unavailable '54001': ExchangeError, // Only Multi-currency margin account can be set to borrow coins automatically // FUNDING error codes 58000-58999 '58000': ExchangeError, // Account type {0} does not supported when getting the sub-account balance '58001': AuthenticationError, // Incorrect trade password '58002': PermissionDenied, // Please activate Savings Account first '58003': ExchangeError, // Currency type is not supported by Savings Account '58004': AccountSuspended, // Account blocked (transfer & withdrawal endpoint: either end of the account does not authorize the transfer) '58005': ExchangeError, // The redeemed amount must be no greater than {0} '58006': ExchangeError, // Service unavailable for token {0} '58007': ExchangeError, // Abnormal Assets interface. Please try again later '58100': ExchangeError, // The trading product triggers risk control, and the platform has suspended the fund transfer-out function with related users. Please wait patiently '58101': AccountSuspended, // Transfer suspended (transfer endpoint: either end of the account does not authorize the transfer) '58102': RateLimitExceeded, // Too frequent transfer (transfer too frequently) '58103': ExchangeError, // Parent account user id does not match sub-account user id '58104': ExchangeError, // Since your P2P transaction is abnormal, you are restricted from making fund transfers. Please contact customer support to remove the restriction '58105': ExchangeError, // Since your P2P transaction is abnormal, you are restricted from making fund transfers. Please transfer funds on our website or app to complete identity verification '58106': ExchangeError, // Please enable the account for spot contract '58107': ExchangeError, // Please enable the account for futures contract '58108': ExchangeError, // Please enable the account for option contract '58109': ExchangeError, // Please enable the account for swap contract '58110': ExchangeError, // The contract triggers risk control, and the platform has suspended the fund transfer function of it. Please wait patiently '58111': ExchangeError, // Funds transfer unavailable as the perpetual contract is charging the funding fee. Please try again later '58112': ExchangeError, // Your fund transfer failed. Please try again later '58114': ExchangeError, // Transfer amount must be more than 0 '58115': ExchangeError, // Sub-account does not exist '58116': ExchangeError, // Transfer amount exceeds the limit '58117': ExchangeError, // Account assets are abnormal, please deal with negative assets before transferring '58200': ExchangeError, // Withdrawal from {0} to {1} is unavailable for this currency '58201': ExchangeError, // Withdrawal amount exceeds the daily limit '58202': ExchangeError, // The minimum withdrawal amount for NEO is 1, and the amount must be an integer '58203': InvalidAddress, // Please add a withdrawal address '58204': AccountSuspended, // Withdrawal suspended '58205': ExchangeError, // Withdrawal amount exceeds the upper limit '58206': ExchangeError, // Withdrawal amount is lower than the lower limit '58207': InvalidAddress, // Withdrawal failed due to address error '58208': ExchangeError, // Withdrawal failed. Please link your email '58209': ExchangeError, // Withdrawal failed. Withdraw feature is not available for sub-accounts '58210': ExchangeError, // Withdrawal fee exceeds the upper limit '58211': ExchangeError, // Withdrawal fee is lower than the lower limit (withdrawal endpoint: incorrect fee) '58212': ExchangeError, // Withdrawal fee should be {0}% of the withdrawal amount '58213': AuthenticationError, // Please set trading password before withdrawal '58300': ExchangeError, // Deposit-address count exceeds the limit '58350': InsufficientFunds, // Insufficient balance // Account error codes 59000-59999 '59000': ExchangeError, // Your settings failed as you have positions or open orders '59001': ExchangeError, // Switching unavailable as you have borrowings '59100': ExchangeError, // You have open positions. Please cancel all open positions before changing the leverage '59101': ExchangeError, // You have pending orders with isolated positions. Please cancel all the pending orders and adjust the leverage '59102': ExchangeError, // Leverage exceeds the maximum leverage. Please adjust the leverage '59103': InsufficientFunds, // Leverage is too low and no sufficient margin in your account. Please adjust the leverage '59104': ExchangeError, // The leverage is too high. The borrowed position has exceeded the maximum position of this leverage. Please adjust the leverage '59105': ExchangeError, // Leverage can not be less than {0}. Please adjust the leverage '59106': ExchangeError, // The max available margin corresponding to your order tier is {0}. Please adjust your margin and place a new order '59107': ExchangeError, // You have pending orders under the service, please modify the leverage after canceling all pending orders '59108': InsufficientFunds, // Low leverage and insufficient margin, please adjust the leverage '59109': ExchangeError, // Account equity less than the required margin amount after adjustment. Please adjust the leverage '59200': InsufficientFunds, // Insufficient account balance '59201': InsufficientFunds, // Negative account balance '59300': ExchangeError, // Margin call failed. Position does not exist '59301': ExchangeError, // Margin adjustment failed for exceeding the max limit '59401': ExchangeError, // Holdings already reached the limit '59500': ExchangeError, // Only the APIKey of the main account has permission '59501': ExchangeError, // Only 50 APIKeys can be created per account '59502': ExchangeError, // Note name cannot be duplicate with the currently created APIKey note name '59503': ExchangeError, // Each APIKey can bind up to 20 IP addresses '59504': ExchangeError, // The sub account does not support the withdrawal function '59505': ExchangeError, // The passphrase format is incorrect '59506': ExchangeError, // APIKey does not exist '59507': ExchangeError, // The two accounts involved in a transfer must be two different sub accounts under the same parent account '59508': AccountSuspended, // The sub account of {0} is suspended // WebSocket error Codes from 60000-63999 '60001': AuthenticationError, // "OK_ACCESS_KEY" can not be empty '60002': AuthenticationError, // "OK_ACCESS_SIGN" can not be empty '60003': AuthenticationError, // "OK_ACCESS_PASSPHRASE" can not be empty '60004': AuthenticationError, // Invalid OK_ACCESS_TIMESTAMP '60005': AuthenticationError, // Invalid OK_ACCESS_KEY '60006': InvalidNonce, // Timestamp request expired '60007': AuthenticationError, // Invalid sign '60008': AuthenticationError, // Login is not supported for public channels '60009': AuthenticationError, // Login failed '60010': AuthenticationError, // Already logged in '60011': AuthenticationError, // Please log in '60012': BadRequest, // Illegal request '60013': BadRequest, // Invalid args '60014': RateLimitExceeded, // Requests too frequent '60015': NetworkError, // Connection closed as there was no data transmission in the last 30 seconds '60016': ExchangeNotAvailable, // Buffer is full, cannot write data '60017': BadRequest, // Invalid url path '60018': BadRequest, // The {0} {1} {2} {3} {4} does not exist '60019': BadRequest, // Invalid op {op} '63999': ExchangeError, // Internal system error }, 'broad': { }, }, 'httpExceptions': { '429': ExchangeNotAvailable, // https://github.com/ccxt/ccxt/issues/9612 }, 'precisionMode': TICK_SIZE, 'options': { 'defaultNetwork': 'ERC20', 'networks': { 'ETH': 'ERC20', 'TRX': 'TRC20', 'OMNI': 'Omni', 'SOLANA': 'Solana', 'POLYGON': 'Polygon', 'OEC': 'OEC', 'ALGO': 'ALGO', // temporarily unavailable }, 'layerTwo': { 'Lightning': true, 'Liquid': true, }, 'fetchOHLCV': { // 'type': 'Candles', // Candles or HistoryCandles, IndexCandles, MarkPriceCandles }, 'createOrder': 'privatePostTradeBatchOrders', // or 'privatePostTradeOrder' or 'privatePostTradeOrderAlgo' 'createMarketBuyOrderRequiresPrice': false, 'fetchMarkets': [ 'spot', 'future', 'swap', 'option' ], // spot, future, swap, option 'defaultType': 'spot', // 'funding', 'spot', 'margin', 'future', 'swap', 'option' // 'fetchBalance': { // 'type': 'spot', // 'funding', 'trading', 'spot' // }, 'fetchLedger': { 'method': 'privateGetAccountBills', // privateGetAccountBillsArchive, privateGetAssetBills }, // 1 = SPOT, 3 = FUTURES, 5 = MARGIN, 6 = FUNDING, 9 = SWAP, 12 = OPTION, 18 = Unified account 'fetchOrder': { 'method': 'privateGetTradeOrder', // privateGetTradeOrdersAlgoHistory }, 'fetchOpenOrders': { 'method': 'privateGetTradeOrdersPending', // privateGetTradeOrdersAlgoPending }, 'cancelOrders': { 'method': 'privatePostTradeCancelBatchOrders', // privatePostTradeCancelAlgos }, 'fetchCanceledOrders': { 'method': 'privateGetTradeOrdersHistory', // privateGetTradeOrdersAlgoHistory }, 'algoOrderTypes': { 'conditional': true, 'trigger': true, 'oco': true, 'move_order_stop': true, 'iceberg': true, 'twap': true, }, 'accountsByType': { 'spot': '1', 'future': '3', 'futures': '3', 'margin': '5', 'funding': '6', 'swap': '9', 'option': '12', 'trading': '18', // unified trading account }, 'accountsById': { '1': 'spot', '3': 'future', '5': 'margin', '6': 'funding', '9': 'swap', '12': 'option', '18': 'trading', // unified trading account }, 'exchangeType': { 'spot': 'SPOT', 'margin': 'MARGIN', 'swap': 'SWAP', 'future': 'FUTURES', 'futures': 'FUTURES', // deprecated 'option': 'OPTION', 'SPOT': 'SPOT', 'MARGIN': 'MARGIN', 'SWAP': 'SWAP', 'FUTURES': 'FUTURES', 'OPTION': 'OPTION', }, 'brokerId': 'e847386590ce4dBC', }, 'commonCurrencies': { // the exchange refers to ERC20 version of Aeternity (AEToken) 'AE': 'AET', // https://github.com/ccxt/ccxt/issues/4981 '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 }, }); } handleMarketTypeAndParams (methodName, market = undefined, params = {}) { const instType = this.safeString (params, 'instType'); params = this.omit (params, 'instType'); const type = this.safeString (params, 'type'); if ((type === undefined) && (instType !== undefined)) { params['type'] = instType; } return super.handleMarketTypeAndParams (methodName, market, params); } convertToInstrumentType (type) { const exchangeTypes = this.safeValue (this.options, 'exchangeType', {}); return this.safeString (exchangeTypes, type, type); } async fetchStatus (params = {}) { const response = await this.publicGetSystemStatus (params); // // Note, if there is no maintenance around, the 'data' array is empty // // { // "code": "0", // "msg": "", // "data": [ // { // "begin": "1621328400000", // "end": "1621329000000", // "href": "https://www.okx.com/support/hc/en-us/articles/360060882172", // "scheDesc": "", // "serviceType": "1", // 0 WebSocket, 1 Spot/Margin, 2 Futures, 3 Perpetual, 4 Options, 5 Trading service // "state": "scheduled", // ongoing, completed, canceled // "system": "classic", // classic, unified // "title": "Classic Spot System Upgrade" // }, // ] // } // const data = this.safeValue (response, 'data', []); const dataLength = data.length; const timestamp = this.milliseconds (); const update = { 'updated': timestamp, 'status': (dataLength === 0) ? 'ok' : 'maintenance', 'eta': undefined, 'url': undefined, 'info': response, }; for (let i = 0; i < data.length; i++) { const event = data[i]; const state = this.safeString (event, 'state'); if (state === 'ongoing') { update['eta'] = this.safeInteger (event, 'end'); update['status'] = 'maintenance'; } } return update; } async fetchTime (params = {}) { const response = await this.publicGetPublicTime (params); // // { // "code": "0", // "data": [ // {"ts": "1621247923668"} // ], // "msg": "" // } // const data = this.safeValue (response, 'data', []); const first = this.safeValue (data, 0, {}); return this.safeInteger (first, 'ts'); } async fetchAccounts (params = {}) { const response = await this.privateGetAccountConfig (params); // // { // "code": "0", // "data": [ // { // "acctLv": "2", // "autoLoan": false, // "ctIsoMode": "automatic", // "greeksType": "PA", // "level": "Lv1", // "levelTmp": "", // "mgnIsoMode": "automatic", // "posMode": "long_short_mode", // "uid": "88018754289672195" // } // ], // "msg": "" // } // const data = this.safeValue (response, 'data', []); const result = []; for (let i = 0; i < data.length; i++) { const account = data[i]; const accountId = this.safeString (account, 'uid'); const type = this.safeString (account, 'acctLv'); result.push ({ 'id': accountId, 'type': type, 'currency': undefined, 'info': account, }); } return result; } async fetchMarkets (params = {}) { const types = this.safeValue (this.options, 'fetchMarkets'); let promises = []; let result = []; for (let i = 0; i < types.length; i++) { promises.push (this.fetchMarketsByType (types[i], params)); } // why not both ¯\_(ツ)_/¯ promises = await Promise.all (promises); for (let i = 0; i < promises.length; i++) { result = this.arrayConcat (result, promises[i]); } return result; } parseMarkets (markets) { const result = []; for (let i = 0; i < markets.length; i++) { result.push (this.parseMarket (markets[i])); } return result; } parseMarket (market) { // // { // "ali