UNPKG

@jalmonter/ccxt

Version:

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

1,038 lines (1,036 loc) 315 kB
'use strict'; var gate$1 = require('./abstract/gate.js'); var Precise = require('./base/Precise.js'); var number = require('./base/functions/number.js'); var errors = require('./base/errors.js'); var sha512 = require('./static_dependencies/noble-hashes/sha512.js'); // --------------------------------------------------------------------------- /** * @class gate * @augments Exchange */ class gate extends gate$1 { describe() { return this.deepExtend(super.describe(), { 'id': 'gate', 'name': 'Gate.io', 'countries': ['KR'], 'rateLimit': 50, 'version': 'v4', 'certified': true, 'pro': true, 'urls': { 'logo': 'https://user-images.githubusercontent.com/1294454/31784029-0313c702-b509-11e7-9ccc-bc0da6a0e435.jpg', 'doc': 'https://www.gate.io/docs/developers/apiv4/en/', 'www': 'https://gate.io/', 'api': { 'public': { 'wallet': 'https://api.gateio.ws/api/v4', 'futures': 'https://api.gateio.ws/api/v4', 'margin': 'https://api.gateio.ws/api/v4', 'delivery': 'https://api.gateio.ws/api/v4', 'spot': 'https://api.gateio.ws/api/v4', 'options': 'https://api.gateio.ws/api/v4', 'sub_accounts': 'https://api.gateio.ws/api/v4', 'earn': 'https://api.gateio.ws/api/v4', }, 'private': { 'withdrawals': 'https://api.gateio.ws/api/v4', 'wallet': 'https://api.gateio.ws/api/v4', 'futures': 'https://api.gateio.ws/api/v4', 'margin': 'https://api.gateio.ws/api/v4', 'delivery': 'https://api.gateio.ws/api/v4', 'spot': 'https://api.gateio.ws/api/v4', 'options': 'https://api.gateio.ws/api/v4', 'subAccounts': 'https://api.gateio.ws/api/v4', 'portfolio': 'https://api.gateio.ws/api/v4', 'rebate': 'https://api.gateio.ws/api/v4', 'earn': 'https://api.gateio.ws/api/v4', 'account': 'https://api.gateio.ws/api/v4', }, }, 'test': { 'public': { 'futures': 'https://fx-api-testnet.gateio.ws/api/v4', 'delivery': 'https://fx-api-testnet.gateio.ws/api/v4', 'options': 'https://fx-api-testnet.gateio.ws/api/v4', }, 'private': { 'futures': 'https://fx-api-testnet.gateio.ws/api/v4', 'delivery': 'https://fx-api-testnet.gateio.ws/api/v4', 'options': 'https://fx-api-testnet.gateio.ws/api/v4', }, }, 'referral': { 'url': 'https://www.gate.io/signup/2436035', 'discount': 0.2, }, }, 'has': { 'CORS': undefined, 'spot': true, 'margin': true, 'swap': true, 'future': true, 'option': true, 'addMargin': true, 'borrowCrossMargin': true, 'borrowIsolatedMargin': true, 'cancelAllOrders': true, 'cancelOrder': true, 'createMarketOrder': true, 'createOrder': true, 'createOrders': true, 'createPostOnlyOrder': true, 'createReduceOnlyOrder': true, 'createStopLimitOrder': true, 'createStopMarketOrder': false, 'createStopOrder': true, 'editOrder': true, 'fetchBalance': true, 'fetchBorrowRateHistories': false, 'fetchBorrowRateHistory': false, 'fetchClosedOrders': true, 'fetchCrossBorrowRate': false, 'fetchCrossBorrowRates': false, 'fetchCurrencies': true, 'fetchDepositAddress': true, 'fetchDeposits': true, 'fetchDepositWithdrawFee': 'emulated', 'fetchDepositWithdrawFees': true, 'fetchFundingHistory': true, 'fetchFundingRate': true, 'fetchFundingRateHistory': true, 'fetchFundingRates': true, 'fetchGreeks': true, 'fetchIndexOHLCV': true, 'fetchIsolatedBorrowRate': false, 'fetchIsolatedBorrowRates': false, 'fetchLedger': true, 'fetchLeverage': false, 'fetchLeverageTiers': true, 'fetchLiquidations': true, 'fetchMarginMode': false, 'fetchMarketLeverageTiers': 'emulated', 'fetchMarkets': true, 'fetchMarkOHLCV': true, 'fetchMyLiquidations': true, 'fetchMySettlementHistory': true, 'fetchMyTrades': true, 'fetchNetworkDepositAddress': true, 'fetchOHLCV': true, 'fetchOpenInterest': false, 'fetchOpenInterestHistory': true, 'fetchOpenOrders': true, 'fetchOrder': true, 'fetchOrderBook': true, 'fetchPosition': true, 'fetchPositionMode': false, 'fetchPositions': true, 'fetchPremiumIndexOHLCV': false, 'fetchSettlementHistory': true, 'fetchTicker': true, 'fetchTickers': true, 'fetchTime': false, 'fetchTrades': true, 'fetchTradingFee': true, 'fetchTradingFees': true, 'fetchTransactionFees': true, 'fetchUnderlyingAssets': true, 'fetchVolatilityHistory': false, 'fetchWithdrawals': true, 'reduceMargin': true, 'repayCrossMargin': true, 'repayIsolatedMargin': true, 'setLeverage': true, 'setMarginMode': false, 'setPositionMode': true, 'signIn': false, 'transfer': true, 'withdraw': true, }, 'api': { 'public': { // All public endpoints 200r/10s per endpoint 'wallet': { 'get': { 'currency_chains': 1, }, }, 'spot': { 'get': { 'currencies': 1, 'currencies/{currency}': 1, 'currency_pairs': 1, 'currency_pairs/{currency_pair}': 1, 'tickers': 1, 'order_book': 1, 'trades': 1, 'candlesticks': 1, 'time': 1, }, }, 'margin': { 'get': { 'currency_pairs': 1, 'currency_pairs/{currency_pair}': 1, 'funding_book': 1, 'cross/currencies': 1, 'cross/currencies/{currency}': 1, 'uni/currency_pairs': 1, 'uni/currency_pairs/{currency_pair}': 1, }, }, 'flash_swap': { 'get': { 'currencies': 1, }, }, 'futures': { 'get': { '{settle}/contracts': 1, '{settle}/contracts/{contract}': 1, '{settle}/order_book': 1, '{settle}/trades': 1, '{settle}/candlesticks': 1, '{settle}/premium_index': 1, '{settle}/tickers': 1, '{settle}/funding_rate': 1, '{settle}/insurance': 1, '{settle}/contract_stats': 1, '{settle}/index_constituents/{index}': 1, '{settle}/liq_orders': 1, }, }, 'delivery': { 'get': { '{settle}/contracts': 1, '{settle}/contracts/{contract}': 1, '{settle}/order_book': 1, '{settle}/trades': 1, '{settle}/candlesticks': 1, '{settle}/tickers': 1, '{settle}/insurance': 1, }, }, 'options': { 'get': { 'underlyings': 1, 'expirations': 1, 'contracts': 1, 'contracts/{contract}': 1, 'settlements': 1, 'settlements/{contract}': 1, 'order_book': 1, 'tickers': 1, 'underlying/tickers/{underlying}': 1, 'candlesticks': 1, 'underlying/candlesticks': 1, 'trades': 1, }, }, 'earn': { 'get': { 'uni/currencies': 1, 'uni/currencies/{currency}': 1, }, }, }, 'private': { // private endpoints default is 150r/10s per endpoint 'withdrawals': { 'post': { 'withdrawals': 20, // 1r/s cost = 20 / 1 = 20 }, 'delete': { 'withdrawals/{withdrawal_id}': 1, }, }, 'wallet': { 'get': { 'deposit_address': 1, 'withdrawals': 1, 'deposits': 1, 'sub_account_transfers': 1, 'withdraw_status': 1, 'sub_account_balances': 2.5, 'sub_account_margin_balances': 2.5, 'sub_account_futures_balances': 2.5, 'sub_account_cross_margin_balances': 2.5, 'saved_address': 1, 'fee': 1, 'total_balance': 2.5, }, 'post': { 'transfers': 2.5, 'sub_account_transfers': 2.5, 'sub_account_to_sub_account': 2.5, }, }, 'subAccounts': { 'get': { 'sub_accounts': 2.5, 'sub_accounts/{user_id}': 2.5, 'sub_accounts/{user_id}/keys': 2.5, 'sub_accounts/{user_id}/keys/{key}': 2.5, }, 'post': { 'sub_accounts': 2.5, 'sub_accounts/{user_id}/keys': 2.5, 'sub_accounts/{user_id}/lock': 2.5, 'sub_accounts/{user_id}/unlock': 2.5, }, 'put': { 'sub_accounts/{user_id}/keys/{key}': 2.5, }, 'delete': { 'sub_accounts/{user_id}/keys/{key}': 2.5, }, }, 'portfolio': { 'get': { 'accounts': 20 / 15, 'account_mode': 20 / 15, 'borrowable': 20 / 15, 'transferable': 20 / 15, 'loans': 20 / 15, 'loan_records': 20 / 15, 'interest_records': 20 / 15, }, 'post': { 'account_mode': 20 / 15, 'loans': 200 / 15, // 15r/10s cost = 20 / 1.5 = 13.33 }, }, 'spot': { // default is 200r/10s 'get': { 'fee': 1, 'batch_fee': 1, 'accounts': 1, 'account_book': 1, 'open_orders': 1, 'orders': 1, 'orders/{order_id}': 1, 'my_trades': 1, 'price_orders': 1, 'price_orders/{order_id}': 1, }, 'post': { 'batch_orders': 0.4, 'cross_liquidate_orders': 1, 'orders': 0.4, 'cancel_batch_orders': 20 / 75, 'countdown_cancel_all': 20 / 75, 'amend_batch_orders': 0.4, 'price_orders': 0.4, }, 'delete': { 'orders': 20 / 75, 'orders/{order_id}': 20 / 75, 'price_orders': 20 / 75, 'price_orders/{order_id}': 20 / 75, }, 'patch': { 'orders/{order_id}': 0.4, }, }, 'margin': { 'get': { 'accounts': 20 / 15, 'account_book': 20 / 15, 'funding_accounts': 20 / 15, 'auto_repay': 20 / 15, 'transferable': 20 / 15, 'loans': 20 / 15, 'loans/{loan_id}': 20 / 15, 'loans/{loan_id}/repayment': 20 / 15, 'loan_records': 20 / 15, 'loan_records/{loan_record_id}': 20 / 15, 'borrowable': 20 / 15, 'cross/accounts': 20 / 15, 'cross/account_book': 20 / 15, 'cross/loans': 20 / 15, 'cross/loans/{loan_id}': 20 / 15, 'cross/repayments': 20 / 15, 'cross/interest_records': 20 / 15, 'cross/transferable': 20 / 15, 'cross/estimate_rate': 20 / 15, 'cross/borrowable': 20 / 15, 'uni/estimate_rate': 20 / 15, 'uni/loans': 20 / 15, 'uni/loan_records': 20 / 15, 'uni/interest_records': 20 / 15, 'uni/borrowable': 20 / 15, }, 'post': { 'auto_repay': 20 / 15, 'loans': 20 / 15, 'merged_loans': 20 / 15, 'loans/{loan_id}/repayment': 20 / 15, 'cross/loans': 20 / 15, 'cross/repayments': 20 / 15, 'uni/loans': 20 / 15, }, 'patch': { 'loans/{loan_id}': 20 / 15, 'loan_records/{loan_record_id}': 20 / 15, }, 'delete': { 'loans/{loan_id}': 20 / 15, }, }, 'flash_swap': { 'get': { 'currencies': 1, 'currency_pairs': 1, 'orders': 1, 'orders/{order_id}': 1, }, 'post': { 'orders': 1, 'orders/preview': 1, }, }, 'futures': { 'get': { '{settle}/accounts': 1, '{settle}/account_book': 1, '{settle}/positions': 1, '{settle}/positions/{contract}': 1, '{settle}/dual_comp/positions/{contract}': 1, '{settle}/orders': 1, '{settle}/orders_timerange': 1, '{settle}/orders/{order_id}': 1, '{settle}/my_trades': 1, '{settle}/my_trades_timerange': 1, '{settle}/position_close': 1, '{settle}/liquidates': 1, '{settle}/auto_deleverages': 1, '{settle}/fee': 1, '{settle}/price_orders': 1, '{settle}/price_orders/{order_id}': 1, }, 'post': { '{settle}/positions/{contract}/margin': 1, '{settle}/positions/{contract}/leverage': 1, '{settle}/positions/{contract}/risk_limit': 1, '{settle}/dual_mode': 1, '{settle}/dual_comp/positions/{contract}/margin': 1, '{settle}/dual_comp/positions/{contract}/leverage': 1, '{settle}/dual_comp/positions/{contract}/risk_limit': 1, '{settle}/orders': 0.4, '{settle}/batch_orders': 0.4, '{settle}/countdown_cancel_all': 0.4, '{settle}/price_orders': 0.4, }, 'put': { '{settle}/orders/{order_id}': 1, }, 'delete': { '{settle}/orders': 20 / 75, '{settle}/orders/{order_id}': 20 / 75, '{settle}/price_orders': 20 / 75, '{settle}/price_orders/{order_id}': 20 / 75, }, }, 'delivery': { 'get': { '{settle}/accounts': 20 / 15, '{settle}/account_book': 20 / 15, '{settle}/positions': 20 / 15, '{settle}/positions/{contract}': 20 / 15, '{settle}/orders': 20 / 15, '{settle}/orders/{order_id}': 20 / 15, '{settle}/my_trades': 20 / 15, '{settle}/position_close': 20 / 15, '{settle}/liquidates': 20 / 15, '{settle}/settlements': 20 / 15, '{settle}/price_orders': 20 / 15, '{settle}/price_orders/{order_id}': 20 / 15, }, 'post': { '{settle}/positions/{contract}/margin': 20 / 15, '{settle}/positions/{contract}/leverage': 20 / 15, '{settle}/positions/{contract}/risk_limit': 20 / 15, '{settle}/orders': 20 / 15, '{settle}/price_orders': 20 / 15, }, 'delete': { '{settle}/orders': 20 / 15, '{settle}/orders/{order_id}': 20 / 15, '{settle}/price_orders': 20 / 15, '{settle}/price_orders/{order_id}': 20 / 15, }, }, 'options': { 'get': { 'my_settlements': 20 / 15, 'accounts': 20 / 15, 'account_book': 20 / 15, 'positions': 20 / 15, 'positions/{contract}': 20 / 15, 'position_close': 20 / 15, 'orders': 20 / 15, 'orders/{order_id}': 20 / 15, 'my_trades': 20 / 15, }, 'post': { 'orders': 20 / 15, }, 'delete': { 'orders': 20 / 15, 'orders/{order_id}': 20 / 15, }, }, 'earn': { 'get': { 'uni/currencies': 20 / 15, 'uni/currencies/{currency}': 20 / 15, 'uni/lends': 20 / 15, 'uni/lend_records': 20 / 15, 'uni/interests/{currency}': 20 / 15, 'uni/interest_records': 20 / 15, 'uni/interest_status/{currency}': 20 / 15, }, 'post': { 'uni/lends': 20 / 15, }, 'put': { 'uni/interest_reinvest': 20 / 15, }, 'patch': { 'uni/lends': 20 / 15, }, }, 'loan': { 'get': { 'collateral/orders': 20 / 15, 'collateral/orders/{order_id}': 20 / 15, 'collateral/repay_records': 20 / 15, 'collateral/collaterals': 20 / 15, 'collateral/total_amount': 20 / 15, 'collateral/ltv': 20 / 15, 'collateral/currencies': 20 / 15, }, 'post': { 'collateral/orders': 20 / 15, 'collateral/repay': 20 / 15, 'collateral/collaterals': 20 / 15, }, }, 'account': { 'get': { 'detail': 20 / 15, 'stp_groups': 20 / 15, 'stp_groups/{stp_id}/users': 20 / 15, }, 'post': { 'stp_groups': 20 / 15, 'stp_groups/{stp_id}/users': 20 / 15, }, 'delete': { 'stp_groups/{stp_id}/users': 20 / 15, }, }, 'rebate': { 'get': { 'agency/transaction_history': 20 / 15, 'agency/commission_history': 20 / 15, }, }, }, }, 'timeframes': { '10s': '10s', '1m': '1m', '5m': '5m', '15m': '15m', '30m': '30m', '1h': '1h', '2h': '2h', '4h': '4h', '8h': '8h', '1d': '1d', '7d': '7d', '1w': '7d', }, // copied from gatev2 'commonCurrencies': { '88MPH': 'MPH', 'AXIS': 'Axis DeFi', 'BIFI': 'Bitcoin File', 'BOX': 'DefiBox', 'BYN': 'BeyondFi', 'EGG': 'Goose Finance', 'GTC': 'Game.com', 'GTC_HT': 'Game.com HT', 'GTC_BSC': 'Game.com BSC', 'HIT': 'HitChain', 'MM': 'Million', 'MPH': 'Morpher', 'POINT': 'GatePoint', 'RAI': 'Rai Reflex Index', 'SBTC': 'Super Bitcoin', 'TNC': 'Trinity Network Credit', 'VAI': 'VAIOT', 'TRAC': 'TRACO', // conflict with OriginTrail (TRAC) }, 'requiredCredentials': { 'apiKey': true, 'secret': true, }, 'headers': { 'X-Gate-Channel-Id': 'ccxt', }, 'options': { 'sandboxMode': false, 'createOrder': { 'expiration': 86400, // for conditional orders }, 'networks': { 'AVAXC': 'AVAX_C', 'BEP20': 'BSC', 'EOS': 'EOS', 'ERC20': 'ETH', 'GATECHAIN': 'GTEVM', 'HRC20': 'HT', 'KUSAMA': 'KSMSM', 'NEAR': 'NEAR', 'OKC': 'OKT', 'OPTIMISM': 'OPETH', 'POLKADOT': 'DOTSM', 'TRC20': 'TRX', }, 'timeInForce': { 'GTC': 'gtc', 'IOC': 'ioc', 'PO': 'poc', 'POC': 'poc', 'FOK': 'fok', }, 'accountsByType': { 'funding': 'spot', 'spot': 'spot', 'margin': 'margin', 'cross_margin': 'cross_margin', 'cross': 'cross_margin', 'isolated': 'margin', 'swap': 'futures', 'future': 'delivery', 'futures': 'futures', 'delivery': 'delivery', 'option': 'options', 'options': 'options', }, 'defaultType': 'spot', 'swap': { 'fetchMarkets': { 'settlementCurrencies': ['usdt', 'btc'], }, }, 'future': { 'fetchMarkets': { 'settlementCurrencies': ['usdt'], }, }, }, 'precisionMode': number.TICK_SIZE, 'fees': { 'trading': { 'tierBased': true, 'feeSide': 'get', 'percentage': true, 'maker': this.parseNumber('0.002'), 'taker': this.parseNumber('0.002'), 'tiers': { // volume is in BTC 'maker': [ [this.parseNumber('0'), this.parseNumber('0.002')], [this.parseNumber('1.5'), this.parseNumber('0.00185')], [this.parseNumber('3'), this.parseNumber('0.00175')], [this.parseNumber('6'), this.parseNumber('0.00165')], [this.parseNumber('12.5'), this.parseNumber('0.00155')], [this.parseNumber('25'), this.parseNumber('0.00145')], [this.parseNumber('75'), this.parseNumber('0.00135')], [this.parseNumber('200'), this.parseNumber('0.00125')], [this.parseNumber('500'), this.parseNumber('0.00115')], [this.parseNumber('1250'), this.parseNumber('0.00105')], [this.parseNumber('2500'), this.parseNumber('0.00095')], [this.parseNumber('3000'), this.parseNumber('0.00085')], [this.parseNumber('6000'), this.parseNumber('0.00075')], [this.parseNumber('11000'), this.parseNumber('0.00065')], [this.parseNumber('20000'), this.parseNumber('0.00055')], [this.parseNumber('40000'), this.parseNumber('0.00055')], [this.parseNumber('75000'), this.parseNumber('0.00055')], ], 'taker': [ [this.parseNumber('0'), this.parseNumber('0.002')], [this.parseNumber('1.5'), this.parseNumber('0.00195')], [this.parseNumber('3'), this.parseNumber('0.00185')], [this.parseNumber('6'), this.parseNumber('0.00175')], [this.parseNumber('12.5'), this.parseNumber('0.00165')], [this.parseNumber('25'), this.parseNumber('0.00155')], [this.parseNumber('75'), this.parseNumber('0.00145')], [this.parseNumber('200'), this.parseNumber('0.00135')], [this.parseNumber('500'), this.parseNumber('0.00125')], [this.parseNumber('1250'), this.parseNumber('0.00115')], [this.parseNumber('2500'), this.parseNumber('0.00105')], [this.parseNumber('3000'), this.parseNumber('0.00095')], [this.parseNumber('6000'), this.parseNumber('0.00085')], [this.parseNumber('11000'), this.parseNumber('0.00075')], [this.parseNumber('20000'), this.parseNumber('0.00065')], [this.parseNumber('40000'), this.parseNumber('0.00065')], [this.parseNumber('75000'), this.parseNumber('0.00065')], ], }, }, 'swap': { 'tierBased': true, 'feeSide': 'base', 'percentage': true, 'maker': this.parseNumber('0.0'), 'taker': this.parseNumber('0.0005'), 'tiers': { 'maker': [ [this.parseNumber('0'), this.parseNumber('0.0000')], [this.parseNumber('1.5'), this.parseNumber('-0.00005')], [this.parseNumber('3'), this.parseNumber('-0.00005')], [this.parseNumber('6'), this.parseNumber('-0.00005')], [this.parseNumber('12.5'), this.parseNumber('-0.00005')], [this.parseNumber('25'), this.parseNumber('-0.00005')], [this.parseNumber('75'), this.parseNumber('-0.00005')], [this.parseNumber('200'), this.parseNumber('-0.00005')], [this.parseNumber('500'), this.parseNumber('-0.00005')], [this.parseNumber('1250'), this.parseNumber('-0.00005')], [this.parseNumber('2500'), this.parseNumber('-0.00005')], [this.parseNumber('3000'), this.parseNumber('-0.00008')], [this.parseNumber('6000'), this.parseNumber('-0.01000')], [this.parseNumber('11000'), this.parseNumber('-0.01002')], [this.parseNumber('20000'), this.parseNumber('-0.01005')], [this.parseNumber('40000'), this.parseNumber('-0.02000')], [this.parseNumber('75000'), this.parseNumber('-0.02005')], ], 'taker': [ [this.parseNumber('0'), this.parseNumber('0.00050')], [this.parseNumber('1.5'), this.parseNumber('0.00048')], [this.parseNumber('3'), this.parseNumber('0.00046')], [this.parseNumber('6'), this.parseNumber('0.00044')], [this.parseNumber('12.5'), this.parseNumber('0.00042')], [this.parseNumber('25'), this.parseNumber('0.00040')], [this.parseNumber('75'), this.parseNumber('0.00038')], [this.parseNumber('200'), this.parseNumber('0.00036')], [this.parseNumber('500'), this.parseNumber('0.00034')], [this.parseNumber('1250'), this.parseNumber('0.00032')], [this.parseNumber('2500'), this.parseNumber('0.00030')], [this.parseNumber('3000'), this.parseNumber('0.00030')], [this.parseNumber('6000'), this.parseNumber('0.00030')], [this.parseNumber('11000'), this.parseNumber('0.00030')], [this.parseNumber('20000'), this.parseNumber('0.00030')], [this.parseNumber('40000'), this.parseNumber('0.00030')], [this.parseNumber('75000'), this.parseNumber('0.00030')], ], }, }, }, // https://www.gate.io/docs/developers/apiv4/en/#label-list 'exceptions': { 'exact': { 'INVALID_PARAM_VALUE': errors.BadRequest, 'INVALID_PROTOCOL': errors.BadRequest, 'INVALID_ARGUMENT': errors.BadRequest, 'INVALID_REQUEST_BODY': errors.BadRequest, 'MISSING_REQUIRED_PARAM': errors.ArgumentsRequired, 'BAD_REQUEST': errors.BadRequest, 'INVALID_CONTENT_TYPE': errors.BadRequest, 'NOT_ACCEPTABLE': errors.BadRequest, 'METHOD_NOT_ALLOWED': errors.BadRequest, 'NOT_FOUND': errors.ExchangeError, 'INVALID_CREDENTIALS': errors.AuthenticationError, 'INVALID_KEY': errors.AuthenticationError, 'IP_FORBIDDEN': errors.AuthenticationError, 'READ_ONLY': errors.PermissionDenied, 'INVALID_SIGNATURE': errors.AuthenticationError, 'MISSING_REQUIRED_HEADER': errors.AuthenticationError, 'REQUEST_EXPIRED': errors.AuthenticationError, 'ACCOUNT_LOCKED': errors.AccountSuspended, 'FORBIDDEN': errors.PermissionDenied, 'SUB_ACCOUNT_NOT_FOUND': errors.ExchangeError, 'SUB_ACCOUNT_LOCKED': errors.AccountSuspended, 'MARGIN_BALANCE_EXCEPTION': errors.ExchangeError, 'MARGIN_TRANSFER_FAILED': errors.ExchangeError, 'TOO_MUCH_FUTURES_AVAILABLE': errors.ExchangeError, 'FUTURES_BALANCE_NOT_ENOUGH': errors.InsufficientFunds, 'ACCOUNT_EXCEPTION': errors.ExchangeError, 'SUB_ACCOUNT_TRANSFER_FAILED': errors.ExchangeError, 'ADDRESS_NOT_USED': errors.ExchangeError, 'TOO_FAST': errors.RateLimitExceeded, 'WITHDRAWAL_OVER_LIMIT': errors.ExchangeError, 'API_WITHDRAW_DISABLED': errors.ExchangeNotAvailable, 'INVALID_WITHDRAW_ID': errors.ExchangeError, 'INVALID_WITHDRAW_CANCEL_STATUS': errors.ExchangeError, 'INVALID_PRECISION': errors.InvalidOrder, 'INVALID_CURRENCY': errors.BadSymbol, 'INVALID_CURRENCY_PAIR': errors.BadSymbol, 'POC_FILL_IMMEDIATELY': errors.OrderImmediatelyFillable, 'ORDER_NOT_FOUND': errors.OrderNotFound, 'CLIENT_ID_NOT_FOUND': errors.OrderNotFound, 'ORDER_CLOSED': errors.InvalidOrder, 'ORDER_CANCELLED': errors.InvalidOrder, 'QUANTITY_NOT_ENOUGH': errors.InvalidOrder, 'BALANCE_NOT_ENOUGH': errors.InsufficientFunds, 'MARGIN_NOT_SUPPORTED': errors.InvalidOrder, 'MARGIN_BALANCE_NOT_ENOUGH': errors.InsufficientFunds, 'AMOUNT_TOO_LITTLE': errors.InvalidOrder, 'AMOUNT_TOO_MUCH': errors.InvalidOrder, 'REPEATED_CREATION': errors.InvalidOrder, 'LOAN_NOT_FOUND': errors.OrderNotFound, 'LOAN_RECORD_NOT_FOUND': errors.OrderNotFound, 'NO_MATCHED_LOAN': errors.ExchangeError, 'NOT_MERGEABLE': errors.ExchangeError, 'NO_CHANGE': errors.ExchangeError, 'REPAY_TOO_MUCH': errors.ExchangeError, 'TOO_MANY_CURRENCY_PAIRS': errors.InvalidOrder, 'TOO_MANY_ORDERS': errors.InvalidOrder, 'TOO_MANY_REQUESTS': errors.RateLimitExceeded, 'MIXED_ACCOUNT_TYPE': errors.InvalidOrder, 'AUTO_BORROW_TOO_MUCH': errors.ExchangeError, 'TRADE_RESTRICTED': errors.InsufficientFunds, 'USER_NOT_FOUND': errors.AccountNotEnabled, 'CONTRACT_NO_COUNTER': errors.ExchangeError, 'CONTRACT_NOT_FOUND': errors.BadSymbol, 'RISK_LIMIT_EXCEEDED': errors.ExchangeError, 'INSUFFICIENT_AVAILABLE': errors.InsufficientFunds, 'LIQUIDATE_IMMEDIATELY': errors.InvalidOrder, 'LEVERAGE_TOO_HIGH': errors.InvalidOrder, 'LEVERAGE_TOO_LOW': errors.InvalidOrder, 'ORDER_NOT_OWNED': errors.ExchangeError, 'ORDER_FINISHED': errors.ExchangeError, 'POSITION_CROSS_MARGIN': errors.ExchangeError, 'POSITION_IN_LIQUIDATION': errors.ExchangeError, 'POSITION_IN_CLOSE': errors.ExchangeError, 'POSITION_EMPTY': errors.InvalidOrder, 'REMOVE_TOO_MUCH': errors.ExchangeError, 'RISK_LIMIT_NOT_MULTIPLE': errors.ExchangeError, 'RISK_LIMIT_TOO_HIGH': errors.ExchangeError, 'RISK_LIMIT_TOO_lOW': errors.ExchangeError, 'PRICE_TOO_DEVIATED': errors.InvalidOrder, 'SIZE_TOO_LARGE': errors.InvalidOrder, 'SIZE_TOO_SMALL': errors.InvalidOrder, 'PRICE_OVER_LIQUIDATION': errors.InvalidOrder, 'PRICE_OVER_BANKRUPT': errors.InvalidOrder, 'ORDER_POC_IMMEDIATE': errors.OrderImmediatelyFillable, 'INCREASE_POSITION': errors.InvalidOrder, 'CONTRACT_IN_DELISTING': errors.ExchangeError, 'INTERNAL': errors.ExchangeNotAvailable, 'SERVER_ERROR': errors.ExchangeNotAvailable, 'TOO_BUSY': errors.ExchangeNotAvailable, 'CROSS_ACCOUNT_NOT_FOUND': errors.ExchangeError, 'RISK_LIMIT_TOO_LOW': errors.BadRequest, 'AUTO_TRIGGER_PRICE_LESS_LAST': errors.InvalidOrder, 'AUTO_TRIGGER_PRICE_GREATE_LAST': errors.InvalidOrder, 'POSITION_HOLDING': errors.BadRequest, 'USER_LOAN_EXCEEDED': errors.BadRequest, // {"label":"USER_LOAN_EXCEEDED","message":"Max loan amount per user would be exceeded"} }, 'broad': {}, }, }); } setSandboxMode(enable) { super.setSandboxMode(enable); this.options['sandboxMode'] = enable; } convertExpireDate(date) { // parse YYMMDD to timestamp const year = date.slice(0, 2); const month = date.slice(2, 4); const day = date.slice(4, 6); const reconstructedDate = '20' + year + '-' + month + '-' + day + 'T00:00:00Z'; return reconstructedDate; } createExpiredOptionMarket(symbol) { // support expired option contracts const quote = 'USDT'; const settle = quote; const optionParts = symbol.split('-'); const symbolBase = symbol.split('/'); const marketIdBase = symbol.split('_'); let base = undefined; let expiry = this.safeString(optionParts, 1); if (symbol.indexOf('/') > -1) { base = this.safeString(symbolBase, 0); } else { base = this.safeString(marketIdBase, 0); expiry = expiry.slice(2, 8); // convert 20230728 to 230728 } const strike = this.safeString(optionParts, 2); const optionType = this.safeString(optionParts, 3); const datetime = this.convertExpireDate(expiry); const timestamp = this.parse8601(datetime); return { 'id': base + '_' + quote + '-' + '20' + expiry + '-' + strike + '-' + optionType, 'symbol': base + '/' + quote + ':' + settle + '-' + expiry + '-' + strike + '-' + optionType, 'base': base, 'quote': quote, 'settle': settle, 'baseId': base, 'quoteId': quote, 'settleId': settle, 'active': false, 'type': 'option', 'linear': undefined, 'inverse': undefined, 'spot': false, 'swap': false, 'future': false, 'option': true, 'margin': false, 'contract': true, 'contractSize': this.parseNumber('1'), 'expiry': timestamp, 'expiryDatetime': datetime, 'optionType': (optionType === 'C') ? 'call' : 'put', 'strike': this.parseNumber(strike), 'precision': { 'amount': this.parseNumber('1'), 'price': undefined, }, 'limits': { 'amount': { 'min': undefined, 'max': undefined, }, 'price': { 'min': undefined, 'max': undefined, }, 'cost': { 'min': undefined, 'max': undefined, }, }, 'info': undefined, }; } market(symbol) { if (this.markets === undefined) { throw new errors.ExchangeError(this.id + ' markets not loaded'); } if (typeof symbol === 'string') { if (symbol in this.markets) { return this.markets[symbol]; } else if (symbol in this.markets_by_id) { const markets = this.markets_by_id[symbol]; const defaultType = this.safeString2(this.options, 'defaultType', 'defaultSubType', 'spot'); for (let i = 0; i < markets.length; i++) { const market = markets[i]; if (market[defaultType]) { return market; } } return markets[0]; } else if ((symbol.indexOf('-C') > -1) || (symbol.indexOf('-P') > -1)) { return this.createExpiredOptionMarket(symbol); } } throw new errors.BadSymbol(this.id + ' does not have market symbol ' + symbol); } safeMarket(marketId = undefined, market = undefined, delimiter = undefined, marketType = undefined) { const isOption = (marketId !== undefined) && ((marketId.indexOf('-C') > -1) || (marketId.indexOf('-P') > -1)); if (isOption && !(marketId in this.markets_by_id)) { // handle expired option contracts return this.createExpiredOptionMarket(marketId); } return super.safeMarket(marketId, market, delimiter, marketType); } async fetchMarkets(params = {}) { /** * @method * @name gate#fetchMarkets * @description retrieves data on all markets for gate * @see https://www.gate.io/docs/developers/apiv4/en/#list-all-currency-pairs-supported // spot * @see https://www.gate.io/docs/developers/apiv4/en/#list-all-supported-currency-pairs-supported-in-margin-trading // margin * @see https://www.gate.io/docs/developers/apiv4/en/#list-all-futures-contracts // swap * @see https://www.gate.io/docs/developers/apiv4/en/#list-all-futures-contracts-2 // future * @see https://www.gate.io/docs/developers/apiv4/en/#list-all-the-contracts-with-specified-underlying-and-expiration-time // option * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object[]} an array of objects representing market data */ const sandboxMode = this.safeValue(this.options, 'sandboxMode', false); let rawPromises = [ this.fetchContractMarkets(params), this.fetchOptionMarkets(params), ]; if (!sandboxMode) { // gate does not have a sandbox for spot markets const mainnetOnly = [this.fetchSpotMarkets(params)]; rawPromises = this.arrayConcat(rawPromises, mainnetOnly); } const promises = await Promise.all(rawPromises); const spotMarkets = this.safeValue(promises, 0, []); const contractMarkets = this.safeValue(promises, 1, []); const optionMarkets = this.safeValue(promises, 2, []); const markets = this.arrayConcat(spotMarkets, contractMarkets); return this.arrayConcat(markets, optionMarkets); } async fetchSpotMarkets(params = {}) { const marginResponse = await this.publicMarginGetCurrencyPairs(params); const spotMarketsResponse = await this.publicSpotGetCurrencyPairs(params); const marginMarkets = this.indexBy(marginResponse, 'id'); // // Spot // // [ // { // "id": "QTUM_ETH", // "base": "QTUM", // "quote": "ETH", // "fee": "0.2", // "min_base_amount": "0.01", // "min_quote_amount": "0.001", // "amount_precision": 3, // "precision": 6, // "trade_status": "tradable", // "sell_start": 0, // "buy_start": 0 // } // ] // // Margin // // [ // { // "id": "ETH_USDT", // "base": "ETH", // "quote": "USDT", // "leverage": 3, // "min_base_amount": "0.01", // "min_quote_amount": "100", // "max_quote_amount": "1000000" // } // ] // const result = []; for (let i = 0; i < spotMarketsResponse.length; i++) { const spotMarket = spotMarketsResponse[i]; const id = this.safeString(spotMarket, 'id'); const marginMarket = this.safeValue(marginMarkets, id); const market = this.deepExtend(marginMarket, spotMarket); const [baseId, quoteId] = id.split('_'); const base = this.safeCurrencyCode(baseId); const quote = this.safeCurrencyCode(quoteId); const takerPercent = this.safeString(market, 'fee'); const makerPercent = this.safeString(market, 'maker_fee_rate', takerPercent); const amountPrecision = this.parseNumber(this.parsePrecision(this.safeString(market, 'amount_precision'))); const tradeStatus = this.safeString(market, 'trade_status'); const leverage = this.safeNumber(market, 'leverage'); const margin = leverage !== undefined; result.push({ 'id': id, 'symbol': base + '/' + quote, 'base': base, 'quote': quote, 'settle': undefined