ccxt-look
Version:
827 lines (815 loc) • 214 kB
JavaScript
'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