UNPKG

astro-perp-ccxt-dev

Version:

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

1,941 lines 89 kB
'use strict';

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

// ----------------------------------------------------------------------------
//  ---------------------------------------------------------------------------
/**
 * @class apex
 * @augments Exchange
 */
class apex extends apex$1 {
    describe() {
        return this.deepExtend(super.describe(), {
            'id': 'apex',
            'name': 'Apex',
            'countries': [],
            'version': 'v3',
            'rateLimit': 20,
            'certified': false,
            'pro': true,
            'dex': true,
            'has': {
                'CORS': undefined,
                'spot': false,
                'margin': false,
                'swap': true,
                'future': false,
                'option': false,
                'addMargin': false,
                'borrowCrossMargin': false,
                'borrowIsolatedMargin': false,
                'cancelAllOrders': true,
                'cancelAllOrdersAfter': false,
                'cancelOrder': true,
                'cancelOrders': false,
                'cancelOrdersForSymbols': false,
                'closeAllPositions': false,
                'closePosition': false,
                'createMarketBuyOrderWithCost': false,
                'createMarketOrderWithCost': false,
                'createMarketSellOrderWithCost': false,
                'createOrder': true,
                'createOrders': false,
                'createPostOnlyOrder': true,
                'createReduceOnlyOrder': true,
                'createStopOrder': true,
                'createTriggerOrder': true,
                'editOrder': false,
                'fetchAccounts': true,
                'fetchBalance': true,
                'fetchBorrowInterest': false,
                'fetchBorrowRateHistories': false,
                'fetchBorrowRateHistory': false,
                'fetchCanceledAndClosedOrders': false,
                'fetchCanceledOrders': false,
                'fetchClosedOrders': false,
                'fetchCrossBorrowRate': false,
                'fetchCrossBorrowRates': false,
                'fetchCurrencies': true,
                'fetchDepositAddress': false,
                'fetchDepositAddresses': false,
                'fetchDeposits': false,
                'fetchDepositWithdrawFee': false,
                'fetchDepositWithdrawFees': false,
                'fetchFundingHistory': true,
                'fetchFundingRate': false,
                'fetchFundingRateHistory': true,
                'fetchFundingRates': false,
                'fetchIndexOHLCV': false,
                'fetchIsolatedBorrowRate': false,
                'fetchIsolatedBorrowRates': false,
                'fetchLedger': false,
                'fetchLeverage': false,
                'fetchLeverageTiers': false,
                'fetchLiquidations': false,
                'fetchMarginMode': false,
                'fetchMarketLeverageTiers': false,
                'fetchMarkets': true,
                'fetchMarkOHLCV': false,
                'fetchMyLiquidations': false,
                'fetchMyTrades': true,
                'fetchOHLCV': true,
                'fetchOpenInterest': true,
                'fetchOpenInterestHistory': false,
                'fetchOpenInterests': false,
                'fetchOpenOrders': true,
                'fetchOrder': true,
                'fetchOrderBook': true,
                'fetchOrders': true,
                'fetchOrderTrades': true,
                'fetchPosition': false,
                'fetchPositionMode': false,
                'fetchPositions': true,
                'fetchPositionsRisk': false,
                'fetchPremiumIndexOHLCV': false,
                'fetchTicker': true,
                'fetchTickers': true,
                'fetchTime': true,
                'fetchTrades': true,
                'fetchTradingFee': false,
                'fetchTradingFees': false,
                'fetchTransfer': true,
                'fetchTransfers': true,
                'fetchWithdrawal': false,
                'fetchWithdrawals': false,
                'reduceMargin': false,
                'repayCrossMargin': false,
                'repayIsolatedMargin': false,
                'sandbox': true,
                'setLeverage': true,
                'setMarginMode': false,
                'setPositionMode': false,
                'transfer': false,
                'withdraw': false,
            },
            'timeframes': {
                '1m': '1',
                '5m': '5',
                '15m': '15',
                '30m': '30',
                '1h': '60',
                '2h': '120',
                '4h': '240',
                '6h': '360',
                '12h': '720',
                '1d': 'D',
                '1w': 'W',
                '1M': 'M',
            },
            'hostname': 'omni.apex.exchange',
            'urls': {
                'logo': 'https://github.com/user-attachments/assets/fef8f2f7-4265-46aa-965e-33a91881cb00',
                'api': {
                    'public': 'https://{hostname}/api',
                    'private': 'https://{hostname}/api',
                },
                'test': {
                    'public': 'https://testnet.omni.apex.exchange/api',
                    'private': 'https://testnet.omni.apex.exchange/api',
                },
                'www': 'https://apex.exchange/',
                'doc': 'https://api-docs.pro.apex.exchange',
                'fees': 'https://apex-pro.gitbook.io/apex-pro/apex-omni-live-now/trading-perpetual-contracts/trading-fees',
                'referral': 'https://omni.apex.exchange/trade',
            },
            'api': {
                'public': {
                    'get': {
                        'v3/symbols': 1,
                        'v3/history-funding': 1,
                        'v3/ticker': 1,
                        'v3/klines': 1,
                        'v3/trades': 1,
                        'v3/depth': 1,
                        'v3/time': 1,
                        'v3/data/all-ticker-info': 1,
                    },
                },
                'private': {
                    'get': {
                        'v3/account': 1,
                        'v3/account-balance': 1,
                        'v3/fills': 1,
                        'v3/order-fills': 1,
                        'v3/order': 1,
                        'v3/history-orders': 1,
                        'v3/order-by-client-order-id': 1,
                        'v3/funding': 1,
                        'v3/historical-pnl': 1,
                        'v3/open-orders': 1,
                        'v3/transfers': 1,
                        'v3/transfer': 1,
                    },
                    'post': {
                        'v3/delete-open-orders': 1,
                        'v3/delete-client-order-id': 1,
                        'v3/delete-order': 1,
                        'v3/order': 1,
                        'v3/set-initial-margin-rate': 1,
                        'v3/transfer-out': 1,
                        'v3/contract-transfer-out': 1,
                    },
                },
            },
            'httpExceptions': {
                '403': errors.RateLimitExceeded, // Forbidden -- You request too many times
            },
            'exceptions': {
                // Uncodumented explanation of error strings:
                // - oc_diff: order cost needed to place this order
                // - new_oc: total order cost of open orders including the order you are trying to open
                // - ob: order balance - the total cost of current open orders
                // - ab: available balance
                'exact': {
                    '20006': 'apikey sign error',
                    '20016': 'request para error',
                    '10001': errors.BadRequest,
                },
                'broad': {
                    'ORDER_PRICE_MUST_GREETER_ZERO': errors.InvalidOrder,
                    'ORDER_POSSIBLE_LEAD_TO_ACCOUNT_LIQUIDATED': errors.InvalidOrder,
                    'ORDER_WITH_THIS_PRICE_CANNOT_REDUCE_POSITION_ONLY': errors.InvalidOrder,
                },
            },
            'fees': {
                'swap': {
                    'taker': this.parseNumber('0.0005'),
                    'maker': this.parseNumber('0.0002'),
                },
            },
            'requiredCredentials': {
                'apiKey': true,
                'secret': true,
                'walletAddress': false,
                'privateKey': false,
                'password': true,
            },
            'precisionMode': number.TICK_SIZE,
            'commonCurrencies': {},
            'options': {
                'defaultType': 'swap',
                'defaultSlippage': 0.05,
                'brokerId': '6956',
            },
            'features': {
                'default': {
                    'sandbox': true,
                    'createOrder': {
                        'marginMode': false,
                        'triggerPrice': true,
                        'triggerPriceType': undefined,
                        'triggerDirection': false,
                        'stopLossPrice': false,
                        'takeProfitPrice': false,
                        'attachedStopLossTakeProfit': undefined,
                        'timeInForce': {
                            'IOC': true,
                            'FOK': true,
                            'PO': true,
                            'GTD': true,
                        },
                        'hedged': false,
                        'selfTradePrevention': false,
                        'trailing': true,
                        'leverage': false,
                        'marketBuyByCost': false,
                        'marketBuyRequiresPrice': false,
                        'iceberg': false,
                    },
                    'createOrders': undefined,
                    'fetchMyTrades': {
                        'marginMode': false,
                        'limit': 500,
                        'daysBack': 100000,
                        'untilDays': 100000,
                        'symbolRequired': false,
                    },
                    'fetchOrder': {
                        'marginMode': false,
                        'trigger': false,
                        'trailing': false,
                        'symbolRequired': false,
                    },
                    'fetchOpenOrders': {
                        'marginMode': false,
                        'limit': undefined,
                        'trigger': false,
                        'trailing': false,
                        'symbolRequired': false,
                    },
                    'fetchOrders': {
                        'marginMode': false,
                        'limit': 100,
                        'daysBack': 100000,
                        'untilDays': 100000,
                        'trigger': false,
                        'trailing': false,
                        'symbolRequired': false,
                    },
                    'fetchClosedOrders': undefined,
                    'fetchOHLCV': {
                        'limit': 200,
                    },
                },
                'swap': {
                    'linear': {
                        'extends': 'default',
                    },
                    'inverse': undefined,
                },
            },
        });
    }
    /**
     * @method
     * @name apex#fetchTime
     * @description fetches the current integer timestamp in milliseconds from the exchange server
     * @see https://api-docs.pro.apex.exchange/#publicapi-v3-for-omni-get-system-time-v3
     * @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.publicGetV3Time(params);
        const data = this.safeDict(response, 'data', {});
        //
        // {
        //    "data": {
        //    "time": 1738837534454
        //     }
        // }
        return this.safeInteger(data, 'time');
    }
    parseBalance(response) {
        //
        // {
        //     "totalEquityValue": "100.000000",
        //     "availableBalance": "100.000000",
        //     "initialMargin": "100.000000",
        //     "maintenanceMargin": "100.000000",
        //     "symbolToOraclePrice": {
        //     "BTC-USDC": {
        //         "oraclePrice": "20000",
        //             "createdTime": 124566
        //     }
        // }
        // }
        //
        const timestamp = this.milliseconds();
        const result = {
            'info': response,
            'timestamp': timestamp,
            'datetime': this.iso8601(timestamp),
        };
        const code = 'USDT';
        const account = this.account();
        account['free'] = this.safeString(response, 'availableBalance');
        account['total'] = this.safeString(response, 'totalEquityValue');
        result[code] = account;
        return this.safeBalance(result);
    }
    /**
     * @method
     * @name apex#fetchBalance
     * @description query for account info
     * @see https://api-docs.pro.apex.exchange/#privateapi-v3-for-omni-get-retrieve-user-account-balance
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
     */
    async fetchBalance(params = {}) {
        await this.loadMarkets();
        const response = await this.privateGetV3AccountBalance(params);
        const data = this.safeDict(response, 'data', {});
        return this.parseBalance(data);
    }
    parseAccount(account) {
        const accountId = this.safeString(account, 'id', '0');
        return {
            'id': accountId,
            'type': undefined,
            'code': undefined,
            'info': account,
        };
    }
    /**
     * @method
     * @name apex#fetchAccount
     * @description query for balance and get the amount of funds available for trading or funds locked in orders
     * @see https://api-docs.pro.apex.exchange/#privateapi-v3-for-omni-get-retrieve-user-account-data
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
     */
    async fetchAccount(params = {}) {
        await this.loadMarkets();
        const response = await this.privateGetV3Account(params);
        const data = this.safeDict(response, 'data', {});
        return this.parseAccount(data);
    }
    /**
     * @method
     * @name apex#fetchCurrencies
     * @description fetches all available currencies on an exchange
     * @see https://api-docs.pro.apex.exchange/#publicapi-v3-for-omni-get-all-config-data-v3
     * @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.publicGetV3Symbols(params);
        const data = this.safeDict(response, 'data', {});
        const spotConfig = this.safeDict(data, 'spotConfig', {});
        const multiChain = this.safeDict(spotConfig, 'multiChain', {});
        // "spotConfig": {
        //     "assets": [
        //         {
        //             "tokenId": "141",
        //             "token": "USDT",
        //             "displayName": "Tether USD Coin",
        //             "decimals": 18,
        //             "showStep": "0.01",
        //             "iconUrl": "https://static-pro.apex.exchange/chains/chain_tokens/Ethereum/Ethereum_USDT.svg",
        //             "l2WithdrawFee": "0",
        //             "enableCollateral": true,
        //             "enableCrossCollateral": false,
        //             "crossCollateralDiscountRate": null,
        //             "isGray": false
        //         }
        //     ],
        // "multiChain": {
        //  "chains": [
        //      {
        //          "chain": "Arbitrum One",
        //          "chainId": "9",
        //          "chainType": "0",
        //          "l1ChainId": "42161",
        //          "chainIconUrl": "https://static-pro.apex.exchange/chains/chain_logos/Arbitrum.svg",
        //          "contractAddress": "0x3169844a120c0f517b4eb4a750c08d8518c8466a",
        //          "swapContractAddress": "0x9e07b6Aef1bbD9E513fc2Eb8873e311E80B4f855",
        //          "stopDeposit": false,
        //          "feeLess": false,
        //          "gasLess": false,
        //          "gasToken": "ETH",
        //          "dynamicFee": true,
        //          "gasTokenDecimals": 18,
        //          "feeGasLimit": 300000,
        //          "blockTimeSeconds": 2,
        //          "rpcUrl": "https://arb.pro.apex.exchange",
        //          "minSwapUsdtAmount": "",
        //          "maxSwapUsdtAmount": "",
        //          "webRpcUrl": "https://arb.pro.apex.exchange",
        //          "webTxUrl": "https://arbiscan.io/tx/",
        //          "backupRpcUrl": "https://arb-mainnet.g.alchemy.com/v2/rGlYUbRHtUav5mfeThCPtsV9GLPt2Xq5",
        //          "txConfirm": 20,
        //          "withdrawGasFeeLess": false,
        //          "tokens": [
        //              {
        //                  "decimals": 6,
        //                  "iconUrl": "https://static-pro.apex.exchange/chains/chain_tokens/Arbitrum/Arbitrum_USDT.svg",
        //                  "token": "USDT",
        //                  "tokenAddress": "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9",
        //                  "pullOff": false,
        //                  "withdrawEnable": true,
        //                  "slippage": "",
        //                  "isDefaultToken": false,
        //                  "displayToken": "USDT",
        //                  "needResetApproval": true,
        //                  "minFee": "2",
        //                  "maxFee": "40",
        //                  "feeRate": "0.0001",
        //                  "maxWithdraw": "",
        //                  "minDeposit": "",
        //                  "minWithdraw": "",
        //                  "maxFastWithdrawAmount": "40000",
        //                  "minFastWithdrawAmount": "1",
        //                  "isGray": false
        //              },
        //              {
        //                  "decimals": 6,
        //                  "iconUrl": "https://static-pro.apex.exchange/chains/chain_tokens/Arbitrum/Arbitrum_USDC.svg",
        //                  "token": "USDC",
        //                  "tokenAddress": "0xaf88d065e77c8cc2239327c5edb3a432268e5831",
        //                  "pullOff": false,
        //                  "withdrawEnable": true,
        //                  "slippage": "",
        //                  "isDefaultToken": false,
        //                  "displayToken": "USDC",
        //                  "needResetApproval": true,
        //                  "minFee": "2",
        //                  "maxFee": "20",
        //                  "feeRate": "0.0001",
        //                  "maxWithdraw": "",
        //                  "minDeposit": "",
        //                  "minWithdraw": "",
        //                  "maxFastWithdrawAmount": "1",
        //                  "minFastWithdrawAmount": "1",
        //                  "isGray": false
        //              }
        //          ]
        //        }
        //     ]
        // }
        const rows = this.safeList(spotConfig, 'assets', []);
        const chains = this.safeList(multiChain, 'chains', []);
        const result = {};
        for (let i = 0; i < rows.length; i++) {
            const currency = rows[i];
            const currencyId = this.safeString(currency, 'token');
            const code = this.safeCurrencyCode(currencyId);
            const name = this.safeString(currency, 'displayName');
            const networks = {};
            for (let j = 0; j < chains.length; j++) {
                const chain = chains[j];
                const tokens = this.safeList(chain, 'tokens', []);
                for (let f = 0; f < tokens.length; f++) {
                    const token = tokens[f];
                    const tokenName = this.safeString(token, 'token');
                    if (tokenName === currencyId) {
                        const networkId = this.safeString(chain, 'chainId');
                        const networkCode = this.networkIdToCode(networkId);
                        networks[networkCode] = {
                            'info': chain,
                            'id': networkId,
                            'network': networkCode,
                            'active': undefined,
                            'deposit': !this.safeBool(chain, 'depositDisable'),
                            'withdraw': this.safeBool(token, 'withdrawEnable'),
                            'fee': this.safeNumber(token, 'minFee'),
                            'precision': this.parseNumber(this.parsePrecision(this.safeString(token, 'decimals'))),
                            'limits': {
                                'withdraw': {
                                    'min': this.safeNumber(token, 'minWithdraw'),
                                    'max': undefined,
                                },
                                'deposit': {
                                    'min': this.safeNumber(chain, 'minDeposit'),
                                    'max': undefined,
                                },
                            },
                        };
                    }
                }
            }
            const networkKeys = Object.keys(networks);
            const networksLength = networkKeys.length;
            const emptyChains = networksLength === 0; // non-functional coins
            const valueForEmpty = emptyChains ? false : undefined;
            result[code] = this.safeCurrencyStructure({
                'info': currency,
                'code': code,
                'id': currencyId,
                'type': 'crypto',
                'name': name,
                'active': undefined,
                'deposit': valueForEmpty,
                'withdraw': valueForEmpty,
                'fee': undefined,
                'precision': undefined,
                'limits': {
                    'amount': {
                        'min': undefined,
                        'max': undefined,
                    },
                    'withdraw': {
                        'min': undefined,
                        'max': undefined,
                    },
                    'deposit': {
                        'min': undefined,
                        'max': undefined,
                    },
                },
                'networks': networks,
            });
        }
        return result;
    }
    /**
     * @method
     * @name apex#fetchMarkets
     * @description retrieves data on all markets for apex
     * @see https://api-docs.pro.apex.exchange/#publicapi-v3-for-omni-get-all-config-data-v3
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @returns {object[]} an array of objects representing market data
     */
    async fetchMarkets(params = {}) {
        const response = await this.publicGetV3Symbols(params);
        const data = this.safeDict(response, 'data', {});
        const contractConfig = this.safeDict(data, 'contractConfig', {});
        const perpetualContract = this.safeList(contractConfig, 'perpetualContract', []);
        // {
        //     "perpetualContract":[
        //         {
        //             "baselinePositionValue": "50000.0000",
        //             "crossId": 30002,
        //             "crossSymbolId": 10,
        //             "crossSymbolName": "BTCUSDT",
        //             "digitMerge": "0.1,0.2,0.4,1,2",
        //             "displayMaxLeverage": "100",
        //             "displayMinLeverage": "1",
        //             "enableDisplay": true,
        //             "enableOpenPosition": true,
        //             "enableTrade": true,
        //             "fundingImpactMarginNotional": "6",
        //             "fundingInterestRate": "0.0003",
        //             "incrementalInitialMarginRate": "0.00250",
        //             "incrementalMaintenanceMarginRate": "0.00100",
        //             "incrementalPositionValue": "50000.0000",
        //             "initialMarginRate": "0.01",
        //             "maintenanceMarginRate": "0.005",
        //             "maxOrderSize": "50",
        //             "maxPositionSize": "100",
        //             "minOrderSize": "0.0010",
        //             "maxMarketPriceRange": "0.025",
        //             "settleAssetId": "USDT",
        //             "baseTokenId": "BTC",
        //             "stepSize": "0.001",
        //             "symbol": "BTC-USDT",
        //             "symbolDisplayName": "BTCUSDT",
        //             "tickSize": "0.1",
        //             "maxMaintenanceMarginRate": "0.5000",
        //             "maxPositionValue": "5000000.0000",
        //             "tagIconUrl": "https://static-pro.apex.exchange/icon/LABLE_HOT.svg",
        //             "tag": "HOT",
        //             "riskTip": false,
        //             "defaultInitialMarginRate": "0.05",
        //             "klineStartTime": 0,
        //             "maxMarketSizeBuffer": "0.98",
        //             "enableFundingSettlement": true,
        //             "indexPriceDecimals": 2,
        //             "indexPriceVarRate": "0.001",
        //             "openPositionOiLimitRate": "0.05",
        //             "fundingMaxRate": "0.000234",
        //             "fundingMinRate": "-0.000234",
        //             "fundingMaxValue": "",
        //             "enableFundingMxValue": true,
        //             "l2PairId": "50001",
        //             "settleTimeStamp": 0,
        //             "isPrelaunch": false,
        //             "riskLimitConfig": {},
        //             "category": "L1"
        //         }
        //     ]
        // }
        return this.parseMarkets(perpetualContract);
    }
    parseMarket(market) {
        const id = this.safeString(market, 'symbol');
        const id2 = this.safeString(market, 'crossSymbolName');
        const quoteId = this.safeString(market, 'l2PairId');
        const baseId = this.safeString(market, 'baseTokenId');
        const quote = this.safeString(market, 'settleAssetId');
        const base = this.safeCurrencyCode(baseId);
        const settleId = this.safeString(market, 'settleAssetId');
        const settle = this.safeCurrencyCode(settleId);
        const symbol = baseId + '/' + quote + ':' + settle;
        const takerFee = this.parseNumber('0.0002');
        const makerFee = this.parseNumber('0.0005');
        return this.safeMarketStructure({
            'id': id,
            'id2': id2,
            'symbol': symbol,
            'base': base,
            'quote': quote,
            'settle': settle,
            'baseId': baseId,
            'quoteId': quoteId,
            'settleId': settleId,
            'type': 'swap',
            'spot': false,
            'margin': undefined,
            'swap': true,
            'future': false,
            'option': false,
            'active': this.safeBool(market, 'enableTrade'),
            'contract': true,
            'linear': true,
            'inverse': false,
            'taker': takerFee,
            'maker': makerFee,
            'contractSize': this.safeNumber(market, 'minOrderSize'),
            'expiry': undefined ,
            'expiryDatetime': undefined ,
            'strike': undefined,
            'optionType': undefined,
            'precision': {
                'amount': this.safeNumber(market, 'stepSize'),
                'price': this.safeNumber(market, 'tickSize'),
            },
            'limits': {
                'leverage': {
                    'min': this.safeNumber(market, 'displayMinLeverage'),
                    'max': this.safeNumber(market, 'displayMaxLeverage'),
                },
                'amount': {
                    'min': this.safeNumber(market, 'minOrderSize'),
                    'max': this.safeNumber(market, 'maxOrderSize'),
                },
                'price': {
                    'min': undefined,
                    'max': undefined,
                },
                'cost': {
                    'min': undefined,
                    'max': undefined,
                },
            },
            'created': undefined,
            'info': market,
        });
    }
    parseTicker(ticker, market = undefined) {
        //
        // {
        //     "symbol": "BTCUSDT",
        //     "price24hPcnt": "0.450141",
        //     "lastPrice": "43511.50",
        //     "highPrice24h": "43513.50",
        //     "lowPrice24h": "29996.00",
        //     "markPrice": "43513.50",
        //     "indexPrice": "40828.94",
        //     "openInterest": "2036854775808",
        //     "turnover24h": "5626085.23749999",
        //     "volume24h": "169.317",
        //     "fundingRate": "0",
        //     "predictedFundingRate": "0",
        //     "nextFundingTime": "10:00:00",
        //     "tradeCount": 100
        // }
        //
        const timestamp = this.milliseconds();
        const marketId = this.safeString(ticker, 'symbol');
        market = this.safeMarket(marketId, market);
        const symbol = this.safeSymbol(marketId, market);
        const last = this.safeString(ticker, 'lastPrice');
        const percentage = this.safeString(ticker, 'price24hPcnt');
        const quoteVolume = this.safeString(ticker, 'turnover24h');
        const baseVolume = this.safeString(ticker, 'volume24h');
        const high = this.safeString(ticker, 'highPrice24h');
        const low = this.safeString(ticker, 'lowPrice24h');
        return this.safeTicker({
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601(timestamp),
            'high': high,
            'low': low,
            'bid': undefined,
            'bidVolume': undefined,
            'ask': undefined,
            'askVolume': undefined,
            'vwap': undefined,
            'open': undefined,
            'close': last,
            'last': last,
            'previousClose': undefined,
            'change': undefined,
            'percentage': percentage,
            'average': undefined,
            'baseVolume': baseVolume,
            'quoteVolume': quoteVolume,
            'markPrice': this.safeString(ticker, 'markPrice'),
            'indexPrice': this.safeString(ticker, 'indexPrice'),
            'info': ticker,
        }, market);
    }
    /**
     * @method
     * @name apex#fetchTicker
     * @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
     * @see https://api-docs.pro.apex.exchange/#publicapi-v3-for-omni-get-ticker-data-v3
     * @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['id2'],
        };
        const response = await this.publicGetV3Ticker(this.extend(request, params));
        const tickers = this.safeList(response, 'data', []);
        const rawTicker = this.safeDict(tickers, 0, {});
        return this.parseTicker(rawTicker, market);
    }
    /**
     * @method
     * @name apex#fetchTickers
     * @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
     * @see https://api-docs.pro.apex.exchange/#publicapi-v3-for-omni-get-ticker-data-v3
     * @param {string} symbols 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 fetchTickers(symbols = undefined, params = {}) {
        await this.loadMarkets();
        const response = await this.publicGetV3DataAllTickerInfo(params);
        const tickers = this.safeList(response, 'data', []);
        return this.parseTickers(tickers, symbols);
    }
    /**
     * @method
     * @name apex#fetchOHLCV
     * @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
     * @see https://api-docs.pro.apex.exchange/#publicapi-v3-for-omni-get-candlestick-chart-data-v3
     * @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
     * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
     */
    async fetchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets();
        const market = this.market(symbol);
        let request = {
            'interval': this.safeString(this.timeframes, timeframe, timeframe),
            'symbol': market['id2'],
        };
        if (limit === undefined) {
            limit = 200; // default is 200 when requested with `since`
        }
        request['limit'] = limit; // max 200, default 200
        [request, params] = this.handleUntilOption('end', request, params);
        if (since !== undefined) {
            request['start'] = since;
        }
        const response = await this.publicGetV3Klines(this.extend(request, params));
        const data = this.safeDict(response, 'data', {});
        const OHLCVs = this.safeList(data, market['id2'], []);
        return this.parseOHLCVs(OHLCVs, market, timeframe, since, limit);
    }
    parseOHLCV(ohlcv, market = undefined) {
        //
        //  {
        //     "start": 1647511440000,
        //     "symbol": "BTC-USD",
        //     "interval": "1",
        //     "low": "40000",
        //     "high": "45000",
        //     "open": "45000",
        //     "close": "40000",
        //     "volume": "1.002",
        //     "turnover": "3"
        //  } {"s":"BTCUSDT","i":"1","t":1741265880000,"c":"90235","h":"90235","l":"90156","o":"90156","v":"0.052","tr":"4690.4466"}
        //
        return [
            this.safeIntegerN(ohlcv, ['start', 't']),
            this.safeNumberN(ohlcv, ['open', 'o']),
            this.safeNumberN(ohlcv, ['high', 'h']),
            this.safeNumberN(ohlcv, ['low', 'l']),
            this.safeNumberN(ohlcv, ['close', 'c']),
            this.safeNumberN(ohlcv, ['volume', 'v']),
        ];
    }
    /**
     * @method
     * @name apex#fetchOrderBook
     * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
     * @see https://api-docs.pro.apex.exchange/#publicapi-v3-for-omni-get-market-depth-v3
     * @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
     * @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['id2'],
        };
        if (limit === undefined) {
            limit = 100; // default is 200 when requested with `since`
        }
        request['limit'] = limit; // max 100, default 100
        const response = await this.publicGetV3Depth(this.extend(request, params));
        //
        // {
        //     "a": [
        //     [
        //         "96576.3",
        //         "0.399"
        //     ],
        //     [
        //         "96577.6",
        //         "0.106"
        //     ]
        // ],
        //     "b": [
        //     [
        //         "96565.2",
        //         "0.131"
        //     ],
        //     [
        //         "96565.1",
        //         "0.038"
        //     ]
        // ],
        //     "s": "BTCUSDT",
        //     "u": 18665465
        // }
        //
        const data = this.safeDict(response, 'data', {});
        const timestamp = this.milliseconds();
        const orderbook = this.parseOrderBook(data, market['symbol'], timestamp, 'b', 'a');
        orderbook['nonce'] = this.safeInteger(data, 'u');
        return orderbook;
    }
    /**
     * @method
     * @name apex#fetchTrades
     * @description get the list of most recent trades for a particular symbol
     * @see https://api-docs.pro.apex.exchange/#publicapi-v3-for-omni-get-newest-trading-data-v3
     * @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
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @param {int} [params.until] the latest time in ms to fetch trades for
     * @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times
     * @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['id2'],
        };
        if (limit === undefined) {
            limit = 500; // default is 50
        }
        request['limit'] = limit;
        const response = await this.publicGetV3Trades(this.extend(request, params));
        //
        // [
        //  {
        //      "i": "993f7f85-9215-5723-9078-2186ae140847",
        //      "p": "96534.3",
        //      "S": "Sell",
        //      "v": "0.261",
        //      "s": "BTCUSDT",
        //      "T": 1739118072710
        //  },
        //  {
        //      "i": "c947c9cf-8c18-5784-89c3-91bdf86ddde8",
        //      "p": "96513.5",
        //      "S": "Sell",
        //      "v": "0.042",
        //      "s": "BTCUSDT",
        //      "T": 1739118075944
        //  }
        //  ]
        //
        const trades = this.safeList(response, 'data', []);
        return this.parseTrades(trades, market, since, limit);
    }
    parseTrade(trade, market = undefined) {
        //
        // [
        //  {
        //      "i": "993f7f85-9215-5723-9078-2186ae140847",
        //      "p": "96534.3",
        //      "S": "Sell",
        //      "v": "0.261",
        //      "s": "BTCUSDT",
        //      "T": 1739118072710
        //  }
        //  ]
        //
        const marketId = this.safeStringN(trade, ['s', 'symbol']);
        market = this.safeMarket(marketId, market);
        const id = this.safeStringN(trade, ['i', 'id']);
        const timestamp = this.safeIntegerN(trade, ['t', 'T', 'createdAt']);
        const priceString = this.safeStringN(trade, ['p', 'price']);
        const amountString = this.safeStringN(trade, ['v', 'size']);
        const side = this.safeStringLowerN(trade, ['S', 'side']);
        const type = this.safeStringN(trade, ['type']);
        const fee = this.safeStringN(trade, ['fee']);
        return this.safeTrade({
            'info': trade,
            'id': id,
            'order': undefined,
            'timestamp': timestamp,
            'datetime': this.iso8601(timestamp),
            'symbol': market['symbol'],
            'type': type,
            'takerOrMaker': undefined,
            'side': side,
            'price': priceString,
            'amount': amountString,
            'cost': undefined,
            'fee': fee,
        }, market);
    }
    /**
     * @method
     * @name apex#fetchOpenInterest
     * @description retrieves the open interest of a contract trading pair
     * @see https://api-docs.pro.apex.exchange/#publicapi-v3-for-omni-get-ticker-data-v3
     * @param {string} symbol unified CCXT market symbol
     * @param {object} [params] exchange specific parameters
     * @returns {object} an open interest structure{@link https://docs.ccxt.com/#/?id=open-interest-structure}
     */
    async fetchOpenInterest(symbol, params = {}) {
        await this.loadMarkets();
        const market = this.market(symbol);
        const request = {
            'symbol': market['id2'],
        };
        const response = await this.publicGetV3Ticker(this.extend(request, params));
        const tickers = this.safeList(response, 'data', []);
        const rawTicker = this.safeDict(tickers, 0, {});
        return this.parseOpenInterest(rawTicker, market);
    }
    parseOpenInterest(interest, market = undefined) {
        //
        // {
        //     "symbol": "BTCUSDT",
        //     "price24hPcnt": "0.450141",
        //     "lastPrice": "43511.50",
        //     "highPrice24h": "43513.50",
        //     "lowPrice24h": "29996.00",
        //     "markPrice": "43513.50",
        //     "indexPrice": "40828.94",
        //     "openInterest": "2036854775808",
        //     "turnover24h": "5626085.23749999",
        //     "volume24h": "169.317",
        //     "fundingRate": "0",
        //     "predictedFundingRate": "0",
        //     "nextFundingTime": "10:00:00",
        //     "tradeCount": 100
        // }
        //
        const timestamp = this.milliseconds();
        const marketId = this.safeString(interest, 'symbol');
        market = this.safeMarket(marketId, market);
        const symbol = this.safeSymbol(marketId, market);
        return this.safeOpenInterest({
            'symbol': symbol,
            'openInterestAmount': this.safeString(interest, 'openInterest'),
            'openInterestValue': undefined,
            'timestamp': timestamp,
            'datetime': this.iso8601(timestamp),
            'info': interest,
        }, market);
    }
    /**
     * @method
     * @name apex#fetchFundingRateHistory
     * @description fetches historical funding rate prices
     * @see https://api-docs.pro.apex.exchange/#publicapi-v3-for-omni-get-funding-rate-history-v3
     * @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.until] timestamp in ms of the latest funding rate
     * @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 {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 = {}) {
        if (symbol === undefined) {
            throw new errors.ArgumentsRequired(this.id + ' fetchFundingRateHistory() requires a symbol argument');
        }
        await this.loadMarkets();
        const request = {};
        const market = this.market(symbol);
        request['symbol'] = market['id'];
        if (since !== undefined) {
            request['beginTimeInclusive'] = since;
        }
        if (limit !== undefined) {
            request['limit'] = limit;
        }
        const page = this.safeInteger(params, 'page');
        if (page !== undefined) {
            request['page'] = page;
        }
        const endTimeExclusive = this.safeIntegerN(params, ['endTime', 'endTimeExclusive', 'until']);
        if (endTimeExclusive !== undefined) {
            request['endTimeExclusive'] = endTimeExclusive;
        }
        const response = await this.publicGetV3HistoryFunding(this.extend(request, params));
        //
        // {
        //     "historyFunds": [
        //     {
        //         "symbol": "BTC-USD",
        //         "rate": "0.0000125000",
        //         "price": "31297.5000008009374142",
        //         "fundingTime": 12315555,
        //         "fundingTimestamp": 12315555
        //     }
        // ],
        //     "totalSize": 11
        // }
        //
        const rates = [];
        const data = this.safeDict(response, 'data', {});
        const resultList = this.safeList(data, 'historyFunds', []);
        for (let i = 0; i < resultList.length; i++) {
            const entry = resultList[i];
            const timestamp = this.safeInteger(entry, 'fundingTimestamp');
            const marketId = this.safeString(entry, 'symbol');
            rates.push({
                'info': entry,
                'symbol': this.safeSymbol(marketId, market),
                'fundingRate': this.safeNumber(entry, 'rate'),
                'timestamp': timestamp,
                'datetime': this.iso8601(timestamp),
            });
        }
        const sorted = this.sortBy(rates, 'timestamp');
        return this.filterBySymbolSinceLimit(sorted, symbol, since, limit);
    }
    parseOrder(order, market = undefined) {
        //
        // {
        //     "id": "1234",
        //     "clientId": "1234",
        //     "accountId": "12345",
        //     "symbol": "BTC-USD",
        //     "side": "SELL",
        //     "price": "18000",
        //     "limitFee": "100",
        //     "fee": "100",
        //     "triggerPrice": "1.2",
        //     "trailingPercent": "0.12",
        //     "size": "100",
        //     "remainingSize": "100",
        //     "type": "LIMIT",
        //     "createdAt": 1647502440973,
        //     "updatedTime": 1647502440973,
        //     "expiresAt": 1647502440973,
        //     "status": "PENDING",
        //     "timeInForce": "GOOD_TIL_CANCEL",
        //     "postOnly": false,
        //     "reduceOnly": false,
        //     "stopPnl": false,
        //     "latestMatchFillPrice": "reason",
        //     "cumMatchFillSize": "0.1",
        //     "cumMatchFillValue": "1000",
        //     "cumMatchFillFee": "1",
        //     "cumSuccessFillSize": "0.1",
        //     "cumSuccessFillValue": "1000",
        //     "cumSuccessFillFee": "1",
        //     "triggerPriceType": "INDEX",
        //     "isOpenTpslOrder": true,
        //     "isSetOpenTp": true,
        //     "isSetOpenSl": false,
        //     "openTpParam": {
        //     "side": "SELL",
        //         "price": "18000",
        //         "limitFee": "100",
        //         "clientOrderId": "111100",
        //         "triggerPrice": "1.2",
        //         "trailingPercent": "0.12",
        //         "size": "100"
        // },
        //     "openSlParam": {
        //     "side": "SELL",
        //         "price": "18000",
        //         "limitFee": "100",
        //         "clientOrderId": "111100",
        //         "triggerPrice": "1.2",
        //         "trailingPercent": "0.12",
        //         "size": "100"
        // }
        // }
        //
        const timestamp = this.safeInteger(order, 'createdAt');
        const orderId = this.safeString(order, 'id');
        const clientOrderId = this.safeString(order, 'clientId');
        const marketId = this.safeString(order, 'symbol');
        market = this.safeMarket(marketId, market);
        const symbol = market['symbol'];
        const price = this.safeString(order, 'price');
        const amount = this.safeString(order, 'size');
        const orderType = this.safeString(order, 'type');
        const status = this.safeString(order, 'status');
        const side = this.safeStringLower(order, 'side');
        // const average = this.omitZero (this.safeString (order, 'avg_fill_price'));
        const remaining = this.omitZero(this.safeString(order, 'remainingSize'));
        const lastUpdateTimestamp = this.safeInteger(order, 'updatedTime');
        return this.safeOrder({
            'id': orderId,
            'clientOrderId': clientOrderId,
            'timestamp': timestamp,
            'datetime': this.iso8601(timestamp),
            'lastTradeTimestamp': undefined,
            'lastUpdateTimestamp': lastUpdateTimestamp,
            'status': this.parseOrderStatus(status),
            'symbol': symbol,
            'type': this.parseOrderType(orderType),
            'timeInForce': this.parseTimeInForce(this.safeString(order, 'timeInForce')),
            'postOnly': this.safeBool(order, 'postOnly'),
            'reduceOnly': this.safeBool(order, 'reduceOnly'),
            'side': side,
            'price': price,
            'triggerPrice': this.safeString(order, 'triggerPrice'),
            'takeProfitPrice': undefined,
            'stopLossPrice': undefined,
            'average': undefined,
            'amount': amount,
            'filled': undefined,
            'remaining': remaining,
            'cost': undefined,
            'trades': undefined,
            'fee': {
                'cost': this.safeString(order, 'fee'),
                'currency': market['settleId'],
            },
            'info': order,
        }, market);
    }
    parseTimeInForce(timeInForce) {
        const timeInForces = {
            'GOOD_TIL_CANCEL': 'GOOD_TIL_CANCEL',
            'FILL_OR_KILL': 'FILL_OR_KILL',
            'IMMEDIATE_OR_CANCEL': 'IMMEDIATE_OR_CANCEL',
            'POST_ONLY': 'POST_ONLY',
        };
        return this.safeString(timeInForces, timeInForce, undefined);
    }
    parseOrderStatus(status) {
        if (status !== undefined) {
            const statuses = {
                'PENDING': 'open',
                'OPEN': 'open',
                'FILLED': 'filled',
                'CANCELING': 'canceled',
                'CANCELED': 'canceled',
                'UNTRIGGERED': 'open',
            };
            return this.safeString(statuses, status, status);
        }
        return status;
    }
    parseOrderType(type) {
        const types = {
            'LIMIT': 'LIMIT',
            'MARKET': 'MARKET',
            'STOP_LIMIT': 'STOP_LIMIT',
            'STOP_MARKET': 'STOP_MARKET',
            'TAKE_PROFIT_LIMIT': 'TAKE_PROFIT_LIMIT',
            'TAKE_PROFIT_MARKET': 'TAKE_PROFIT_MARKET',
        };
        return this.safeStringUpper(types, type, type);
    }
    safeMarket(marketId = undefined, market = undefined, delimiter = undefined, marketType = undefined) {
        if (market === undefined && marketId !== undefined) {
            if (marketId in this.markets) {
                market = this.markets[marketId];
            }
            else if (marketId in this.markets_by_id) {
                market = this.markets_by_id[marketId];
            }
            else {
                const newMarketId = this.addHyphenBeforeUsdt(marketId);
                if (newMarketId in this.markets_by_id) {
                    const markets = this.markets_by_id[newMarketId];
                    const numMarkets = markets.length;
                    if (numMarkets > 0) {
                        if (this.markets_by_id[newMarketId][0]['id2'] === marketId) {
                            market = this.markets_by_id[newMarketId][0];
                        }
                    }
                }
            }
        }
        return super.safeMarket(marketId, market, delimiter, marketType);
    }
    generateRandomClientIdOmni(_accountId) {
        const accountId = _accountId || this.randNumber(12).toString();
        return 'apexomni-' + accountId + '-' + this.milliseconds().toString() + '-' + this.randNumber(6).toString();
    }
    addHyphenBeforeUsdt(symbol) {
        const uppercaseSymbol = symbol.toUpperCase();
        const index = uppercaseSymbol.indexOf('USDT');
        const symbolChar = this.safeString(symbol, index - 1);
        if (index > 0 && symbolChar !== '-') {
            return symbol.slice(0, index) + '-' + symbol.slice(index);
        }
        return symbol;
    }
    getSeeds() {
        const seeds = this.safeString(this.options, 'seeds');
        if (seeds === undefined) {
            throw new errors.ArgumentsRequired(this.id + ' the "seeds" key is required in the options to access private endpoints. You can find it in API Management > Omni Key, and then set it as exchange.options["seeds"] = XXXX');
        }
        return seeds;
    }
    async getAccountId() {
        const accountId = this.safeString(this.options, 'accountId', '0');
        if (accountId === '0') {
            const accountData = await this.fetchAccount();
            this.options['accountId'] = this.safeString(accountData, 'id', '0');
        }
        return this.options['accountId'];
    }
    /**
     * @method
     * @name apex#createOrder
     * @description create a trade order
     * @see https://api-docs.pro.apex.exchange/#privateapi-v3-for-omni-post-creating-orders
     * @param {string} symbol unified symbol of the market to create an order in
     * @param {string} type 'market' or 'limit'
     * @param {string} side 'buy' or 'sell'
     * @param {float} amount how much of currency you want to trade in units of base currency
     * @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @param {float} [params.triggerPrice] The price a trigger order is triggered at
     * @param {string} [params.timeInForce] "GTC", "IOC", or "POST_ONLY"
     * @param {bool} [params.postOnly] true or false
     * @param {bool} [params.reduceOnly] Ensures that the executed order does not flip the opened position.
     * @param {string} [params.clientOrderId] a unique id for the order
     * @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);
        const orderType = type.toUpperCase();
        const orderSide = side.toUpperCase();
        const orderSize = this.amountToPrecision(symbol, amount);
        let orderPrice = '0';
        if (price !== undefined) {
            orderPrice = this.priceToPrecision(symbol, price);
        }
        const fees = this.safeDict(this.fees, 'swap', {});
        const taker = this.safeNumber(fees, 'taker', 0.0005);
        const maker = this.safeNumber(fees, 'maker', 0.0002);
        const limitFee = this.decimalToPrecision(Precise["default"].stringAdd(Precise["default"].stringMul(Precise["default"].stringMul(orderPrice, orderSize), taker.toString()), market['precision']['price'].toString()), number.TRUNCATE, market['precision']['price'], this.precisionMode, this.paddingMode);
        const timeNow = this.milliseconds();
        // const triggerPrice = this.safeString2 (params, 'triggerPrice', 'stopPrice');
        const isMarket = orderType === 'MARKET';
        if (isMarket && (price === undefined)) {
            throw new errors.ArgumentsRequired(this.id + ' createOrder() requires a price argument for market orders');
        }
        let timeInForce = this.safeStringUpper(params, 'timeInForce');
        const postOnly = this.isPostOnly(isMarket, undefined, params);
        if (timeInForce === undefined) {
            timeInForce = 'GOOD_TIL_CANCEL';
        }
        if (!isMarket) {
            if (postOnly) {
                timeInForce = 'POST_ONLY';
            }
            else if (timeInForce === 'ioc') {
                timeInForce = 'IMMEDIATE_OR_CANCEL';
            }
        }
        params = this.omit(params, 'timeInForce');
        params = this.omit(params, 'postOnly');
        let clientOrderId = this.safeStringN(params, ['clientId', 'clientOrderId', 'client_order_id']);
        const accountId = await this.getAccountId();
        if (clientOrderId === undefined) {
            clientOrderId = this.generateRandomClientIdOmni(accountId);
        }
        params = this.omit(params, ['clientId', 'clientOrderId', 'client_order_id']);
        const orderToSign = {
            'accountId': accountId,
            'slotId': clientOrderId,
            'nonce': clientOrderId,
            'pairId': market['quoteId'],
            'size': orderSize,
            'price': orderPrice,
            'direction': orderSide,
            'makerFeeRate': maker.toString(),
            'takerFeeRate': taker.toString(),
        };
        const signature = await this.getZKContractSignatureObj(this.remove0xPrefix(this.getSeeds()), orderToSign);
        const request = {
            'symbol': market['id'],
            'side': orderSide,
            'type': orderType,
            'size': orderSize,
            'price': orderPrice,
            'limitFee': limitFee,
            'expiration': Math.floor(timeNow / 1000 + 30 * 24 * 60 * 60),
            'timeInForce': timeInForce,
            'clientId': clientOrderId,
            'brokerId': this.safeString(this.options, 'brokerId', '6956'),
        };
        request['signature'] = signature;
        const response = await this.privatePostV3Order(this.extend(request, params));
        const data = this.safeDict(response, 'data', {});
        return this.parseOrder(data, market);
    }
    /**
     * @method
     * @name apex#transfer
     * @description transfer currency internally between wallets on the same account
     * @param {string} code unified currency code
     * @param {float} amount amount to transfer
     * @param {string} fromAccount account to transfer from
     * @param {string} toAccount account to transfer to
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @param {string} [params.transferId] UUID, which is unique across the platform
     * @returns {object} a [transfer structure]{@link https://docs.ccxt.com/#/?id=transfer-structure}
     */
    async transfer(code, amount, fromAccount, toAccount, params = {}) {
        await this.loadMarkets();
        const configResponse = await this.publicGetV3Symbols(params);
        const configData = this.safeDict(configResponse, 'data', {});
        const contractConfig = this.safeDict(configData, 'contractConfig', {});
        const contractAssets = this.safeList(contractConfig, 'assets', []);
        const spotConfig = this.safeDict(configData, 'spotConfig', {});
        const spotAssets = this.safeList(spotConfig, 'assets', []);
        const globalConfig = this.safeDict(spotConfig, 'global', {});
        const receiverAddress = this.safeString(globalConfig, 'contractAssetPoolEthAddress', '');
        const receiverZkAccountId = this.safeString(globalConfig, 'contractAssetPoolZkAccountId', '');
        const receiverSubAccountId = this.safeString(globalConfig, 'contractAssetPoolSubAccount', '');
        const receiverAccountId = this.safeString(globalConfig, 'contractAssetPoolAccountId', '');
        const accountResponse = await this.privateGetV3Account(params);
        const accountData = this.safeDict(accountResponse, 'data', {});
        const spotAccount = this.safeDict(accountData, 'spotAccount', {});
        const zkAccountId = this.safeString(spotAccount, 'zkAccountId', '');
        const subAccountId = this.safeString(spotAccount, 'defaultSubAccountId', '0');
        const subAccounts = this.safeList(spotAccount, 'subAccounts', []);
        let nonce = '0';
        if (subAccounts.length > 0) {
            nonce = this.safeString(subAccounts[0], 'nonce', '0');
        }
        const ethAddress = this.safeString(accountData, 'ethereumAddress', '');
        const accountId = this.safeString(accountData, 'id', '');
        let currency = {};
        let assets = [];
        if (fromAccount !== undefined && fromAccount.toLowerCase() === 'contract') {
            assets = contractAssets;
        }
        else {
            assets = spotAssets;
        }
        for (let i = 0; i < assets.length; i++) {
            if (this.safeString(assets[i], 'token', '') === code) {
                currency = assets[i];
            }
        }
        const tokenId = this.safeString(currency, 'tokenId', '');
        const amountNumber = this.parseToInt(amount * (Math.pow(10, this.safeNumber(currency, 'decimals', 0))));
        const timestampSeconds = this.parseToInt(this.milliseconds() / 1000);
        let clientOrderId = this.safeStringN(params, ['clientId', 'clientOrderId', 'client_order_id']);
        if (clientOrderId === undefined) {
            clientOrderId = this.generateRandomClientIdOmni(this.safeString(this.options, 'accountId'));
        }
        params = this.omit(params, ['clientId', 'clientOrderId', 'client_order_id']);
        if (fromAccount !== undefined && fromAccount.toLowerCase() === 'contract') {
            const formattedUint32 = '4294967295';
            const zkSignAccountId = Precise["default"].stringMod(accountId, formattedUint32);
            const expireTime = timestampSeconds + 3600 * 24 * 28;
            const orderToSign = {
                'zkAccountId': zkSignAccountId,
                'receiverAddress': ethAddress,
                'subAccountId': subAccountId,
                'receiverSubAccountId': subAccountId,
                'tokenId': tokenId,
                'amount': amountNumber.toString(),
                'fee': '0',
                'nonce': clientOrderId,
                'timestampSeconds': expireTime,
                'isContract': true,
            };
            const signature = await this.getZKTransferSignatureObj(this.remove0xPrefix(this.getSeeds()), orderToSign);
            const request = {
                'amount': amount,
                'expireTime': expireTime,
                'clientWithdrawId': clientOrderId,
                'signature': signature,
                'token': code,
                'ethAddress': ethAddress,
            };
            const response = await this.privatePostV3ContractTransferOut(this.extend(request, params));
            const data = this.safeDict(response, 'data', {});
            const currentTime = this.milliseconds();
            return this.extend(this.parseTransfer(data, this.currency(code)), {
                'timestamp': currentTime,
                'datetime': this.iso8601(currentTime),
                'amount': this.parseNumber(amount),
                'fromAccount': 'contract',
                'toAccount': 'spot',
            });
        }
        else {
            const orderToSign = {
                'zkAccountId': zkAccountId,
                'receiverAddress': receiverAddress,
                'subAccountId': subAccountId,
                'receiverSubAccountId': receiverSubAccountId,
                'tokenId': tokenId,
                'amount': amountNumber.toString(),
                'fee': '0',
                'nonce': nonce,
                'timestampSeconds': timestampSeconds,
            };
            const signature = await this.getZKTransferSignatureObj(this.remove0xPrefix(this.getSeeds()), orderToSign);
            const request = {
                'amount': amount.toString(),
                'timestamp': timestampSeconds,
                'clientTransferId': clientOrderId,
                'signature': signature,
                'zkAccountId': zkAccountId,
                'subAccountId': subAccountId,
                'fee': '0',
                'token': code,
                'tokenId': tokenId,
                'receiverAccountId': receiverAccountId,
                'receiverZkAccountId': receiverZkAccountId,
                'receiverSubAccountId': receiverSubAccountId,
                'receiverAddress': receiverAddress,
                'nonce': nonce,
            };
            const response = await this.privatePostV3TransferOut(this.extend(request, params));
            const data = this.safeDict(response, 'data', {});
            const currentTime = this.milliseconds();
            return this.extend(this.parseTransfer(data, this.currency(code)), {
                'timestamp': currentTime,
                'datetime': this.iso8601(currentTime),
                'amount': this.parseNumber(amount),
                'fromAccount': 'spot',
                'toAccount': 'contract',
            });
        }
    }
    parseTransfer(transfer, currency = undefined) {
        const currencyId = this.safeString(transfer, 'coin');
        const timestamp = this.safeInteger(transfer, 'timestamp');
        const fromAccount = this.safeString(transfer, 'fromAccount');
        const toAccount = this.safeString(transfer, 'toAccount');
        return {
            'info': transfer,
            'id': this.safeStringN(transfer, ['transferId', 'id']),
            'timestamp': timestamp,
            'datetime': this.iso8601(timestamp),
            'currency': this.safeCurrencyCode(currencyId, currency),
            'amount': this.safeNumber(transfer, 'amount'),
            'fromAccount': fromAccount,
            'toAccount': toAccount,
            'status': this.safeString(transfer, 'status'),
        };
    }
    /**
     * @method
     * @name apex#cancelAllOrders
     * @description cancel all open orders in a market
     * @see https://api-docs.pro.apex.exchange/#privateapi-v3-for-omni-post-cancel-all-open-orders
     * @param {string} symbol unified market symbol of the market to cancel orders in
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
     */
    async cancelAllOrders(symbol = undefined, params = {}) {
        await this.loadMarkets();
        let market = undefined;
        const request = {};
        if (symbol !== undefined) {
            market = this.market(symbol);
            request['symbol'] = market['id'];
        }
        const response = await this.privatePostV3DeleteOpenOrders(this.extend(request, params));
        const data = this.safeDict(response, 'data', {});
        return data;
    }
    /**
     * @method
     * @name apex#cancelOrder
     * @description cancels an open order
     * @see https://api-docs.pro.apex.exchange/#privateapi-v3-for-omni-post-cancel-order
     * @param {string} id order id
     * @param symbol
     * @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 cancelOrder(id, symbol = undefined, params = {}) {
        const request = {};
        const clientOrderId = this.safeStringN(params, ['clientId', 'clientOrderId', 'client_order_id']);
        let response = undefined;
        if (clientOrderId !== undefined) {
            request['id'] = clientOrderId;
            params = this.omit(params, ['clientId', 'clientOrderId', 'client_order_id']);
            response = await this.privatePostV3DeleteClientOrderId(this.extend(request, params));
        }
        else {
            request['id'] = id;
            response = await this.privatePostV3DeleteOrder(this.extend(request, params));
        }
        const data = this.safeDict(response, 'data', {});
        return data;
    }
    /**
     * @method
     * @name apex#fetchOrder
     * @description fetches information on an order made by the user
     * @see https://api-docs.pro.apex.exchange/#privateapi-v3-for-omni-get-order-id
     * @see https://api-docs.pro.apex.exchange/#privateapi-v3-for-omni-get-order-by-clientorderid
     * @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.clientOrderId] a unique id for the order
     * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
     */
    async fetchOrder(id, symbol = undefined, params = {}) {
        await this.loadMarkets();
        const request = {};
        const clientOrderId = this.safeStringN(params, ['clientId', 'clientOrderId', 'client_order_id']);
        let response = undefined;
        if (clientOrderId !== undefined) {
            request['id'] = clientOrderId;
            params = this.omit(params, ['clientId', 'clientOrderId', 'client_order_id']);
            response = await this.privateGetV3OrderByClientOrderId(this.extend(request, params));
        }
        else {
            request['id'] = id;
            response = await this.privateGetV3Order(this.extend(request, params));
        }
        const data = this.safeDict(response, 'data', {});
        return this.parseOrder(data);
    }
    /**
     * @method
     * @name apex#fetchOpenOrders
     * @description fetches information on multiple orders made by the user
     * @see https://api-docs.pro.apex.exchange/#privateapi-v3-for-omni-get-open-orders
     * @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
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
     */
    async fetchOpenOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets();
        const response = await this.privateGetV3OpenOrders(params);
        const orders = this.safeList(response, 'data', []);
        return this.parseOrders(orders, undefined, since, limit);
    }
    /**
     * @method
     * @name apex#fetchOrders
     * @description fetches information on multiple orders made by the user *classic accounts only*
     * @see https://api-docs.pro.apex.exchange/#privateapi-v3-for-omni-get-all-order-history
     * @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 100
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @param {object} [params.until] end time, ms
     * @param {boolean} [params.status] "PENDING", "OPEN", "FILLED", "CANCELED", "EXPIRED", "UNTRIGGERED"
     * @param {boolean} [params.side] BUY or SELL
     * @param {string} [params.type] "LIMIT", "MARKET","STOP_LIMIT", "STOP_MARKET", "TAKE_PROFIT_LIMIT","TAKE_PROFIT_MARKET"
     * @param {string} [params.orderType] "ACTIVE","CONDITION","HISTORY"
     * @param {boolean} [params.page] Page numbers start from 0
     * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
     */
    async fetchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets();
        const request = {};
        let market = undefined;
        if (symbol !== undefined) {
            market = this.market(symbol);
            request['symbol'] = market['id'];
        }
        if (since !== undefined) {
            request['beginTimeInclusive'] = since;
        }
        if (limit !== undefined) {
            request['limit'] = limit;
        }
        const endTimeExclusive = this.safeIntegerN(params, ['endTime', 'endTimeExclusive', 'until']);
        if (endTimeExclusive !== undefined) {
            request['endTimeExclusive'] = endTimeExclusive;
            params = this.omit(params, ['endTime', 'endTimeExclusive', 'until']);
        }
        const response = await this.privateGetV3HistoryOrders(this.extend(request, params));
        const data = this.safeDict(response, 'data', {});
        const orders = this.safeList(data, 'orders', []);
        return this.parseOrders(orders, market, since, limit);
    }
    /**
     * @method
     * @name apex#fetchOrderTrades
     * @description fetch all the trades made from a single order
     * @see https://api-docs.pro.apex.exchange/#privateapi-v3-for-omni-get-trade-history
     * @param {string} id order id
     * @param {string} symbol unified market symbol
     * @param {int} [since] the earliest time in ms to fetch trades for
     * @param {int} [limit] the maximum number of trades to retrieve
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
     */
    async fetchOrderTrades(id, symbol = undefined, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets();
        const request = {};
        const clientOrderId = this.safeString2(params, 'clientOrderId', 'clientId');
        if (clientOrderId !== undefined) {
            request['clientOrderId'] = clientOrderId;
        }
        else {
            request['orderId'] = id;
        }
        params = this.omit(params, ['clientOrderId', 'clientId']);
        const response = await this.privateGetV3OrderFills(this.extend(request, params));
        const data = this.safeDict(response, 'data', {});
        const orders = this.safeList(data, 'orders', []);
        return this.parseTrades(orders, undefined, since, limit);
    }
    /**
     * @method
     * @name apex#fetchMyTrades
     * @description fetches information on multiple orders made by the user *classic accounts only*
     * @see https://api-docs.pro.apex.exchange/#privateapi-v3-for-omni-get-trade-history
     * @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 100
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @param {object} [params.until] end time
     * @param {boolean} [params.side] BUY or SELL
     * @param {string} [params.orderType] "LIMIT", "MARKET","STOP_LIMIT", "STOP_MARKET", "TAKE_PROFIT_LIMIT","TAKE_PROFIT_MARKET"
     * @param {boolean} [params.page] Page numbers start from 0
     * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
     */
    async fetchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets();
        const request = {};
        let market = undefined;
        if (symbol !== undefined) {
            market = this.market(symbol);
            request['symbol'] = market['id'];
        }
        if (since !== undefined) {
            request['beginTimeInclusive'] = since;
        }
        if (limit !== undefined) {
            request['limit'] = limit;
        }
        const endTimeExclusive = this.safeIntegerN(params, ['endTime', 'endTimeExclusive', 'until']);
        if (endTimeExclusive !== undefined) {
            request['endTimeExclusive'] = endTimeExclusive;
            params = this.omit(params, ['endTime', 'endTimeExclusive', 'until']);
        }
        const response = await this.privateGetV3Fills(this.extend(request, params));
        const data = this.safeDict(response, 'data', {});
        const orders = this.safeList(data, 'orders', []);
        return this.parseTrades(orders, market, since, limit);
    }
    /**
     * @method
     * @name apex#fetchFundingHistory
     * @description fetches information on multiple orders made by the user *classic accounts only*
     * @see https://api-docs.pro.apex.exchange/#privateapi-v3-for-omni-get-funding-rate
     * @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 100
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @param {object} [params.until] end time, ms
     * @param {boolean} [params.side] BUY or SELL
     * @param {boolean} [params.page] Page numbers start from 0
     * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=funding-history-structure}
     */
    async fetchFundingHistory(symbol = undefined, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets();
        const request = {};
        let market = undefined;
        if (symbol !== undefined) {
            market = this.market(symbol);
            request['symbol'] = market['id'];
        }
        if (since !== undefined) {
            request['beginTimeInclusive'] = since;
        }
        if (limit !== undefined) {
            request['limit'] = limit;
        }
        const endTimeExclusive = this.safeIntegerN(params, ['endTime', 'endTimeExclusive', 'until']);
        if (endTimeExclusive !== undefined) {
            params = this.omit(params, ['endTime', 'endTimeExclusive', 'until']);
            request['endTimeExclusive'] = endTimeExclusive;
        }
        const response = await this.privateGetV3Funding(this.extend(request, params));
        const data = this.safeDict(response, 'data', {});
        const fundingValues = this.safeList(data, 'fundingValues', []);
        return this.parseIncomes(fundingValues, market, since, limit);
    }
    parseIncome(income, market = undefined) {
        //
        // {
        //     "id": "1234",
        //     "symbol": "BTC-USDT",
        //     "fundingValue": "10000",
        //     "rate": "0.0000125000",
        //     "positionSize": "500",
        //     "price": "90",
        //     "side": "LONG",
        //     "status": "SUCCESS",
        //     "fundingTime": 1647502440973,
        //     "transactionId": "1234556"
        // }
        //
        const marketId = this.safeString(income, 'symbol');
        market = this.safeMarket(marketId, market, undefined, 'contract');
        const code = 'USDT';
        const timestamp = this.safeInteger(income, 'fundingTime');
        return {
            'info': income,
            'symbol': this.safeSymbol(marketId, market),
            'code': code,
            'timestamp': timestamp,
            'datetime': this.iso8601(timestamp),
            'id': this.safeString(income, 'id'),
            'amount': this.safeNumber(income, 'fundingValue'),
            'rate': this.safeNumber(income, 'rate'),
        };
    }
    /**
     * @method
     * @name apex#setLeverage
     * @description set the level of leverage for a market
     * @see https://api-docs.pro.apex.exchange/#privateapi-v3-for-omni-post-sets-the-initial-margin-rate-of-a-contract
     * @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 market = this.market(symbol);
        const leverageString = this.numberToString(leverage);
        const initialMarginRate = Precise["default"].stringDiv('1', leverageString, 4);
        const request = {
            'symbol': market['id'],
            'initialMarginRate': initialMarginRate,
        };
        const response = await this.privatePostV3SetInitialMarginRate(this.extend(request, params));
        const data = this.safeDict(response, 'data', {});
        return data;
    }
    /**
     * @method
     * @name apex#fetchPositions
     * @description fetch all open positions
     * @see https://api-docs.pro.apex.exchange/#privateapi-v3-for-omni-get-retrieve-user-account-data
     * @param {string[]} [symbols] list of unified market symbols
     * @param {object} [params] extra parameters specific to the exchange API endpoint
     * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
     */
    async fetchPositions(symbols = undefined, params = {}) {
        await this.loadMarkets();
        const response = await this.privateGetV3Account(params);
        const data = this.safeDict(response, 'data', {});
        const positions = this.safeList(data, 'positions', []);
        return this.parsePositions(positions, symbols);
    }
    parsePosition(position, market = undefined) {
        //
        // {
        //     "symbol": "BTC-USDT",
        //     "status": "",
        //     "side": "LONG",
        //     "size": "0.000",
        //     "entryPrice": "0.00",
        //     "exitPrice": "",
        //     "createdAt": 1690366452416,
        //     "updatedTime": 1690366452416,
        //     "fee": "0.000000",
        //     "fundingFee": "0.000000",
        //     "lightNumbers": "",
        //     "customInitialMarginRate": "0"
        // }
        const marketId = this.safeString(position, 'symbol');
        market = this.safeMarket(marketId, market);
        const symbol = market['symbol'];
        const side = this.safeStringLower(position, 'side');
        const quantity = this.safeString(position, 'size');
        const timestamp = this.safeInteger(position, 'updatedTime');
        let leverage = 20;
        const customInitialMarginRate = this.safeStringN(position, ['customInitialMarginRate', 'customImr'], '0');
        if (this.precisionFromString(customInitialMarginRate) !== 0) {
            leverage = this.parseToInt(Precise["default"].stringDiv('1', customInitialMarginRate, 4));
        }
        return this.safePosition({
            'info': position,
            'id': this.safeString(position, 'id'),
            'symbol': symbol,
            'entryPrice': this.safeString(position, 'entryPrice'),
            'markPrice': undefined,
            'notional': undefined,
            'collateral': undefined,
            'unrealizedPnl': undefined,
            'side': side,
            'contracts': this.parseNumber(quantity),
            'contractSize': undefined,
            'timestamp': timestamp,
            'datetime': this.iso8601(timestamp),
            'hedged': undefined,
            'maintenanceMargin': undefined,
            'maintenanceMarginPercentage': undefined,
            'initialMargin': undefined,
            'initialMarginPercentage': undefined,
            'leverage': leverage,
            'liquidationPrice': undefined,
            'marginRatio': undefined,
            'marginMode': undefined,
            'percentage': undefined,
        });
    }
    sign(path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let url = this.implodeHostname(this.urls['api'][api]) + '/' + path;
        headers = {
            'User-Agent': 'apex-CCXT',
            'Accept': 'application/json',
            'Content-Type': 'application/x-www-form-urlencoded',
        };
        let signPath = '/api/' + path;
        let signBody = body;
        if (method.toUpperCase() !== 'POST') {
            if (Object.keys(params).length) {
                signPath += '?' + this.rawencode(params);
                url += '?' + this.rawencode(params);
            }
        }
        else {
            const sortedQuery = this.keysort(params);
            signBody = this.rawencode(sortedQuery);
        }
        if (api === 'private') {
            this.checkRequiredCredentials();
            const timestamp = this.milliseconds().toString();
            let messageString = timestamp + method.toUpperCase() + signPath;
            if (signBody !== undefined) {
                messageString = messageString + signBody;
            }
            const signature = this.hmac(this.encode(messageString), this.encode(this.stringToBase64(this.secret)), sha256.sha256, 'base64');
            headers['APEX-SIGNATURE'] = signature;
            headers['APEX-API-KEY'] = this.apiKey;
            headers['APEX-TIMESTAMP'] = timestamp;
            headers['APEX-PASSPHRASE'] = this.password;
        }
        return { 'url': url, 'method': method, 'body': signBody, 'headers': headers };
    }
    handleErrors(code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
        //
        // {"code":3,"msg":"Order price must be greater than 0. Order price is 0.","key":"ORDER_PRICE_MUST_GREETER_ZERO","detail":{"price":"0"}}
        // {"code":400,"msg":"strconv.ParseInt: parsing \"dsfdfsd\": invalid syntax","timeCost":5320995}
        //
        if (response === undefined) {
            return undefined;
        }
        const errorCode = this.safeInteger(response, 'code');
        if (errorCode !== undefined && errorCode !== 0) {
            const feedback = this.id + ' ' + body;
            const message = this.safeString2(response, 'key', 'msg');
            this.throwBroadlyMatchedException(this.exceptions['broad'], message, feedback);
            const status = code.toString();
            this.throwExactlyMatchedException(this.exceptions['exact'], status, feedback);
            throw new errors.ExchangeError(feedback);
        }
        return undefined;
    }
}

module.exports = apex;