sfccxt
Version:
A JavaScript / Python / PHP cryptocurrency trading library with support for 130+ exchanges
1,051 lines (1,043 loc) • 221 kB
JavaScript
'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