UNPKG

sfccxt

Version:

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

1,051 lines (1,043 loc) 221 kB
'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const Precise = require ('./base/Precise'); const { TICK_SIZE } = require ('./base/functions/number'); const { ExchangeError, BadRequest, ArgumentsRequired, AuthenticationError, PermissionDenied, AccountSuspended, InsufficientFunds, RateLimitExceeded, ExchangeNotAvailable, BadSymbol, InvalidOrder, OrderNotFound, NotSupported, AccountNotEnabled, OrderImmediatelyFillable } = require ('./base/errors'); module.exports = class gate extends Exchange { describe () { return this.deepExtend (super.describe (), { 'id': 'gate', 'name': 'Gate.io', 'countries': [ 'KR' ], 'rateLimit': 10 / 3, // 300 requests per second or 3.33ms '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/apiv4/en/index.html', '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', }, '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', }, }, 'test': { 'public': { 'futures': 'https://fx-api-testnet.gateio.ws/api/v4', 'delivery': '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', }, }, 'referral': { 'url': 'https://www.gate.io/ref/2436035', 'discount': 0.2, }, }, 'has': { 'CORS': undefined, 'spot': true, 'margin': true, 'swap': true, 'future': true, 'option': undefined, 'borrowMargin': true, 'cancelAllOrders': true, 'cancelOrder': true, 'createMarketOrder': false, 'createOrder': true, 'createPostOnlyOrder': true, 'createStopLimitOrder': true, 'createStopMarketOrder': false, 'createStopOrder': true, 'editOrder': true, 'fetchBalance': true, 'fetchBorrowRate': false, 'fetchBorrowRateHistories': false, 'fetchBorrowRateHistory': false, 'fetchBorrowRates': false, 'fetchClosedOrders': true, 'fetchCurrencies': true, 'fetchDepositAddress': true, 'fetchDeposits': true, 'fetchDepositWithdrawFee': 'emulated', 'fetchDepositWithdrawFees': true, 'fetchFundingHistory': true, 'fetchFundingRate': true, 'fetchFundingRateHistory': true, 'fetchFundingRates': true, 'fetchIndexOHLCV': true, 'fetchLeverage': false, 'fetchLeverageTiers': true, 'fetchMarginMode': false, 'fetchMarketLeverageTiers': 'emulated', 'fetchMarkets': true, 'fetchMarkOHLCV': true, 'fetchMyTrades': true, 'fetchNetworkDepositAddress': true, 'fetchOHLCV': true, 'fetchOpenInterestHistory': false, 'fetchOpenOrders': true, 'fetchOrder': true, 'fetchOrderBook': true, 'fetchPositionMode': false, 'fetchPositions': true, 'fetchPremiumIndexOHLCV': false, 'fetchTicker': true, 'fetchTickers': true, 'fetchTime': false, 'fetchTrades': true, 'fetchTradingFee': true, 'fetchTradingFees': true, 'fetchTransactionFees': true, 'fetchWithdrawals': true, 'repayMargin': true, 'setLeverage': true, 'setMarginMode': false, 'transfer': true, 'withdraw': true, }, 'api': { 'public': { 'wallet': { 'get': { 'currency_chains': 1.5, }, }, 'spot': { 'get': { 'currencies': 1, 'currencies/{currency}': 1, 'currency_pairs': 1, 'currency_pairs/{currency_pair}': 1, 'tickers': 1, 'order_book': 1, 'trades': 1, 'candlesticks': 1, }, }, 'margin': { 'get': { 'currency_pairs': 1, 'currency_pairs/{currency_pair}': 1, 'cross/currencies': 1, 'cross/currencies/{currency}': 1, 'funding_book': 1, }, }, 'futures': { 'get': { '{settle}/contracts': 1.5, '{settle}/contracts/{contract}': 1.5, '{settle}/order_book': 1.5, '{settle}/trades': 1.5, '{settle}/candlesticks': 1.5, '{settle}/tickers': 1.5, '{settle}/funding_rate': 1.5, '{settle}/insurance': 1.5, '{settle}/contract_stats': 1.5, '{settle}/liq_orders': 1.5, }, }, 'delivery': { 'get': { '{settle}/contracts': 1.5, '{settle}/contracts/{contract}': 1.5, '{settle}/order_book': 1.5, '{settle}/trades': 1.5, '{settle}/candlesticks': 1.5, '{settle}/tickers': 1.5, '{settle}/insurance': 1.5, }, }, 'options': { 'get': { 'underlyings': 1.5, 'expirations': 1.5, 'contracts': 1.5, 'contracts/{contract}': 1.5, 'settlements': 1.5, 'settlements/{contract}': 1.5, 'order_book': 1.5, 'tickers': 1.5, 'underlying/tickers/{underlying}': 1.5, 'candlesticks': 1.5, 'underlying/candlesticks': 1.5, 'trades': 1.5, }, }, }, 'private': { 'withdrawals': { 'post': { 'withdrawals': 3000, // 3000 = 10 seconds }, 'delete': { 'withdrawals/{withdrawal_id}': 300, }, }, 'wallet': { 'get': { 'deposit_address': 300, 'withdrawals': 300, 'deposits': 300, 'sub_account_transfers': 300, 'withdraw_status': 300, 'sub_account_balances': 300, 'fee': 300, 'total_balance': 300, }, 'post': { 'transfers': 300, 'sub_account_transfers': 300, }, }, 'subAccounts': { 'get': { 'sub_accounts': 1, 'sub_accounts/{user_id}': 1, 'sub_accounts/{user_id}/keys': 1, 'sub_accounts/{user_id}/keys/{key}': 1, }, 'post': { 'sub_accounts': 1, 'sub_accounts/{user_id}/keys': 1, 'sub_accounts/{user_id}/lock': 1, 'sub_accounts/{user_id}/unlock': 1, }, 'put': { 'sub_accounts/{user_id}/keys/{key}': 1, }, 'delete': { 'sub_accounts/{user_id}/keys/{key}': 1, }, }, 'spot': { 'get': { 'accounts': 1, 'open_orders': 1, 'orders': 1, 'orders/{order_id}': 1, 'my_trades': 1, 'price_orders': 1, 'price_orders/{order_id}': 1, }, 'post': { 'batch_orders': 1, 'orders': 1, 'cancel_batch_orders': 1, 'price_orders': 1, }, 'delete': { 'orders': 1, 'orders/{order_id}': 1, 'price_orders': 1, 'price_orders/{order_id}': 1, }, 'patch': { 'orders/{order_id}': 1, }, }, 'margin': { 'get': { 'accounts': 1.5, 'account_book': 1.5, 'funding_accounts': 1.5, 'loans': 1.5, 'loans/{loan_id}': 1.5, 'loans/{loan_id}/repayment': 1.5, 'loan_records': 1.5, 'loan_records/{load_record_id}': 1.5, 'auto_repay': 1.5, 'transferable': 1.5, 'cross/accounts': 1.5, 'cross/account_book': 1.5, 'cross/loans': 1.5, 'cross/loans/{loan_id}': 1.5, 'cross/loans/repayments': 1.5, 'cross/transferable': 1.5, 'loan_records/{loan_record_id}': 1.5, 'borrowable': 1.5, 'cross/repayments': 1.5, 'cross/borrowable': 1.5, }, 'post': { 'loans': 1.5, 'merged_loans': 1.5, 'loans/{loan_id}/repayment': 1.5, 'auto_repay': 1.5, 'cross/loans': 1.5, 'cross/loans/repayments': 1.5, 'cross/repayments': 1.5, }, 'patch': { 'loans/{loan_id}': 1.5, 'loan_records/{loan_record_id}': 1.5, }, 'delete': { 'loans/{loan_id}': 1.5, }, }, 'futures': { 'get': { '{settle}/accounts': 1.5, '{settle}/account_book': 1.5, '{settle}/positions': 1.5, '{settle}/positions/{contract}': 1.5, '{settle}/orders': 1.5, '{settle}/orders/{order_id}': 1.5, '{settle}/my_trades': 1.5, '{settle}/position_close': 1.5, '{settle}/liquidates': 1.5, '{settle}/price_orders': 1.5, '{settle}/price_orders/{order_id}': 1.5, '{settle}/dual_comp/positions/{contract}': 1.5, }, 'post': { '{settle}/positions/{contract}/margin': 1.5, '{settle}/positions/{contract}/leverage': 1.5, '{settle}/positions/{contract}/risk_limit': 1.5, '{settle}/dual_mode': 1.5, '{settle}/dual_comp/positions/{contract}': 1.5, '{settle}/dual_comp/positions/{contract}/margin': 1.5, '{settle}/dual_comp/positions/{contract}/leverage': 1.5, '{settle}/dual_comp/positions/{contract}/risk_limit': 1.5, '{settle}/orders': 1.5, '{settle}/price_orders': 1.5, }, 'delete': { '{settle}/orders': 1.5, '{settle}/orders/{order_id}': 1.5, '{settle}/price_orders': 1.5, '{settle}/price_orders/{order_id}': 1.5, }, }, 'delivery': { 'get': { '{settle}/accounts': 1.5, '{settle}/account_book': 1.5, '{settle}/positions': 1.5, '{settle}/positions/{contract}': 1.5, '{settle}/orders': 1.5, '{settle}/orders/{order_id}': 1.5, '{settle}/my_trades': 1.5, '{settle}/position_close': 1.5, '{settle}/liquidates': 1.5, '{settle}/price_orders': 1.5, '{settle}/price_orders/{order_id}': 1.5, '{settle}/settlements': 1.5, }, 'post': { '{settle}/positions/{contract}/margin': 1.5, '{settle}/positions/{contract}/leverage': 1.5, '{settle}/positions/{contract}/risk_limit': 1.5, '{settle}/orders': 1.5, '{settle}/price_orders': 1.5, }, 'delete': { '{settle}/orders': 1.5, '{settle}/orders/{order_id}': 1.5, '{settle}/price_orders': 1.5, '{settle}/price_orders/{order_id}': 1.5, }, }, 'options': { 'get': { 'accounts': 1.5, 'account_book': 1.5, 'positions': 1.5, 'positions/{contract}': 1.5, 'position_close': 1.5, 'orders': 1.5, 'orders/{order_id}': 1.5, 'my_trades': 1.5, }, 'post': { 'orders': 1.5, }, 'delete': { 'orders': 1.5, 'orders/{order_id}': 1.5, }, }, }, }, 'timeframes': { '10s': '10s', '1m': '1m', '5m': '5m', '15m': '15m', '30m': '30m', '1h': '1h', '4h': '4h', '8h': '8h', '1d': '1d', '7d': '7d', '1w': '7d', }, // copied from gatev2 'commonCurrencies': { '88MPH': 'MPH', 'AXIS': 'Axis DeFi', 'BIFI': 'Bitcoin File', 'BOX': 'DefiBox', 'BTCBEAR': 'BEAR', 'BTCBULL': 'BULL', 'BYN': 'BeyondFi', 'EGG': 'Goose Finance', 'GTC': 'Game.com', // conflict with Gitcoin and Gastrocoin 'GTC_HT': 'Game.com HT', 'GTC_BSC': 'Game.com BSC', 'HIT': 'HitChain', 'MM': 'Million', // conflict with MilliMeter 'MPH': 'Morpher', // conflict with 88MPH 'POINT': 'GatePoint', 'RAI': 'Rai Reflex Index', // conflict with RAI Finance 'SBTC': 'Super Bitcoin', 'TNC': 'Trinity Network Credit', 'TON': 'TONToken', 'VAI': 'VAIOT', }, 'requiredCredentials': { 'apiKey': true, 'secret': true, }, 'headers': { 'X-Gate-Channel-Id': 'ccxt', }, 'options': { 'createOrder': { 'expiration': 86400, // for conditional orders }, 'networks': { 'TRC20': 'TRX', 'ERC20': 'ETH', 'BEP20': 'BSC', }, 'timeInForce': { 'GTC': 'gtc', 'IOC': 'ioc', 'PO': 'poc', 'POC': 'poc', }, 'accountsByType': { 'funding': 'spot', 'spot': 'spot', 'margin': 'margin', 'cross_margin': 'cross_margin', 'cross': 'cross_margin', 'isolated': 'margin', 'swap': 'futures', 'future': 'delivery', 'futures': 'futures', 'delivery': 'delivery', }, 'defaultType': 'spot', 'swap': { 'fetchMarkets': { 'settlementCurrencies': [ 'usdt', 'btc' ], }, }, 'future': { 'fetchMarkets': { 'settlementCurrencies': [ 'usdt', 'btc' ], }, }, }, 'precisionMode': 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/apiv4/en/index.html#label-list 'exceptions': { 'exact': { 'INVALID_PARAM_VALUE': BadRequest, 'INVALID_PROTOCOL': BadRequest, 'INVALID_ARGUMENT': BadRequest, 'INVALID_REQUEST_BODY': BadRequest, 'MISSING_REQUIRED_PARAM': ArgumentsRequired, 'BAD_REQUEST': BadRequest, 'INVALID_CONTENT_TYPE': BadRequest, 'NOT_ACCEPTABLE': BadRequest, 'METHOD_NOT_ALLOWED': BadRequest, 'NOT_FOUND': ExchangeError, 'INVALID_CREDENTIALS': AuthenticationError, 'INVALID_KEY': AuthenticationError, 'IP_FORBIDDEN': AuthenticationError, 'READ_ONLY': PermissionDenied, 'INVALID_SIGNATURE': AuthenticationError, 'MISSING_REQUIRED_HEADER': AuthenticationError, 'REQUEST_EXPIRED': AuthenticationError, 'ACCOUNT_LOCKED': AccountSuspended, 'FORBIDDEN': PermissionDenied, 'SUB_ACCOUNT_NOT_FOUND': ExchangeError, 'SUB_ACCOUNT_LOCKED': AccountSuspended, 'MARGIN_BALANCE_EXCEPTION': ExchangeError, 'MARGIN_TRANSFER_FAILED': ExchangeError, 'TOO_MUCH_FUTURES_AVAILABLE': ExchangeError, 'FUTURES_BALANCE_NOT_ENOUGH': InsufficientFunds, 'ACCOUNT_EXCEPTION': ExchangeError, 'SUB_ACCOUNT_TRANSFER_FAILED': ExchangeError, 'ADDRESS_NOT_USED': ExchangeError, 'TOO_FAST': RateLimitExceeded, 'WITHDRAWAL_OVER_LIMIT': ExchangeError, 'API_WITHDRAW_DISABLED': ExchangeNotAvailable, 'INVALID_WITHDRAW_ID': ExchangeError, 'INVALID_WITHDRAW_CANCEL_STATUS': ExchangeError, 'INVALID_PRECISION': InvalidOrder, 'INVALID_CURRENCY': BadSymbol, 'INVALID_CURRENCY_PAIR': BadSymbol, 'POC_FILL_IMMEDIATELY': OrderImmediatelyFillable, // {"label":"POC_FILL_IMMEDIATELY","message":"Order would match and take immediately so its cancelled"} 'ORDER_NOT_FOUND': OrderNotFound, 'CLIENT_ID_NOT_FOUND': OrderNotFound, 'ORDER_CLOSED': InvalidOrder, 'ORDER_CANCELLED': InvalidOrder, 'QUANTITY_NOT_ENOUGH': InvalidOrder, 'BALANCE_NOT_ENOUGH': InsufficientFunds, 'MARGIN_NOT_SUPPORTED': InvalidOrder, 'MARGIN_BALANCE_NOT_ENOUGH': InsufficientFunds, 'AMOUNT_TOO_LITTLE': InvalidOrder, 'AMOUNT_TOO_MUCH': InvalidOrder, 'REPEATED_CREATION': InvalidOrder, 'LOAN_NOT_FOUND': OrderNotFound, 'LOAN_RECORD_NOT_FOUND': OrderNotFound, 'NO_MATCHED_LOAN': ExchangeError, 'NOT_MERGEABLE': ExchangeError, 'NO_CHANGE': ExchangeError, 'REPAY_TOO_MUCH': ExchangeError, 'TOO_MANY_CURRENCY_PAIRS': InvalidOrder, 'TOO_MANY_ORDERS': InvalidOrder, 'MIXED_ACCOUNT_TYPE': InvalidOrder, 'AUTO_BORROW_TOO_MUCH': ExchangeError, 'TRADE_RESTRICTED': InsufficientFunds, 'USER_NOT_FOUND': AccountNotEnabled, 'CONTRACT_NO_COUNTER': ExchangeError, 'CONTRACT_NOT_FOUND': BadSymbol, 'RISK_LIMIT_EXCEEDED': ExchangeError, 'INSUFFICIENT_AVAILABLE': InsufficientFunds, 'LIQUIDATE_IMMEDIATELY': InvalidOrder, 'LEVERAGE_TOO_HIGH': InvalidOrder, 'LEVERAGE_TOO_LOW': InvalidOrder, 'ORDER_NOT_OWNED': ExchangeError, 'ORDER_FINISHED': ExchangeError, 'POSITION_CROSS_MARGIN': ExchangeError, 'POSITION_IN_LIQUIDATION': ExchangeError, 'POSITION_IN_CLOSE': ExchangeError, 'POSITION_EMPTY': InvalidOrder, 'REMOVE_TOO_MUCH': ExchangeError, 'RISK_LIMIT_NOT_MULTIPLE': ExchangeError, 'RISK_LIMIT_TOO_HIGH': ExchangeError, 'RISK_LIMIT_TOO_lOW': ExchangeError, 'PRICE_TOO_DEVIATED': InvalidOrder, 'SIZE_TOO_LARGE': InvalidOrder, 'SIZE_TOO_SMALL': InvalidOrder, 'PRICE_OVER_LIQUIDATION': InvalidOrder, 'PRICE_OVER_BANKRUPT': InvalidOrder, 'ORDER_POC_IMMEDIATE': OrderImmediatelyFillable, // {"label":"ORDER_POC_IMMEDIATE","detail":"order price 1700 while counter price 1793.55"} 'INCREASE_POSITION': InvalidOrder, 'CONTRACT_IN_DELISTING': ExchangeError, 'INTERNAL': ExchangeNotAvailable, 'SERVER_ERROR': ExchangeNotAvailable, 'TOO_BUSY': ExchangeNotAvailable, 'CROSS_ACCOUNT_NOT_FOUND': ExchangeError, 'RISK_LIMIT_TOO_LOW': BadRequest, // {"label":"RISK_LIMIT_TOO_LOW","detail":"limit 1000000"} }, }, 'broad': {}, }); } async fetchMarkets (params = {}) { /** * @method * @name gate#fetchMarkets * @description retrieves data on all markets for gate * @param {object} params extra parameters specific to the exchange api endpoint * @returns {[object]} an array of objects representing market data */ let result = []; const [ type, query ] = this.handleMarketTypeAndParams ('fetchMarkets', undefined, params); if (type === 'spot' || type === 'margin') { result = await this.fetchSpotMarkets (query); } if (type === 'swap' || type === 'future') { result = await this.fetchContractMarkets (query); // futures and swaps } if (type === 'option') { result = await this.fetchOptionMarkets (query); } const resultLength = result.length; if (resultLength === 0) { throw new ExchangeError (this.id + " does not support '" + type + "' type, set exchange.options['defaultType'] to " + "'spot', 'margin', 'swap', 'future' or 'option'"); // eslint-disable-line quotes } return result; } 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, 'baseId': baseId, 'quoteId': quoteId, 'settleId': undefined, 'type': 'spot', 'spot': true, 'margin': margin, 'swap': false, 'future': false, 'option': false, 'active': (tradeStatus === 'tradable'), 'contract': false, 'linear': undefined, 'inverse': undefined, // Fee is in %, so divide by 100 'taker': this.parseNumber (Precise.stringDiv (takerPercent, '100')), 'maker': this.parseNumber (Precise.stringDiv (makerPercent, '100')), 'contractSize': undefined, 'expiry': undefined, 'expiryDatetime': undefined, 'strike': undefined, 'optionType': undefined, 'precision': { 'amount': amountPrecision, 'price': this.parseNumber (this.parsePrecision (this.safeString (market, 'precision'))), }, 'limits': { 'leverage': { 'min': this.parseNumber ('1'), 'max': this.safeNumber (market, 'leverage', 1), }, 'amount': { 'min': this.safeNumber (spotMarket, 'min_base_amount', amountPrecision), 'max': undefined, }, 'price': { 'min': undefined, 'max': undefined, }, 'cost': { 'min': this.safeNumber (market, 'min_quote_amount'), 'max': margin ? this.safeNumber (market, 'max_quote_amount') : undefined, }, }, 'info': market, }); } return result; } async fetchContractMarkets (params) { const result = []; const swapSettlementCurrencies = this.getSettlementCurrencies ('swap', 'fetchMarkets'); const futureSettlementCurrencies = this.getSettlementCurrencies ('future', 'fetchMarkets'); for (let c = 0; c < swapSettlementCurrencies.length; c++) { const settleId = swapSettlementCurrencies[c]; const query = params; query['settle'] = settleId; const response = await this.publicFuturesGetSettleContracts (query); for (let i = 0; i < response.length; i++) { const parsedMarket = this.parseContractMarket (response[i], settleId); result.push (parsedMarket); } } for (let c = 0; c < futureSettlementCurrencies.length; c++) { const settleId = futureSettlementCurrencies[c]; const query = params; query['settle'] = settleId; const response = await this.publicDeliveryGetSettleContracts (query); for (let i = 0; i < response.length; i++) { const parsedMarket = this.parseContractMarket (response[i], settleId); result.push (parsedMarket); } } return result; } parseContractMarket (market, settleId) { // // Perpetual swap // // { // "name": "BTC_USDT", // "type": "direct", // "quanto_multiplier": "0.0001", // "ref_discount_rate": "0", // "order_price_deviate": "0.5", // "maintenance_rate": "0.005", // "mark_type": "index", // "last_price": "38026", // "mark_price": "37985.6", // "index_price": "37954.92", // "funding_rate_indicative": "0.000219", // "mark_price_round": "0.01", // "funding_offset": 0, // "in_delisting": false, // "risk_limit_base": "1000000", // "interest_rate": "0.0003", // "order_price_round": "0.1", // "order_size_min": 1, // "ref_rebate_rate": "0.2", // "funding_interval": 28800, // "risk_limit_step": "1000000", // "leverage_min": "1", // "leverage_max": "100", // "risk_limit_max": "8000000", // "maker_fee_rate": "-0.00025", // "taker_fee_rate": "0.00075", // "funding_rate": "0.002053", // "order_size_max": 1000000, // "funding_next_apply": 1610035200, // "short_users": 977, // "config_change_time": 1609899548, // "trade_size": 28530850594, // "position_size": 5223816, // "long_users": 455, // "funding_impact_value": "60000", // "orders_limit": 50, // "trade_id": 10851092, // "orderbook_id": 2129638396 // } // // Delivery Futures // // { // "name": "BTC_USDT_20200814", // "underlying": "BTC_USDT", // "cycle": "WEEKLY", // "type": "direct", // "quanto_multiplier": "0.0001", // "mark_type": "index", // "last_price": "9017", // "mark_price": "9019", // "index_price": "9005.3", // "basis_rate": "0.185095", // "basis_value": "13.7", // "basis_impact_value": "100000", // "settle_price": "0", // "settle_price_interval": 60, // "settle_price_duration": 1800, // "settle_fee_rate": "0.0015", // "expire_time": 1593763200, // "order_price_round": "0.1", // "mark_price_round": "0.1", // "leverage_min": "1", // "leverage_max": "100", // "maintenance_rate": "1000000", // "risk_limit_base": "140.726652109199", // "risk_limit_step": "1000000", // "risk_limit_max": "8000000", // "maker_fee_rate": "-0.00025", // "taker_fee_rate": "0.00075", // "ref_discount_rate": "0", // "ref_rebate_rate": "0.2", // "order_price_deviate": "0.5", // "order_size_min": 1, // "order_size_max": 1000000, // "orders_limit": 50, // "orderbook_id": 63, // "trade_id": 26, // "trade_size": 435, // "position_size": 130, // "config_change_time": 1593158867, // "in_delisting": false // } // const id = this.safeString (market, 'name'); const parts = id.split ('_'); const baseId = this.safeString (parts, 0); const quoteId = this.safeString (parts, 1); const date = this.safeString (parts, 2); const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); const settle = this.safeCurrencyCode (settleId); const expiry = this.safeTimestamp (market, 'expire_time'); let symbol = ''; let marketType = 'swap'; if (date !== undefined) { symbol = base + '/' + quote + ':' + settle + '-' + this.yymmdd (expiry, ''); marketType = 'future'; } else { symbol = base + '/' + quote + ':' + settle; } const priceDeviate = this.safeString (market, 'order_price_deviate'); const markPrice = this.safeString (market, 'mark_price'); const minMultiplier = Precise.stringSub ('1', priceDeviate); const maxMultiplier = Precise.stringAdd ('1', priceDeviate); const minPrice = Precise.stringMul (minMultiplier, markPrice); const maxPrice = Precise.stringMul (maxMultiplier, markPrice); const takerPercent = this.safeString (market, 'taker_fee_rate'); const makerPercent = this.safeString (market, 'maker_fee_rate', takerPercent); const isLinear = quote === settle; return { 'id': id, 'symbol': symbol, 'base': base, 'quote': quote, 'settle': settle, 'baseId': baseId, 'quoteId': quoteId, 'settleId': settleId, 'type': marketType, 'spot': false, 'margin': false, 'swap': marketType === 'swap', 'future': marketType === 'future', 'option': marketType === 'option', 'active': true, 'contract': true, 'linear': isLinear, 'inverse': !isLinear, 'taker': this.parseNumber (Precise.stringDiv (takerPercent, '100')), // Fee is in %, so divide by 100 'maker': this.parseNumber (Precise.stringDiv (makerPercent, '100')), 'contractSize': this.safeNumber (market, 'quanto_multiplier'), 'expiry': expiry, 'expiryDatetime': this.iso8601 (expiry), 'strike': undefined, 'optionType': undefined, 'precision': { 'amount': this.parseNumber ('1'), // all contracts have this step size 'price': this.safeNumber (market, 'order_price_round'), }, 'limits': { 'leverage': { 'min': this.safeNumber (market, 'leverage_min'), 'max': this.safeNumber (market, 'leverage_max'), }, 'amount': { 'min': this.safeNumber (market, 'order_size_min'), 'max': this.safeNumber (market, 'order_size_max'), }, 'price': { 'min': this.parseNumber (minPrice), 'max': this.parseNumber (maxPrice), }, 'cost': { 'min': undefined, 'max': undefined, }, }, 'info': market, }; } async fetchOptionMarkets (params = {}) { const result = []; const underlyings = await this.fetchOptionUnderlyings (); for (let i = 0; i < underlyings.length; i++) { const underlying = underlyings[i]; const query = params; query['underlying'] = underlying; const response = await this.publicOptionsGetContracts (query); // // [ // { // "orders_limit": "50", // "order_size_max": "100000", // "mark_price_round": "0.1", // "order_size_min": "1", // "position_limit": "1000000", // "orderbook_id": "575967", // "order_price_deviate": "0.9", // "is_call": true, // true means Call false means Put // "last_price": "93.9", // "bid1_size": "0", // "bid1_price": "0", // "taker_fee_rate": "0.0004", // "underlying": "BTC_USDT", // "create_time": "1646381188", // "price_limit_fee_rate": "0.1", // "maker_fee_rate": "0.0004", // "trade_id": "727", // "order_price_round": "0.1", // "settle_fee_rate": "0.0001", // "trade_size": "1982", // "ref_rebate_rate": "0", // "name": "BTC_USDT-20220311-44000-C", // "underlying_price": "39194.26", // "strike_price": "44000", // "multiplier": "0.0001", // "ask1_price": "0", // "ref_discount_rate": "0", // "expiration_time": "1646985600", // "mark_price": "12.15", // "position_size": "4", // "ask1_size": "0", // "tag": "WEEK" // } // ] // for (let i = 0; i < response.length; i++) { const market = response[i]; const id = this.safeString (market, 'name'); const parts = underlying.split ('_'); const baseId = this.safeString (parts, 0); const quoteId = this.safeString (parts, 1); const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); let symbol = base + '/' + quote; const expiry = this.safeTimestamp (market, 'expiration_time'); const strike = this.safeString (market, 'strike_price'); const isCall