UNPKG

astro-perp-ccxt-dev

Version:

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

4,324 lines 199 kB
'use strict';

var hashkey$1 = require('./abstract/hashkey.js');
var errors = require('./base/errors.js');
var Precise = require('./base/Precise.js');
var number = require('./base/functions/number.js');
var sha256 = require('./static_dependencies/noble-hashes/sha256.js');

// ----------------------------------------------------------------------------
// ---------------------------------------------------------------------------
/**
 * @class hashkey
 * @augments Exchange
 */
class hashkey extends hashkey$1 {
    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': errors.BadRequest,
                    '0002': errors.AuthenticationError,
                    '0003': errors.RateLimitExceeded,
                    '0102': errors.AuthenticationError,
                    '0103': errors.AuthenticationError,
                    '0104': errors.PermissionDenied,
                    '0201': errors.ExchangeError,
                    '0202': errors.PermissionDenied,
                    '0206': errors.BadRequest,
                    '0207': errors.BadRequest,
                    '0209': errors.BadRequest,
                    '0210': errors.BadRequest,
                    '0211': errors.OrderNotFound,
                    '0401': errors.InsufficientFunds,
                    '0402': errors.BadRequest,
                    '-1000': errors.ExchangeError,
                    '-1001': errors.ExchangeError,
                    '-100010': errors.BadSymbol,
                    '-100012': errors.BadSymbol,
                    '-1002': errors.AuthenticationError,
                    '-1004': errors.BadRequest,
                    '-1005': errors.PermissionDenied,
                    '-1006': errors.ExchangeError,
                    '-1007': errors.RequestTimeout,
                    '-1014': errors.InvalidOrder,
                    '-1015': errors.InvalidOrder,
                    '-1020': errors.OperationRejected,
                    '-1021': errors.InvalidNonce,
                    '-1024': errors.BadRequest,
                    '-1101': errors.ExchangeNotAvailable,
                    '-1115': errors.InvalidOrder,
                    '-1117': errors.InvalidOrder,
                    '-1123': errors.InvalidOrder,
                    '-1124': errors.InvalidOrder,
                    '-1126': errors.InvalidOrder,
                    '-1129': errors.BadRequest,
                    '-1130': errors.BadRequest,
                    '-1132': errors.BadRequest,
                    '-1133': errors.BadRequest,
                    '-1135': errors.BadRequest,
                    '-1136': errors.BadRequest,
                    '-1138': errors.InvalidOrder,
                    '-1137': errors.InvalidOrder,
                    '-1139': errors.OrderImmediatelyFillable,
                    '-1140': errors.InvalidOrder,
                    '-1141': errors.DuplicateOrderId,
                    '-1142': errors.OrderNotFillable,
                    '-1143': errors.OrderNotFound,
                    '-1144': errors.OperationRejected,
                    '-1145': errors.NotSupported,
                    '-1146': errors.RequestTimeout,
                    '-1147': errors.RequestTimeout,
                    '-1148': errors.InvalidOrder,
                    '-1149': errors.OperationRejected,
                    '-1150': errors.OperationFailed,
                    '-1151': errors.OperationRejected,
                    '-1152': errors.AccountNotEnabled,
                    '-1153': errors.InvalidOrder,
                    '-1154': errors.InvalidOrder,
                    '-1155': errors.OperationRejected,
                    '-1156': errors.OperationFailed,
                    '-1157': errors.OperationFailed,
                    '-1158': errors.OperationFailed,
                    '-1159': errors.AccountNotEnabled,
                    '-1160': errors.AccountNotEnabled,
                    '-1161': errors.OperationFailed,
                    '-1162': errors.ContractUnavailable,
                    '-1163': errors.InvalidAddress,
                    '-1164': errors.OperationFailed,
                    '-1165': errors.ArgumentsRequired,
                    '-1166': errors.OperationRejected,
                    '-1167': errors.BadRequest,
                    '-1168': errors.BadRequest,
                    '-1169': errors.PermissionDenied,
                    '-1170': errors.PermissionDenied,
                    '-1171': errors.PermissionDenied,
                    '-1172': errors.BadRequest,
                    '-1173': errors.BadRequest,
                    '-1174': errors.PermissionDenied,
                    '-1175': errors.BadRequest,
                    '-1176': errors.BadRequest,
                    '-1177': errors.InvalidOrder,
                    '-1178': errors.AccountNotEnabled,
                    '-1179': errors.AccountSuspended,
                    '-1181': errors.ExchangeError,
                    '-1193': errors.OperationRejected,
                    '-1194': errors.OperationRejected,
                    '-1195': errors.BadRequest,
                    '-1196': errors.BadRequest,
                    '-1200': errors.BadRequest,
                    '-1201': errors.BadRequest,
                    '-1202': errors.BadRequest,
                    '-1203': errors.BadRequest,
                    '-1204': errors.BadRequest,
                    '-1205': errors.AccountNotEnabled,
                    '-1206': errors.BadRequest,
                    '-1207': errors.BadRequest,
                    '-1208': errors.BadRequest,
                    '-1209': errors.BadRequest,
                    '-2001': errors.ExchangeNotAvailable,
                    '-2002': errors.OperationFailed,
                    '-2003': errors.OperationFailed,
                    '-2004': errors.OperationFailed,
                    '-2005': errors.RequestTimeout,
                    '-2010': errors.OperationRejected,
                    '-2011': errors.OperationRejected,
                    '-2016': errors.OperationRejected,
                    '-2017': errors.OperationRejected,
                    '-2018': errors.OperationRejected,
                    '-2019': errors.PermissionDenied,
                    '-2020': errors.PermissionDenied,
                    '-2021': errors.PermissionDenied,
                    '-2022': errors.OperationRejected,
                    '-2023': errors.AuthenticationError,
                    '-2024': errors.AccountNotEnabled,
                    '-2025': errors.AccountNotEnabled,
                    '-2026': errors.BadRequest,
                    '-2027': errors.OperationRejected,
                    '-2028': errors.OperationRejected,
                    '-2029': errors.OperationRejected,
                    '-2030': errors.InsufficientFunds,
                    '-2031': errors.NotSupported,
                    '-2032': errors.OperationRejected,
                    '-2033': errors.OperationFailed,
                    '-2034': errors.InsufficientFunds,
                    '-2035': errors.OperationRejected,
                    '-2036': errors.NotSupported,
                    '-2037': errors.ExchangeError,
                    '-2038': errors.InsufficientFunds,
                    '-2039': errors.NotSupported,
                    '-2040': errors.ExchangeNotAvailable,
                    '-2041': errors.BadRequest,
                    '-2042': errors.OperationRejected,
                    '-2043': errors.OperationRejected,
                    '-2044': errors.BadRequest,
                    '-2045': errors.BadRequest,
                    '-2046': errors.BadRequest,
                    '-2048': errors.BadRequest,
                    '-2049': errors.BadRequest,
                    '-2050': errors.BadRequest,
                    '-2051': errors.OperationRejected,
                    '-2052': errors.OperationRejected,
                    '-2053': errors.OperationRejected,
                    '-2054': errors.BadRequest,
                    '-2055': errors.BadRequest,
                    '-2056': errors.BadRequest,
                    '-2057': errors.BadRequest,
                    '-3117': errors.PermissionDenied,
                    '-3143': errors.PermissionDenied,
                    '-3144': errors.PermissionDenied,
                    '-3145': errors.DDoSProtection,
                    '-4001': errors.BadRequest,
                    '-4002': errors.BadRequest,
                    '-4003': errors.InsufficientFunds,
                    '-4004': errors.BadRequest,
                    '-4005': errors.BadRequest,
                    '-4006': errors.AccountNotEnabled,
                    '-4007': errors.NotSupported,
                    '-4008': errors.AccountNotEnabled,
                    '-4009': errors.PermissionDenied,
                    '-4010': errors.PermissionDenied,
                    '-4011': errors.ExchangeError,
                    '-4012': errors.ExchangeError,
                    '-4013': errors.OperationFailed, // Withdraw repeatly
                },
                'broad': {},
            },
            'precisionMode': number.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["default"].stringDiv(amountPrecisionString, contractSizeString);
            amountMinLimitString = Precise["default"].stringDiv(amountMinLimitString, contractSizeString);
            amountMaxLimitString = Precise["default"].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["default"].stringGt(minInitialMargin, maxInitialMargin)) {
                    [minInitialMargin, maxInitialMargin] = [maxInitialMargin, minInitialMargin];
                }
                minLeverage = this.parseToInt(Precise["default"].stringDiv('1', maxInitialMargin));
                maxLeverage = this.parseToInt(Precise["default"].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} an associative dictionary of currencies
     */
    async fetchCurrencies(params = {}) {
        const response = await this.publicGetApiV1ExchangeInfo(params);
        const coins = this.safeList(response, 'coins');
        //
        //     {
        //         ...
        //         "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 result = {};
        for (let i = 0; i < coins.length; i++) {
            const currecy = coins[i];
            const currencyId = this.safeString(currecy, 'coinId');
            const code = this.safeCurrencyCode(currencyId);
            const networks = this.safeList(currecy, 'chainTypes');
            const parsedNetworks = {};
            for (let j = 0; j < networks.length; j++) {
                const network = networks[j];
                const networkId = this.safeString(network, 'chainType');
                const networkCode = this.networkCodeToId(networkId);
                parsedNetworks[networkCode] = {
                    'id': networkId,
                    'network': networkCode,
                    'limits': {
                        'withdraw': {
                            'min': this.safeNumber(network, 'minWithdrawQuantity'),
                            'max': this.parseNumber(this.omitZero(this.safeString(network, 'maxWithdrawQuantity'))),
                        },
                        'deposit': {
                            'min': this.safeNumber(network, 'minDepositQuantity'),
                            'max': undefined,
                        },
                    },
                    'active': undefined,
                    'deposit': this.safeBool(network, 'allowDeposit'),
                    'withdraw': this.safeBool(network, 'allowWithdraw'),
                    'fee': this.safeNumber(network, 'withdrawFee'),
                    'precision': undefined,
                    'info': network,
                };
            }
            const rawType = this.safeString(currecy, 'tokenType');
            const type = (rawType === 'REAL_MONEY') ? 'fiat' : 'crypto';
            result[code] = this.safeCurrencyStructure({
                'id': currencyId,
                'code': code,
                'precision': undefined,
                'type': type,
                'name': this.safeString(currecy, 'coinFullName'),
                'active': undefined,
                'deposit': this.safeBool(currecy, 'allowDeposit'),
                'withdraw': this.safeBool(currecy, 'allowWithdraw'),
                'fee': undefined,
                'limits': {
                    'deposit': {
                        'min': undefined,
                        'max': undefined,
                    },
                    'withdraw': {
                        'min': undefined,
                        'max': undefined,
                    },
                },
                'networks': parsedNetworks,
                'info': currecy,
            });
        }
        return result;
    }
    /**
     * @method
     * @name hashkey#fetchOrderBook
     * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
     * @see https://hashkeyglobal-apidoc.readme.io/reference/get-order-book
     * @param {string} symbol unified symbol of the market to fetch the order book for
     * @param {int} [limit] the maximum amount of order book entries to return (maximum value is 200)
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
     */
    async fetchOrderBook(symbol, limit = undefined, params = {}) {
        await this.loadMarkets();
        const market = this.market(symbol);
        const request = {
            'symbol': market['id'],
        };
        if (limit !== undefined) {
            request['limit'] = limit;
        }
        const response = await this.publicGetQuoteV1Depth(this.extend(request, params));
        //
        //     {
        //         "t": 1721681436393,
        //         "b": [
        //             ["67902.49", "0.00112"],
        //             ["67901.08", "0.01014"]
        //             ...
        //         ],
        //         "a": [
        //             ["67905.99", "0.87134"],
        //             ["67906", "0.57361"]
        //             ...
        //         ]
        //     }
        //
        const timestamp = this.safeInteger(response, 't');
        return this.parseOrderBook(response, symbol, timestamp, 'b', 'a');
    }
    /**
     * @method
     * @name hashkey#fetchTrades
     * @description get the list of most recent trades for a particular symbol
     * @see https://hashkeyglobal-apidoc.readme.io/reference/get-recent-trade-list
     * @param {string} symbol unified symbol of the market to fetch trades for
     * @param {int} [since] timestamp in ms of the earliest trade to fetch
     * @param {int} [limit] the maximum amount of trades to fetch (maximum value is 100)
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
     */
    async fetchTrades(symbol, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets();
        const market = this.market(symbol);
        const request = {
            'symbol': market['id'],
        };
        if (limit !== undefined) {
            request['limit'] = limit;
        }
        const response = await this.publicGetQuoteV1Trades(this.extend(request, params));
        //
        //     [
        //         {
        //             "t": 1721682745779,
        //             "p": "67835.99",
        //             "q": "0.00017",
        //             "ibm": true
        //         },
        //         ...
        //     ]
        //
        return this.parseTrades(response, market, since, limit);
    }
    /**
     * @method
     * @name hashkey#fetchMyTrades
     * @description fetch all trades made by the user
     * @see https://hashkeyglobal-apidoc.readme.io/reference/get-account-trade-list
     * @see https://hashkeyglobal-apidoc.readme.io/reference/query-futures-trades
     * @see https://hashkeyglobal-apidoc.readme.io/reference/get-sub-account-user
     * @param {string} symbol *is mandatory for swap markets* unified market symbol
     * @param {int} [since] the earliest time in ms to fetch trades for
     * @param {int} [limit] the maximum amount of trades to fetch (default 200, max 500)
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @param {string} [params.type] 'spot' or 'swap' - the type of the market to fetch trades for (default 'spot')
     * @param {int} [params.until] the latest time in ms to fetch trades for, only supports the last 30 days timeframe
     * @param {string} [params.fromId] srarting trade id
     * @param {string} [params.toId] ending trade id
     * @param {string} [params.clientOrderId] *spot markets only* filter trades by orderId
     * @param {string} [params.accountId] account id to fetch the orders from
     * @returns {Trade[]} a list of [trade structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#trade-structure}
     */
    async fetchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
        const methodName = 'fetchMyTrades';
        await this.loadMarkets();
        const request = {};
        let market = undefined;
        if (symbol !== undefined) {
            market = this.market(symbol);
        }
        let marketType = 'spot';
        [marketType, params] = this.handleMarketTypeAndParams(methodName, market, params);
        if (since !== undefined) {
            request['startTime'] = since;
        }
        if (limit !== undefined) {
            request['limit'] = limit;
        }
        let until = undefined;
        [until, params] = this.handleOptionAndParams(params, methodName, 'until');
        if (until !== undefined) {
            request['endTime'] = until;
        }
        let accountId = undefined;
        [accountId, params] = this.handleOptionAndParams(params, methodName, 'accountId');
        let response = undefined;
        if (marketType === 'spot') {
            if (market !== undefined) {
                request['symbol'] = market['id'];
            }
            if (accountId !== undefined) {
                request['accountId'] = accountId;
            }
            response = await this.privateGetApiV1AccountTrades(this.extend(request, params));
            //
            //     [
            //         {
            //             "id": "1739352552862964736",
            //             "clientOrderId": "1722082982086472",
            //             "ticketId": "1739352552795029504",
            //             "symbol": "ETHUSDT",
            //             "symbolName": "ETHUSDT",
            //             "orderId": "1739352552762301440",
            //             "matchOrderId": "0",
            //             "price": "3289.96",
            //             "qty": "0.001",
            //             "commission": "0.0000012",
            //             "commissionAsset": "ETH",
            //             "time": "1722082982097",
            //             "isBuyer": true,
            //             "isMaker": false,
            //             "fee": {
            //                 "feeCoinId": "ETH",
            //                 "feeCoinName": "ETH",
            //                 "fee": "0.0000012"
            //             },
            //             "feeCoinId": "ETH",
            //             "feeAmount": "0.0000012",
            //             "makerRebate": "0"
            //         },
            //         ...
            //     ]
            //
        }
        else if (marketType === 'swap') {
            if (symbol === undefined) {
                throw new errors.ArgumentsRequired(this.id + ' ' + methodName + '() requires a symbol argument for swap markets');
            }
            request['symbol'] = market['id'];
            if (accountId !== undefined) {
                request['subAccountId'] = accountId;
                response = await this.privateGetApiV1FuturesSubAccountUserTrades(this.extend(request, params));
            }
            else {
                response = await this.privateGetApiV1FuturesUserTrades(this.extend(request, params));
                //
                //     [
                //         {
                //             "time": "1722429951648",
                //             "tradeId": "1742263144691139328",
                //             "orderId": "1742263144028363776",
                //             "symbol": "ETHUSDT-PERPETUAL",
                //             "price": "3327.54",
                //             "quantity": "4",
                //             "commissionAsset": "USDT",
                //             "commission": "0.00798609",
                //             "makerRebate": "0",
                //             "type": "LIMIT",
                //             "side": "BUY_OPEN",
                //             "realizedPnl": "0",
                //             "isMarker": false
                //         }
                //     ]
                //
            }
        }
        else {
            throw new errors.NotSupported(this.id + ' ' + methodName + '() is not supported for ' + marketType + ' type of markets');
        }
        return this.parseTrades(response, market, since, limit);
    }
    parseTrade(trade, market = undefined) {
        //
        // fetchTrades
        //
        //     {
        //         "t": 1721682745779,
        //         "p": "67835.99",
        //         "q": "0.00017",
        //         "ibm": true
        //     }
        //
        // fetchMyTrades spot
        //
        //     {
        //         "id": "1739352552862964736",
        //         "clientOrderId": "1722082982086472",
        //         "ticketId": "1739352552795029504",
        //         "symbol": "ETHUSDT",
        //         "symbolName": "ETHUSDT",
        //         "orderId": "1739352552762301440",
        //         "matchOrderId": "0",
        //         "price": "3289.96",
        //         "qty": "0.001",
        //         "commission": "0.0000012",
        //         "commissionAsset": "ETH",
        //         "time": "1722082982097",
        //         "isBuyer": true,
        //         "isMaker": false,
        //         "fee": {
        //             "feeCoinId": "ETH",
        //             "feeCoinName": "ETH",
        //             "fee": "0.0000012"
        //         },
        //         "feeCoinId": "ETH",
        //         "feeAmount": "0.0000012",
        //         "makerRebate": "0"
        //     }
        //
        // fetchMyTrades swap
        //     {
        //         "time": "1722429951648",
        //         "tradeId": "1742263144691139328",
        //         "orderId": "1742263144028363776",
        //         "symbol": "ETHUSDT-PERPETUAL",
        //         "price": "3327.54",
        //         "quantity": "4",
        //         "commissionAsset": "USDT",
        //         "commission": "0.00798609",
        //         "makerRebate": "0",
        //         "type": "LIMIT",
        //         "side": "BUY_OPEN",
        //         "realizedPnl": "0",
        //         "isMarker": false
        //     }
        const timestamp = this.safeInteger2(trade, 't', 'time');
        const marketId = this.safeString(trade, 'symbol');
        market = this.safeMarket(marketId, market);
        let side = this.safeStringLower(trade, 'side'); // swap trades have side param
        if (side !== undefined) {
            side = this.safeString(side.split('_'), 0);
        }
        const isBuyer = this.safeBool(trade, 'isBuyer');
        if (isBuyer !== undefined) {
            side = isBuyer ? 'buy' : 'sell';
        }
        let takerOrMaker = undefined;
        const isMaker = this.safeBoolN(trade, ['isMaker', 'isMarker']);
        if (isMaker !== undefined) {
            takerOrMaker = isMaker ? 'maker' : 'taker';
        }
        const isBuyerMaker = this.safeBool(trade, 'ibm');
        // if public trade
        if (isBuyerMaker !== undefined) {
            takerOrMaker = 'taker';
            side = isBuyerMaker ? 'sell' : 'buy';
        }
        let feeCost = this.safeString(trade, 'commission');
        let feeCurrncyId = this.safeString(trade, 'commissionAsset');
        const feeInfo = this.safeDict(trade, 'fee');
        let fee = undefined;
        if (feeInfo !== undefined) {
            feeCost = this.safeString(feeInfo, 'fee');
            feeCurrncyId = this.safeString(feeInfo, 'feeCoinId');
        }
        if (feeCost !== undefined) {
            fee = {
                'cost': this.parseNumber(feeCost),
                'currency': this.safeCurrencyCode(feeCurrncyId),
            };
        }
        return this.safeTrade({
            'id': this.safeString2(trade, 'id', 'tradeId'),
            'timestamp': timestamp,
            'datetime': this.iso8601(timestamp),
            'symbol': market['symbol'],
            'side': side,
            'price': this.safeString2(trade, 'p', 'price'),
            'amount': this.safeStringN(trade, ['q', 'qty', 'quantity']),
            'cost': undefined,
            'takerOrMaker': takerOrMaker,
            'type': undefined,
            'order': this.safeString(trade, 'orderId'),
            'fee': fee,
            'info': trade,
        }, market);
    }
    /**
     * @method
     * @name hashkey#fetchOHLCV
     * @see https://hashkeyglobal-apidoc.readme.io/reference/get-kline
     * @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
     * @param {string} symbol unified symbol of the market to fetch OHLCV data for
     * @param {string} timeframe the length of time each candle represents
     * @param {int} [since] timestamp in ms of the earliest candle to fetch
     * @param {int} [limit] the maximum amount of candles to fetch
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @param {int} [params.until] timestamp in ms of the latest candle to fetch
     * @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
     * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
     */
    async fetchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
        const methodName = 'fetchOHLCV';
        await this.loadMarkets();
        let paginate = false;
        [paginate, params] = this.handleOptionAndParams(params, methodName, 'paginate');
        if (paginate) {
            return await this.fetchPaginatedCallDeterministic('fetchOHLCV', symbol, since, limit, timeframe, params, 1000);
        }
        const market = this.market(symbol);
        timeframe = this.safeString(this.timeframes, timeframe, timeframe);
        const request = {
            'symbol': market['id'],
            'interval': timeframe,
        };
        if (since !== undefined) {
            request['startTime'] = since;
        }
        if (limit !== undefined) {
            request['limit'] = limit;
        }
        let until = undefined;
        [until, params] = this.handleOptionAndParams(params, methodName, 'until');
        if (until !== undefined) {
            request['endTime'] = until;
        }
        const response = await this.publicGetQuoteV1Klines(this.extend(request, params));
        //
        //     [
        //         [
        //             1721684280000,
        //             "67832.49",
        //             "67862.5",
        //             "67832.49",
        //             "67861.44",
        //             "0.01122",0,
        //             "761.2763533",68,
        //             "0.00561",
        //             "380.640643"
        //         ],
        //         ...
        //     ]
        //
        return this.parseOHLCVs(response, market, timeframe, since, limit);
    }
    parseOHLCV(ohlcv, market = undefined) {
        //
        //     [
        //         1721684280000,
        //         "67832.49",
        //         "67862.5",
        //         "67832.49",
        //         "67861.44",
        //         "0.01122",0,
        //         "761.2763533",68,
        //         "0.00561",
        //         "380.640643"
        //     ]
        //
        return [
            this.safeInteger(ohlcv, 0),
            this.safeNumber(ohlcv, 1),
            this.safeNumber(ohlcv, 2),
            this.safeNumber(ohlcv, 3),
            this.safeNumber(ohlcv, 4),
            this.safeNumber(ohlcv, 5),
        ];
    }
    /**
     * @method
     * @name hashkey#fetchTicker
     * @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
     * @see https://hashkeyglobal-apidoc.readme.io/reference/get-24hr-ticker-price-change
     * @param {string} symbol unified symbol of the market to fetch the ticker for
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
     */
    async fetchTicker(symbol, params = {}) {
        await this.loadMarkets();
        const market = this.market(symbol);
        const request = {
            'symbol': market['id'],
        };
        const response = await this.publicGetQuoteV1Ticker24hr(this.extend(request, params));
        //
        //     [
        //         {
        //             "t": 1721685896846,
        //             "s": "BTCUSDT-PERPETUAL",
        //             "c": "67756.7",
        //             "h": "68479.9",
        //             "l": "66594.3",
        //             "o": "68279.7",
        //             "b": "67756.6",
        //             "a": "67756.7",
        //             "v": "1604722",
        //             "qv": "108827258.7761"
        //         }
        //     ]
        //
        const ticker = this.safeDict(response, 0, {});
        return this.parseTicker(ticker, market);
    }
    /**
     * @method
     * @name hashkey#fetchTickers
     * @description fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
     * @see https://hashkeyglobal-apidoc.readme.io/reference/get-24hr-ticker-price-change
     * @param {string[]} [symbols] unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure}
     */
    async fetchTickers(symbols = undefined, params = {}) {
        await this.loadMarkets();
        symbols = this.marketSymbols(symbols);
        const response = await this.publicGetQuoteV1Ticker24hr(params);
        return this.parseTickers(response, symbols);
    }
    parseTicker(ticker, market = undefined) {
        //
        //     {
        //         "t": 1721685896846,
        //         "s": "BTCUSDT-PERPETUAL",
        //         "c": "67756.7",
        //         "h": "68479.9",
        //         "l": "66594.3",
        //         "o": "68279.7",
        //         "b": "67756.6",
        //         "a": "67756.7",
        //         "v": "1604722",
        //         "qv": "108827258.7761"
        //     }
        //
        const timestamp = this.safeInteger(ticker, 't');
        const marketId = this.safeString(ticker, 's');
        market = this.safeMarket(marketId, market);
        const symbol = market['symbol'];
        const last = this.safeString(ticker, 'c');
        return this.safeTicker({
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601(timestamp),
            'high': this.safeString(ticker, 'h'),
            'low': this.safeString(ticker, 'l'),
            'bid': this.safeString(ticker, 'b'),
            'bidVolume': undefined,
            'ask': this.safeString(ticker, 'a'),
            'askVolume': undefined,
            'vwap': undefined,
            'open': this.safeString(ticker, 'o'),
            'close': last,
            'last': last,
            'previousClose': undefined,
            'change': undefined,
            'percentage': undefined,
            'average': undefined,
            'baseVolume': this.safeString(ticker, 'v'),
            'quoteVolume': this.safeString(ticker, 'qv'),
            'info': ticker,
        }, market);
    }
    /**
     * @method
     * @name hashkey#fetchLastPrices
     * @description fetches the last price for multiple markets
     * @see https://hashkeyglobal-apidoc.readme.io/reference/get-symbol-price-ticker
     * @param {string[]} [symbols] unified symbols of the markets to fetch the last prices
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @param {string} [params.symbol] the id of the market to fetch last price for
     * @returns {object} a dictionary of lastprices structures
     */
    async fetchLastPrices(symbols = undefined, params = {}) {
        await this.loadMarkets();
        symbols = this.marketSymbols(symbols);
        const request = {};
        const response = await this.publicGetQuoteV1TickerPrice(this.extend(request, params));
        //
        //     [
        //         {
        //             "s": "BTCUSDT-PERPETUAL",
        //             "p": "64871"
        //         },
        //         ...
        //     ]
        //
        return this.parseLastPrices(response, symbols);
    }
    parseLastPrice(entry, market = undefined) {
        const marketId = this.safeString(entry, 's');
        market = this.safeMarket(marketId, market);
        return {
            'symbol': market['symbol'],
            'timestamp': undefined,
            'datetime': undefined,
            'price': this.safeNumber(entry, 'p'),
            'side': undefined,
            'info': entry,
        };
    }
    /**
     * @method
     * @name hashkey#fetchBalance
     * @description query for balance and get the amount of funds available for trading or funds locked in orders
     * @see https://hashkeyglobal-apidoc.readme.io/reference/get-account-information
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @param {string} [params.accountId] account ID, for Master Key only
     * @param {string} [params.type] 'spot' or 'swap' - the type of the market to fetch balance for (default 'spot')
     * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
     */
    async fetchBalance(params = {}) {
        await this.loadMarkets();
        const request = {};
        const methodName = 'fetchBalance';
        let marketType = 'spot';
        [marketType, params] = this.handleMarketTypeAndParams(methodName, undefined, params, marketType);
        if (marketType === 'swap') {
            const response = await this.privateGetApiV1FuturesBalance(params);
            //
            //     [
            //         {
            //             "balance": "30.63364672",
            //             "availableBalance": "28.85635534",
            //             "positionMargin": "4.3421",
            //             "orderMargin": "0",
            //             "asset": "USDT",
            //             "crossUnRealizedPnl": "2.5649"
            //         }
            //     ]
            //
            const balance = this.safeDict(response, 0, {});
            return this.parseSwapBalance(balance);
        }
        else if (marketType === 'spot') {
            const response = await this.privateGetApiV1Account(this.extend(request, params));
            //
            //     {
            //         "balances": [
            //             {
            //                 "asset":"USDT",
            //                 "assetId":"USDT",
            //                 "assetName":"USDT",
            //                 "total":"40",
            //                 "free":"40",
            //                 "locked":"0"
            //             },
            //             ...
            //         ],
            //         "userId": "1732885739572845312"
            //     }
            //
            return this.parseBalance(response);
        }
        else {
            throw new errors.NotSupported(this.id + ' ' + methodName + '() is not supported for ' + marketType + ' type of markets');
        }
    }
    parseBalance(balance) {
        //
        //     {
        //         "balances": [
        //             {
        //                 "asset":"USDT",
        //                 "assetId":"USDT",
        //                 "assetName":"USDT",
        //                 "total":"40",
        //                 "free":"40",
        //                 "locked":"0"
        //             },
        //             ...
        //         ],
        //         "userId": "1732885739572845312"
        //     }
        //
        const result = {
            'info': balance,
        };
        const balances = this.safeList(balance, 'balances', []);
        for (let i = 0; i < balances.length; i++) {
            const balanceEntry = balances[i];
            const currencyId = this.safeString(balanceEntry, 'asset');
            const code = this.safeCurrencyCode(currencyId);
            const account = this.account();
            account['total'] = this.safeString(balanceEntry, 'total');
            account['free'] = this.safeString(balanceEntry, 'free');
            account['used'] = this.safeString(balanceEntry, 'locked');
            result[code] = account;
        }
        return this.safeBalance(result);
    }
    parseSwapBalance(balance) {
        //
        //     {
        //         "balance": "30.63364672",
        //         "availableBalance": "28.85635534",
        //         "positionMargin": "4.3421",
        //         "orderMargin": "0",
        //         "asset": "USDT",
        //         "crossUnRealizedPnl": "2.5649"
        //     }
        //
        const currencyId = this.safeString(balance, 'asset');
        const code = this.safeCurrencyCode(currencyId);
        const account = this.account();
        account['total'] = this.safeString(balance, 'balance');
        const positionMargin = this.safeString(balance, 'positionMargin');
        const orderMargin = this.safeString(balance, 'orderMargin');
        account['used'] = Precise["default"].stringAdd(positionMargin, orderMargin);
        const result = {
            'info': balance,
        };
        result[code] = account;
        return this.safeBalance(result);
    }
    /**
     * @method
     * @name hashkey#fetchDepositAddress
     * @description fetch the deposit address for a currency associated with this account
     * @see https://hashkeyglobal-apidoc.readme.io/reference/get-deposit-address
     * @param {string} code unified currency code (default is 'USDT')
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @param {string} [params.network] network for fetch deposit address (default is 'ETH')
     * @returns {object} an [address structure]{@link https://docs.ccxt.com/#/?id=address-structure}
     */
    async fetchDepositAddress(code, params = {}) {
        await this.loadMarkets();
        const currency = this.currency(code);
        const request = {
            'coin': currency['id'],
        };
        let networkCode = undefined;
        [networkCode, params] = this.handleNetworkCodeAndParams(params);
        if (networkCode === undefined) {
            networkCode = this.defaultNetworkCode(code);
        }
        request['chainType'] = this.networkCodeToId(networkCode, code);
        const response = await this.privateGetApiV1AccountDepositAddress(this.extend(request, params));
        //
        //     {
        //         "canDeposit": true,
        //         "address": "0x61AAd7F763e2C7fF1CC996918740F67f9dC8BF4e",
        //         "addressExt": "",
        //         "minQuantity": "1",
        //         "needAddressTag": false,
        //         "requiredConfirmTimes": 64,
        //         "canWithdrawConfirmTimes": 64,
        //         "coinType": "ERC20_TOKEN"
        //     }
        //
        const depositAddress = this.parseDepositAddress(response, currency);
        depositAddress['network'] = networkCode;
        return depositAddress;
    }
    parseDepositAddress(depositAddress, currency = undefined) {
        //
        //     {
        //         "canDeposit": true,
        //         "address": "0x61AAd7F763e2C7fF1CC996918740F67f9dC8BF4e",
        //         "addressExt": "",
        //         "minQuantity": "1",
        //         "needAddressTag": false,
        //         "requiredConfirmTimes": 64,
        //         "canWithdrawConfirmTimes": 64,
        //         "coinType": "ERC20_TOKEN"
        //     }
        //
        const address = this.safeString(depositAddress, 'address');
        this.checkAddress(address);
        let tag = this.safeString(depositAddress, 'addressExt');
        if (tag === '') {
            tag = undefined;
        }
        return {
            'info': depositAddress,
            'currency': currency['code'],
            'network': undefined,
            'address': address,
            'tag': tag,
        };
    }
    /**
     * @method
     * @name hashkey#fetchDeposits
     * @description fetch all deposits made to an account
     * @see https://hashkeyglobal-apidoc.readme.io/reference/get-deposit-history
     * @param {string} code unified currency code of the currency transferred
     * @param {int} [since] the earliest time in ms to fetch transfers for (default 24 hours ago)
     * @param {int} [limit] the maximum number of transfer structures to retrieve (default 50, max 200)
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @param {int} [params.until] the latest time in ms to fetch transfers for (default time now)
     * @param {int} [params.fromId] starting ID (To be released)
     * @returns {object[]} a list of [transfer structures]{@link https://docs.ccxt.com/#/?id=transfer-structure}
     */
    async fetchDeposits(code = undefined, since = undefined, limit = undefined, params = {}) {
        const methodName = 'fetchDeposits';
        await this.loadMarkets();
        const request = {};
        let currency = undefined;
        if (code !== undefined) {
            currency = this.currency(code);
            request['coin'] = currency['id'];
        }
        if (since !== undefined) {
            request['startTime'] = since;
        }
        if (limit !== undefined) {
            request['limit'] = limit;
        }
        let until = undefined;
        [until, params] = this.handleOptionAndParams(params, methodName, 'until');
        if (until !== undefined) {
            request['endTime'] = until;
        }
        const response = await this.privateGetApiV1AccountDepositOrders(this.extend(request, params));
        //
        //     [
        //         {
        //             "time": "1721641082163",
        //             "coin": "TRXUSDT",
        //             "coinName": "TRXUSDT",
        //             "address": "TBA6CypYJizwA9XdC7Ubgc5F1bxrQ7SqPt",
        //             "quantity": "86.00000000000000000000",
        //             "status": 4,
        //             "statusCode": "4",
        //             "txId": "0970c14da4d7412295fa7b21c03a08da319e746a0d59ef14462a74183d118da4"
        //         }
        //     ]
        //
        return this.parseTransactions(response, currency, since, limit, { 'type': 'deposit' });
    }
    /**
     * @method
     * @name hashkey#fetchWithdrawals
     * @description fetch all withdrawals made from an account
     * @see https://hashkeyglobal-apidoc.readme.io/reference/withdrawal-records
     * @param {string} code unified currency code of the currency transferred
     * @param {int} [since] the earliest time in ms to fetch transfers for (default 24 hours ago)
     * @param {int} [limit] the maximum number of transfer structures to retrieve (default 50, max 200)
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @param {int} [params.until] the latest time in ms to fetch transfers for (default time now)
     * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
     */
    async fetchWithdrawals(code = undefined, since = undefined, limit = undefined, params = {}) {
        const methodName = 'fetchWithdrawals';
        await this.loadMarkets();
        const request = {};
        let currency = undefined;
        if (code !== undefined) {
            currency = this.currency(code);
            request['coin'] = currency['id'];
        }
        if (since !== undefined) {
            request['startTime'] = since;
        }
        if (limit !== undefined) {
            request['limit'] = limit;
        }
        let until = undefined;
        [until, params] = this.handleOptionAndParams(params, methodName, 'until');
        if (until !== undefined) {
            request['endTime'] = until;
        }
        const response = await this.privateGetApiV1AccountWithdrawOrders(this.extend(request, params));
        //
        //     [
        //         {
        //             "time": "1723545505366",
        //             "id": "W611267400947572736",
        //             "coin": "USDT",
        //             "coinId": "USDT",
        //             "coinName": "USDT",
        //             "address": "TQbkBMnWnJNGTAUpFS4kvv4NRLzUAnGAes",
        //             "quantity": "2.00000000",
        //             "arriveQuantity": "2.00000000",
        //             "txId": "f83f94e7d2e81fbec98c66c25d6615872cc2d426145629b6cf22e5e0a0753715",
        //             "addressUrl": "TQbkBMnWnJNGTAUpFS4kvv4NRLzUAnGAes",
        //             "feeCoinId": "USDT",
        //             "feeCoinName": "USDT",
        //             "fee": "1.00000000",
        //             "remark": "",
        //             "platform": ""
        //         }
        //     ]
        //
        return this.parseTransactions(response, currency, since, limit, { 'type': 'withdrawal' });
    }
    /**
     * @method
     * @name hashkey#withdraw
     * @description make a withdrawal
     * @see https://hashkeyglobal-apidoc.readme.io/reference/withdraw
     * @param {string} code unified currency code
     * @param {float} amount the amount to withdraw
     * @param {string} address the address to withdraw to
     * @param {string} tag
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @param {string} [params.network] network for withdraw
     * @param {string} [params.clientOrderId] client order id
     * @param {string} [params.platform] the platform to withdraw to (hashkey, HashKey HK)
     * @returns {object} a [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure}
     */
    async withdraw(code, amount, address, tag = undefined, params = {}) {
        [tag, params] = this.handleWithdrawTagAndParams(tag, params);
        await this.loadMarkets();
        const currency = this.currency(code);
        const request = {
            'coin': currency['id'],
            'address': address,
            'quantity': amount,
        };
        if (tag !== undefined) {
            request['addressExt'] = tag;
        }
        let networkCode = undefined;
        [networkCode, params] = this.handleNetworkCodeAndParams(params);
        if (networkCode !== undefined) {
            request['chainType'] = this.networkCodeToId(networkCode);
        }
        const response = await this.privatePostApiV1AccountWithdraw(this.extend(request, params));
        //
        //     {
        //         "success": true,
        //         "id": "0",
        //         "orderId": "W611267400947572736",
        //         "accountId": "1732885739589466115"
        //     }
        //
        return this.parseTransaction(response, currency);
    }
    parseTransaction(transaction, currency = undefined) {
        //
        //  fetchDeposits
        //     {
        //         "time": "1721641082163",
        //         "coin": "TRXUSDT", // todo how to parse it?
        //         "coinName": "TRXUSDT",
        //         "address": "TBA6CypYJizwA9XdC7Ubgc5F1bxrQ7SqPt",
        //         "quantity": "86.00000000000000000000",
        //         "status": 4,
        //         "statusCode": "4",
        //         "txId": "0970c14da4d7412295fa7b21c03a08da319e746a0d59ef14462a74183d118da4"
        //     }
        //
        // fetchWithdrawals
        //     {
        //         "time": "1723545505366",
        //         "id": "W611267400947572736",
        //         "coin": "USDT",
        //         "coinId": "USDT",
        //         "coinName": "USDT",
        //         "address": "TQbkBMnWnJNGTAUpFS4kvv4NRLzUAnGAes",
        //         "quantity": "2.00000000",
        //         "arriveQuantity": "2.00000000",
        //         "txId": "f83f94e7d2e81fbec98c66c25d6615872cc2d426145629b6cf22e5e0a0753715",
        //         "addressUrl": "TQbkBMnWnJNGTAUpFS4kvv4NRLzUAnGAes",
        //         "feeCoinId": "USDT",
        //         "feeCoinName": "USDT",
        //         "fee": "1.00000000",
        //         "remark": "",
        //         "platform": ""
        //     }
        //
        // withdraw
        //     {
        //         "success": true,
        //         "id": "0",
        //         "orderId": "W611267400947572736",
        //         "accountId": "1732885739589466115"
        //     }
        //
        const id = this.safeString2(transaction, 'id', 'orderId');
        const address = this.safeString(transaction, 'address');
        let status = this.safeString(transaction, 'status'); // for fetchDeposits
        if (status === undefined) {
            const success = this.safeBool(transaction, 'success', false); // for withdraw
            if (success) {
                status = 'ok';
            }
            else {
                const addressUrl = this.safeString(transaction, 'addressUrl'); // for fetchWithdrawals
                if (addressUrl !== undefined) {
                    status = 'ok';
                }
            }
        }
        const txid = this.safeString(transaction, 'txId');
        const coin = this.safeString(transaction, 'coin');
        const code = this.safeCurrencyCode(coin, currency);
        const timestamp = this.safeInteger(transaction, 'time');
        const amount = this.safeNumber(transaction, 'quantity');
        const feeCost = this.safeNumber(transaction, 'fee');
        let fee = undefined;
        if (feeCost !== undefined) {
            fee = {
                'cost': feeCost,
                'currency': code,
            };
        }
        return {
            'info': transaction,
            'id': id,
            'txid': txid,
            'timestamp': timestamp,
            'datetime': this.iso8601(timestamp),
            'network': undefined,
            'address': address,
            'addressTo': undefined,
            'addressFrom': undefined,
            'tag': undefined,
            'tagTo': undefined,
            'tagFrom': undefined,
            'type': undefined,
            'amount': amount,
            'currency': code,
            'status': this.parseTransactionStatus(status),
            'updated': undefined,
            'internal': undefined,
            'comment': undefined,
            'fee': fee,
        };
    }
    parseTransactionStatus(status) {
        const statuses = {
            '1': 'pending',
            '2': 'pending',
            '3': 'failed',
            '4': 'ok',
            '5': 'pending',
            '6': 'ok',
            '7': 'failed',
            '8': 'cancelled',
            '9': 'failed',
            '10': 'failed',
            'successful': 'ok',
            'success': 'ok',
        };
        return this.safeString(statuses, status, status);
    }
    /**
     * @method
     * @name hashkey#transfer
     * @description transfer currency internally between wallets on the same account
     * @see https://hashkeyglobal-apidoc.readme.io/reference/new-account-transfer
     * @param {string} code unified currency code
     * @param {float} amount amount to transfer
     * @param {string} fromAccount account id to transfer from
     * @param {string} toAccount account id to transfer to
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @param {string} [params.clientOrderId] a unique id for the transfer
     * @param {string} [params.remark] a note for the transfer
     * @returns {object} a [transfer structure]{@link https://docs.ccxt.com/#/?id=transfer-structure}
     */
    async transfer(code, amount, fromAccount, toAccount, params = {}) {
        await this.loadMarkets();
        const currency = this.currency(code);
        const request = {
            'coin': currency['id'],
            'quantity': this.currencyToPrecision(code, amount),
            'fromAccountId': fromAccount,
            'toAccountId': toAccount,
        };
        const response = await this.privatePostApiV1AccountAssetTransfer(this.extend(request, params));
        //
        //     {
        //         "success": true,
        //         "timestamp": 1722260230773,
        //         "clientOrderId": "",
        //         "orderId": "1740839420695806720"
        //     }
        //
        return this.parseTransfer(response, currency);
    }
    parseTransfer(transfer, currency = undefined) {
        const timestamp = this.safeInteger(transfer, 'timestamp');
        const currencyId = this.safeString(currency, 'id');
        let status = undefined;
        const success = this.safeBool(transfer, 'success', false);
        if (success) {
            status = 'ok';
        }
        return {
            'id': this.safeString(transfer, 'orderId'),
            'timestamp': timestamp,
            'datetime': this.iso8601(timestamp),
            'currency': this.safeCurrencyCode(currencyId, currency),
            'amount': undefined,
            'fromAccount': undefined,
            'toAccount': undefined,
            'status': status,
            'info': transfer,
        };
    }
    /**
     * @method
     * @name hashkey#fetchAccounts
     * @description fetch all the accounts associated with a profile
     * @see https://hashkeyglobal-apidoc.readme.io/reference/query-sub-account
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @returns {object} a dictionary of [account structures]{@link https://docs.ccxt.com/#/?id=account-structure} indexed by the account type
     */
    async fetchAccounts(params = {}) {
        await this.loadMarkets();
        const response = await this.privateGetApiV1AccountType(params);
        //
        //     [
        //         {
        //             "accountId": "1732885739589466112",
        //             "accountLabel": "Main Trading Account",
        //             "accountType": 1,
        //             "accountIndex": 0
        //         },
        //         ...
        //     ]
        //
        return this.parseAccounts(response, params);
    }
    parseAccount(account) {
        const accountLabel = this.safeString(account, 'accountLabel');
        let label = '';
        if (accountLabel === 'Main Trading Account' || accountLabel === 'Main Future Account') {
            label = 'main';
        }
        else if (accountLabel === 'Sub Main Trading Account' || accountLabel === 'Sub Main Future Account') {
            label = 'sub';
        }
        const accountType = this.parseAccountType(this.safeString(account, 'accountType'));
        const type = label + ' ' + accountType;
        return {
            'id': this.safeString(account, 'accountId'),
            'type': type,
            'code': undefined,
            'info': account,
        };
    }
    parseAccountType(type) {
        const types = {
            '1': 'spot account',
            '3': 'swap account',
            '5': 'custody account',
            '6': 'fiat account',
        };
        return this.safeString(types, type, type);
    }
    encodeAccountType(type) {
        const types = {
            'spot': '1',
            'swap': '3',
            'custody': '5',
        };
        return this.safeInteger(types, type, type);
    }
    encodeFlowType(type) {
        const types = {
            'trade': '1',
            'fee': '3',
            'transfer': '51',
            'deposit': '900',
            'withdraw': '904',
        };
        return this.safeInteger(types, type, type);
    }
    /**
     * @method
     * @name hashkey#fetchLedger
     * @description fetch the history of changes, actions done by the user or operations that altered the balance of the user
     * @see https://hashkeyglobal-apidoc.readme.io/reference/get-account-transaction-list
     * @param {string} [code] unified currency code, default is undefined (not used)
     * @param {int} [since] timestamp in ms of the earliest ledger entry, default is undefined
     * @param {int} [limit] max number of ledger entries to return, default is undefined
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @param {int} [params.until] the latest time in ms to fetch entries for
     * @param {int} [params.flowType] trade, fee, transfer, deposit, withdrawal
     * @param {int} [params.accountType] spot, swap, custody
     * @returns {object} a [ledger structure]{@link https://docs.ccxt.com/#/?id=ledger}
     */
    async fetchLedger(code = undefined, since = undefined, limit = undefined, params = {}) {
        const methodName = 'fetchLedger';
        if (since === undefined) {
            throw new errors.ArgumentsRequired(this.id + ' ' + methodName + '() requires a since argument');
        }
        let until = undefined;
        [until, params] = this.handleOptionAndParams(params, methodName, 'until');
        if (until === undefined) {
            throw new errors.ArgumentsRequired(this.id + ' ' + methodName + '() requires an until argument');
        }
        await this.loadMarkets();
        const currency = this.currency(code);
        const request = {};
        request['startTime'] = since;
        if (limit !== undefined) {
            request['limit'] = limit;
        }
        request['endTime'] = until;
        let flowType = undefined;
        [flowType, params] = this.handleOptionAndParams(params, methodName, 'flowType');
        if (flowType !== undefined) {
            request['flowType'] = this.encodeFlowType(flowType);
        }
        let accountType = undefined;
        [accountType, params] = this.handleOptionAndParams(params, methodName, 'accountType');
        if (accountType !== undefined) {
            request['accountType'] = this.encodeAccountType(accountType);
        }
        const response = await this.privateGetApiV1AccountBalanceFlow(this.extend(request, params));
        //
        //     [
        //         {
        //             "id": "1740844413612065537",
        //             "accountId": "1732885739589466112",
        //             "coin": "USDT",
        //             "coinId": "USDT",
        //             "coinName": "USDT",
        //             "flowTypeValue": 51,
        //             "flowType": "USER_ACCOUNT_TRANSFER",
        //             "flowName": "",
        //             "change": "-1",
        //             "total": "8.015680088",
        //             "created": "1722260825765"
        //         },
        //         ...
        //     ]
        //
        return this.parseLedger(response, currency, since, limit);
    }
    parseLedgerEntryType(type) {
        const types = {
            '1': 'trade',
            '2': 'fee',
            '51': 'transfer',
            '900': 'deposit',
            '904': 'withdraw',
        };
        return this.safeString(types, type, type);
    }
    parseLedgerEntry(item, currency = undefined) {
        //
        //     {
        //         "id": "1740844413612065537",
        //         "accountId": "1732885739589466112",
        //         "coin": "USDT",
        //         "coinId": "USDT",
        //         "coinName": "USDT",
        //         "flowTypeValue": 51,
        //         "flowType": "USER_ACCOUNT_TRANSFER",
        //         "flowName": "",
        //         "change": "-1",
        //         "total": "8.015680088",
        //         "created": "1722260825765"
        //     }
        //
        const id = this.safeString(item, 'id');
        const account = this.safeString(item, 'accountId');
        const timestamp = this.safeInteger(item, 'created');
        const type = this.parseLedgerEntryType(this.safeString(item, 'flowTypeValue'));
        const currencyId = this.safeString(item, 'coin');
        const code = this.safeCurrencyCode(currencyId, currency);
        currency = this.safeCurrency(currencyId, currency);
        const amountString = this.safeString(item, 'change');
        const amount = this.parseNumber(amountString);
        let direction = 'in';
        if (amountString.indexOf('-') >= 0) {
            direction = 'out';
        }
        const afterString = this.safeString(item, 'total');
        const after = this.parseNumber(afterString);
        const status = 'ok';
        return this.safeLedgerEntry({
            'info': item,
            'id': id,
            'timestamp': timestamp,
            'datetime': this.iso8601(timestamp),
            'account': account,
            'direction': direction,
            'referenceId': undefined,
            'referenceAccount': undefined,
            'type': type,
            'currency': code,
            'symbol': undefined,
            'amount': amount,
            'before': undefined,
            'after': after,
            'status': status,
            'fee': undefined,
        }, currency);
    }
    /**
     * @method
     * @name hashkey#createOrder
     * @description create a trade order
     * @see https://hashkeyglobal-apidoc.readme.io/reference/test-new-order
     * @see https://hashkeyglobal-apidoc.readme.io/reference/create-order
     * @see https://hashkeyglobal-apidoc.readme.io/reference/create-new-futures-order
     * @param {string} symbol unified symbol of the market to create an order in
     * @param {string} type 'market' or 'limit' or 'LIMIT_MAKER' for spot, 'market' or 'limit' or 'STOP' for swap
     * @param {string} side 'buy' or 'sell'
     * @param {float} amount how much of you want to trade in units of the base currency
     * @param {float} [price] the price that the order is to be fulfilled, in units of the quote currency, ignored in market orders
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @param {float} [params.cost] *spot market buy only* the quote quantity that can be used as an alternative for the amount
     * @param {boolean} [params.test] *spot markets only* whether to use the test endpoint or not, default is false
     * @param {bool} [params.postOnly] if true, the order will only be posted to the order book and not executed immediately
     * @param {string} [params.timeInForce] "GTC" or "IOC" or "PO" for spot, 'GTC' or 'FOK' or 'IOC' or 'LIMIT_MAKER' or 'PO' for swap
     * @param {string} [params.clientOrderId] a unique id for the order - is mandatory for swap
     * @param {float} [params.triggerPrice] *swap markets only* The price at which a trigger order is triggered at
     * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
     */
    async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets();
        const market = this.market(symbol);
        if (market['spot']) {
            return await this.createSpotOrder(symbol, type, side, amount, price, params);
        }
        else if (market['swap']) {
            return await this.createSwapOrder(symbol, type, side, amount, price, params);
        }
        else {
            throw new errors.NotSupported(this.id + ' createOrder() is not supported for ' + market['type'] + ' type of markets');
        }
    }
    /**
     * @method
     * @name hashkey#createMarketBuyOrderWithCost
     * @description create a market buy order by providing the symbol and cost
     * @param {string} symbol unified symbol of the market to create an order in
     * @param {float} cost how much you want to trade in units of the quote currency
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
     */
    async createMarketBuyOrderWithCost(symbol, cost, params = {}) {
        await this.loadMarkets();
        const market = this.market(symbol);
        if (!market['spot']) {
            throw new errors.NotSupported(this.id + ' createMarketBuyOrderWithCost() is supported for spot markets only');
        }
        const req = {
            'cost': cost,
        };
        return await this.createOrder(symbol, 'market', 'buy', cost, undefined, this.extend(req, params));
    }
    /**
     * @method
     * @name hashkey#createSpotOrder
     * @description create a trade order on spot market
     * @see https://hashkeyglobal-apidoc.readme.io/reference/test-new-order
     * @see https://hashkeyglobal-apidoc.readme.io/reference/create-order
     * @param {string} symbol unified symbol of the market to create an order in
     * @param {string} type 'market' or 'limit' or 'LIMIT_MAKER'
     * @param {string} side 'buy' or 'sell'
     * @param {float} amount how much of you want to trade in units of the base currency
     * @param {float} [price] the price that the order is to be fulfilled, in units of the quote currency, ignored in market orders
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @param {float} [params.cost] *market buy only* the quote quantity that can be used as an alternative for the amount
     * @param {bool} [params.test] whether to use the test endpoint or not, default is false
     * @param {bool} [params.postOnly] if true, the order will only be posted to the order book and not executed immediately
     * @param {string} [params.timeInForce] 'GTC', 'IOC', or 'PO'
     * @param {string} [params.clientOrderId] a unique id for the order
     * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
     */
    async createSpotOrder(symbol, type, side, amount, price = undefined, params = {}) {
        const triggerPrice = this.safeString2(params, 'stopPrice', 'triggerPrice');
        if (triggerPrice !== undefined) {
            throw new errors.NotSupported(this.id + ' trigger orders are not supported for spot markets');
        }
        await this.loadMarkets();
        const market = this.market(symbol);
        const isMarketBuy = (type === 'market') && (side === 'buy');
        const cost = this.safeString(params, 'cost');
        if ((!isMarketBuy) && (cost !== undefined)) {
            throw new errors.NotSupported(this.id + ' createOrder() supports cost parameter for spot market buy orders only');
        }
        const request = this.createSpotOrderRequest(symbol, type, side, amount, price, params);
        let response = {};
        const test = this.safeBool(params, 'test');
        if (test) {
            params = this.omit(params, 'test');
            response = await this.privatePostApiV1SpotOrderTest(request);
        }
        else if (isMarketBuy && (cost === undefined)) {
            response = await this.privatePostApiV11SpotOrder(request); // the endpoint for market buy orders by amount
            //
            //     {
            //         "accountId": "1732885739589466112",
            //         "symbol": "ETHUSDT",
            //         "symbolName": "ETHUSDT",
            //         "clientOrderId": "1722005792096557",
            //         "orderId": "1738705036219839744",
            //         "transactTime": "1722005792106",
            //         "price": "0",
            //         "origQty": "0.006",
            //         "executedQty": "0.0059",
            //         "status": "FILLED",
            //         "timeInForce": "IOC",
            //         "type": "MARKET",
            //         "side": "BUY",
            //         "reqAmount": "0",
            //         "concentration": ""
            //     }
            //
        }
        else {
            response = await this.privatePostApiV1SpotOrder(request); // the endpoint for market buy orders by cost and other orders
            //
            // market buy
            //     {
            //         "accountId": "1732885739589466112",
            //         "symbol": "ETHUSDT",
            //         "symbolName": "ETHUSDT",
            //         "clientOrderId": "1722004623170558",
            //         "orderId": "1738695230608169984",
            //         "transactTime": "1722004623186",
            //         "price": "0",
            //         "origQty": "0",
            //         "executedQty": "0.0061",
            //         "status": "FILLED",
            //         "timeInForce": "IOC",
            //         "type": "MARKET",
            //         "side": "BUY",
            //         "reqAmount": "20",
            //         "concentration": ""
            //     }
            //
            // market sell
            //     {
            //         "accountId": "1732885739589466112",
            //         "symbol": "ETHUSDT",
            //         "symbolName": "ETHUSDT",
            //         "clientOrderId": "1722005654516362",
            //         "orderId": "1738703882140316928",
            //         "transactTime": "1722005654529",
            //         "price": "0",
            //         "origQty": "0.006",
            //         "executedQty": "0.006",
            //         "status": "FILLED",
            //         "timeInForce": "IOC",
            //         "type": "MARKET",
            //         "side": "SELL",
            //         "reqAmount": "0",
            //         "concentration": ""
            //     }
            //
            // limit
            //     {
            //         "accountId": "1732885739589466112",
            //         "symbol": "ETHUSDT",
            //         "symbolName": "ETHUSDT",
            //         "clientOrderId": "1722006209978370",
            //         "orderId": "1738708541676585728",
            //         "transactTime": "1722006209989",
            //         "price": "5000",
            //         "origQty": "0.005",
            //         "executedQty": "0",
            //         "status": "NEW",
            //         "timeInForce": "GTC",
            //         "type": "LIMIT_MAKER",
            //         "side": "SELL",
            //         "reqAmount": "0",
            //         "concentration": ""
            //     }
            //
        }
        return this.parseOrder(response, market);
    }
    createOrderRequest(symbol, type, side, amount, price = undefined, params = {}) {
        const market = this.market(symbol);
        if (market['spot']) {
            return this.createSpotOrderRequest(symbol, type, side, amount, price, params);
        }
        else if (market['swap']) {
            return this.createSwapOrderRequest(symbol, type, side, amount, price, params);
        }
        else {
            throw new errors.NotSupported(this.id + ' ' + 'createOrderRequest() is not supported for ' + market['type'] + ' type of markets');
        }
    }
    createSpotOrderRequest(symbol, type, side, amount, price = undefined, params = {}) {
        /**
         * @method
         * @ignore
         * @name hashkey#createSpotOrderRequest
         * @description helper function to build request
         * @param {string} symbol unified symbol of the market to create an order in
         * @param {string} type 'market' or 'limit' or 'LIMIT_MAKER'
         * @param {string} side 'buy' or 'sell'
         * @param {float} amount how much of you want to trade in units of the base currency
         * @param {float} [price] the price that the order is to be fulfilled, in units of the quote currency, ignored in market orders
         * @param {object} [params] extra parameters specific to the exchange API endpoint
         * @param {float} [params.cost] *market buy only* the quote quantity that can be used as an alternative for the amount
         * @param {bool} [params.postOnly] if true, the order will only be posted to the order book and not executed immediately
         * @param {string} [params.timeInForce] "GTC", "IOC", or "PO"
         * @param {string} [params.clientOrderId] a unique id for the order
         * @returns {object} request to be sent to the exchange
         */
        const market = this.market(symbol);
        type = type.toUpperCase();
        const request = {
            'symbol': market['id'],
            'side': side.toUpperCase(),
            'type': type,
        };
        if (amount !== undefined) {
            request['quantity'] = this.amountToPrecision(symbol, amount);
        }
        let cost = undefined;
        [cost, params] = this.handleParamString(params, 'cost');
        if (cost !== undefined) {
            request['quantity'] = this.costToPrecision(symbol, cost);
        }
        if (price !== undefined) {
            request['price'] = this.priceToPrecision(symbol, price);
        }
        const isMarketOrder = type === 'MARKET';
        let postOnly = false;
        [postOnly, params] = this.handlePostOnly(isMarketOrder, type === 'LIMIT_MAKER', params);
        if (postOnly && (type === 'LIMIT')) {
            request['type'] = 'LIMIT_MAKER';
        }
        let clientOrderId = undefined;
        [clientOrderId, params] = this.handleParamString(params, 'clientOrderId');
        if (clientOrderId !== undefined) {
            params['newClientOrderId'] = clientOrderId;
        }
        return this.extend(request, params);
    }
    createSwapOrderRequest(symbol, type, side, amount, price = undefined, params = {}) {
        /**
         * @method
         * @ignore
         * @name hashkey#createSwapOrderRequest
         * @description helper function to build request
         * @param {string} symbol unified symbol of the market to create an order in
         * @param {string} type 'market' or 'limit' or 'STOP'
         * @param {string} side 'buy' or 'sell'
         * @param {float} amount how much of you want to trade in units of the base currency
         * @param {float} [price] the price that the order is to be fulfilled, in units of the quote currency, ignored in market orders
         * @param {object} [params] extra parameters specific to the exchange API endpoint
         * @param {bool} [params.postOnly] if true, the order will only be posted to the order book and not executed immediately
         * @param {bool} [params.reduceOnly] true or false whether the order is reduce only
         * @param {float} [params.triggerPrice] The price at which a trigger order is triggered at
         * @param {string} [params.timeInForce] 'GTC', 'FOK', 'IOC', 'LIMIT_MAKER' or 'PO'
         * @param {string} [params.clientOrderId] a unique id for the order
         * @returns {object} request to be sent to the exchange
         */
        const market = this.market(symbol);
        const request = {
            'symbol': market['id'],
            'type': 'LIMIT',
            'quantity': this.amountToPrecision(symbol, amount),
        };
        const isMarketOrder = type === 'market';
        if (isMarketOrder) {
            request['priceType'] = 'MARKET';
        }
        if (price !== undefined) {
            request['price'] = this.priceToPrecision(symbol, price);
            request['priceType'] = 'INPUT';
        }
        let reduceOnly = false;
        [reduceOnly, params] = this.handleParamBool(params, 'reduceOnly', reduceOnly);
        let suffix = '_OPEN';
        if (reduceOnly) {
            suffix = '_CLOSE';
        }
        request['side'] = side.toUpperCase() + suffix;
        let timeInForce = undefined;
        [timeInForce, params] = this.handleParamString(params, 'timeInForce');
        let postOnly = false;
        [postOnly, params] = this.handlePostOnly(isMarketOrder, timeInForce === 'LIMIT_MAKER', params);
        if (postOnly) {
            timeInForce = 'LIMIT_MAKER';
        }
        if (timeInForce !== undefined) {
            request['timeInForce'] = timeInForce;
        }
        const clientOrderId = this.safeString(params, 'clientOrderId');
        if (clientOrderId === undefined) {
            request['clientOrderId'] = this.uuid();
        }
        const triggerPrice = this.safeString(params, 'triggerPrice');
        if (triggerPrice !== undefined) {
            request['stopPrice'] = this.priceToPrecision(symbol, triggerPrice);
            request['type'] = 'STOP';
            params = this.omit(params, 'triggerPrice');
        }
        return this.extend(request, params);
    }
    /**
     * @method
     * @name hashkey#createSwapOrder
     * @description create a trade order on swap market
     * @see https://hashkeyglobal-apidoc.readme.io/reference/create-new-futures-order
     * @param {string} symbol unified symbol of the market to create an order in
     * @param {string} type 'market' or 'limit' or 'STOP'
     * @param {string} side 'buy' or 'sell'
     * @param {float} amount how much of you want to trade in units of the base currency
     * @param {float} [price] the price that the order is to be fulfilled, in units of the quote currency, ignored in market orders
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @param {bool} [params.postOnly] if true, the order will only be posted to the order book and not executed immediately
     * @param {bool} [params.reduceOnly] true or false whether the order is reduce only
     * @param {float} [params.triggerPrice] The price at which a trigger order is triggered at
     * @param {string} [params.timeInForce] 'GTC', 'FOK', 'IOC', 'LIMIT_MAKER' or 'PO'
     * @param {string} [params.clientOrderId] a unique id for the order
     * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
     */
    async createSwapOrder(symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets();
        const market = this.market(symbol);
        const request = this.createSwapOrderRequest(symbol, type, side, amount, price, params);
        const response = await this.privatePostApiV1FuturesOrder(this.extend(request, params));
        //
        //     {
        //         "time": "1722429951611",
        //         "updateTime": "1722429951648",
        //         "orderId": "1742263144028363776",
        //         "clientOrderId": "1722429950315",
        //         "symbol": "ETHUSDT-PERPETUAL",
        //         "price": "3460.62",
        //         "leverage": "5",
        //         "origQty": "10",
        //         "executedQty": "10",
        //         "avgPrice": "0",
        //         "marginLocked": "6.9212",
        //         "type": "LIMIT",
        //         "side": "BUY_OPEN",
        //         "timeInForce": "IOC",
        //         "status": "FILLED",
        //         "priceType": "MARKET",
        //         "contractMultiplier": "0.00100000"
        //     }
        //
        return this.parseOrder(response, market);
    }
    /**
     * @method
     * @name hashkey#createOrders
     * @description create a list of trade orders (all orders should be of the same symbol)
     * @see https://hashkeyglobal-apidoc.readme.io/reference/create-multiple-orders
     * @see https://hashkeyglobal-apidoc.readme.io/reference/batch-create-new-futures-order
     * @param {Array} orders list of orders to create, each object should contain the parameters required by createOrder, namely symbol, type, side, amount, price and params
     * @param {object} [params] extra parameters specific to the api endpoint
     * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
     */
    async createOrders(orders, params = {}) {
        await this.loadMarkets();
        const ordersRequests = [];
        for (let i = 0; i < orders.length; i++) {
            const rawOrder = orders[i];
            const symbol = this.safeString(rawOrder, 'symbol');
            const type = this.safeString(rawOrder, 'type');
            const side = this.safeString(rawOrder, 'side');
            const amount = this.safeNumber(rawOrder, 'amount');
            const price = this.safeNumber(rawOrder, 'price');
            const orderParams = this.safeDict(rawOrder, 'params', {});
            const orderRequest = this.createOrderRequest(symbol, type, side, amount, price, orderParams);
            const clientOrderId = this.safeString(orderRequest, 'clientOrderId');
            if (clientOrderId === undefined) {
                orderRequest['clientOrderId'] = this.uuid(); // both spot and swap endpoints require clientOrderId
            }
            ordersRequests.push(orderRequest);
        }
        const firstOrder = ordersRequests[0];
        const firstSymbol = this.safeString(firstOrder, 'symbol');
        const market = this.market(firstSymbol);
        const request = {
            'orders': ordersRequests,
        };
        let response = undefined;
        if (market['spot']) {
            response = await this.privatePostApiV1SpotBatchOrders(this.extend(request, params));
            //
            //     {
            //         "code": 0,
            //         "result": [
            //             {
            //                 "code": "0000",
            //                 "order": {
            //                     "accountId": "1732885739589466112",
            //                     "symbol": "ETHUSDT",
            //                     "symbolName": "ETHUSDT",
            //                     "clientOrderId": "1722701490163000",
            //                     "orderId": "1744540984757258752",
            //                     "transactTime": "1722701491385",
            //                     "price": "1500",
            //                     "origQty": "0.001",
            //                     "executedQty": "0",
            //                     "status": "NEW",
            //                     "timeInForce": "GTC",
            //                     "type": "LIMIT",
            //                     "side": "BUY",
            //                     "reqAmount": "0"
            //                 }
            //             }
            //         ],
            //         "concentration": ""
            //     }
            //
        }
        else if (market['swap']) {
            response = await this.privatePostApiV1FuturesBatchOrders(this.extend(request, params));
            //
            //     {
            //         "code": "0000",
            //         "result": [
            //             {
            //                 "code": "0000",
            //                 "order": {
            //                     "time": "1722704251911",
            //                     "updateTime": "1722704251918",
            //                     "orderId": "1744564141727808768",
            //                     "clientOrderId": "1722704250648000",
            //                     "symbol": "ETHUSDT-PERPETUAL",
            //                     "price": "1500",
            //                     "leverage": "4",
            //                     "origQty": "1",
            //                     "executedQty": "0",
            //                     "avgPrice": "0",
            //                     "marginLocked": "0.375",
            //                     "type": "LIMIT",
            //                     "side": "BUY_OPEN",
            //                     "timeInForce": "GTC",
            //                     "status": "NEW",
            //                     "priceType": "INPUT",
            //                     "isLiquidationOrder": false,
            //                     "indexPrice": "0",
            //                     "liquidationType": ""
            //                 }
            //             },
            //             {
            //                 "code": "0207",
            //                 "msg": "Create limit order sell price too low"
            //             }
            //         ]
            //     }
            //
        }
        else {
            throw new errors.NotSupported(this.id + ' ' + 'createOrderRequest() is not supported for ' + market['type'] + ' type of markets');
        }
        const result = this.safeList(response, 'result', []);
        const responseOrders = [];
        for (let i = 0; i < result.length; i++) {
            const responseEntry = this.safeDict(result, i, {});
            const responseOrder = this.safeDict(responseEntry, 'order', {});
            responseOrders.push(responseOrder);
        }
        return this.parseOrders(responseOrders);
    }
    /**
     * @method
     * @name hashkey#cancelOrder
     * @description cancels an open order
     * @see https://hashkeyglobal-apidoc.readme.io/reference/cancel-order
     * @see https://hashkeyglobal-apidoc.readme.io/reference/cancel-futures-order
     * @param {string} id order id
     * @param {string} symbol unified symbol of the market the order was made in
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @param {string} [params.type] 'spot' or 'swap' - the type of the market to fetch entry for (default 'spot')
     * @param {string} [params.clientOrderId] a unique id for the order that can be used as an alternative for the id
     * @param {bool} [params.trigger] *swap markets only* true for canceling a trigger order (default false)
     * @param {bool} [params.stop] *swap markets only* an alternative for trigger param
     * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
     */
    async cancelOrder(id, symbol = undefined, params = {}) {
        const methodName = 'cancelOrder';
        this.checkTypeParam(methodName, params);
        await this.loadMarkets();
        const request = {};
        const clientOrderId = this.safeString(params, 'clientOrderId');
        if (clientOrderId === undefined) {
            request['orderId'] = id;
        }
        let market = undefined;
        if (symbol !== undefined) {
            market = this.market(symbol);
        }
        let marketType = 'spot';
        [marketType, params] = this.handleMarketTypeAndParams(methodName, market, params, marketType);
        let response = undefined;
        if (marketType === 'spot') {
            response = await this.privateDeleteApiV1SpotOrder(this.extend(request, params));
            //
            //     {
            //         "accountId": "1732885739589466112",
            //         "symbol": "ETHUSDT",
            //         "clientOrderId": "1722006209978370",
            //         "orderId": "1738708541676585728",
            //         "transactTime": "1722006209989",
            //         "price": "5000",
            //         "origQty": "0.005",
            //         "executedQty": "0",
            //         "status": "NEW",
            //         "timeInForce": "GTC",
            //         "type": "LIMIT_MAKER",
            //         "side": "SELL"
            //     }
            //
        }
        else if (marketType === 'swap') {
            let isTrigger = false;
            [isTrigger, params] = this.handleTriggerOptionAndParams(params, methodName, isTrigger);
            if (isTrigger) {
                request['type'] = 'STOP';
            }
            else {
                request['type'] = 'LIMIT';
            }
            if (market !== undefined) {
                request['symbol'] = market['id'];
            }
            response = await this.privateDeleteApiV1FuturesOrder(this.extend(request, params));
            //
            //     {
            //         "time": "1722432302919",
            //         "updateTime": "1722432302925",
            //         "orderId": "1742282868229463040",
            //         "clientOrderId": "1722432301670",
            //         "symbol": "ETHUSDT-PERPETUAL",
            //         "price": "4000",
            //         "leverage": "5",
            //         "origQty": "10",
            //         "executedQty": "0",
            //         "avgPrice": "0",
            //         "marginLocked": "0",
            //         "type": "LIMIT_MAKER",
            //         "side": "SELL_CLOSE",
            //         "timeInForce": "GTC",
            //         "status": "NEW",
            //         "priceType": "INPUT",
            //         "isLiquidationOrder": false,
            //         "indexPrice": "0",
            //         "liquidationType": ""
            //     }
            //
        }
        else {
            throw new errors.NotSupported(this.id + ' ' + methodName + '() is not supported for ' + marketType + ' type of markets');
        }
        return this.parseOrder(response);
    }
    /**
     * @method
     * @name hashkey#cancelAllOrders
     * @description cancel all open orders
     * @see https://hashkeyglobal-apidoc.readme.io/reference/cancel-all-open-orders
     * @see https://hashkeyglobal-apidoc.readme.io/reference/batch-cancel-futures-order
     * @param {string} symbol unified market symbol, only orders in the market of this symbol are cancelled when symbol is not undefined
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @param {string} [params.side] 'buy' or 'sell'
     * @returns {object} response from exchange
     */
    async cancelAllOrders(symbol = undefined, params = {}) {
        // Does not cancel trigger orders. For canceling trigger order use cancelOrder() or cancelOrders()
        const methodName = 'cancelAllOrders';
        if (symbol === undefined) {
            throw new errors.ArgumentsRequired(this.id + ' ' + methodName + '() requires a symbol argument');
        }
        await this.loadMarkets();
        const market = this.market(symbol);
        const request = {
            'symbol': market['id'],
        };
        const side = this.safeString(params, 'side');
        if (side !== undefined) {
            request['side'] = side;
        }
        let response = undefined;
        if (market['spot']) {
            response = await this.privateDeleteApiV1SpotOpenOrders(this.extend(request, params));
            //
            //     { "success": true }
            //
        }
        else if (market['swap']) {
            response = await this.privateDeleteApiV1FuturesBatchOrders(this.extend(request, params));
            //
            //     { "message": "success", "timestamp": "1723127222198", "code": "0000" }
            //
        }
        else {
            throw new errors.NotSupported(this.id + ' ' + methodName + '() is not supported for ' + market['type'] + ' type of markets');
        }
        const order = this.safeOrder(response);
        order['info'] = response;
        return [order];
    }
    /**
     * @method
     * @name hashkey#cancelOrders
     * @description cancel multiple orders
     * @see https://hashkeyglobal-apidoc.readme.io/reference/cancel-multiple-orders
     * @see https://hashkeyglobal-apidoc.readme.io/reference/batch-cancel-futures-order-by-order-id
     * @param {string[]} ids order ids
     * @param {string} [symbol] unified market symbol (not used by hashkey)
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @param {string} [params.type] 'spot' or 'swap' - the type of the market to fetch entry for (default 'spot')
     * @returns {object} an list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
     */
    async cancelOrders(ids, symbol = undefined, params = {}) {
        const methodName = 'cancelOrders';
        await this.loadMarkets();
        const request = {};
        const orderIds = ids.join(',');
        request['ids'] = orderIds;
        let market = undefined;
        if (symbol !== undefined) {
            market = this.market(symbol);
        }
        let marketType = 'spot';
        [marketType, params] = this.handleMarketTypeAndParams(methodName, market, params, marketType);
        let response = undefined;
        if (marketType === 'spot') {
            response = await this.privateDeleteApiV1SpotCancelOrderByIds(this.extend(request));
            //
            //     {
            //         "code": "0000",
            //         "result": []
            //     }
            //
        }
        else if (marketType === 'swap') {
            response = this.privateDeleteApiV1FuturesCancelOrderByIds(this.extend(request));
        }
        else {
            throw new errors.NotSupported(this.id + ' ' + methodName + '() is not supported for ' + marketType + ' type of markets');
        }
        const order = this.safeOrder(response);
        order['info'] = response;
        return [order];
    }
    /**
     * @method
     * @name hashkey#fetchOrder
     * @description fetches information on an order made by the user
     * @see https://hashkeyglobal-apidoc.readme.io/reference/query-order
     * @see https://hashkeyglobal-apidoc.readme.io/reference/get-futures-order
     * @param {string} id the order id
     * @param {string} symbol unified symbol of the market the order was made in
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @param {string} [params.type] 'spot' or 'swap' - the type of the market to fetch entry for (default 'spot')
     * @param {string} [params.clientOrderId] a unique id for the order that can be used as an alternative for the id
     * @param {string} [params.accountId] *spot markets only* account id to fetch the order from
     * @param {bool} [params.trigger] *swap markets only* true for fetching a trigger order (default false)
     * @param {bool} [params.stop] *swap markets only* an alternative for trigger param
     * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
     */
    async fetchOrder(id, symbol = undefined, params = {}) {
        const methodName = 'fetchOrder';
        this.checkTypeParam(methodName, params);
        await this.loadMarkets();
        const request = {};
        let clientOrderId = undefined;
        [clientOrderId, params] = this.handleParamString(params, 'clientOrderId');
        if (clientOrderId === undefined) {
            request['orderId'] = id;
        }
        let market = undefined;
        if (symbol !== undefined) {
            market = this.market(symbol);
        }
        let marketType = 'spot';
        [marketType, params] = this.handleMarketTypeAndParams(methodName, market, params, marketType);
        let response = undefined;
        if (marketType === 'spot') {
            if (clientOrderId !== undefined) {
                request['origClientOrderId'] = clientOrderId;
            }
            response = await this.privateGetApiV1SpotOrder(this.extend(request, params));
            //
            //     {
            //         "accountId": "1732885739589466112",
            //         "exchangeId": "301",
            //         "symbol": "ETHUSDT",
            //         "symbolName": "ETHUSDT",
            //         "clientOrderId": "1722004623170558",
            //         "orderId": "1738695230608169984",
            //         "price": "0",
            //         "origQty": "0",
            //         "executedQty": "0.0061",
            //         "cummulativeQuoteQty": "19.736489",
            //         "cumulativeQuoteQty": "19.736489",
            //         "avgPrice": "3235.49",
            //         "status": "FILLED",
            //         "timeInForce": "IOC",
            //         "type": "MARKET",
            //         "side": "BUY",
            //         "stopPrice": "0.0",
            //         "icebergQty": "0.0",
            //         "time": "1722004623186",
            //         "updateTime": "1722004623406",
            //         "isWorking": true,
            //         "reqAmount": "20",
            //         "feeCoin": "",
            //         "feeAmount": "0",
            //         "sumFeeAmount": "0"
            //     }
            //
        }
        else if (marketType === 'swap') {
            let isTrigger = false;
            [isTrigger, params] = this.handleTriggerOptionAndParams(params, methodName, isTrigger);
            if (isTrigger) {
                request['type'] = 'STOP';
            }
            response = await this.privateGetApiV1FuturesOrder(this.extend(request, params));
            //
            //     {
            //         "time": "1722429951611",
            //         "updateTime": "1722429951700",
            //         "orderId": "1742263144028363776",
            //         "clientOrderId": "1722429950315",
            //         "symbol": "ETHUSDT-PERPETUAL",
            //         "price": "3460.62",
            //         "leverage": "5",
            //         "origQty": "10",
            //         "executedQty": "10",
            //         "avgPrice": "3327.52",
            //         "marginLocked": "0",
            //         "type": "LIMIT",
            //         "side": "BUY_OPEN",
            //         "timeInForce": "IOC",
            //         "status": "FILLED",
            //         "priceType": "MARKET",
            //         "isLiquidationOrder": false,
            //         "indexPrice": "0",
            //         "liquidationType": ""
            //     }
            //
        }
        else {
            throw new errors.NotSupported(this.id + ' ' + methodName + '() is not supported for ' + marketType + ' type of markets');
        }
        return this.parseOrder(response);
    }
    /**
     * @method
     * @name hashkey#fetchOpenOrders
     * @description fetch all unfilled currently open orders
     * @see https://hashkeyglobal-apidoc.readme.io/reference/get-current-open-orders
     * @see https://hashkeyglobal-apidoc.readme.io/reference/get-sub-account-open-orders
     * @see https://hashkeyglobal-apidoc.readme.io/reference/sub
     * @see https://hashkeyglobal-apidoc.readme.io/reference/query-open-futures-orders
     * @param {string} [symbol] unified market symbol of the market orders were made in - is mandatory for swap markets
     * @param {int} [since] the earliest time in ms to fetch orders for
     * @param {int} [limit] the maximum number of order structures to retrieve - default 500, maximum 1000
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @param {string} [params.type] 'spot' or 'swap' - the type of the market to fetch entries for (default 'spot')
     * @param {string} [params.orderId] *spot markets only* the id of the order to fetch
     * @param {string} [params.side] *spot markets only* 'buy' or 'sell' - the side of the orders to fetch
     * @param {string} [params.fromOrderId] *swap markets only* the id of the order to start from
     * @param {bool} [params.trigger] *swap markets only* true for fetching trigger orders (default false)
     * @param {bool} [params.stop] *swap markets only* an alternative for trigger param
     * @param {string} [params.accountId] account id to fetch the orders from
     * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
     */
    async fetchOpenOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
        const methodName = 'fetchOpenOrders';
        this.checkTypeParam(methodName, params);
        await this.loadMarkets();
        let market = undefined;
        if (symbol !== undefined) {
            market = this.market(symbol);
        }
        let marketType = 'spot';
        [marketType, params] = this.handleMarketTypeAndParams(methodName, market, params, marketType);
        params = this.extend({ 'methodName': methodName }, params);
        if (marketType === 'spot') {
            return await this.fetchOpenSpotOrders(symbol, since, limit, params);
        }
        else if (marketType === 'swap') {
            return await this.fetchOpenSwapOrders(symbol, since, limit, params);
        }
        else {
            throw new errors.NotSupported(this.id + ' ' + methodName + '() is not supported for ' + marketType + ' type of markets');
        }
    }
    /**
     * @method
     * @ignore
     * @name hashkey#fetchOpenSpotOrders
     * @description fetch all unfilled currently open orders for spot markets
     * @see https://hashkeyglobal-apidoc.readme.io/reference/get-current-open-orders
     * @see https://hashkeyglobal-apidoc.readme.io/reference/sub
     * @param {string} [symbol] unified market symbol of the market orders were made in
     * @param {int} [since] the earliest time in ms to fetch orders for
     * @param {int} [limit] the maximum number of order structures to retrieve - default 500, maximum 1000
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @param {string} [params.orderId] the id of the order to fetch
     * @param {string} [params.side] 'buy' or 'sell' - the side of the orders to fetch
     * @param {string} [params.accountId] account id to fetch the orders from
     * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
     */
    async fetchOpenSpotOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets();
        let methodName = 'fetchOpenSpotOrders';
        [methodName, params] = this.handleParamString(params, 'methodName', methodName);
        let market = undefined;
        const request = {};
        let response = undefined;
        let accountId = undefined;
        [accountId, params] = this.handleOptionAndParams(params, methodName, 'accountId');
        if (accountId !== undefined) {
            request['subAccountId'] = accountId;
            response = await this.privateGetApiV1SpotSubAccountOpenOrders(this.extend(request, params));
        }
        else {
            if (symbol !== undefined) {
                market = this.market(symbol);
                request['symbol'] = market['id'];
            }
            if (limit !== undefined) {
                request['limit'] = limit;
            }
            response = await this.privateGetApiV1SpotOpenOrders(this.extend(request, params));
            //
            //     [
            //         {
            //             "accountId": "1732885739589466112",
            //             "exchangeId": "301",
            //             "symbol": "ETHUSDT",
            //             "symbolName": "ETHUSDT",
            //             "clientOrderId": "1",
            //             "orderId": "1739491435386897152",
            //             "price": "2000",
            //             "origQty": "0.001",
            //             "executedQty": "0",
            //             "cummulativeQuoteQty": "0",
            //             "cumulativeQuoteQty": "0",
            //             "avgPrice": "0",
            //             "status": "NEW",
            //             "timeInForce": "GTC",
            //             "type": "LIMIT",
            //             "side": "BUY",
            //             "stopPrice": "0.0",
            //             "icebergQty": "0.0",
            //             "time": "1722099538193",
            //             "updateTime": "1722099538197",
            //             "isWorking": true,
            //             "reqAmount": "0"
            //         }
            //     ]
            //
        }
        return this.parseOrders(response, market, since, limit);
    }
    /**
     * @method
     * @ignore
     * @name hashkey#fetchOpenSwapOrders
     * @description fetch all unfilled currently open orders for swap markets
     * @see https://hashkeyglobal-apidoc.readme.io/reference/query-open-futures-orders
     * @see https://hashkeyglobal-apidoc.readme.io/reference/get-sub-account-open-orders
     * @param {string} symbol *is mandatory* unified market symbol of the market orders were made in
     * @param {int} [since] the earliest time in ms to fetch orders for
     * @param {int} [limit] the maximum number of order structures to retrieve - maximum 500
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @param {string} [params.fromOrderId] the id of the order to start from
     * @param {bool} [params.trigger] true for fetching trigger orders (default false)
     * @param {bool} [params.stop] an alternative for trigger param
     * @param {string} [params.accountId] account id to fetch the orders from
     * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
     */
    async fetchOpenSwapOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
        let methodName = 'fetchOpenSwapOrders';
        [methodName, params] = this.handleParamString(params, 'methodName', methodName);
        if (symbol === undefined) {
            throw new errors.ArgumentsRequired(this.id + ' ' + methodName + '() requires a symbol argument for swap market orders');
        }
        const market = this.market(symbol);
        const request = {
            'symbol': market['id'],
        };
        let isTrigger = false;
        [isTrigger, params] = this.handleTriggerOptionAndParams(params, methodName, isTrigger);
        if (isTrigger) {
            request['type'] = 'STOP';
        }
        else {
            request['type'] = 'LIMIT';
        }
        if (limit !== undefined) {
            request['limit'] = limit;
        }
        let response = undefined;
        let accountId = undefined;
        [accountId, params] = this.handleOptionAndParams(params, methodName, 'accountId');
        if (accountId !== undefined) {
            request['subAccountId'] = accountId;
            response = await this.privateGetApiV1FuturesSubAccountOpenOrders(this.extend(request, params));
        }
        else {
            response = await this.privateGetApiV1FuturesOpenOrders(this.extend(request, params));
            // 'LIMIT'
            //     [
            //         {
            //             "time": "1722432302919",
            //             "updateTime": "1722432302925",
            //             "orderId": "1742282868229463040",
            //             "clientOrderId": "1722432301670",
            //             "symbol": "ETHUSDT-PERPETUAL",
            //             "price": "4000",
            //             "leverage": "5",
            //             "origQty": "10",
            //             "executedQty": "0",
            //             "avgPrice": "0",
            //             "marginLocked": "0",
            //             "type": "LIMIT_MAKER",
            //             "side": "SELL_CLOSE",
            //             "timeInForce": "GTC",
            //             "status": "NEW",
            //             "priceType": "INPUT",
            //             "isLiquidationOrder": false,
            //             "indexPrice": "0",
            //             "liquidationType": ""
            //         }
            //     ]
            //
            // 'STOP'
            //     [
            //         {
            //             "time": "1722433095688",
            //             "updateTime": "1722433095688",
            //             "orderId": "1742289518466225664",
            //             "accountId": "1735619524953226496",
            //             "clientOrderId": "1722433094438",
            //             "symbol": "ETHUSDT-PERPETUAL",
            //             "price": "3700",
            //             "leverage": "0",
            //             "origQty": "10",
            //             "type": "STOP",
            //             "side": "SELL_CLOSE",
            //             "status": "ORDER_NEW",
            //             "stopPrice": "3600"
            //         }
            //     ]
        }
        return this.parseOrders(response, market, since, limit);
    }
    /**
     * @method
     * @name hashkey#fetchCanceledAndClosedOrders
     * @description fetches information on multiple canceled and closed orders made by the user
     * @see https://hashkeyglobal-apidoc.readme.io/reference/get-all-orders
     * @see https://hashkeyglobal-apidoc.readme.io/reference/query-futures-history-orders
     * @see https://hashkeyglobal-apidoc.readme.io/reference/get-sub-account-history-orders
     * @param {string} symbol *is mandatory for swap markets* unified market symbol of the market orders were made in
     * @param {int} [since] the earliest time in ms to fetch orders for
     * @param {int} [limit] the maximum number of order structures to retrieve - default 500, maximum 1000
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @param {int} [params.until] the latest time in ms to fetch entries for - only supports the last 90 days timeframe
     * @param {string} [params.type] 'spot' or 'swap' - the type of the market to fetch entries for (default 'spot')
     * @param {string} [params.orderId] *spot markets only* the id of the order to fetch
     * @param {string} [params.side] *spot markets only* 'buy' or 'sell' - the side of the orders to fetch
     * @param {string} [params.fromOrderId] *swap markets only* the id of the order to start from
     * @param {bool} [params.trigger] *swap markets only* the id of the order to start from true for fetching trigger orders (default false)
     * @param {bool} [params.stop] *swap markets only* the id of the order to start from an alternative for trigger param
     * @param {string} [params.accountId] account id to fetch the orders from
     * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
     */
    async fetchCanceledAndClosedOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
        const methodName = 'fetchCanceledAndClosedOrders';
        this.checkTypeParam(methodName, params);
        await this.loadMarkets();
        const request = {};
        if (limit !== undefined) {
            request['limit'] = limit;
        }
        if (since !== undefined) {
            request['startTime'] = since;
        }
        let until = undefined;
        [until, params] = this.handleOptionAndParams(params, methodName, 'until');
        if (until !== undefined) {
            request['endTime'] = until;
        }
        let accountId = undefined;
        [accountId, params] = this.handleOptionAndParams(params, methodName, 'accountId');
        let market = undefined;
        if (symbol !== undefined) {
            market = this.market(symbol);
        }
        let marketType = 'spot';
        [marketType, params] = this.handleMarketTypeAndParams(methodName, market, params, marketType);
        let response = undefined;
        if (marketType === 'spot') {
            if (market !== undefined) {
                request['symbol'] = market['id'];
            }
            if (accountId !== undefined) {
                request['accountId'] = accountId;
            }
            response = await this.privateGetApiV1SpotTradeOrders(this.extend(request, params));
            //
            //     [
            //         {
            //             "accountId": "1732885739589466112",
            //             "exchangeId": "301",
            //             "symbol": "ETHUSDT",
            //             "symbolName": "ETHUSDT",
            //             "clientOrderId": "1722082982086472",
            //             "orderId": "1739352552762301440",
            //             "price": "0",
            //             "origQty": "0.001",
            //             "executedQty": "0.001",
            //             "cummulativeQuoteQty": "3.28996",
            //             "cumulativeQuoteQty": "3.28996",
            //             "avgPrice": "3289.96",
            //             "status": "FILLED",
            //             "timeInForce": "IOC",
            //             "type": "MARKET",
            //             "side": "BUY",
            //             "stopPrice": "0.0",
            //             "icebergQty": "0.0",
            //             "time": "1722082982093",
            //             "updateTime": "1722082982097",
            //             "isWorking": true,
            //             "reqAmount": "0"
            //         },
            //         ...
            //     ]
            //
        }
        else if (marketType === 'swap') {
            if (symbol === undefined) {
                throw new errors.ArgumentsRequired(this.id + ' ' + methodName + '() requires a symbol argument for swap markets');
            }
            request['symbol'] = market['id'];
            let isTrigger = false;
            [isTrigger, params] = this.handleTriggerOptionAndParams(params, methodName, isTrigger);
            if (isTrigger) {
                request['type'] = 'STOP';
            }
            else {
                request['type'] = 'LIMIT';
            }
            if (accountId !== undefined) {
                request['subAccountId'] = accountId;
                response = await this.privateGetApiV1FuturesSubAccountHistoryOrders(this.extend(request, params));
            }
            else {
                response = await this.privateGetApiV1FuturesHistoryOrders(this.extend(request, params));
                //
                //     [
                //         {
                //             "time": "1722429951611",
                //             "updateTime": "1722429951700",
                //             "orderId": "1742263144028363776",
                //             "clientOrderId": "1722429950315",
                //             "symbol": "ETHUSDT-PERPETUAL",
                //             "price": "3460.62",
                //             "leverage": "5",
                //             "origQty": "10",
                //             "executedQty": "10",
                //             "avgPrice": "3327.52",
                //             "marginLocked": "0",
                //             "type": "LIMIT",
                //             "side": "BUY_OPEN",
                //             "timeInForce": "IOC",
                //             "status": "FILLED",
                //             "priceType": "MARKET",
                //             "isLiquidationOrder": false,
                //             "indexPrice": "0",
                //             "liquidationType": ""
                //         }
                //     ]
                //
            }
        }
        else {
            throw new errors.NotSupported(this.id + ' ' + methodName + '() is not supported for ' + marketType + ' type of markets');
        }
        return this.parseOrders(response, market, since, limit);
    }
    checkTypeParam(methodName, params) {
        // some hashkey endpoints have a type param for swap markets that defines the type of an order
        // type param is reserved in ccxt for defining the type of the market
        // current method warns user if he provides the exchange specific value in type parameter
        const paramsType = this.safeString(params, 'type');
        if ((paramsType !== undefined) && (paramsType !== 'spot') && (paramsType !== 'swap')) {
            throw new errors.BadRequest(this.id + ' ' + methodName + ' () type parameter can not be "' + paramsType + '". It should define the type of the market ("spot" or "swap"). To define the type of an order use the trigger parameter (true for trigger orders)');
        }
    }
    handleTriggerOptionAndParams(params, methodName, defaultValue = undefined) {
        let isTrigger = defaultValue;
        [isTrigger, params] = this.handleOptionAndParams2(params, methodName, 'stop', 'trigger', isTrigger);
        return [isTrigger, params];
    }
    parseOrder(order, market = undefined) {
        //
        // createOrder spot
        //     {
        //         "accountId": "1732885739589466112",
        //         "symbol": "ETHUSDT",
        //         "symbolName": "ETHUSDT",
        //         "clientOrderId": "1722004623170558",
        //         "orderId": "1738695230608169984",
        //         "transactTime": "1722004623186",
        //         "price": "0",
        //         "origQty": "0",
        //         "executedQty": "0.0061",
        //         "status": "FILLED",
        //         "timeInForce": "IOC",
        //         "type": "MARKET",
        //         "side": "BUY",
        //         "reqAmount": "20",
        //         "concentration": ""
        //     }
        //
        // fetchOrder spot
        //     {
        //         "accountId": "1732885739589466112",
        //         "exchangeId": "301",
        //         "symbol": "ETHUSDT",
        //         "symbolName": "ETHUSDT",
        //         "clientOrderId": "1722004623170558",
        //         "orderId": "1738695230608169984",
        //         "price": "0",
        //         "origQty": "0",
        //         "executedQty": "0.0061",
        //         "cummulativeQuoteQty": "19.736489",
        //         "cumulativeQuoteQty": "19.736489",
        //         "avgPrice": "3235.49",
        //         "status": "FILLED",
        //         "timeInForce": "IOC",
        //         "type": "MARKET",
        //         "side": "BUY",
        //         "stopPrice": "0.0",
        //         "icebergQty": "0.0",
        //         "time": "1722004623186",
        //         "updateTime": "1722004623406",
        //         "isWorking": true,
        //         "reqAmount": "20",
        //         "feeCoin": "",
        //         "feeAmount": "0",
        //         "sumFeeAmount": "0"
        //     }
        //
        // cancelOrder
        //     {
        //         "accountId": "1732885739589466112",
        //         "symbol": "ETHUSDT",
        //         "clientOrderId": "1722006209978370",
        //         "orderId": "1738708541676585728",
        //         "transactTime": "1722006209989",
        //         "price": "5000",
        //         "origQty": "0.005",
        //         "executedQty": "0",
        //         "status": "NEW",
        //         "timeInForce": "GTC",
        //         "type": "LIMIT_MAKER",
        //         "side": "SELL"
        //     }
        //
        // createOrder swap
        //     {
        //         "time": "1722429951611",
        //         "updateTime": "1722429951648",
        //         "orderId": "1742263144028363776",
        //         "clientOrderId": "1722429950315",
        //         "symbol": "ETHUSDT-PERPETUAL",
        //         "price": "3460.62",
        //         "leverage": "5",
        //         "origQty": "10",
        //         "executedQty": "10",
        //         "avgPrice": "0",
        //         "marginLocked": "6.9212",
        //         "type": "LIMIT",
        //         "side": "BUY_OPEN",
        //         "timeInForce": "IOC",
        //         "status": "FILLED",
        //         "priceType": "MARKET",
        //         "contractMultiplier": "0.00100000"
        //     }
        //
        // fetchOrder swap
        //     {
        //         "time": "1722429951611",
        //         "updateTime": "1722429951700",
        //         "orderId": "1742263144028363776",
        //         "clientOrderId": "1722429950315",
        //         "symbol": "ETHUSDT-PERPETUAL",
        //         "price": "3460.62",
        //         "leverage": "5",
        //         "origQty": "10",
        //         "executedQty": "10",
        //         "avgPrice": "3327.52",
        //         "marginLocked": "0",
        //         "type": "LIMIT",
        //         "side": "BUY_OPEN",
        //         "timeInForce": "IOC",
        //         "status": "FILLED",
        //         "priceType": "MARKET",
        //         "isLiquidationOrder": false,
        //         "indexPrice": "0",
        //         "liquidationType": ""
        //     }
        //
        const marketId = this.safeString(order, 'symbol');
        market = this.safeMarket(marketId, market);
        const timestamp = this.safeInteger2(order, 'transactTime', 'time');
        const status = this.safeString(order, 'status');
        let type = this.safeString(order, 'type');
        const priceType = this.safeString(order, 'priceType');
        if (priceType === 'MARKET') {
            type = 'market';
        }
        let price = this.omitZero(this.safeString(order, 'price'));
        if (type === 'STOP') {
            if (price === undefined) {
                type = 'market';
            }
            else {
                type = 'limit';
            }
        }
        let timeInForce = this.safeString(order, 'timeInForce');
        let postOnly = undefined;
        [type, timeInForce, postOnly] = this.parseOrderTypeTimeInForceAndPostOnly(type, timeInForce);
        const average = this.omitZero(this.safeString(order, 'avgPrice'));
        if (price === undefined) {
            price = average;
        }
        let side = this.safeStringLower(order, 'side');
        let reduceOnly = undefined;
        [side, reduceOnly] = this.parseOrderSideAndReduceOnly(side);
        let feeCurrncyId = this.safeString(order, 'feeCoin');
        if (feeCurrncyId === '') {
            feeCurrncyId = undefined;
        }
        return this.safeOrder({
            'id': this.safeString(order, 'orderId'),
            'clientOrderId': this.safeString(order, 'clientOrderId'),
            'datetime': this.iso8601(timestamp),
            'timestamp': timestamp,
            'lastTradeTimestamp': undefined,
            'lastUpdateTimestamp': this.safeInteger(order, 'updateTime'),
            'status': this.parseOrderStatus(status),
            'symbol': market['symbol'],
            'type': type,
            'timeInForce': timeInForce,
            'side': side,
            'price': price,
            'average': average,
            'amount': this.omitZero(this.safeString(order, 'origQty')),
            'filled': this.safeString(order, 'executedQty'),
            'remaining': undefined,
            'triggerPrice': this.omitZero(this.safeString(order, 'stopPrice')),
            'takeProfitPrice': undefined,
            'stopLossPrice': undefined,
            'cost': this.omitZero(this.safeString2(order, 'cumulativeQuoteQty', 'cummulativeQuoteQty')),
            'trades': undefined,
            'fee': {
                'currency': this.safeCurrencyCode(feeCurrncyId),
                'amount': this.omitZero(this.safeString(order, 'feeAmount')),
            },
            'reduceOnly': reduceOnly,
            'postOnly': postOnly,
            'info': order,
        }, market);
    }
    parseOrderSideAndReduceOnly(unparsed) {
        const parts = unparsed.split('_');
        const side = parts[0];
        let reduceOnly = undefined;
        const secondPart = this.safeString(parts, 1);
        if (secondPart !== undefined) {
            if (secondPart === 'open') {
                reduceOnly = false;
            }
            else if ((secondPart === 'close')) {
                reduceOnly = true;
            }
        }
        return [side, reduceOnly];
    }
    parseOrderStatus(status) {
        const statuses = {
            'NEW': 'open',
            'PARTIALLY_FILLED': 'open',
            'PARTIALLY_CANCELED': 'canceled',
            'FILLED': 'closed',
            'CANCELED': 'canceled',
            'ORDER_CANCELED': 'canceled',
            'PENDING_CANCEL': 'canceled',
            'REJECTED': 'rejected',
            'ORDER_NEW': 'open',
        };
        return this.safeString(statuses, status, status);
    }
    parseOrderTypeTimeInForceAndPostOnly(type, timeInForce) {
        let postOnly = undefined;
        if (type === 'LIMIT_MAKER') {
            postOnly = true;
        }
        else if ((timeInForce === 'LIMIT_MAKER') || (timeInForce === 'MAKER')) {
            postOnly = true;
            timeInForce = 'PO';
        }
        type = this.parseOrderType(type);
        return [type, timeInForce, postOnly];
    }
    parseOrderType(type) {
        const types = {
            'MARKET': 'market',
            'LIMIT': 'limit',
            'LIMIT_MAKER': 'limit',
            'MARKET_OF_BASE': 'market',
        };
        return this.safeString(types, type, type);
    }
    /**
     * @method
     * @name hashkey#fetchFundingRate
     * @description fetch the current funding rate
     * @see https://hashkeyglobal-apidoc.readme.io/reference/get-futures-funding-rate
     * @param {string} symbol unified market symbol
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @returns {object} a [funding rate structure]{@link https://docs.ccxt.com/#/?id=funding-rate-structure}
     */
    async fetchFundingRate(symbol, params = {}) {
        await this.loadMarkets();
        const market = this.market(symbol);
        const request = {
            'symbol': market['id'],
            'timestamp': this.milliseconds(),
        };
        const response = await this.publicGetApiV1FuturesFundingRate(this.extend(request, params));
        //
        //     [
        //         { "symbol": "ETHUSDT-PERPETUAL", "rate": "0.0001", "nextSettleTime": "1722297600000" }
        //     ]
        //
        const rate = this.safeDict(response, 0, {});
        return this.parseFundingRate(rate, market);
    }
    /**
     * @method
     * @name hashkey#fetchFundingRates
     * @description fetch the funding rate for multiple markets
     * @see https://hashkeyglobal-apidoc.readme.io/reference/get-futures-funding-rate
     * @param {string[]|undefined} symbols list of unified market symbols
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @returns {object[]} a list of [funding rate structures]{@link https://docs.ccxt.com/#/?id=funding-rates-structure}, indexed by market symbols
     */
    async fetchFundingRates(symbols = undefined, params = {}) {
        await this.loadMarkets();
        symbols = this.marketSymbols(symbols);
        const request = {
            'timestamp': this.milliseconds(),
        };
        const response = await this.publicGetApiV1FuturesFundingRate(this.extend(request, params));
        //
        //     [
        //         { "symbol": "BTCUSDT-PERPETUAL", "rate": "0.0001", "nextSettleTime": "1722297600000" },
        //         { "symbol": "ETHUSDT-PERPETUAL", "rate": "0.0001", "nextSettleTime": "1722297600000" }
        //     ]
        //
        return this.parseFundingRates(response, symbols);
    }
    parseFundingRate(contract, market = undefined) {
        //
        //     {
        //         "symbol": "ETHUSDT-PERPETUAL",
        //         "rate": "0.0001",
        //         "nextSettleTime": "1722297600000"
        //     }
        //
        const marketId = this.safeString(contract, 'symbol');
        market = this.safeMarket(marketId, market, undefined, 'swap');
        const fundingRate = this.safeNumber(contract, 'rate');
        const fundingTimestamp = this.safeInteger(contract, 'nextSettleTime');
        return {
            'info': contract,
            'symbol': market['symbol'],
            'markPrice': undefined,
            'indexPrice': undefined,
            'interestRate': undefined,
            'estimatedSettlePrice': undefined,
            'timestamp': undefined,
            'datetime': undefined,
            'fundingRate': fundingRate,
            'fundingTimestamp': undefined,
            'fundingDatetime': undefined,
            'nextFundingRate': undefined,
            'nextFundingTimestamp': fundingTimestamp,
            'nextFundingDatetime': this.iso8601(fundingTimestamp),
            'previousFundingRate': undefined,
            'previousFundingTimestamp': undefined,
            'previousFundingDatetime': undefined,
            'interval': undefined,
        };
    }
    /**
     * @method
     * @name hashkey#fetchFundingRateHistory
     * @description fetches historical funding rate prices
     * @see https://hashkeyglobal-apidoc.readme.io/reference/get-futures-history-funding-rate
     * @param {string} symbol unified symbol of the market to fetch the funding rate history for
     * @param {int} [since] timestamp in ms of the earliest funding rate to fetch
     * @param {int} [limit] the maximum amount of [funding rate structures]{@link https://docs.ccxt.com/#/?id=funding-rate-history-structure} to fetch
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @param {int} [params.fromId] the id of the entry to start from
     * @param {int} [params.endId] the id of the entry to end with
     * @returns {object[]} a list of [funding rate structures]{@link https://docs.ccxt.com/#/?id=funding-rate-history-structure}
     */
    async fetchFundingRateHistory(symbol = undefined, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets();
        if (symbol === undefined) {
            throw new errors.ArgumentsRequired(this.id + ' fetchFundingRateHistory() requires a symbol argument');
        }
        const market = this.market(symbol);
        const request = {
            'symbol': market['id'],
        };
        if (limit !== undefined) {
            request['limit'] = limit;
        }
        const response = await this.publicGetApiV1FuturesHistoryFundingRate(this.extend(request, params));
        //
        //     [
        //         {
        //             "id": "10698",
        //             "symbol": "ETHUSDT-PERPETUAL",
        //             "settleTime": "1722268800000",
        //             "settleRate": "0.0001"
        //         },
        //         ...
        //     ]
        //
        const rates = [];
        for (let i = 0; i < response.length; i++) {
            const entry = response[i];
            const timestamp = this.safeInteger(entry, 'settleTime');
            rates.push({
                'info': entry,
                'symbol': this.safeSymbol(this.safeString(entry, 'symbol'), market, undefined, 'swap'),
                'fundingRate': this.safeNumber(entry, 'settleRate'),
                'timestamp': timestamp,
                'datetime': this.iso8601(timestamp),
            });
        }
        const sorted = this.sortBy(rates, 'timestamp');
        return this.filterBySinceLimit(sorted, since, limit);
    }
    /**
     * @method
     * @description fetch open positions for a market
     * @name hashkey#fetchPositions
     * @see https://hashkeyglobal-apidoc.readme.io/reference/get-futures-positions
     * @description fetch all open positions
     * @param {string[]|undefined} symbols list of unified market symbols
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @param {string} [params.side] 'LONG' or 'SHORT' - the direction of the position (if not provided, positions for both sides will be returned)
     * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
     */
    async fetchPositions(symbols = undefined, params = {}) {
        const methodName = 'fetchPositions';
        if ((symbols === undefined)) {
            throw new errors.ArgumentsRequired(this.id + ' ' + methodName + '() requires a symbol argument with one single market symbol');
        }
        else {
            const symbolsLength = symbols.length;
            if (symbolsLength !== 1) {
                throw new errors.NotSupported(this.id + ' ' + methodName + '() is supported for a symbol argument with one single market symbol only');
            }
        }
        await this.loadMarkets();
        return await this.fetchPositionsForSymbol(symbols[0], this.extend({ 'methodName': 'fetchPositions' }, params));
    }
    /**
     * @method
     * @description fetch open positions for a single market
     * @name hashkey#fetchPositionsForSymbol
     * @see https://hashkeyglobal-apidoc.readme.io/reference/get-futures-positions
     * @description fetch all open positions for specific symbol
     * @param {string} symbol unified market symbol
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @param {string} [params.side] 'LONG' or 'SHORT' - the direction of the position (if not provided, positions for both sides will be returned)
     * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
     */
    async fetchPositionsForSymbol(symbol, params = {}) {
        await this.loadMarkets();
        const market = this.market(symbol);
        let methodName = 'fetchPosition';
        [methodName, params] = this.handleParamString(params, 'methodName', methodName);
        if (!market['swap']) {
            throw new errors.NotSupported(this.id + ' ' + methodName + '() supports swap markets only');
        }
        const request = {
            'symbol': market['id'],
        };
        const response = await this.privateGetApiV1FuturesPositions(this.extend(request, params));
        //
        //     [
        //         {
        //             "symbol": "ETHUSDT-PERPETUAL",
        //             "side": "LONG",
        //             "avgPrice": "3327.52",
        //             "position": "10",
        //             "available": "0",
        //             "leverage": "5",
        //             "lastPrice": "3324.44",
        //             "positionValue": "33.2752",
        //             "liquidationPrice": "-953.83",
        //             "margin": "6.9012",
        //             "marginRate": "",
        //             "unrealizedPnL": "-0.0288",
        //             "profitRate": "-0.0041",
        //             "realizedPnL": "-0.0199",
        //             "minMargin": "0.2173"
        //         }
        //     ]
        //
        return this.parsePositions(response, [symbol]);
    }
    parsePosition(position, market = undefined) {
        const marketId = this.safeString(position, 'symbol');
        market = this.safeMarket(marketId, market);
        const symbol = market['symbol'];
        return this.safePosition({
            'symbol': symbol,
            'id': undefined,
            'timestamp': undefined,
            'datetime': undefined,
            'contracts': this.safeNumber(position, 'position'),
            'contractSize': undefined,
            'side': this.safeStringLower(position, 'side'),
            'notional': this.safeNumber(position, 'positionValue'),
            'leverage': this.safeInteger(position, 'leverage'),
            'unrealizedPnl': this.safeNumber(position, 'unrealizedPnL'),
            'realizedPnl': this.safeNumber(position, 'realizedPnL'),
            'collateral': undefined,
            'entryPrice': this.safeNumber(position, 'avgPrice'),
            'markPrice': undefined,
            'liquidationPrice': this.safeNumber(position, 'liquidationPrice'),
            'marginMode': 'cross',
            'hedged': true,
            'maintenanceMargin': this.safeNumber(position, 'minMargin'),
            'maintenanceMarginPercentage': undefined,
            'initialMargin': this.safeNumber(position, 'margin'),
            'initialMarginPercentage': undefined,
            'marginRatio': undefined,
            'lastUpdateTimestamp': undefined,
            'lastPrice': this.safeNumber(position, 'lastPrice'),
            'stopLossPrice': undefined,
            'takeProfitPrice': undefined,
            'percentage': undefined,
            'info': position,
        });
    }
    /**
     * @method
     * @name hashkey#fetchLeverage
     * @description fetch the set leverage for a market
     * @see https://hashkeyglobal-apidoc.readme.io/reference/query-futures-leverage-trade
     * @param {string} symbol unified market symbol
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @returns {object} a [leverage structure]{@link https://docs.ccxt.com/#/?id=leverage-structure}
     */
    async fetchLeverage(symbol, params = {}) {
        await this.loadMarkets();
        const market = this.market(symbol);
        const request = {
            'symbol': market['id'],
        };
        const response = await this.privateGetApiV1FuturesLeverage(this.extend(request, params));
        //
        //     [
        //         {
        //             "symbolId": "ETHUSDT-PERPETUAL",
        //             "leverage": "5",
        //             "marginType": "CROSS"
        //         }
        //     ]
        //
        const leverage = this.safeDict(response, 0, {});
        return this.parseLeverage(leverage, market);
    }
    parseLeverage(leverage, market = undefined) {
        const marginMode = this.safeStringLower(leverage, 'marginType');
        const leverageValue = this.safeNumber(leverage, 'leverage');
        return {
            'info': leverage,
            'symbol': market['symbol'],
            'marginMode': marginMode,
            'longLeverage': leverageValue,
            'shortLeverage': leverageValue,
        };
    }
    /**
     * @method
     * @name hashkey#setLeverage
     * @description set the level of leverage for a market
     * @see https://hashkeyglobal-apidoc.readme.io/reference/change-futures-leverage-trade
     * @param {float} leverage the rate of leverage
     * @param {string} symbol unified market symbol
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @returns {object} response from the exchange
     */
    async setLeverage(leverage, symbol = undefined, params = {}) {
        if (symbol === undefined) {
            throw new errors.ArgumentsRequired(this.id + ' setLeverage() requires a symbol argument');
        }
        await this.loadMarkets();
        const request = {
            'leverage': leverage,
        };
        const market = this.market(symbol);
        request['symbol'] = market['id'];
        const response = await this.privatePostApiV1FuturesLeverage(this.extend(request, params));
        //
        //     {
        //         "code": "0000",
        //         "symbolId": "ETHUSDT-PERPETUAL",
        //         "leverage": "3"
        //     }
        //
        return this.parseLeverage(response, market);
    }
    /**
     * @method
     * @name hashkey#fetchLeverageTiers
     * @description retrieve information on the maximum leverage, and maintenance margin for trades of varying trade sizes
     * @see https://hashkeyglobal-apidoc.readme.io/reference/exchangeinfo
     * @param {string[]|undefined} symbols list of unified market symbols
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @returns {object} a dictionary of [leverage tiers structures]{@link https://docs.ccxt.com/#/?id=leverage-tiers-structure}, indexed by market symbols
     */
    async fetchLeverageTiers(symbols = undefined, params = {}) {
        await this.loadMarkets();
        const response = await this.publicGetApiV1ExchangeInfo(params);
        // response is the same as in fetchMarkets()
        const data = this.safeList(response, 'contracts', []);
        symbols = this.marketSymbols(symbols);
        return this.parseLeverageTiers(data, symbols, 'symbol');
    }
    parseMarketLeverageTiers(info, market = undefined) {
        //
        //     {
        //         "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 riskLimits = this.safeList(info, 'riskLimits', []);
        const marketId = this.safeString(info, 'symbol');
        market = this.safeMarket(marketId, market);
        const tiers = [];
        for (let i = 0; i < riskLimits.length; i++) {
            const tier = riskLimits[i];
            const initialMarginRate = this.safeString(tier, 'initialMargin');
            tiers.push({
                'tier': this.sum(i, 1),
                'symbol': this.safeSymbol(marketId, market),
                'currency': market['settle'],
                'minNotional': undefined,
                'maxNotional': this.safeNumber(tier, 'quantity'),
                'maintenanceMarginRate': this.safeNumber(tier, 'maintMargin'),
                'maxLeverage': this.parseNumber(Precise["default"].stringDiv('1', initialMarginRate)),
                'info': tier,
            });
        }
        return tiers;
    }
    /**
     * @method
     * @name hashkey#fetchTradingFee
     * @description fetch the trading fees for a market
     * @see https://developers.binance.com/docs/wallet/asset/trade-fee // spot
     * @see https://hashkeyglobal-apidoc.readme.io/reference/get-futures-commission-rate-request-weight // swap
     * @param {string} symbol unified market symbol
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @returns {object} a [fee structure]{@link https://docs.ccxt.com/#/?id=fee-structure}
     */
    async fetchTradingFee(symbol, params = {}) {
        await this.loadMarkets();
        const market = this.market(symbol);
        const methodName = 'fetchTradingFee';
        let response = undefined;
        if (market['spot']) {
            response = await this.fetchTradingFees(params);
            return this.safeDict(response, symbol);
        }
        else if (market['swap']) {
            response = await this.privateGetApiV1FuturesCommissionRate(this.extend({ 'symbol': market['id'] }, params));
            return this.parseTradingFee(response, market);
            //
            //     {
            //         "openMakerFee": "0.00025",
            //         "openTakerFee": "0.0006",
            //         "closeMakerFee": "0.00025",
            //         "closeTakerFee": "0.0006"
            //     }
            //
        }
        else {
            throw new errors.NotSupported(this.id + ' ' + methodName + '() is not supported for ' + market['type'] + ' type of markets');
        }
    }
    /**
     * @method
     * @name hashkey#fetchTradingFees
     * @description *for spot markets only* fetch the trading fees for multiple markets
     * @see https://developers.binance.com/docs/wallet/asset/trade-fee
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @returns {object} a dictionary of [fee structures]{@link https://docs.ccxt.com/#/?id=fee-structure} indexed by market symbols
     */
    async fetchTradingFees(params = {}) {
        await this.loadMarkets();
        const response = await this.privateGetApiV1AccountVipInfo(params);
        //
        //     {
        //         "code": 0,
        //         "vipLevel": "0",
        //         "tradeVol30Day": "67",
        //         "totalAssetBal": "0",
        //         "data": [
        //             {
        //                 "symbol": "UXLINKUSDT",
        //                 "productType": "Token-Token",
        //                 "buyMakerFeeCurrency": "UXLINK",
        //                 "buyTakerFeeCurrency": "UXLINK",
        //                 "sellMakerFeeCurrency": "USDT",
        //                 "sellTakerFeeCurrency": "USDT",
        //                 "actualMakerRate": "0.0012",
        //                 "actualTakerRate": "0.0012"
        //             },
        //             ...
        //         ],
        //         "updateTimestamp": "1722320137809"
        //     }
        //
        const data = this.safeList(response, 'data', []);
        const result = {};
        for (let i = 0; i < data.length; i++) {
            const fee = this.safeDict(data, i, {});
            const parsedFee = this.parseTradingFee(fee);
            result[parsedFee['symbol']] = parsedFee;
        }
        return result;
    }
    parseTradingFee(fee, market = undefined) {
        //
        // spot
        //     {
        //         "symbol": "UXLINKUSDT",
        //         "productType": "Token-Token",
        //         "buyMakerFeeCurrency": "UXLINK",
        //         "buyTakerFeeCurrency": "UXLINK",
        //         "sellMakerFeeCurrency": "USDT",
        //         "sellTakerFeeCurrency": "USDT",
        //         "actualMakerRate": "0.0012",
        //         "actualTakerRate": "0.0012"
        //     }
        //
        // swap
        //     {
        //         "openMakerFee": "0.00025",
        //         "openTakerFee": "0.0006",
        //         "closeMakerFee": "0.00025",
        //         "closeTakerFee": "0.0006"
        //     }
        //
        const marketId = this.safeString(fee, 'symbol');
        market = this.safeMarket(marketId, market);
        return {
            'info': fee,
            'symbol': market['symbol'],
            'maker': this.safeNumber2(fee, 'openMakerFee', 'actualMakerRate'),
            'taker': this.safeNumber2(fee, 'openTakerFee', 'actualTakerRate'),
            'percentage': true,
            'tierBased': true,
        };
    }
    sign(path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let url = this.urls['api'][api] + '/' + path;
        let query = undefined;
        if (api === 'private') {
            this.checkRequiredCredentials();
            const timestamp = this.milliseconds();
            const additionalParams = {
                'timestamp': timestamp,
            };
            const recvWindow = this.safeInteger(this.options, 'recvWindow');
            if (recvWindow !== undefined) {
                additionalParams['recvWindow'] = recvWindow;
            }
            headers = {
                'X-HK-APIKEY': this.apiKey,
                'Content-Type': 'application/x-www-form-urlencoded',
            };
            let signature = undefined;
            if ((method === 'POST') && ((path === 'api/v1/spot/batchOrders') || (path === 'api/v1/futures/batchOrders'))) {
                headers['Content-Type'] = 'application/json';
                body = this.json(this.safeList(params, 'orders'));
                signature = this.hmac(this.encode(this.customUrlencode(additionalParams)), this.encode(this.secret), sha256.sha256);
                query = this.customUrlencode(this.extend(additionalParams, { 'signature': signature }));
                url += '?' + query;
            }
            else {
                const totalParams = this.extend(additionalParams, params);
                signature = this.hmac(this.encode(this.customUrlencode(totalParams)), this.encode(this.secret), sha256.sha256);
                totalParams['signature'] = signature;
                query = this.customUrlencode(totalParams);
                if (method === 'GET') {
                    url += '?' + query;
                }
                else {
                    body = query;
                }
            }
            headers['INPUT-SOURCE'] = this.safeString(this.options, 'broker', '10000700011');
            headers['broker_sign'] = signature;
        }
        else {
            query = this.urlencode(params);
            if (query.length !== 0) {
                url += '?' + query;
            }
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }
    customUrlencode(params = {}) {
        let result = this.urlencode(params);
        result = result.replace('%2C', ',');
        return result;
    }
    handleErrors(code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
        if (response === undefined) {
            return undefined;
        }
        let errorInArray = false;
        let responseCodeString = this.safeString(response, 'code', undefined);
        const responseCodeInteger = this.safeInteger(response, 'code', undefined); // some codes in response are returned as '0000' others as 0
        if (responseCodeInteger === 0) {
            const result = this.safeList(response, 'result', []); // for batch methods
            for (let i = 0; i < result.length; i++) {
                const entry = this.safeDict(result, i);
                const entryCodeInteger = this.safeInteger(entry, 'code');
                if (entryCodeInteger !== 0) {
                    errorInArray = true;
                    responseCodeString = this.safeString(entry, 'code');
                }
            }
        }
        if ((code !== 200) || errorInArray) {
            const feedback = this.id + ' ' + body;
            this.throwBroadlyMatchedException(this.exceptions['broad'], responseCodeString, feedback);
            this.throwExactlyMatchedException(this.exceptions['exact'], responseCodeString, feedback);
            throw new errors.ExchangeError(feedback);
        }
        return undefined;
    }
}

module.exports = hashkey;