ccxt
Version:
1,103 lines (1,101 loc) • 194 kB
JavaScript
// ----------------------------------------------------------------------------
// PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
// https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
// EDIT THE CORRESPONDENT .ts FILE INSTEAD
// ---------------------------------------------------------------------------
import Exchange from './abstract/hashkey.js';
import { AccountNotEnabled, AccountSuspended, ArgumentsRequired, AuthenticationError, BadRequest, BadSymbol, ContractUnavailable, DDoSProtection, DuplicateOrderId, ExchangeError, ExchangeNotAvailable, InsufficientFunds, InvalidAddress, InvalidNonce, InvalidOrder, NotSupported, OperationFailed, OperationRejected, OrderImmediatelyFillable, OrderNotFillable, OrderNotFound, PermissionDenied, RateLimitExceeded, RequestTimeout } from './base/errors.js';
import { Precise } from './base/Precise.js';
import { TICK_SIZE } from './base/functions/number.js';
import { sha256 } from './static_dependencies/noble-hashes/sha256.js';
// ---------------------------------------------------------------------------
/**
* @class hashkey
* @augments Exchange
*/
export default class hashkey extends Exchange {
describe() {
return this.deepExtend(super.describe(), {
'id': 'hashkey',
'name': 'HashKey Global',
'countries': ['BM'],
'rateLimit': 100,
'version': 'v1',
'certified': true,
'pro': true,
'has': {
'CORS': undefined,
'spot': true,
'margin': false,
'swap': false,
'future': false,
'option': false,
'addMargin': false,
'cancelAllOrders': true,
'cancelAllOrdersAfter': false,
'cancelOrder': true,
'cancelOrders': true,
'cancelWithdraw': false,
'closePosition': false,
'createConvertTrade': false,
'createDepositAddress': false,
'createMarketBuyOrderWithCost': true,
'createMarketOrder': true,
'createMarketOrderWithCost': false,
'createMarketSellOrderWithCost': false,
'createOrder': true,
'createOrderWithTakeProfitAndStopLoss': false,
'createReduceOnlyOrder': true,
'createStopLimitOrder': true,
'createStopLossOrder': false,
'createStopMarketOrder': true,
'createStopOrder': true,
'createTakeProfitOrder': false,
'createTrailingAmountOrder': false,
'createTrailingPercentOrder': false,
'createTriggerOrder': true,
'fetchAccounts': true,
'fetchBalance': true,
'fetchCanceledAndClosedOrders': true,
'fetchCanceledOrders': true,
'fetchClosedOrder': true,
'fetchClosedOrders': false,
'fetchConvertCurrencies': false,
'fetchConvertQuote': false,
'fetchConvertTrade': false,
'fetchConvertTradeHistory': false,
'fetchCurrencies': true,
'fetchDepositAddress': true,
'fetchDepositAddresses': false,
'fetchDepositAddressesByNetwork': false,
'fetchDeposits': true,
'fetchDepositsWithdrawals': false,
'fetchFundingHistory': false,
'fetchFundingRate': true,
'fetchFundingRateHistory': true,
'fetchFundingRates': true,
'fetchIndexOHLCV': false,
'fetchLedger': true,
'fetchLeverage': true,
'fetchLeverageTiers': true,
'fetchMarginAdjustmentHistory': false,
'fetchMarginMode': false,
'fetchMarketLeverageTiers': 'emulated',
'fetchMarkets': true,
'fetchMarkOHLCV': false,
'fetchMyTrades': true,
'fetchOHLCV': true,
'fetchOpenInterestHistory': false,
'fetchOpenOrder': false,
'fetchOpenOrders': true,
'fetchOrder': true,
'fetchOrderBook': true,
'fetchOrders': false,
'fetchOrderTrades': false,
'fetchPosition': false,
'fetchPositionHistory': false,
'fetchPositionMode': false,
'fetchPositions': true,
'fetchPositionsForSymbol': true,
'fetchPositionsHistory': false,
'fetchPremiumIndexOHLCV': false,
'fetchStatus': true,
'fetchTicker': true,
'fetchTickers': true,
'fetchTime': true,
'fetchTrades': true,
'fetchTradingFee': true,
'fetchTradingFees': true,
'fetchTransactions': false,
'fetchTransfers': false,
'fetchWithdrawals': true,
'reduceMargin': false,
'sandbox': false,
'setLeverage': true,
'setMargin': false,
'setPositionMode': false,
'transfer': true,
'withdraw': true,
},
'timeframes': {
'1m': '1m',
'3m': '3m',
'5m': '5m',
'15m': '15m',
'30m': '30m',
'1h': '1h',
'2h': '2h',
'4h': '4h',
'6h': '6h',
'8h': '8h',
'12h': '12h',
'1d': '1d',
'1w': '1w',
'1M': '1M',
},
'urls': {
'logo': 'https://github.com/user-attachments/assets/6dd6127b-cc19-4a13-9b29-a98d81f80e98',
'api': {
'public': 'https://api-glb.hashkey.com',
'private': 'https://api-glb.hashkey.com',
},
'test': {
'public': 'https://api-glb.sim.hashkeydev.com',
'private': 'https://api-glb.sim.hashkeydev.com',
},
'www': 'https://global.hashkey.com/',
'doc': 'https://hashkeyglobal-apidoc.readme.io/',
'fees': 'https://support.global.hashkey.com/hc/en-us/articles/13199900083612-HashKey-Global-Fee-Structure',
'referral': 'https://global.hashkey.com/en-US/register/invite?invite_code=82FQUN',
},
'api': {
'public': {
'get': {
'api/v1/exchangeInfo': 5,
'quote/v1/depth': 1,
'quote/v1/trades': 1,
'quote/v1/klines': 1,
'quote/v1/ticker/24hr': 1,
'quote/v1/ticker/price': 1,
'quote/v1/ticker/bookTicker': 1,
'quote/v1/depth/merged': 1,
'quote/v1/markPrice': 1,
'quote/v1/index': 1,
'api/v1/futures/fundingRate': 1,
'api/v1/futures/historyFundingRate': 1,
'api/v1/ping': 1,
'api/v1/time': 1,
},
},
'private': {
'get': {
'api/v1/spot/order': 1,
'api/v1/spot/openOrders': 1,
'api/v1/spot/tradeOrders': 5,
'api/v1/futures/leverage': 1,
'api/v1/futures/order': 1,
'api/v1/futures/openOrders': 1,
'api/v1/futures/userTrades': 1,
'api/v1/futures/positions': 1,
'api/v1/futures/historyOrders': 1,
'api/v1/futures/balance': 1,
'api/v1/futures/liquidationAssignStatus': 1,
'api/v1/futures/riskLimit': 1,
'api/v1/futures/commissionRate': 1,
'api/v1/futures/getBestOrder': 1,
'api/v1/account/vipInfo': 1,
'api/v1/account': 1,
'api/v1/account/trades': 5,
'api/v1/account/type': 5,
'api/v1/account/checkApiKey': 1,
'api/v1/account/balanceFlow': 5,
'api/v1/spot/subAccount/openOrders': 1,
'api/v1/spot/subAccount/tradeOrders': 1,
'api/v1/subAccount/trades': 1,
'api/v1/futures/subAccount/openOrders': 1,
'api/v1/futures/subAccount/historyOrders': 1,
'api/v1/futures/subAccount/userTrades': 1,
'api/v1/account/deposit/address': 1,
'api/v1/account/depositOrders': 1,
'api/v1/account/withdrawOrders': 1,
},
'post': {
'api/v1/userDataStream': 1,
'api/v1/spot/orderTest': 1,
'api/v1/spot/order': 1,
'api/v1.1/spot/order': 1,
'api/v1/spot/batchOrders': 5,
'api/v1/futures/leverage': 1,
'api/v1/futures/order': 1,
'api/v1/futures/position/trading-stop': 3,
'api/v1/futures/batchOrders': 5,
'api/v1/account/assetTransfer': 1,
'api/v1/account/authAddress': 1,
'api/v1/account/withdraw': 1,
},
'put': {
'api/v1/userDataStream': 1,
},
'delete': {
'api/v1/spot/order': 1,
'api/v1/spot/openOrders': 5,
'api/v1/spot/cancelOrderByIds': 5,
'api/v1/futures/order': 1,
'api/v1/futures/batchOrders': 1,
'api/v1/futures/cancelOrderByIds': 1,
'api/v1/userDataStream': 1,
},
},
},
'fees': {
'trading': {
'spot': {
'tierBased': true,
'percentage': true,
'feeSide': 'get',
'maker': this.parseNumber('0.0012'),
'taker': this.parseNumber('0.0012'),
'tiers': {
'maker': [
[this.parseNumber('0'), this.parseNumber('0.0012')],
[this.parseNumber('1000000'), this.parseNumber('0.00080')],
[this.parseNumber('5000000'), this.parseNumber('0.00070')],
[this.parseNumber('10000000'), this.parseNumber('0.00060')],
[this.parseNumber('50000000'), this.parseNumber('0.00040')],
[this.parseNumber('200000000'), this.parseNumber('0.00030')],
[this.parseNumber('400000000'), this.parseNumber('0.00010')],
[this.parseNumber('800000000'), this.parseNumber('0.00')],
],
'taker': [
[this.parseNumber('0'), this.parseNumber('0.0012')],
[this.parseNumber('1000000'), this.parseNumber('0.00090')],
[this.parseNumber('5000000'), this.parseNumber('0.00085')],
[this.parseNumber('10000000'), this.parseNumber('0.00075')],
[this.parseNumber('50000000'), this.parseNumber('0.00065')],
[this.parseNumber('200000000'), this.parseNumber('0.00045')],
[this.parseNumber('400000000'), this.parseNumber('0.00040')],
[this.parseNumber('800000000'), this.parseNumber('0.00035')],
],
},
},
'swap': {
'tierBased': true,
'percentage': true,
'feeSide': 'get',
'maker': this.parseNumber('0.00025'),
'taker': this.parseNumber('0.00060'),
'tiers': {
'maker': [
[this.parseNumber('0'), this.parseNumber('0.00025')],
[this.parseNumber('1000000'), this.parseNumber('0.00016')],
[this.parseNumber('5000000'), this.parseNumber('0.00014')],
[this.parseNumber('10000000'), this.parseNumber('0.00012')],
[this.parseNumber('50000000'), this.parseNumber('0.000080')],
[this.parseNumber('200000000'), this.parseNumber('0.000060')],
[this.parseNumber('400000000'), this.parseNumber('0.000020')],
[this.parseNumber('800000000'), this.parseNumber('0.00')],
],
'taker': [
[this.parseNumber('0'), this.parseNumber('0.00060')],
[this.parseNumber('1000000'), this.parseNumber('0.00050')],
[this.parseNumber('5000000'), this.parseNumber('0.00045')],
[this.parseNumber('10000000'), this.parseNumber('0.00040')],
[this.parseNumber('50000000'), this.parseNumber('0.00035')],
[this.parseNumber('200000000'), this.parseNumber('0.00030')],
[this.parseNumber('400000000'), this.parseNumber('0.00025')],
[this.parseNumber('800000000'), this.parseNumber('0.00020')],
],
},
},
},
},
'options': {
'broker': '10000700011',
'recvWindow': undefined,
'sandboxMode': false,
'networks': {
'BTC': 'BTC',
'ERC20': 'ETH',
'AVAX': 'AvalancheC',
'SOL': 'Solana',
'MATIC': 'Polygon',
'ATOM': 'Cosmos',
'DOT': 'Polkadot',
'LTC': 'LTC',
'OPTIMISM': 'Optimism',
'ARB': 'Arbitrum',
'DOGE': 'Dogecoin',
'TRC20': 'Tron',
'ZKSYNC': 'zkSync',
'TON': 'TON',
'KLAYTN': 'Klaytn',
'MERLINCHAIN': 'Merlin Chain',
},
'networksById': {
'BTC': 'BTC',
'Bitcoin': 'BTC',
'ETH': 'ERC20',
'ERC20': 'ERC20',
'AvalancheC': 'AVAX',
'AVAX C-Chain': 'AVAX',
'Solana': 'SOL',
'Cosmos': 'ATOM',
'Arbitrum': 'ARB',
'Polygon': 'MATIC',
'Optimism': 'OPTIMISM',
'Polkadot': 'DOT',
'LTC': 'LTC',
'Litecoin': 'LTC',
'Dogecoin': 'DOGE',
'Merlin Chain': 'MERLINCHAIN',
'zkSync': 'ZKSYNC',
'TRC20': 'TRC20',
'Tron': 'TRC20',
'TON': 'TON',
'BSC(BEP20)': 'BSC',
'Klaytn': 'KLAYTN',
},
'defaultNetwork': 'ERC20',
},
'features': {
'default': {
'sandbox': true,
'createOrder': {
'marginMode': false,
'triggerPrice': false,
'triggerPriceType': undefined,
'triggerDirection': false,
'stopLossPrice': false,
'takeProfitPrice': false,
'attachedStopLossTakeProfit': undefined,
'timeInForce': {
'IOC': true,
'FOK': true,
'PO': true,
'GTD': false,
},
'hedged': false,
'trailing': false,
'leverage': false,
'marketBuyByCost': true,
'marketBuyRequiresPrice': true,
'selfTradePrevention': true,
'iceberg': false,
},
'createOrders': {
'max': 20,
},
'fetchMyTrades': {
'marginMode': false,
'limit': 1000,
'daysBack': 30,
'untilDays': 30,
'symbolRequired': false,
},
'fetchOrder': {
'marginMode': false,
'trigger': false,
'trailing': false,
'symbolRequired': false,
},
'fetchOpenOrders': {
'marginMode': false,
'limit': 1000,
'trigger': false,
'trailing': false,
'symbolRequired': false,
},
'fetchOrders': undefined,
'fetchClosedOrders': undefined,
'fetchOHLCV': {
'limit': 1000,
},
},
'spot': {
'extends': 'default',
},
'forDerivatives': {
'extends': 'default',
'createOrder': {
'triggerPrice': true,
'selfTradePrevention': true,
},
'fetchOpenOrders': {
'trigger': true,
'limit': 500,
},
},
'swap': {
'linear': {
'extends': 'forDerivatives',
},
'inverse': undefined,
},
'future': {
'linear': undefined,
'inverse': undefined,
},
},
'commonCurrencies': {},
'exceptions': {
'exact': {
'0001': BadRequest,
'0002': AuthenticationError,
'0003': RateLimitExceeded,
'0102': AuthenticationError,
'0103': AuthenticationError,
'0104': PermissionDenied,
'0201': ExchangeError,
'0202': PermissionDenied,
'0206': BadRequest,
'0207': BadRequest,
'0209': BadRequest,
'0210': BadRequest,
'0211': OrderNotFound,
'0401': InsufficientFunds,
'0402': BadRequest,
'-1000': ExchangeError,
'-1001': ExchangeError,
'-100010': BadSymbol,
'-100012': BadSymbol,
'-1002': AuthenticationError,
'-1004': BadRequest,
'-1005': PermissionDenied,
'-1006': ExchangeError,
'-1007': RequestTimeout,
'-1014': InvalidOrder,
'-1015': InvalidOrder,
'-1020': OperationRejected,
'-1021': InvalidNonce,
'-1024': BadRequest,
'-1101': ExchangeNotAvailable,
'-1115': InvalidOrder,
'-1117': InvalidOrder,
'-1123': InvalidOrder,
'-1124': InvalidOrder,
'-1126': InvalidOrder,
'-1129': BadRequest,
'-1130': BadRequest,
'-1132': BadRequest,
'-1133': BadRequest,
'-1135': BadRequest,
'-1136': BadRequest,
'-1138': InvalidOrder,
'-1137': InvalidOrder,
'-1139': OrderImmediatelyFillable,
'-1140': InvalidOrder,
'-1141': DuplicateOrderId,
'-1142': OrderNotFillable,
'-1143': OrderNotFound,
'-1144': OperationRejected,
'-1145': NotSupported,
'-1146': RequestTimeout,
'-1147': RequestTimeout,
'-1148': InvalidOrder,
'-1149': OperationRejected,
'-1150': OperationFailed,
'-1151': OperationRejected,
'-1152': AccountNotEnabled,
'-1153': InvalidOrder,
'-1154': InvalidOrder,
'-1155': OperationRejected,
'-1156': OperationFailed,
'-1157': OperationFailed,
'-1158': OperationFailed,
'-1159': AccountNotEnabled,
'-1160': AccountNotEnabled,
'-1161': OperationFailed,
'-1162': ContractUnavailable,
'-1163': InvalidAddress,
'-1164': OperationFailed,
'-1165': ArgumentsRequired,
'-1166': OperationRejected,
'-1167': BadRequest,
'-1168': BadRequest,
'-1169': PermissionDenied,
'-1170': PermissionDenied,
'-1171': PermissionDenied,
'-1172': BadRequest,
'-1173': BadRequest,
'-1174': PermissionDenied,
'-1175': BadRequest,
'-1176': BadRequest,
'-1177': InvalidOrder,
'-1178': AccountNotEnabled,
'-1179': AccountSuspended,
'-1181': ExchangeError,
'-1193': OperationRejected,
'-1194': OperationRejected,
'-1195': BadRequest,
'-1196': BadRequest,
'-1200': BadRequest,
'-1201': BadRequest,
'-1202': BadRequest,
'-1203': BadRequest,
'-1204': BadRequest,
'-1205': AccountNotEnabled,
'-1206': BadRequest,
'-1207': BadRequest,
'-1208': BadRequest,
'-1209': BadRequest,
'-2001': ExchangeNotAvailable,
'-2002': OperationFailed,
'-2003': OperationFailed,
'-2004': OperationFailed,
'-2005': RequestTimeout,
'-2010': OperationRejected,
'-2011': OperationRejected,
'-2016': OperationRejected,
'-2017': OperationRejected,
'-2018': OperationRejected,
'-2019': PermissionDenied,
'-2020': PermissionDenied,
'-2021': PermissionDenied,
'-2022': OperationRejected,
'-2023': AuthenticationError,
'-2024': AccountNotEnabled,
'-2025': AccountNotEnabled,
'-2026': BadRequest,
'-2027': OperationRejected,
'-2028': OperationRejected,
'-2029': OperationRejected,
'-2030': InsufficientFunds,
'-2031': NotSupported,
'-2032': OperationRejected,
'-2033': OperationFailed,
'-2034': InsufficientFunds,
'-2035': OperationRejected,
'-2036': NotSupported,
'-2037': ExchangeError,
'-2038': InsufficientFunds,
'-2039': NotSupported,
'-2040': ExchangeNotAvailable,
'-2041': BadRequest,
'-2042': OperationRejected,
'-2043': OperationRejected,
'-2044': BadRequest,
'-2045': BadRequest,
'-2046': BadRequest,
'-2048': BadRequest,
'-2049': BadRequest,
'-2050': BadRequest,
'-2051': OperationRejected,
'-2052': OperationRejected,
'-2053': OperationRejected,
'-2054': BadRequest,
'-2055': BadRequest,
'-2056': BadRequest,
'-2057': BadRequest,
'-3117': PermissionDenied,
'-3143': PermissionDenied,
'-3144': PermissionDenied,
'-3145': DDoSProtection,
'-4001': BadRequest,
'-4002': BadRequest,
'-4003': InsufficientFunds,
'-4004': BadRequest,
'-4005': BadRequest,
'-4006': AccountNotEnabled,
'-4007': NotSupported,
'-4008': AccountNotEnabled,
'-4009': PermissionDenied,
'-4010': PermissionDenied,
'-4011': ExchangeError,
'-4012': ExchangeError,
'-4013': OperationFailed, // Withdraw repeatly
},
'broad': {},
},
'precisionMode': TICK_SIZE,
});
}
/**
* @method
* @name hashkey#fetchTime
* @description fetches the current integer timestamp in milliseconds from the exchange server
* @see https://hashkeyglobal-apidoc.readme.io/reference/check-server-time
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {int} the current integer timestamp in milliseconds from the exchange server
*/
async fetchTime(params = {}) {
const response = await this.publicGetApiV1Time(params);
//
// {
// "serverTime": 1721661553214
// }
//
return this.safeInteger(response, 'serverTime');
}
/**
* @method
* @name hashkey#fetchStatus
* @description the latest known information on the availability of the exchange API
* @see https://hashkeyglobal-apidoc.readme.io/reference/test-connectivity
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [status structure]{@link https://docs.ccxt.com/#/?id=exchange-status-structure}
*/
async fetchStatus(params = {}) {
const response = await this.publicGetApiV1Ping(params);
//
// {}
//
return {
'status': 'ok',
'updated': undefined,
'eta': undefined,
'url': undefined,
'info': response,
};
}
/**
* @method
* @name hashkey#fetchMarkets
* @description retrieves data on all markets for the exchange
* @see https://hashkeyglobal-apidoc.readme.io/reference/exchangeinfo
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string} [params.symbol] the id of the market to fetch
* @returns {object[]} an array of objects representing market data
*/
async fetchMarkets(params = {}) {
const request = {};
const response = await this.publicGetApiV1ExchangeInfo(this.extend(request, params));
//
// {
// "timezone": "UTC",
// "serverTime": "1721661653952",
// "brokerFilters": [],
// "symbols": [
// {
// "symbol": "BTCUSDT",
// "symbolName": "BTCUSDT",
// "status": "TRADING",
// "baseAsset": "BTC",
// "baseAssetName": "BTC",
// "baseAssetPrecision": "0.00001",
// "quoteAsset": "USDT",
// "quoteAssetName": "USDT",
// "quotePrecision": "0.0000001",
// "retailAllowed": true,
// "piAllowed": true,
// "corporateAllowed": true,
// "omnibusAllowed": true,
// "icebergAllowed": false,
// "isAggregate": false,
// "allowMargin": false,
// "filters": [
// {
// "minPrice": "0.01",
// "maxPrice": "100000.00000000",
// "tickSize": "0.01",
// "filterType": "PRICE_FILTER"
// },
// {
// "minQty": "0.00001",
// "maxQty": "8",
// "stepSize": "0.00001",
// "marketOrderMinQty": "0.00001",
// "marketOrderMaxQty": "4",
// "filterType": "LOT_SIZE"
// },
// {
// "minNotional": "1",
// "filterType": "MIN_NOTIONAL"
// },
// {
// "minAmount": "1",
// "maxAmount": "400000",
// "minBuyPrice": "0",
// "marketOrderMinAmount": "1",
// "marketOrderMaxAmount": "200000",
// "filterType": "TRADE_AMOUNT"
// },
// {
// "maxSellPrice": "0",
// "buyPriceUpRate": "0.1",
// "sellPriceDownRate": "0.1",
// "filterType": "LIMIT_TRADING"
// },
// {
// "buyPriceUpRate": "0.1",
// "sellPriceDownRate": "0.1",
// "filterType": "MARKET_TRADING"
// },
// {
// "noAllowMarketStartTime": "1710485700000",
// "noAllowMarketEndTime": "1710486000000",
// "limitOrderStartTime": "0",
// "limitOrderEndTime": "0",
// "limitMinPrice": "0",
// "limitMaxPrice": "0",
// "filterType": "OPEN_QUOTE"
// }
// ]
// }
// ],
// "options": [ ],
// "contracts": [
// {
// "filters": [
// {
// "minPrice": "0.1",
// "maxPrice": "100000.00000000",
// "tickSize": "0.1",
// "filterType": "PRICE_FILTER"
// },
// {
// "minQty": "0.001",
// "maxQty": "10",
// "stepSize": "0.001",
// "marketOrderMinQty": "0",
// "marketOrderMaxQty": "0",
// "filterType": "LOT_SIZE"
// },
// {
// "minNotional": "0",
// "filterType": "MIN_NOTIONAL"
// },
// {
// "maxSellPrice": "999999",
// "buyPriceUpRate": "0.05",
// "sellPriceDownRate": "0.05",
// "maxEntrustNum": 200,
// "maxConditionNum": 200,
// "filterType": "LIMIT_TRADING"
// },
// {
// "buyPriceUpRate": "0.05",
// "sellPriceDownRate": "0.05",
// "filterType": "MARKET_TRADING"
// },
// {
// "noAllowMarketStartTime": "0",
// "noAllowMarketEndTime": "0",
// "limitOrderStartTime": "0",
// "limitOrderEndTime": "0",
// "limitMinPrice": "0",
// "limitMaxPrice": "0",
// "filterType": "OPEN_QUOTE"
// }
// ],
// "exchangeId": "301",
// "symbol": "BTCUSDT-PERPETUAL",
// "symbolName": "BTCUSDT-PERPETUAL",
// "status": "TRADING",
// "baseAsset": "BTCUSDT-PERPETUAL",
// "baseAssetPrecision": "0.001",
// "quoteAsset": "USDT",
// "quoteAssetPrecision": "0.1",
// "icebergAllowed": false,
// "inverse": false,
// "index": "USDT",
// "marginToken": "USDT",
// "marginPrecision": "0.0001",
// "contractMultiplier": "0.001",
// "underlying": "BTC",
// "riskLimits": [
// {
// "riskLimitId": "200000722",
// "quantity": "1000.00",
// "initialMargin": "0.10",
// "maintMargin": "0.005",
// "isWhite": false
// },
// {
// "riskLimitId": "200000723",
// "quantity": "2000.00",
// "initialMargin": "0.10",
// "maintMargin": "0.01",
// "isWhite": false
// }
// ]
// }
// ],
// "coins": [
// {
// "orgId": "9001",
// "coinId": "BTC",
// "coinName": "BTC",
// "coinFullName": "Bitcoin",
// "allowWithdraw": true,
// "allowDeposit": true,
// "tokenType": "CHAIN_TOKEN",
// "chainTypes": [
// {
// "chainType": "Bitcoin",
// "withdrawFee": "0",
// "minWithdrawQuantity": "0.002",
// "maxWithdrawQuantity": "0",
// "minDepositQuantity": "0.0005",
// "allowDeposit": true,
// "allowWithdraw": true
// }
// ]
// }
// ]
// }
//
const spotMarkets = this.safeList(response, 'symbols', []);
const swapMarkets = this.safeList(response, 'contracts', []);
let markets = this.arrayConcat(spotMarkets, swapMarkets);
if (this.isEmpty(markets)) {
markets = [response]; // if user provides params.symbol the exchange returns a single object insted of list of objects
}
return this.parseMarkets(markets);
}
parseMarket(market) {
// spot
// {
// "symbol": "BTCUSDT",
// "symbolName": "BTCUSDT",
// "status": "TRADING",
// "baseAsset": "BTC",
// "baseAssetName": "BTC",
// "baseAssetPrecision": "0.00001",
// "quoteAsset": "USDT",
// "quoteAssetName": "USDT",
// "quotePrecision": "0.0000001",
// "retailAllowed": true,
// "piAllowed": true,
// "corporateAllowed": true,
// "omnibusAllowed": true,
// "icebergAllowed": false,
// "isAggregate": false,
// "allowMargin": false,
// "filters": [
// {
// "minPrice": "0.01",
// "maxPrice": "100000.00000000",
// "tickSize": "0.01",
// "filterType": "PRICE_FILTER"
// },
// {
// "minQty": "0.00001",
// "maxQty": "8",
// "stepSize": "0.00001",
// "marketOrderMinQty": "0.00001",
// "marketOrderMaxQty": "4",
// "filterType": "LOT_SIZE"
// },
// {
// "minNotional": "1",
// "filterType": "MIN_NOTIONAL"
// },
// {
// "minAmount": "1",
// "maxAmount": "400000",
// "minBuyPrice": "0",
// "marketOrderMinAmount": "1",
// "marketOrderMaxAmount": "200000",
// "filterType": "TRADE_AMOUNT"
// },
// {
// "maxSellPrice": "0",
// "buyPriceUpRate": "0.1",
// "sellPriceDownRate": "0.1",
// "filterType": "LIMIT_TRADING"
// },
// {
// "buyPriceUpRate": "0.1",
// "sellPriceDownRate": "0.1",
// "filterType": "MARKET_TRADING"
// },
// {
// "noAllowMarketStartTime": "1710485700000",
// "noAllowMarketEndTime": "1710486000000",
// "limitOrderStartTime": "0",
// "limitOrderEndTime": "0",
// "limitMinPrice": "0",
// "limitMaxPrice": "0",
// "filterType": "OPEN_QUOTE"
// }
// ]
// }
//
// swap
// {
// "filters": [
// {
// "minPrice": "0.1",
// "maxPrice": "100000.00000000",
// "tickSize": "0.1",
// "filterType": "PRICE_FILTER"
// },
// {
// "minQty": "0.001",
// "maxQty": "10",
// "stepSize": "0.001",
// "marketOrderMinQty": "0",
// "marketOrderMaxQty": "0",
// "filterType": "LOT_SIZE"
// },
// {
// "minNotional": "0",
// "filterType": "MIN_NOTIONAL"
// },
// {
// "maxSellPrice": "999999",
// "buyPriceUpRate": "0.05",
// "sellPriceDownRate": "0.05",
// "maxEntrustNum": 200,
// "maxConditionNum": 200,
// "filterType": "LIMIT_TRADING"
// },
// {
// "buyPriceUpRate": "0.05",
// "sellPriceDownRate": "0.05",
// "filterType": "MARKET_TRADING"
// },
// {
// "noAllowMarketStartTime": "0",
// "noAllowMarketEndTime": "0",
// "limitOrderStartTime": "0",
// "limitOrderEndTime": "0",
// "limitMinPrice": "0",
// "limitMaxPrice": "0",
// "filterType": "OPEN_QUOTE"
// }
// ],
// "exchangeId": "301",
// "symbol": "BTCUSDT-PERPETUAL",
// "symbolName": "BTCUSDT-PERPETUAL",
// "status": "TRADING",
// "baseAsset": "BTCUSDT-PERPETUAL",
// "baseAssetPrecision": "0.001",
// "quoteAsset": "USDT",
// "quoteAssetPrecision": "0.1",
// "icebergAllowed": false,
// "inverse": false,
// "index": "USDT",
// "marginToken": "USDT",
// "marginPrecision": "0.0001",
// "contractMultiplier": "0.001",
// "underlying": "BTC",
// "riskLimits": [
// {
// "riskLimitId": "200000722",
// "quantity": "1000.00",
// "initialMargin": "0.10",
// "maintMargin": "0.005",
// "isWhite": false
// },
// {
// "riskLimitId": "200000723",
// "quantity": "2000.00",
// "initialMargin": "0.10",
// "maintMargin": "0.01",
// "isWhite": false
// }
// ]
// }
//
const marketId = this.safeString(market, 'symbol');
const quoteId = this.safeString(market, 'quoteAsset');
const quote = this.safeCurrencyCode(quoteId);
const settleId = this.safeString(market, 'marginToken');
const settle = this.safeCurrencyCode(settleId);
let baseId = this.safeString(market, 'baseAsset');
let marketType = 'spot';
let isSpot = true;
let isSwap = false;
let suffix = '';
const parts = marketId.split('-');
const secondPart = this.safeString(parts, 1);
if (secondPart === 'PERPETUAL') {
marketType = 'swap';
isSpot = false;
isSwap = true;
baseId = this.safeString(market, 'underlying');
suffix += ':' + settleId;
}
const base = this.safeCurrencyCode(baseId);
const symbol = base + '/' + quote + suffix;
const status = this.safeString(market, 'status');
const active = status === 'TRADING';
let isLinear = undefined;
let subType = undefined;
const isInverse = this.safeBool(market, 'inverse');
if (isInverse !== undefined) {
if (isInverse) {
isLinear = false;
subType = 'inverse';
}
else {
isLinear = true;
subType = 'linear';
}
}
const filtersList = this.safeList(market, 'filters', []);
const filters = this.indexBy(filtersList, 'filterType');
const priceFilter = this.safeDict(filters, 'PRICE_FILTER', {});
const amountFilter = this.safeDict(filters, 'LOT_SIZE', {});
const costFilter = this.safeDict(filters, 'MIN_NOTIONAL', {});
const minCostString = this.omitZero(this.safeString(costFilter, 'min_notional'));
const contractSizeString = this.safeString(market, 'contractMultiplier');
let amountPrecisionString = this.safeString(amountFilter, 'stepSize');
let amountMinLimitString = this.safeString(amountFilter, 'minQty');
let amountMaxLimitString = this.safeString(amountFilter, 'maxQty');
let minLeverage = undefined;
let maxLeverage = undefined;
if (isSwap) {
amountPrecisionString = Precise.stringDiv(amountPrecisionString, contractSizeString);
amountMinLimitString = Precise.stringDiv(amountMinLimitString, contractSizeString);
amountMaxLimitString = Precise.stringDiv(amountMaxLimitString, contractSizeString);
const riskLimits = this.safeList(market, 'riskLimits');
if (riskLimits !== undefined) {
const first = this.safeDict(riskLimits, 0);
const arrayLength = riskLimits.length;
const last = this.safeDict(riskLimits, arrayLength - 1);
let minInitialMargin = this.safeString(first, 'initialMargin');
let maxInitialMargin = this.safeString(last, 'initialMargin');
if (Precise.stringGt(minInitialMargin, maxInitialMargin)) {
[minInitialMargin, maxInitialMargin] = [maxInitialMargin, minInitialMargin];
}
minLeverage = this.parseToInt(Precise.stringDiv('1', maxInitialMargin));
maxLeverage = this.parseToInt(Precise.stringDiv('1', minInitialMargin));
}
}
const tradingFees = this.safeDict(this.fees, 'trading');
const fees = isSpot ? this.safeDict(tradingFees, 'spot') : this.safeDict(tradingFees, 'swap');
return this.safeMarketStructure({
'id': marketId,
'symbol': symbol,
'base': base,
'quote': quote,
'baseId': baseId,
'quoteId': quoteId,
'active': active,
'type': marketType,
'subType': subType,
'spot': isSpot,
'margin': this.safeBool(market, 'allowMargin'),
'swap': isSwap,
'future': false,
'option': false,
'contract': isSwap,
'settle': settle,
'settleId': settleId,
'contractSize': this.parseNumber(contractSizeString),
'linear': isLinear,
'inverse': isInverse,
'taker': this.safeNumber(fees, 'taker'),
'maker': this.safeNumber(fees, 'maker'),
'percentage': this.safeBool(fees, 'percentage'),
'tierBased': this.safeBool(fees, 'tierBased'),
'feeSide': this.safeString(fees, 'feeSide'),
'expiry': undefined,
'expiryDatetime': undefined,
'strike': undefined,
'optionType': undefined,
'precision': {
'amount': this.parseNumber(amountPrecisionString),
'price': this.safeNumber(priceFilter, 'tickSize'),
},
'limits': {
'amount': {
'min': this.parseNumber(amountMinLimitString),
'max': this.parseNumber(amountMaxLimitString),
},
'price': {
'min': this.safeNumber(priceFilter, 'minPrice'),
'max': this.safeNumber(priceFilter, 'maxPrice'),
},
'leverage': {
'min': minLeverage,
'max': maxLeverage,
},
'cost': {
'min': this.parseNumber(minCostString),
'max': undefined,
},
},
'created': undefined,
'info': market,
});
}
/**
* @method
* @name hashkey#fetchCurrencies
* @description fetches all available currencies on an exchange
* @see https://hashkeyglobal-apidoc.readme.io/reference/exchangeinfo
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a