<?php

namespace ccxt\async;

// PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
// https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code

use Exception; // a common import
use ccxt\async\abstract\coinex as Exchange;
use ccxt\ExchangeError;
use ccxt\ArgumentsRequired;
use ccxt\BadRequest;
use ccxt\BadSymbol;
use ccxt\InvalidOrder;
use ccxt\NotSupported;
use ccxt\Precise;
use \React\Async;
use \React\Promise;
use \React\Promise\PromiseInterface;

class coinex extends Exchange {

    public function describe(): mixed {
        return $this->deep_extend(parent::describe(), array(
            'id' => 'coinex',
            'name' => 'CoinEx',
            'version' => 'v2',
            'countries' => array( 'CN' ),
            // IP ratelimit is 400 requests per second
            // rateLimit = 1000ms / 400 = 2.5
            // 200 per 2 seconds => 100 per second => weight = 4
            // 120 per 2 seconds => 60 per second => weight = 6.667
            // 80 per 2 seconds => 40 per second => weight = 10
            // 60 per 2 seconds => 30 per second => weight = 13.334
            // 40 per 2 seconds => 20 per second => weight = 20
            // 20 per 2 seconds => 10 per second => weight = 40
            // v1 is per 2 seconds and v2 is per 1 second
            'rateLimit' => 2.5,
            'pro' => true,
            'certified' => true,
            'has' => array(
                'CORS' => null,
                'spot' => true,
                'margin' => true,
                'swap' => true,
                'future' => false,
                'option' => false,
                'addMargin' => true,
                'borrowCrossMargin' => false,
                'borrowIsolatedMargin' => true,
                'cancelAllOrders' => true,
                'cancelOrder' => true,
                'cancelOrders' => true,
                'closeAllPositions' => false,
                'closePosition' => true,
                'createDepositAddress' => true,
                'createMarketBuyOrderWithCost' => true,
                'createMarketOrderWithCost' => false,
                'createMarketSellOrderWithCost' => false,
                'createOrder' => true,
                'createOrders' => true,
                'createReduceOnlyOrder' => true,
                'createStopLossOrder' => true,
                'createStopOrder' => true,
                'createTakeProfitOrder' => true,
                'createTriggerOrder' => true,
                'editOrder' => true,
                'fetchBalance' => true,
                'fetchBorrowInterest' => true,
                'fetchBorrowRateHistories' => false,
                'fetchBorrowRateHistory' => false,
                'fetchClosedOrders' => true,
                'fetchCrossBorrowRate' => false,
                'fetchCrossBorrowRates' => false,
                'fetchCurrencies' => true,
                'fetchDepositAddress' => true,
                'fetchDepositAddresses' => false,
                'fetchDepositAddressesByNetwork' => false,
                'fetchDeposits' => true,
                'fetchDepositWithdrawFee' => true,
                'fetchDepositWithdrawFees' => true,
                'fetchFundingHistory' => true,
                'fetchFundingInterval' => true,
                'fetchFundingIntervals' => false,
                'fetchFundingRate' => true,
                'fetchFundingRateHistory' => true,
                'fetchFundingRates' => true,
                'fetchIndexOHLCV' => false,
                'fetchIsolatedBorrowRate' => true,
                'fetchIsolatedBorrowRates' => false,
                'fetchLeverage' => true,
                'fetchLeverages' => false,
                'fetchLeverageTiers' => true,
                'fetchMarginAdjustmentHistory' => true,
                'fetchMarketLeverageTiers' => 'emulated',
                'fetchMarkets' => true,
                'fetchMarkOHLCV' => false,
                'fetchMyTrades' => true,
                'fetchOHLCV' => true,
                'fetchOpenOrders' => true,
                'fetchOrder' => true,
                'fetchOrderBook' => true,
                'fetchPosition' => true,
                'fetchPositionHistory' => true,
                'fetchPositions' => true,
                'fetchPositionsHistory' => false,
                'fetchPositionsRisk' => false,
                'fetchPremiumIndexOHLCV' => false,
                'fetchTicker' => true,
                'fetchTickers' => true,
                'fetchTime' => true,
                'fetchTrades' => true,
                'fetchTradingFee' => true,
                'fetchTradingFees' => true,
                'fetchTransfer' => false,
                'fetchTransfers' => true,
                'fetchWithdrawal' => false,
                'fetchWithdrawals' => true,
                'reduceMargin' => true,
                'repayCrossMargin' => false,
                'repayIsolatedMargin' => true,
                'setLeverage' => true,
                'setMarginMode' => true,
                'setPositionMode' => false,
                'transfer' => true,
                'withdraw' => true,
            ),
            'timeframes' => array(
                '1m' => '1min',
                '3m' => '3min',
                '5m' => '5min',
                '15m' => '15min',
                '30m' => '30min',
                '1h' => '1hour',
                '2h' => '2hour',
                '4h' => '4hour',
                '6h' => '6hour',
                '12h' => '12hour',
                '1d' => '1day',
                '3d' => '3day',
                '1w' => '1week',
            ),
            'urls' => array(
                'logo' => 'https://user-images.githubusercontent.com/51840849/87182089-1e05fa00-c2ec-11ea-8da9-cc73b45abbbc.jpg',
                'api' => array(
                    'public' => 'https://api.coinex.com',
                    'private' => 'https://api.coinex.com',
                    'perpetualPublic' => 'https://api.coinex.com/perpetual',
                    'perpetualPrivate' => 'https://api.coinex.com/perpetual',
                ),
                'www' => 'https://www.coinex.com',
                'doc' => 'https://docs.coinex.com/api/v2',
                'fees' => 'https://www.coinex.com/fees',
                'referral' => 'https://www.coinex.com/register?refer_code=yw5fz',
            ),
            'api' => array(
                'v1' => array(
                    'public' => array(
                        'get' => array(
                            'amm/market' => 1,
                            'common/currency/rate' => 1,
                            'common/asset/config' => 1,
                            'common/maintain/info' => 1,
                            'common/temp-maintain/info' => 1,
                            'margin/market' => 1,
                            'market/info' => 1,
                            'market/list' => 1,
                            'market/ticker' => 1,
                            'market/ticker/all' => 1,
                            'market/depth' => 1,
                            'market/deals' => 1,
                            'market/kline' => 1,
                            'market/detail' => 1,
                        ),
                    ),
                    'private' => array(
                        'get' => array(
                            'account/amm/balance' => 40,
                            'account/investment/balance' => 40,
                            'account/balance/history' => 40,
                            'account/market/fee' => 40,
                            'balance/coin/deposit' => 40,
                            'balance/coin/withdraw' => 40,
                            'balance/info' => 40,
                            'balance/deposit/address/{coin_type}' => 40,
                            'contract/transfer/history' => 40,
                            'credit/info' => 40,
                            'credit/balance' => 40,
                            'investment/transfer/history' => 40,
                            'margin/account' => 1,
                            'margin/config' => 1,
                            'margin/loan/history' => 40,
                            'margin/transfer/history' => 40,
                            'order/deals' => 40,
                            'order/finished' => 40,
                            'order/pending' => 8,
                            'order/status' => 8,
                            'order/status/batch' => 8,
                            'order/user/deals' => 40,
                            'order/stop/finished' => 40,
                            'order/stop/pending' => 8,
                            'order/user/trade/fee' => 1,
                            'order/market/trade/info' => 1,
                            'sub_account/balance' => 1,
                            'sub_account/transfer/history' => 40,
                            'sub_account/auth/api' => 40,
                            'sub_account/auth/api/{user_auth_id}' => 40,
                        ),
                        'post' => array(
                            'balance/coin/withdraw' => 40,
                            'contract/balance/transfer' => 40,
                            'margin/flat' => 40,
                            'margin/loan' => 40,
                            'margin/transfer' => 40,
                            'order/limit/batch' => 40,
                            'order/ioc' => 13.334,
                            'order/limit' => 13.334,
                            'order/market' => 13.334,
                            'order/modify' => 13.334,
                            'order/stop/limit' => 13.334,
                            'order/stop/market' => 13.334,
                            'order/stop/modify' => 13.334,
                            'sub_account/transfer' => 40,
                            'sub_account/register' => 1,
                            'sub_account/unfrozen' => 40,
                            'sub_account/frozen' => 40,
                            'sub_account/auth/api' => 40,
                        ),
                        'put' => array(
                            'balance/deposit/address/{coin_type}' => 40,
                            'sub_account/unfrozen' => 40,
                            'sub_account/frozen' => 40,
                            'sub_account/auth/api/{user_auth_id}' => 40,
                            'v1/account/settings' => 40,
                        ),
                        'delete' => array(
                            'balance/coin/withdraw' => 40,
                            'order/pending/batch' => 40,
                            'order/pending' => 13.334,
                            'order/stop/pending' => 40,
                            'order/stop/pending/{id}' => 13.334,
                            'order/pending/by_client_id' => 40,
                            'order/stop/pending/by_client_id' => 40,
                            'sub_account/auth/api/{user_auth_id}' => 40,
                            'sub_account/authorize/{id}' => 40,
                        ),
                    ),
                    'perpetualPublic' => array(
                        'get' => array(
                            'ping' => 1,
                            'time' => 1,
                            'market/list' => 1,
                            'market/limit_config' => 1,
                            'market/ticker' => 1,
                            'market/ticker/all' => 1,
                            'market/depth' => 1,
                            'market/deals' => 1,
                            'market/funding_history' => 1,
                            'market/kline' => 1,
                        ),
                    ),
                    'perpetualPrivate' => array(
                        'get' => array(
                            'market/user_deals' => 1,
                            'asset/query' => 40,
                            'order/pending' => 8,
                            'order/finished' => 40,
                            'order/stop_finished' => 40,
                            'order/stop_pending' => 8,
                            'order/status' => 8,
                            'order/stop_status' => 8,
                            'position/finished' => 40,
                            'position/pending' => 40,
                            'position/funding' => 40,
                            'position/adl_history' => 40,
                            'market/preference' => 40,
                            'position/margin_history' => 40,
                            'position/settle_history' => 40,
                        ),
                        'post' => array(
                            'market/adjust_leverage' => 1,
                            'market/position_expect' => 1,
                            'order/put_limit' => 20,
                            'order/put_market' => 20,
                            'order/put_stop_limit' => 20,
                            'order/put_stop_market' => 20,
                            'order/modify' => 20,
                            'order/modify_stop' => 20,
                            'order/cancel' => 20,
                            'order/cancel_all' => 40,
                            'order/cancel_batch' => 40,
                            'order/cancel_stop' => 20,
                            'order/cancel_stop_all' => 40,
                            'order/close_limit' => 20,
                            'order/close_market' => 20,
                            'position/adjust_margin' => 20,
                            'position/stop_loss' => 20,
                            'position/take_profit' => 20,
                            'position/market_close' => 20,
                            'order/cancel/by_client_id' => 20,
                            'order/cancel_stop/by_client_id' => 20,
                            'market/preference' => 20,
                        ),
                    ),
                ),
                'v2' => array(
                    'public' => array(
                        'get' => array(
                            'maintain/info' => 1,
                            'ping' => 1,
                            'time' => 1,
                            'spot/market' => 1,
                            'spot/ticker' => 1,
                            'spot/depth' => 1,
                            'spot/deals' => 1,
                            'spot/kline' => 1,
                            'spot/index' => 1,
                            'futures/market' => 1,
                            'futures/ticker' => 1,
                            'futures/depth' => 1,
                            'futures/deals' => 1,
                            'futures/kline' => 1,
                            'futures/index' => 1,
                            'futures/funding-rate' => 1,
                            'futures/funding-rate-history' => 1,
                            'futures/position-level' => 1,
                            'futures/liquidation-history' => 1,
                            'futures/basis-history' => 1,
                            'assets/deposit-withdraw-config' => 1,
                            'assets/all-deposit-withdraw-config' => 1,
                        ),
                    ),
                    'private' => array(
                        'get' => array(
                            'account/subs' => 1,
                            'account/subs/api-detail' => 40,
                            'account/subs/info' => 1,
                            'account/subs/api' => 40,
                            'account/subs/transfer-history' => 40,
                            'account/subs/spot-balance' => 1,
                            'account/trade-fee-rate' => 40,
                            'assets/spot/balance' => 40,
                            'assets/futures/balance' => 40,
                            'assets/margin/balance' => 1,
                            'assets/financial/balance' => 40,
                            'assets/amm/liquidity' => 40,
                            'assets/credit/info' => 40,
                            'assets/margin/borrow-history' => 40,
                            'assets/margin/interest-limit' => 1,
                            'assets/deposit-address' => 40,
                            'assets/deposit-history' => 40,
                            'assets/withdraw' => 40,
                            'assets/transfer-history' => 40,
                            'spot/order-status' => 8,
                            'spot/batch-order-status' => 8,
                            'spot/pending-order' => 8,
                            'spot/finished-order' => 40,
                            'spot/pending-stop-order' => 8,
                            'spot/finished-stop-order' => 40,
                            'spot/user-deals' => 40,
                            'spot/order-deals' => 40,
                            'futures/order-status' => 8,
                            'futures/batch-order-status' => 1,
                            'futures/pending-order' => 8,
                            'futures/finished-order' => 40,
                            'futures/pending-stop-order' => 8,
                            'futures/finished-stop-order' => 40,
                            'futures/user-deals' => 1,
                            'futures/order-deals' => 1,
                            'futures/pending-position' => 40,
                            'futures/finished-position' => 1,
                            'futures/position-margin-history' => 1,
                            'futures/position-funding-history' => 40,
                            'futures/position-adl-history' => 1,
                            'futures/position-settle-history' => 1,
                        ),
                        'post' => array(
                            'account/subs' => 40,
                            'account/subs/frozen' => 40,
                            'account/subs/unfrozen' => 40,
                            'account/subs/api' => 40,
                            'account/subs/edit-api' => 40,
                            'account/subs/delete-api' => 40,
                            'account/subs/transfer' => 40,
                            'account/settings' => 40,
                            'assets/margin/borrow' => 40,
                            'assets/margin/repay' => 40,
                            'assets/renewal-deposit-address' => 40,
                            'assets/withdraw' => 40,
                            'assets/cancel-withdraw' => 40,
                            'assets/transfer' => 40,
                            'assets/amm/add-liquidity' => 1,
                            'assets/amm/remove-liquidity' => 1,
                            'spot/order' => 13.334,
                            'spot/stop-order' => 13.334,
                            'spot/batch-order' => 40,
                            'spot/batch-stop-order' => 1,
                            'spot/modify-order' => 13.334,
                            'spot/modify-stop-order' => 13.334,
                            'spot/cancel-all-order' => 1,
                            'spot/cancel-order' => 6.667,
                            'spot/cancel-stop-order' => 6.667,
                            'spot/cancel-batch-order' => 10,
                            'spot/cancel-batch-stop-order' => 10,
                            'spot/cancel-order-by-client-id' => 1,
                            'spot/cancel-stop-order-by-client-id' => 1,
                            'futures/order' => 20,
                            'futures/stop-order' => 20,
                            'futures/batch-order' => 1,
                            'futures/batch-stop-order' => 1,
                            'futures/modify-order' => 20,
                            'futures/modify-stop-order' => 20,
                            'futures/cancel-all-order' => 1,
                            'futures/cancel-order' => 10,
                            'futures/cancel-stop-order' => 10,
                            'futures/cancel-batch-order' => 20,
                            'futures/cancel-batch-stop-order' => 20,
                            'futures/cancel-order-by-client-id' => 1,
                            'futures/cancel-stop-order-by-client-id' => 1,
                            'futures/close-position' => 20,
                            'futures/adjust-position-margin' => 20,
                            'futures/adjust-position-leverage' => 20,
                            'futures/set-position-stop-loss' => 20,
                            'futures/set-position-take-profit' => 20,
                        ),
                    ),
                ),
            ),
            'fees' => array(
                'trading' => array(
                    'maker' => 0.001,
                    'taker' => 0.001,
                ),
                'funding' => array(
                    'withdraw' => array(
                        'BCH' => 0.0,
                        'BTC' => 0.001,
                        'LTC' => 0.001,
                        'ETH' => 0.001,
                        'ZEC' => 0.0001,
                        'DASH' => 0.0001,
                    ),
                ),
            ),
            'limits' => array(
                'amount' => array(
                    'min' => 0.001,
                    'max' => null,
                ),
            ),
            'options' => array(
                'brokerId' => 'x-167673045',
                'createMarketBuyOrderRequiresPrice' => true,
                'defaultType' => 'spot', // spot, swap, margin
                'defaultSubType' => 'linear', // linear, inverse
                'fetchDepositAddress' => array(
                    'fillResponseFromRequest' => true,
                ),
                'accountsByType' => array(
                    'spot' => 'SPOT',
                    'margin' => 'MARGIN',
                    'swap' => 'FUTURES',
                ),
                'accountsById' => array(
                    'SPOT' => 'spot',
                    'MARGIN' => 'margin',
                    'FUTURES' => 'swap',
                ),
                'networks' => array(
                    'BTC' => 'BTC',
                    'BEP20' => 'BSC',
                    'TRC20' => 'TRC20',
                    'ERC20' => 'ERC20',
                    'BRC20' => 'BRC20',
                    'SOL' => 'SOL',
                    'TON' => 'TON',
                    'BSV' => 'BSV',
                    'AVAXC' => 'AVA_C',
                    'AVAXX' => 'AVA',
                    'SUI' => 'SUI',
                    'ACA' => 'ACA',
                    'CHZ' => 'CHILIZ',
                    'ADA' => 'ADA',
                    'ARB' => 'ARBITRUM',
                    'ARBNOVA' => 'ARBITRUM_NOVA',
                    'OP' => 'OPTIMISM',
                    'APT' => 'APTOS',
                    'ATOM' => 'ATOM',
                    'FTM' => 'FTM',
                    'BCH' => 'BCH',
                    'ASTR' => 'ASTR',
                    'LTC' => 'LTC',
                    'MATIC' => 'MATIC',
                    'CRONOS' => 'CRONOS',
                    'DASH' => 'DASH',
                    'DOT' => 'DOT',
                    'ETC' => 'ETC',
                    'ETHW' => 'ETHPOW',
                    'FIL' => 'FIL',
                    'ZIL' => 'ZIL',
                    'DOGE' => 'DOGE',
                    'TIA' => 'CELESTIA',
                    'SEI' => 'SEI',
                    'XRP' => 'XRP',
                    'XMR' => 'XMR',
                    // CSC, AE, BASE, AIPG, AKASH, POLKADOTASSETHUB ?, ALEO, STX, ALGO, ALPH, BLAST, AR, ARCH, ARDR, ARK, ARRR, MANTA, NTRN, LUNA, AURORA, AVAIL, ASC20, AVA, AYA, AZERO, BAN, BAND, BB, RUNES, BEAM, BELLSCOIN, BITCI, NEAR, AGORIC, BLOCX, BNC, BOBA, BRISE, KRC20, CANTO, CAPS, CCD, CELO, CFX, CHI, CKB, CLORE, CLV, CORE, CSPR, CTXC, DAG, DCR, DERO, DESO, DEFI, DGB, DNX, DOCK, DOGECHAIN, DYDX, DYMENSION, EGLD, ELA, ELF, ENJIN, EOSIO, ERG, ETN_SC, EVMOS, EWC, SGB, FACT, FB, FET, FIO, FIRO, NEO3, FLOW, FLARE, FLUX, LINEA, FREN, FSN, FB_BRC20, GLMR, GRIN, GRS, HACASH, HBAR, HERB, HIVE, MAPO, HMND, HNS, ZKSYNC, HTR, HUAHUA, MERLIN, ICP, ICX, INJ, IOST, IOTA, IOTX, IRIS, IRON, ONE, JOYSTREAM, KAI, KAR, KAS, KAVA, KCN, KDA, KLAY, KLY, KMD, KSM, KUB, KUJIRA, LAT, LBC, LUNC, LUKSO, MARS, METIS, MINA, MANTLE, MOB, MODE, MONA, MOVR, MTL, NEOX, NEXA, NIBI, NIMIQ, NMC, ONOMY, NRG, WAVES, NULS, OAS, OCTA, OLT, ONT, OORT, ORAI, OSMO, P3D, COMPOSABLE, PIVX, RON, POKT, POLYMESH, PRE_MARKET, PYI, QKC, QTUM, QUBIC, RSK, ROSE, ROUTE, RTM, THORCHAIN, RVN, RADIANT, SAGA, SALVIUM, SATOX, SC, SCP, _NULL, SCRT, SDN, RGBPP, SELF, SMH, SPACE, STARGAZE, STC, STEEM, STRATISEVM, STRD, STARKNET, SXP, SYS, TAIKO, TAO, TARA, TENET, THETA, TT, VENOM, VECHAIN, TOMO, VITE, VLX, VSYS, VTC, WAN, WAXP, WEMIX, XCH, XDC, XEC, XELIS, NEM, XHV, XLM, XNA, NANO, XPLA, XPR, XPRT, XRD, XTZ, XVG, XYM, ZANO, ZEC, ZEN, ZEPH, ZETA
                ),
            ),
            'features' => array(
                'spot' => array(
                    'sandbox' => false,
                    'createOrder' => array(
                        'marginMode' => true,
                        'triggerPrice' => true,
                        'triggerPriceType' => null,
                        'triggerDirection' => false,
                        'stopLossPrice' => false, // todo
                        'takeProfitPrice' => false, // todo
                        'attachedStopLossTakeProfit' => null,
                        'timeInForce' => array(
                            'IOC' => true,
                            'FOK' => true,
                            'PO' => true,
                            'GTD' => false,
                        ),
                        'hedged' => false,
                        'trailing' => false,
                        'leverage' => false,
                        'marketBuyByCost' => true,
                        'marketBuyRequiresPrice' => true,
                        'selfTradePrevention' => true, // todo => implement
                        'iceberg' => true, // todo implement
                    ),
                    'createOrders' => array(
                        'max' => 5,
                    ),
                    'fetchMyTrades' => array(
                        'marginMode' => true,
                        'limit' => 1000,
                        'daysBack' => null,
                        'untilDays' => 100000,
                        'symbolRequired' => true,
                    ),
                    'fetchOrder' => array(
                        'marginMode' => false,
                        'trigger' => false,
                        'trailing' => false,
                        'symbolRequired' => true,
                    ),
                    'fetchOpenOrders' => array(
                        'marginMode' => true,
                        'limit' => 1000,
                        'trigger' => true,
                        'trailing' => false,
                        'symbolRequired' => false,
                    ),
                    'fetchOrders' => null,
                    'fetchClosedOrders' => array(
                        'marginMode' => true,
                        'limit' => 1000,
                        'daysBack' => null,
                        'daysBackCanceled' => null,
                        'untilDays' => null,
                        'trigger' => true,
                        'trailing' => false,
                        'symbolRequired' => false,
                    ),
                    'fetchOHLCV' => array(
                        'limit' => 1000,
                    ),
                ),
                'forDerivatives' => array(
                    'extends' => 'spot',
                    'createOrder' => array(
                        'marginMode' => true,
                        'stopLossPrice' => true,
                        'takeProfitPrice' => true,
                    ),
                    'fetchOpenOrders' => array(
                        'marginMode' => false,
                    ),
                    'fetchClosedOrders' => array(
                        'marginMode' => false,
                    ),
                ),
                'swap' => array(
                    'linear' => array(
                        'extends' => 'forDerivatives',
                    ),
                    'inverse' => array(
                        'extends' => 'forDerivatives',
                    ),
                ),
                'future' => array(
                    'linear' => null,
                    'inverse' => null,
                ),
            ),
            'commonCurrencies' => array(
                'ACM' => 'Actinium',
            ),
            'precisionMode' => TICK_SIZE,
            'exceptions' => array(
                'exact' => array(
                    // https://github.com/coinexcom/coinex_exchange_api/wiki/013error_code
                    '23' => '\\ccxt\\PermissionDenied', // IP Prohibited
                    '24' => '\\ccxt\\AuthenticationError',
                    '25' => '\\ccxt\\AuthenticationError',
                    '34' => '\\ccxt\\AuthenticationError', // Access id is expires
                    '35' => '\\ccxt\\ExchangeNotAvailable', // Service unavailable
                    '36' => '\\ccxt\\RequestTimeout', // Service timeout
                    '213' => '\\ccxt\\RateLimitExceeded', // Too many requests
                    '107' => '\\ccxt\\InsufficientFunds',
                    '158' => '\\ccxt\\PermissionDenied', // array("code":158,"data":array(),"message":"API permission is not allowed")
                    '600' => '\\ccxt\\OrderNotFound',
                    '601' => '\\ccxt\\InvalidOrder',
                    '602' => '\\ccxt\\InvalidOrder',
                    '606' => '\\ccxt\\InvalidOrder',
                    '3008' => '\\ccxt\\RequestTimeout', // Service busy, please try again later.
                    '3109' => '\\ccxt\\InsufficientFunds', // array("code":3109,"data":array(),"message":"balance not enough")
                    '3127' => '\\ccxt\\InvalidOrder', // The order quantity is below the minimum requirement. Please adjust the order quantity.
                    '3600' => '\\ccxt\\OrderNotFound', // array("code":3600,"data":array(),"message":"Order not found")
                    '3606' => '\\ccxt\\InvalidOrder', // The price difference between the order price and the latest price is too large. Please adjust the order amount accordingly.
                    '3610' => '\\ccxt\\ExchangeError', // Order cancellation prohibited during the Call Auction period.
                    '3612' => '\\ccxt\\InvalidOrder', // The est. ask price is lower than the current bottom ask price. Please reduce the amount.
                    '3613' => '\\ccxt\\InvalidOrder', // The est. bid price is higher than the current top bid price. Please reduce the amount.
                    '3614' => '\\ccxt\\InvalidOrder', // The deviation between your est. filled price and the index price. Please reduce the amount.
                    '3615' => '\\ccxt\\InvalidOrder', // The deviation between your order price and the index price is too high. Please adjust your order price and try again.
                    '3616' => '\\ccxt\\InvalidOrder', // The order price exceeds the current top bid price. Please adjust the order price and try again.
                    '3617' => '\\ccxt\\InvalidOrder', // The order price exceeds the current bottom ask price. Please adjust the order price and try again.
                    '3618' => '\\ccxt\\InvalidOrder', // The deviation between your order price and the index price is too high. Please adjust your order price and try again.
                    '3619' => '\\ccxt\\InvalidOrder', // The deviation between your order price and the trigger price is too high. Please adjust your order price and try again.
                    '3620' => '\\ccxt\\InvalidOrder', // Market order submission is temporarily unavailable due to insufficient depth in the current market
                    '3621' => '\\ccxt\\InvalidOrder', // This order can't be completely executed and has been canceled.
                    '3622' => '\\ccxt\\InvalidOrder', // This order can't be set Only and has been canceled.
                    '3627' => '\\ccxt\\InvalidOrder', // The current market depth is low, please reduce your order amount and try again.
                    '3628' => '\\ccxt\\InvalidOrder', // The current market depth is low, please reduce your order amount and try again.
                    '3629' => '\\ccxt\\InvalidOrder', // The current market depth is low, please reduce your order amount and try again.
                    '3632' => '\\ccxt\\InvalidOrder', // The order price exceeds the current top bid price. Please adjust the order price and try again.
                    '3633' => '\\ccxt\\InvalidOrder', // The order price exceeds the current bottom ask price. Please adjust the order price and try again.
                    '3634' => '\\ccxt\\InvalidOrder', // The deviation between your est. filled price and the index price is too high. Please reduce the amount and try again.
                    '3635' => '\\ccxt\\InvalidOrder', // The deviation between your est. filled price and the index price is too high. Please reduce the amount and try again.
                    '4001' => '\\ccxt\\ExchangeNotAvailable', // Service unavailable, please try again later.
                    '4002' => '\\ccxt\\RequestTimeout', // Service request timed out, please try again later.
                    '4003' => '\\ccxt\\ExchangeError', // Internal error, please contact customer service for help.
                    '4004' => '\\ccxt\\BadRequest', // Parameter error, please check whether the request parameters are abnormal.
                    '4005' => '\\ccxt\\AuthenticationError', // Abnormal access_id, please check whether the value passed by X-COINEX-KEY is normal.
                    '4006' => '\\ccxt\\AuthenticationError', // Signature verification failed, please check the signature according to the documentation instructions.
                    '4007' => '\\ccxt\\PermissionDenied', // IP address prohibited, please check whether the whitelist or export IP is normal.
                    '4008' => '\\ccxt\\AuthenticationError', // Abnormal X-COIN-SIGN value, please check.
                    '4009' => '\\ccxt\\ExchangeError', // Abnormal request method, please check.
                    '4010' => '\\ccxt\\ExchangeError', // Expired request, please try again later.
                    '4011' => '\\ccxt\\PermissionDenied', // User prohibited from accessing, please contact customer service for help.
                    '4017' => '\\ccxt\\ExchangeError', // Signature expired, please try again later.
                    '4115' => '\\ccxt\\AccountSuspended', // User prohibited from trading, please contact customer service for help.
                    '4117' => '\\ccxt\\BadSymbol', // Trading property_exists($this, prohibited) market, please try again later.
                    '4123' => '\\ccxt\\RateLimitExceeded', // Rate limit triggered. Please adjust your strategy and reduce the request rate.
                    '4130' => '\\ccxt\\ExchangeError', // Futures trading prohibited, please try again later.
                    '4158' => '\\ccxt\\ExchangeError', // Trading prohibited, please try again later.
                    '4213' => '\\ccxt\\RateLimitExceeded', // The request is too frequent, please try again later.
                    '4512' => '\\ccxt\\PermissionDenied', // Insufficient sub-account permissions, please check.
                ),
                'broad' => array(
                    'ip not allow visit' => '\\ccxt\\PermissionDenied',
                    'service too busy' => '\\ccxt\\ExchangeNotAvailable',
                    'Service is not available during funding fee settlement' => '\\ccxt\\OperationFailed',
                ),
            ),
        ));
    }

    public function fetch_currencies($params = array ()): PromiseInterface {
        return Async\async(function () use ($params) {
            /**
             * fetches all available currencies on an exchange
             *
             * @see https://docs.coinex.com/api/v2/assets/deposit-withdrawal/http/list-all-deposit-withdrawal-config
             *
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} an associative dictionary of currencies
             */
            $response = Async\await($this->v2PublicGetAssetsAllDepositWithdrawConfig ($params));
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             {
            //                 "asset" => array(
            //                     "ccy" => "CET",
            //                     "deposit_enabled" => true,
            //                     "withdraw_enabled" => true,
            //                     "inter_transfer_enabled" => true,
            //                     "is_st" => false
            //                 ),
            //                 "chains" => array(
            //                     array(
            //                         "chain" => "CSC",
            //                         "min_deposit_amount" => "0.8",
            //                         "min_withdraw_amount" => "8",
            //                         "deposit_enabled" => true,
            //                         "withdraw_enabled" => true,
            //                         "deposit_delay_minutes" => 0,
            //                         "safe_confirmations" => 10,
            //                         "irreversible_confirmations" => 20,
            //                         "deflation_rate" => "0",
            //                         "withdrawal_fee" => "0.026",
            //                         "withdrawal_precision" => 8,
            //                         "memo" => "",
            //                         "is_memo_required_for_deposit" => false,
            //                         "explorer_asset_url" => ""
            //                     ),
            //                 )
            //             }
            //         ),
            //         "message" => "OK"
            //     }
            //
            $data = $this->safe_list($response, 'data', array());
            $result = array();
            for ($i = 0; $i < count($data); $i++) {
                $coin = $data[$i];
                $asset = $this->safe_dict($coin, 'asset', array());
                $chains = $this->safe_list($coin, 'chains', array());
                $currencyId = $this->safe_string($asset, 'ccy');
                if ($currencyId === null) {
                    continue; // coinex returns empty structures for some reason
                }
                $code = $this->safe_currency_code($currencyId);
                $canDeposit = $this->safe_bool($asset, 'deposit_enabled');
                $canWithdraw = $this->safe_bool($asset, 'withdraw_enabled');
                $firstChain = $this->safe_dict($chains, 0, array());
                $firstPrecisionString = $this->parse_precision($this->safe_string($firstChain, 'withdrawal_precision'));
                $networks = array();
                for ($j = 0; $j < count($chains); $j++) {
                    $chain = $chains[$j];
                    $networkId = $this->safe_string($chain, 'chain');
                    $networkCode = $this->network_id_to_code($networkId, $code);
                    if ($networkId === null) {
                        continue;
                    }
                    $precisionString = $this->parse_precision($this->safe_string($chain, 'withdrawal_precision'));
                    $feeString = $this->safe_string($chain, 'withdrawal_fee');
                    $minNetworkDepositString = $this->safe_string($chain, 'min_deposit_amount');
                    $minNetworkWithdrawString = $this->safe_string($chain, 'min_withdraw_amount');
                    $canDepositChain = $this->safe_bool($chain, 'deposit_enabled');
                    $canWithdrawChain = $this->safe_bool($chain, 'withdraw_enabled');
                    $network = array(
                        'id' => $networkId,
                        'network' => $networkCode,
                        'name' => null,
                        'active' => $canDepositChain && $canWithdrawChain,
                        'deposit' => $canDepositChain,
                        'withdraw' => $canWithdrawChain,
                        'fee' => $this->parse_number($feeString),
                        'precision' => $this->parse_number($precisionString),
                        'limits' => array(
                            'amount' => array(
                                'min' => null,
                                'max' => null,
                            ),
                            'deposit' => array(
                                'min' => $this->parse_number($minNetworkDepositString),
                                'max' => null,
                            ),
                            'withdraw' => array(
                                'min' => $this->parse_number($minNetworkWithdrawString),
                                'max' => null,
                            ),
                        ),
                        'info' => $chain,
                    );
                    $networks[$networkCode] = $network;
                }
                $result[$code] = $this->safe_currency_structure(array(
                    'id' => $currencyId,
                    'code' => $code,
                    'name' => null,
                    'active' => $canDeposit && $canWithdraw,
                    'deposit' => $canDeposit,
                    'withdraw' => $canWithdraw,
                    'fee' => null,
                    'precision' => $this->parse_number($firstPrecisionString),
                    'limits' => array(
                        'amount' => array(
                            'min' => null,
                            'max' => null,
                        ),
                        'deposit' => array(
                            'min' => null,
                            'max' => null,
                        ),
                        'withdraw' => array(
                            'min' => null,
                            'max' => null,
                        ),
                    ),
                    'networks' => $networks,
                    'type' => 'crypto',
                    'info' => $coin,
                ));
            }
            return $result;
        }) ();
    }

    public function fetch_markets($params = array ()): PromiseInterface {
        return Async\async(function () use ($params) {
            /**
             * retrieves data on all markets for coinex
             *
             * @see https://docs.coinex.com/api/v2/spot/market/http/list-market
             * @see https://docs.coinex.com/api/v2/futures/market/http/list-market
             *
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array[]} an array of objects representing market data
             */
            $promisesUnresolved = array(
                $this->fetch_spot_markets($params),
                $this->fetch_contract_markets($params),
            );
            $promises = Async\await(Promise\all($promisesUnresolved));
            $spotMarkets = $promises[0];
            $swapMarkets = $promises[1];
            return $this->array_concat($spotMarkets, $swapMarkets);
        }) ();
    }

    public function fetch_spot_markets($params): PromiseInterface {
        return Async\async(function () use ($params) {
            $response = Async\await($this->v2PublicGetSpotMarket ($params));
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             {
            //                 "market" => "BTCUSDT",
            //                 "taker_fee_rate" => "0.002",
            //                 "maker_fee_rate" => "0.002",
            //                 "min_amount" => "0.0005",
            //                 "base_ccy" => "BTC",
            //                 "quote_ccy" => "USDT",
            //                 "base_ccy_precision" => 8,
            //                 "quote_ccy_precision" => 2,
            //                 "is_amm_available" => true,
            //                 "is_margin_available" => true,
            //                 "is_pre_trading_available" => true,
            //                 "is_api_trading_available" => true
            //             }
            //         ),
            //         "message" => "OK"
            //     }
            //
            $markets = $this->safe_list($response, 'data', array());
            $result = array();
            for ($i = 0; $i < count($markets); $i++) {
                $market = $markets[$i];
                $id = $this->safe_string($market, 'market');
                $baseId = $this->safe_string($market, 'base_ccy');
                $quoteId = $this->safe_string($market, 'quote_ccy');
                $base = $this->safe_currency_code($baseId);
                $quote = $this->safe_currency_code($quoteId);
                $symbol = $base . '/' . $quote;
                $result[] = array(
                    'id' => $id,
                    'symbol' => $symbol,
                    'base' => $base,
                    'quote' => $quote,
                    'settle' => null,
                    'baseId' => $baseId,
                    'quoteId' => $quoteId,
                    'settleId' => null,
                    'type' => 'spot',
                    'spot' => true,
                    'margin' => $this->safe_bool($market, 'is_margin_available'),
                    'swap' => false,
                    'future' => false,
                    'option' => false,
                    'active' => $this->safe_bool($market, 'is_api_trading_available'),
                    'contract' => false,
                    'linear' => null,
                    'inverse' => null,
                    'taker' => $this->safe_number($market, 'taker_fee_rate'),
                    'maker' => $this->safe_number($market, 'maker_fee_rate'),
                    'contractSize' => null,
                    'expiry' => null,
                    'expiryDatetime' => null,
                    'strike' => null,
                    'optionType' => null,
                    'precision' => array(
                        'amount' => $this->parse_number($this->parse_precision($this->safe_string($market, 'base_ccy_precision'))),
                        'price' => $this->parse_number($this->parse_precision($this->safe_string($market, 'quote_ccy_precision'))),
                    ),
                    'limits' => array(
                        'leverage' => array(
                            'min' => null,
                            'max' => null,
                        ),
                        'amount' => array(
                            'min' => $this->safe_number($market, 'min_amount'),
                            'max' => null,
                        ),
                        'price' => array(
                            'min' => null,
                            'max' => null,
                        ),
                        'cost' => array(
                            'min' => null,
                            'max' => null,
                        ),
                    ),
                    'created' => null,
                    'info' => $market,
                );
            }
            return $result;
        }) ();
    }

    public function fetch_contract_markets($params) {
        return Async\async(function () use ($params) {
            $response = Async\await($this->v2PublicGetFuturesMarket ($params));
            //
            //     {
            //         "code" => 0,
            //         "data" => [
            //             array(
            //                 "base_ccy" => "BTC",
            //                 "base_ccy_precision" => 8,
            //                 "contract_type" => "inverse",
            //                 "leverage" => ["1","2","3","5","8","10","15","20","30","50","100"],
            //                 "maker_fee_rate" => "0",
            //                 "market" => "BTCUSD",
            //                 "min_amount" => "10",
            //                 "open_interest_volume" => "2566879",
            //                 "quote_ccy" => "USD",
            //                 "quote_ccy_precision" => 2,
            //                 "taker_fee_rate" => "0"
            //             ),
            //         ],
            //         "message" => "OK"
            //     }
            //
            $markets = $this->safe_list($response, 'data', array());
            $result = array();
            for ($i = 0; $i < count($markets); $i++) {
                $entry = $markets[$i];
                $fees = $this->fees;
                $leverages = $this->safe_list($entry, 'leverage', array());
                $subType = $this->safe_string($entry, 'contract_type');
                $linear = ($subType === 'linear');
                $inverse = ($subType === 'inverse');
                $id = $this->safe_string($entry, 'market');
                $baseId = $this->safe_string($entry, 'base_ccy');
                $quoteId = $this->safe_string($entry, 'quote_ccy');
                $base = $this->safe_currency_code($baseId);
                $quote = $this->safe_currency_code($quoteId);
                $settleId = ($subType === 'linear') ? 'USDT' : $baseId;
                $settle = $this->safe_currency_code($settleId);
                $symbol = $base . '/' . $quote . ':' . $settle;
                $leveragesLength = count($leverages);
                $result[] = array(
                    'id' => $id,
                    'symbol' => $symbol,
                    'base' => $base,
                    'quote' => $quote,
                    'settle' => $settle,
                    'baseId' => $baseId,
                    'quoteId' => $quoteId,
                    'settleId' => $settleId,
                    'type' => 'swap',
                    'spot' => false,
                    'margin' => false,
                    'swap' => true,
                    'future' => false,
                    'option' => false,
                    'active' => null,
                    'contract' => true,
                    'linear' => $linear,
                    'inverse' => $inverse,
                    'taker' => $fees['trading']['taker'],
                    'maker' => $fees['trading']['maker'],
                    'contractSize' => $this->parse_number('1'),
                    'expiry' => null,
                    'expiryDatetime' => null,
                    'strike' => null,
                    'optionType' => null,
                    'precision' => array(
                        'amount' => $this->parse_number($this->parse_precision($this->safe_string($entry, 'base_ccy_precision'))),
                        'price' => $this->parse_number($this->parse_precision($this->safe_string($entry, 'quote_ccy_precision'))),
                    ),
                    'limits' => array(
                        'leverage' => array(
                            'min' => $this->safe_number($leverages, 0),
                            'max' => $this->safe_number($leverages, $leveragesLength - 1),
                        ),
                        'amount' => array(
                            'min' => $this->safe_number($entry, 'min_amount'),
                            'max' => null,
                        ),
                        'price' => array(
                            'min' => null,
                            'max' => null,
                        ),
                        'cost' => array(
                            'min' => null,
                            'max' => null,
                        ),
                    ),
                    'created' => null,
                    'info' => $entry,
                );
            }
            return $result;
        }) ();
    }

    public function parse_ticker(array $ticker, ?array $market = null): array {
        //
        // Spot fetchTicker, fetchTickers
        //
        //     {
        //         "close" => "62393.47",
        //         "high" => "64106.41",
        //         "last" => "62393.47",
        //         "low" => "59650.01",
        //         "market" => "BTCUSDT",
        //         "open" => "61616.15",
        //         "period" => 86400,
        //         "value" => "28711273.4065667262",
        //         "volume" => "461.76557205",
        //         "volume_buy" => "11.41506354",
        //         "volume_sell" => "7.3240169"
        //     }
        //
        // Swap fetchTicker, fetchTickers
        //
        //     {
        //         "close" => "62480.08",
        //         "high" => "64100",
        //         "index_price" => "62443.05",
        //         "last" => "62480.08",
        //         "low" => "59600",
        //         "mark_price" => "62443.05",
        //         "market" => "BTCUSDT",
        //         "open" => "61679.98",
        //         "period" => 86400,
        //         "value" => "180226025.69791713065326633165",
        //         "volume" => "2900.2218",
        //         "volume_buy" => "7.3847",
        //         "volume_sell" => "6.1249"
        //     }
        //
        $marketType = (is_array($ticker) && array_key_exists('mark_price', $ticker)) ? 'swap' : 'spot';
        $marketId = $this->safe_string($ticker, 'market');
        $symbol = $this->safe_symbol($marketId, $market, null, $marketType);
        return $this->safe_ticker(array(
            'symbol' => $symbol,
            'timestamp' => null,
            'datetime' => null,
            'high' => $this->safe_string($ticker, 'high'),
            'low' => $this->safe_string($ticker, 'low'),
            'bid' => null,
            'bidVolume' => $this->safe_string($ticker, 'volume_buy'),
            'ask' => null,
            'askVolume' => $this->safe_string($ticker, 'volume_sell'),
            'vwap' => null,
            'open' => $this->safe_string($ticker, 'open'),
            'close' => $this->safe_string($ticker, 'close'),
            'last' => $this->safe_string($ticker, 'last'),
            'previousClose' => null,
            'change' => null,
            'percentage' => null,
            'average' => null,
            'baseVolume' => $this->safe_string($ticker, 'volume'),
            'quoteVolume' => null,
            'markPrice' => $this->safe_string($ticker, 'mark_price'),
            'indexPrice' => $this->safe_string($ticker, 'index_price'),
            'info' => $ticker,
        ), $market);
    }

    public function fetch_ticker(string $symbol, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $params) {
            /**
             * fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific $market
             *
             * @see https://docs.coinex.com/api/v2/spot/market/http/list-$market-ticker
             * @see https://docs.coinex.com/api/v2/futures/market/http/list-$market-ticker
             *
             * @param {string} $symbol unified $symbol of the $market to fetch the ticker for
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=ticker-structure ticker structure~
             */
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $request = array(
                'market' => $market['id'],
            );
            $response = null;
            if ($market['swap']) {
                $response = Async\await($this->v2PublicGetFuturesTicker ($this->extend($request, $params)));
            } else {
                $response = Async\await($this->v2PublicGetSpotTicker ($this->extend($request, $params)));
            }
            //
            // Spot
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             {
            //                 "close" => "62393.47",
            //                 "high" => "64106.41",
            //                 "last" => "62393.47",
            //                 "low" => "59650.01",
            //                 "market" => "BTCUSDT",
            //                 "open" => "61616.15",
            //                 "period" => 86400,
            //                 "value" => "28711273.4065667262",
            //                 "volume" => "461.76557205",
            //                 "volume_buy" => "11.41506354",
            //                 "volume_sell" => "7.3240169"
            //             }
            //         ),
            //         "message" => "OK"
            //     }
            //
            // Swap
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             {
            //                 "close" => "62480.08",
            //                 "high" => "64100",
            //                 "index_price" => "62443.05",
            //                 "last" => "62480.08",
            //                 "low" => "59600",
            //                 "mark_price" => "62443.05",
            //                 "market" => "BTCUSDT",
            //                 "open" => "61679.98",
            //                 "period" => 86400,
            //                 "value" => "180226025.69791713065326633165",
            //                 "volume" => "2900.2218",
            //                 "volume_buy" => "7.3847",
            //                 "volume_sell" => "6.1249"
            //             }
            //         ),
            //         "message" => "OK"
            //     }
            //
            $data = $this->safe_list($response, 'data', array());
            $result = $this->safe_dict($data, 0, array());
            return $this->parse_ticker($result, $market);
        }) ();
    }

    public function fetch_tickers(?array $symbols = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbols, $params) {
            /**
             * fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each $market
             *
             * @see https://docs.coinex.com/api/v2/spot/market/http/list-$market-ticker
             * @see https://docs.coinex.com/api/v2/futures/market/http/list-$market-ticker
             *
             * @param {string[]|null} $symbols unified $symbols of the markets to fetch the ticker for, all $market tickers are returned if not assigned
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} a dictionary of ~@link https://docs.ccxt.com/#/?id=ticker-structure ticker structures~
             */
            Async\await($this->load_markets());
            $symbols = $this->market_symbols($symbols);
            $market = null;
            if ($symbols !== null) {
                $symbol = $this->safe_value($symbols, 0);
                $market = $this->market($symbol);
            }
            list($marketType, $query) = $this->handle_market_type_and_params('fetchTickers', $market, $params);
            $response = null;
            if ($marketType === 'swap') {
                $response = Async\await($this->v2PublicGetFuturesTicker ($query));
            } else {
                $response = Async\await($this->v2PublicGetSpotTicker ($query));
            }
            //
            // Spot
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             {
            //                 "close" => "62393.47",
            //                 "high" => "64106.41",
            //                 "last" => "62393.47",
            //                 "low" => "59650.01",
            //                 "market" => "BTCUSDT",
            //                 "open" => "61616.15",
            //                 "period" => 86400,
            //                 "value" => "28711273.4065667262",
            //                 "volume" => "461.76557205",
            //                 "volume_buy" => "11.41506354",
            //                 "volume_sell" => "7.3240169"
            //             }
            //         ),
            //         "message" => "OK"
            //     }
            //
            // Swap
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             {
            //                 "close" => "62480.08",
            //                 "high" => "64100",
            //                 "index_price" => "62443.05",
            //                 "last" => "62480.08",
            //                 "low" => "59600",
            //                 "mark_price" => "62443.05",
            //                 "market" => "BTCUSDT",
            //                 "open" => "61679.98",
            //                 "period" => 86400,
            //                 "value" => "180226025.69791713065326633165",
            //                 "volume" => "2900.2218",
            //                 "volume_buy" => "7.3847",
            //                 "volume_sell" => "6.1249"
            //             }
            //         ),
            //         "message" => "OK"
            //     }
            //
            $data = $this->safe_list($response, 'data', array());
            return $this->parse_tickers($data, $symbols);
        }) ();
    }

    public function fetch_time($params = array ()): PromiseInterface {
        return Async\async(function () use ($params) {
            /**
             * fetches the current integer timestamp in milliseconds from the exchange server
             *
             * @see https://docs.coinex.com/api/v2/common/http/time
             *
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {int} the current integer timestamp in milliseconds from the exchange server
             */
            $response = Async\await($this->v2PublicGetTime ($params));
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             "timestamp" => 1711699867777
            //         ),
            //         "message" => "OK"
            //     }
            //
            $data = $this->safe_dict($response, 'data', array());
            return $this->safe_integer($data, 'timestamp');
        }) ();
    }

    public function fetch_order_book(string $symbol, ?int $limit = 20, $params = array ()) {
        return Async\async(function () use ($symbol, $limit, $params) {
            /**
             * fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other $data
             *
             * @see https://docs.coinex.com/api/v2/spot/market/http/list-$market-$depth
             * @see https://docs.coinex.com/api/v2/futures/market/http/list-$market-$depth
             *
             * @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 {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} A dictionary of ~@link https://docs.ccxt.com/#/?id=order-book-structure order book structures~ indexed by $market symbols
             */
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            if ($limit === null) {
                $limit = 20; // default
            }
            $request = array(
                'market' => $market['id'],
                'limit' => $limit,
                'interval' => '0',
            );
            $response = null;
            if ($market['swap']) {
                $response = Async\await($this->v2PublicGetFuturesDepth ($this->extend($request, $params)));
                //
                //     {
                //         "code" => 0,
                //         "data" => array(
                //             "depth" => array(
                //                 "asks" => [
                //                     ["70851.94", "0.2119"],
                //                     ["70851.95", "0.0004"],
                //                     ["70851.96", "0.0004"]
                //                 ],
                //                 "bids" => [
                //                     ["70851.93", "1.0314"],
                //                     ["70850.93", "0.0021"],
                //                     ["70850.42", "0.0306"]
                //                 ],
                //                 "checksum" => 2956436260,
                //                 "last" => "70851.94",
                //                 "updated_at" => 1712824003252
                //             ),
                //             "is_full" => true,
                //             "market" => "BTCUSDT"
                //         ),
                //         "message" => "OK"
                //     }
                //
            } else {
                $response = Async\await($this->v2PublicGetSpotDepth ($this->extend($request, $params)));
                //
                //     {
                //         "code" => 0,
                //         "data" => array(
                //             "depth" => array(
                //                 "asks" => [
                //                     ["70875.31", "0.28670282"],
                //                     ["70875.32", "0.31008114"],
                //                     ["70875.42", "0.05876653"]
                //                 ],
                //                 "bids" => [
                //                     ["70855.3", "0.00632222"],
                //                     ["70855.29", "0.36216834"],
                //                     ["70855.17", "0.10166802"]
                //                 ],
                //                 "checksum" => 2313816665,
                //                 "last" => "70857.19",
                //                 "updated_at" => 1712823790987
                //             ),
                //             "is_full" => true,
                //             "market" => "BTCUSDT"
                //         ),
                //         "message" => "OK"
                //     }
                //
            }
            $data = $this->safe_dict($response, 'data', array());
            $depth = $this->safe_dict($data, 'depth', array());
            $timestamp = $this->safe_integer($depth, 'updated_at');
            return $this->parse_order_book($depth, $symbol, $timestamp);
        }) ();
    }

    public function parse_trade(array $trade, ?array $market = null): array {
        //
        // Spot and Swap fetchTrades (public)
        //
        //     {
        //         "amount" => "0.00049432",
        //         "created_at" => 1713849825667,
        //         "deal_id" => 4137517302,
        //         "price" => "66251",
        //         "side" => "buy"
        //     }
        //
        // Spot and Margin fetchMyTrades (private)
        //
        //     {
        //         "amount" => "0.00010087",
        //         "created_at" => 1714618087585,
        //         "deal_id" => 4161200602,
        //         "margin_market" => "",
        //         "market" => "BTCUSDT",
        //         "order_id" => 117654919342,
        //         "price" => "57464.04",
        //         "side" => "sell"
        //     }
        //
        // Swap fetchMyTrades (private)
        //
        //     {
        //         "deal_id" => 1180222387,
        //         "created_at" => 1714119054558,
        //         "market" => "BTCUSDT",
        //         "side" => "buy",
        //         "order_id" => 136915589622,
        //         "price" => "64376",
        //         "amount" => "0.0001",
        //         "role" => "taker",
        //         "fee" => "0.0299",
        //         "fee_ccy" => "USDT"
        //     }
        //
        $timestamp = $this->safe_integer($trade, 'created_at');
        $defaultType = $this->safe_string($this->options, 'defaultType');
        if ($market !== null) {
            $defaultType = $market['type'];
        }
        $marketId = $this->safe_string($trade, 'market');
        $market = $this->safe_market($marketId, $market, null, $defaultType);
        $feeCostString = $this->safe_string($trade, 'fee');
        $fee = null;
        if ($feeCostString !== null) {
            $feeCurrencyId = $this->safe_string($trade, 'fee_ccy');
            $feeCurrencyCode = $this->safe_currency_code($feeCurrencyId);
            $fee = array(
                'cost' => $feeCostString,
                'currency' => $feeCurrencyCode,
            );
        }
        return $this->safe_trade(array(
            'info' => $trade,
            'timestamp' => $timestamp,
            'datetime' => $this->iso8601($timestamp),
            'symbol' => $market['symbol'],
            'id' => $this->safe_string($trade, 'deal_id'),
            'order' => $this->safe_string($trade, 'order_id'),
            'type' => null,
            'side' => $this->safe_string($trade, 'side'),
            'takerOrMaker' => $this->safe_string($trade, 'role'),
            'price' => $this->safe_string($trade, 'price'),
            'amount' => $this->safe_string($trade, 'amount'),
            'cost' => $this->safe_string($trade, 'deal_money'),
            'fee' => $fee,
        ), $market);
    }

    public function fetch_trades(string $symbol, ?int $since = null, ?int $limit = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $since, $limit, $params) {
            /**
             * get the list of the most recent trades for a particular $symbol
             *
             * @see https://docs.coinex.com/api/v2/spot/market/http/list-$market-deals
             * @see https://docs.coinex.com/api/v2/futures/market/http/list-$market-deals
             *
             * @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 {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {Trade[]} a list of ~@link https://docs.ccxt.com/#/?id=public-trades trade structures~
             */
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $request = array(
                'market' => $market['id'],
                // 'last_id' => 0,
            );
            if ($limit !== null) {
                $request['limit'] = $limit;
            }
            $response = null;
            if ($market['swap']) {
                $response = Async\await($this->v2PublicGetFuturesDeals ($this->extend($request, $params)));
            } else {
                $response = Async\await($this->v2PublicGetSpotDeals ($this->extend($request, $params)));
            }
            //
            // Spot and Swap
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             array(
            //                 "amount" => "0.00049432",
            //                 "created_at" => 1713849825667,
            //                 "deal_id" => 4137517302,
            //                 "price" => "66251",
            //                 "side" => "buy"
            //             ),
            //         ),
            //         "message" => "OK"
            //     }
            //
            return $this->parse_trades($response['data'], $market, $since, $limit);
        }) ();
    }

    public function fetch_trading_fee(string $symbol, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $params) {
            /**
             * fetch the trading fees for a $market
             *
             * @see https://docs.coinex.com/api/v2/spot/market/http/list-$market
             * @see https://docs.coinex.com/api/v2/futures/market/http/list-$market
             *
             * @param {string} $symbol unified $market $symbol
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=fee-structure fee structure~
             */
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $request = array(
                'market' => $market['id'],
            );
            $response = null;
            if ($market['spot']) {
                $response = Async\await($this->v2PublicGetSpotMarket ($this->extend($request, $params)));
                //
                //     {
                //         "code" => 0,
                //         "data" => array(
                //             {
                //                 "base_ccy" => "BTC",
                //                 "base_ccy_precision" => 8,
                //                 "is_amm_available" => false,
                //                 "is_margin_available" => true,
                //                 "maker_fee_rate" => "0.002",
                //                 "market" => "BTCUSDT",
                //                 "min_amount" => "0.0001",
                //                 "quote_ccy" => "USDT",
                //                 "quote_ccy_precision" => 2,
                //                 "taker_fee_rate" => "0.002"
                //             }
                //         ),
                //         "message" => "OK"
                //     }
                //
            } else {
                $response = Async\await($this->v2PublicGetFuturesMarket ($this->extend($request, $params)));
                //
                //     {
                //         "code" => 0,
                //         "data" => [
                //             {
                //                 "base_ccy" => "BTC",
                //                 "base_ccy_precision" => 8,
                //                 "contract_type" => "linear",
                //                 "leverage" => ["1","2","3","5","8","10","15","20","30","50","100"],
                //                 "maker_fee_rate" => "0",
                //                 "market" => "BTCUSDT",
                //                 "min_amount" => "0.0001",
                //                 "open_interest_volume" => "185.7498",
                //                 "quote_ccy" => "USDT",
                //                 "quote_ccy_precision" => 2,
                //                 "taker_fee_rate" => "0"
                //             }
                //         ],
                //         "message" => "OK"
                //     }
                //
            }
            $data = $this->safe_list($response, 'data', array());
            $result = $this->safe_dict($data, 0, array());
            return $this->parse_trading_fee($result, $market);
        }) ();
    }

    public function fetch_trading_fees($params = array ()): PromiseInterface {
        return Async\async(function () use ($params) {
            /**
             * fetch the trading fees for multiple markets
             *
             * @see https://docs.coinex.com/api/v2/spot/market/http/list-$market
             * @see https://docs.coinex.com/api/v2/futures/market/http/list-$market
             *
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} a dictionary of ~@link https://docs.ccxt.com/#/?id=fee-structure fee structures~ indexed by $market symbols
             */
            Async\await($this->load_markets());
            $type = null;
            list($type, $params) = $this->handle_market_type_and_params('fetchTradingFees', null, $params);
            $response = null;
            if ($type === 'swap') {
                $response = Async\await($this->v2PublicGetFuturesMarket ($params));
                //
                //     {
                //         "code" => 0,
                //         "data" => [
                //             {
                //                 "base_ccy" => "BTC",
                //                 "base_ccy_precision" => 8,
                //                 "contract_type" => "linear",
                //                 "leverage" => ["1","2","3","5","8","10","15","20","30","50","100"],
                //                 "maker_fee_rate" => "0",
                //                 "market" => "BTCUSDT",
                //                 "min_amount" => "0.0001",
                //                 "open_interest_volume" => "185.7498",
                //                 "quote_ccy" => "USDT",
                //                 "quote_ccy_precision" => 2,
                //                 "taker_fee_rate" => "0"
                //             }
                //         ],
                //         "message" => "OK"
                //     }
                //
            } else {
                $response = Async\await($this->v2PublicGetSpotMarket ($params));
                //
                //     {
                //         "code" => 0,
                //         "data" => array(
                //             array(
                //                 "base_ccy" => "BTC",
                //                 "base_ccy_precision" => 8,
                //                 "is_amm_available" => false,
                //                 "is_margin_available" => true,
                //                 "maker_fee_rate" => "0.002",
                //                 "market" => "BTCUSDT",
                //                 "min_amount" => "0.0001",
                //                 "quote_ccy" => "USDT",
                //                 "quote_ccy_precision" => 2,
                //                 "taker_fee_rate" => "0.002"
                //             ),
                //         ),
                //         "message" => "OK"
                //     }
                //
            }
            $data = $this->safe_list($response, 'data', array());
            $result = array();
            for ($i = 0; $i < count($data); $i++) {
                $entry = $data[$i];
                $marketId = $this->safe_string($entry, 'market');
                $market = $this->safe_market($marketId, null, null, $type);
                $symbol = $market['symbol'];
                $result[$symbol] = $this->parse_trading_fee($entry, $market);
            }
            return $result;
        }) ();
    }

    public function parse_trading_fee(array $fee, ?array $market = null): array {
        $marketId = $this->safe_value($fee, 'market');
        $symbol = $this->safe_symbol($marketId, $market);
        return array(
            'info' => $fee,
            'symbol' => $symbol,
            'maker' => $this->safe_number($fee, 'maker_fee_rate'),
            'taker' => $this->safe_number($fee, 'taker_fee_rate'),
            'percentage' => true,
            'tierBased' => true,
        );
    }

    public function parse_ohlcv($ohlcv, ?array $market = null): array {
        //
        //     {
        //         "close" => "66999.95",
        //         "created_at" => 1713934620000,
        //         "high" => "66999.95",
        //         "low" => "66988.53",
        //         "market" => "BTCUSDT",
        //         "open" => "66988.53",
        //         "value" => "0.1572393",        // base volume
        //         "volume" => "10533.2501364336" // quote volume
        //     }
        //
        return array(
            $this->safe_integer($ohlcv, 'created_at'),
            $this->safe_number($ohlcv, 'open'),
            $this->safe_number($ohlcv, 'high'),
            $this->safe_number($ohlcv, 'low'),
            $this->safe_number($ohlcv, 'close'),
            $this->safe_number($ohlcv, 'value'),
        );
    }

    public function fetch_ohlcv(string $symbol, $timeframe = '1m', ?int $since = null, ?int $limit = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $timeframe, $since, $limit, $params) {
            /**
             * fetches historical candlestick $data containing the open, high, low, and close price, and the volume of a $market
             *
             * @see https://docs.coinex.com/api/v2/spot/market/http/list-$market-kline
             * @see https://docs.coinex.com/api/v2/futures/market/http/list-$market-kline
             *
             * @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 {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {int[][]} A list of candles ordered, open, high, low, close, volume
             */
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $request = array(
                'market' => $market['id'],
                'period' => $this->safe_string($this->timeframes, $timeframe, $timeframe),
            );
            if ($limit !== null) {
                $request['limit'] = $limit;
            }
            $response = null;
            if ($market['swap']) {
                $response = Async\await($this->v2PublicGetFuturesKline ($this->extend($request, $params)));
            } else {
                $response = Async\await($this->v2PublicGetSpotKline ($this->extend($request, $params)));
            }
            //
            // Spot and Swap
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             array(
            //                 "close" => "66999.95",
            //                 "created_at" => 1713934620000,
            //                 "high" => "66999.95",
            //                 "low" => "66988.53",
            //                 "market" => "BTCUSDT",
            //                 "open" => "66988.53",
            //                 "value" => "0.1572393",
            //                 "volume" => "10533.2501364336"
            //             ),
            //         ),
            //         "message" => "OK"
            //     }
            //
            $data = $this->safe_list($response, 'data', array());
            return $this->parse_ohlcvs($data, $market, $timeframe, $since, $limit);
        }) ();
    }

    public function fetch_margin_balance($params = array ()) {
        return Async\async(function () use ($params) {
            Async\await($this->load_markets());
            $response = Async\await($this->v2PrivateGetAssetsMarginBalance ($params));
            //
            //     {
            //         "data" => array(
            //             array(
            //                 "margin_account" => "BTCUSDT",
            //                 "base_ccy" => "BTC",
            //                 "quote_ccy" => "USDT",
            //                 "available" => array(
            //                     "base_ccy" => "0.00000026",
            //                     "quote_ccy" => "0"
            //                 ),
            //                 "frozen" => array(
            //                     "base_ccy" => "0",
            //                     "quote_ccy" => "0"
            //                 ),
            //                 "repaid" => array(
            //                     "base_ccy" => "0",
            //                     "quote_ccy" => "0"
            //                 ),
            //                 "interest" => array(
            //                     "base_ccy" => "0",
            //                     "quote_ccy" => "0"
            //                 ),
            //                 "rik_rate" => "",
            //                 "liq_price" => ""
            //             ),
            //         ),
            //         "code" => 0,
            //         "message" => "OK"
            //     }
            //
            $result = array( 'info' => $response );
            $balances = $this->safe_list($response, 'data', array());
            for ($i = 0; $i < count($balances); $i++) {
                $entry = $balances[$i];
                $free = $this->safe_dict($entry, 'available', array());
                $used = $this->safe_dict($entry, 'frozen', array());
                $loan = $this->safe_dict($entry, 'repaid', array());
                $interest = $this->safe_dict($entry, 'interest', array());
                $baseAccount = $this->account();
                $baseCurrencyId = $this->safe_string($entry, 'base_ccy');
                $baseCurrencyCode = $this->safe_currency_code($baseCurrencyId);
                $baseAccount['free'] = $this->safe_string($free, 'base_ccy');
                $baseAccount['used'] = $this->safe_string($used, 'base_ccy');
                $baseDebt = $this->safe_string($loan, 'base_ccy');
                $baseInterest = $this->safe_string($interest, 'base_ccy');
                $baseAccount['debt'] = Precise::string_add($baseDebt, $baseInterest);
                $result[$baseCurrencyCode] = $baseAccount;
            }
            return $this->safe_balance($result);
        }) ();
    }

    public function fetch_spot_balance($params = array ()) {
        return Async\async(function () use ($params) {
            Async\await($this->load_markets());
            $response = Async\await($this->v2PrivateGetAssetsSpotBalance ($params));
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             {
            //                 "available" => "0.00000046",
            //                 "ccy" => "USDT",
            //                 "frozen" => "0"
            //             }
            //         ),
            //         "message" => "OK"
            //     }
            //
            $result = array( 'info' => $response );
            $balances = $this->safe_list($response, 'data', array());
            for ($i = 0; $i < count($balances); $i++) {
                $entry = $balances[$i];
                $currencyId = $this->safe_string($entry, 'ccy');
                $code = $this->safe_currency_code($currencyId);
                $account = $this->account();
                $account['free'] = $this->safe_string($entry, 'available');
                $account['used'] = $this->safe_string($entry, 'frozen');
                $result[$code] = $account;
            }
            return $this->safe_balance($result);
        }) ();
    }

    public function fetch_swap_balance($params = array ()) {
        return Async\async(function () use ($params) {
            Async\await($this->load_markets());
            $response = Async\await($this->v2PrivateGetAssetsFuturesBalance ($params));
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             {
            //                 "available" => "0.00000046",
            //                 "ccy" => "USDT",
            //                 "frozen" => "0",
            //                 "margin" => "0",
            //                 "transferrable" => "0.00000046",
            //                 "unrealized_pnl" => "0"
            //             }
            //         ),
            //         "message" => "OK"
            //     }
            //
            $result = array( 'info' => $response );
            $balances = $this->safe_list($response, 'data', array());
            for ($i = 0; $i < count($balances); $i++) {
                $entry = $balances[$i];
                $currencyId = $this->safe_string($entry, 'ccy');
                $code = $this->safe_currency_code($currencyId);
                $account = $this->account();
                $account['free'] = $this->safe_string($entry, 'available');
                $account['used'] = $this->safe_string($entry, 'frozen');
                $result[$code] = $account;
            }
            return $this->safe_balance($result);
        }) ();
    }

    public function fetch_financial_balance($params = array ()) {
        return Async\async(function () use ($params) {
            Async\await($this->load_markets());
            $response = Async\await($this->v2PrivateGetAssetsFinancialBalance ($params));
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             {
            //                 "available" => "0.00000046",
            //                 "ccy" => "USDT",
            //                 "frozen" => "0"
            //             }
            //         ),
            //         "message" => "OK"
            //     }
            //
            $result = array( 'info' => $response );
            $balances = $this->safe_list($response, 'data', array());
            for ($i = 0; $i < count($balances); $i++) {
                $entry = $balances[$i];
                $currencyId = $this->safe_string($entry, 'ccy');
                $code = $this->safe_currency_code($currencyId);
                $account = $this->account();
                $account['free'] = $this->safe_string($entry, 'available');
                $account['used'] = $this->safe_string($entry, 'frozen');
                $result[$code] = $account;
            }
            return $this->safe_balance($result);
        }) ();
    }

    public function fetch_balance($params = array ()): PromiseInterface {
        return Async\async(function () use ($params) {
            /**
             * query for balance and get the amount of funds available for trading or funds locked in orders
             *
             * @see https://docs.coinex.com/api/v2/assets/balance/http/get-spot-balance         // spot
             * @see https://docs.coinex.com/api/v2/assets/balance/http/get-futures-balance      // swap
             * @see https://docs.coinex.com/api/v2/assets/balance/http/get-marigin-balance      // margin
             * @see https://docs.coinex.com/api/v2/assets/balance/http/get-financial-balance    // financial
             *
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {string} [$params->type] 'margin', 'swap', 'financial', or 'spot'
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=balance-structure balance structure~
             */
            $marketType = null;
            list($marketType, $params) = $this->handle_market_type_and_params('fetchBalance', null, $params);
            $marginMode = null;
            list($marginMode, $params) = $this->handle_margin_mode_and_params('fetchBalance', $params);
            $isMargin = ($marginMode !== null) || ($marketType === 'margin');
            if ($marketType === 'swap') {
                return Async\await($this->fetch_swap_balance($params));
            } elseif ($marketType === 'financial') {
                return Async\await($this->fetch_financial_balance($params));
            } elseif ($isMargin) {
                return Async\await($this->fetch_margin_balance($params));
            } else {
                return Async\await($this->fetch_spot_balance($params));
            }
        }) ();
    }

    public function parse_order_status(?string $status) {
        $statuses = array(
            'rejected' => 'rejected',
            'open' => 'open',
            'not_deal' => 'open',
            'part_deal' => 'open',
            'done' => 'closed',
            'cancel' => 'canceled',
        );
        return $this->safe_string($statuses, $status, $status);
    }

    public function parse_order(array $order, ?array $market = null): array {
        //
        // Spot and Margin createOrder, createOrders, editOrder, cancelOrders, cancelOrder, fetchOpenOrders
        //
        //     {
        //         "amount" => "0.0001",
        //         "base_fee" => "0",
        //         "ccy" => "BTC",
        //         "client_id" => "x-167673045-a0a3c6461459a801",
        //         "created_at" => 1714114386250,
        //         "discount_fee" => "0",
        //         "filled_amount" => "0",
        //         "filled_value" => "0",
        //         "last_fill_amount" => "0",
        //         "last_fill_price" => "0",
        //         "maker_fee_rate" => "0.002",
        //         "market" => "BTCUSDT",
        //         "market_type" => "SPOT",
        //         "order_id" => 117178743547,
        //         "price" => "61000",
        //         "quote_fee" => "0",
        //         "side" => "buy",
        //         "taker_fee_rate" => "0.002",
        //         "type" => "limit",
        //         "unfilled_amount" => "0.0001",
        //         "updated_at" => 1714114386250
        //     }
        //
        // Spot and Margin fetchClosedOrders
        //
        //     {
        //         "order_id" => 117180532345,
        //         "market" => "BTCUSDT",
        //         "market_type" => "SPOT",
        //         "side" => "sell",
        //         "type" => "market",
        //         "ccy" => "BTC",
        //         "amount" => "0.00015484",
        //         "price" => "0",
        //         "client_id" => "",
        //         "created_at" => 1714116494219,
        //         "updated_at" => 0,
        //         "base_fee" => "0",
        //         "quote_fee" => "0.0199931699632",
        //         "discount_fee" => "0",
        //         "maker_fee_rate" => "0",
        //         "taker_fee_rate" => "0.002",
        //         "unfilled_amount" => "0",
        //         "filled_amount" => "0.00015484",
        //         "filled_value" => "9.9965849816"
        //     }
        //
        // Spot, Margin and Swap trigger createOrder, createOrders, editOrder
        //
        //     {
        //         "stop_id" => 117180138153
        //     }
        //
        // Swap createOrder, createOrders, editOrder, cancelOrders, cancelOrder, fetchOpenOrders, fetchClosedOrders, closePosition
        //
        //     {
        //         "amount" => "0.0001",
        //         "client_id" => "x-167673045-1471b81d747080a0",
        //         "created_at" => 1714116769986,
        //         "fee" => "0",
        //         "fee_ccy" => "USDT",
        //         "filled_amount" => "0",
        //         "filled_value" => "0",
        //         "last_filled_amount" => "0",
        //         "last_filled_price" => "0",
        //         "maker_fee_rate" => "0.0003",
        //         "market" => "BTCUSDT",
        //         "market_type" => "FUTURES",
        //         "order_id" => 136913377780,
        //         "price" => "61000.42",
        //         "realized_pnl" => "0",
        //         "side" => "buy",
        //         "taker_fee_rate" => "0.0005",
        //         "type" => "limit",
        //         "unfilled_amount" => "0.0001",
        //         "updated_at" => 1714116769986
        //     }
        //
        // Swap stopLossPrice and takeProfitPrice createOrder
        //
        //     {
        //         "adl_level" => 1,
        //         "ath_margin_size" => "2.14586666",
        //         "ath_position_amount" => "0.0001",
        //         "avg_entry_price" => "64376",
        //         "bkr_price" => "0",
        //         "close_avbl" => "0.0001",
        //         "cml_position_value" => "6.4376",
        //         "created_at" => 1714119054558,
        //         "leverage" => "3",
        //         "liq_price" => "0",
        //         "maintenance_margin_rate" => "0.005",
        //         "maintenance_margin_value" => "0.03218632",
        //         "margin_avbl" => "2.14586666",
        //         "margin_mode" => "cross",
        //         "market" => "BTCUSDT",
        //         "market_type" => "FUTURES",
        //         "max_position_value" => "6.4376",
        //         "open_interest" => "0.0001",
        //         "position_id" => 303884204,
        //         "position_margin_rate" => "3.10624785634397912265",
        //         "realized_pnl" => "-0.0032188",
        //         "settle_price" => "64376",
        //         "settle_value" => "6.4376",
        //         "side" => "long",
        //         "stop_loss_price" => "62000",
        //         "stop_loss_type" => "latest_price",
        //         "take_profit_price" => "0",
        //         "take_profit_type" => "",
        //         "unrealized_pnl" => "0",
        //         "updated_at" => 1714119054559
        //     }
        //
        // Swap fetchOrder
        //
        //     {
        //         "amount" => "0.0001",
        //         "client_id" => "x-167673045-da5f31dcd478a829",
        //         "created_at" => 1714460987164,
        //         "fee" => "0",
        //         "fee_ccy" => "USDT",
        //         "filled_amount" => "0",
        //         "filled_value" => "0",
        //         "last_filled_amount" => "0",
        //         "last_filled_price" => "0",
        //         "maker_fee_rate" => "0.0003",
        //         "market" => "BTCUSDT",
        //         "market_type" => "FUTURES",
        //         "order_id" => 137319868771,
        //         "price" => "61000",
        //         "realized_pnl" => "0",
        //         "side" => "buy",
        //         "status" => "open",
        //         "taker_fee_rate" => "0.0005",
        //         "type" => "limit",
        //         "unfilled_amount" => "0.0001",
        //         "updated_at" => 1714460987164
        //     }
        //
        // Spot and Margin fetchOrder
        //
        //     {
        //         "amount" => "0.0001",
        //         "base_fee" => "0",
        //         "ccy" => "BTC",
        //         "client_id" => "x-167673045-da918d6724e3af81",
        //         "created_at" => 1714461638958,
        //         "discount_fee" => "0",
        //         "filled_amount" => "0",
        //         "filled_value" => "0",
        //         "last_fill_amount" => "0",
        //         "last_fill_price" => "0",
        //         "maker_fee_rate" => "0.002",
        //         "market" => "BTCUSDT",
        //         "market_type" => "SPOT",
        //         "order_id" => 117492012985,
        //         "price" => "61000",
        //         "quote_fee" => "0",
        //         "side" => "buy",
        //         "status" => "open",
        //         "taker_fee_rate" => "0.002",
        //         "type" => "limit",
        //         "unfilled_amount" => "0.0001",
        //         "updated_at" => 1714461638958
        //     }
        //
        // Swap trigger fetchOpenOrders, fetchClosedOrders - Spot and Swap trigger cancelOrders, cancelOrder
        //
        //     {
        //         "amount" => "0.0001",
        //         "client_id" => "x-167673045-a7d7714c6478acf6",
        //         "created_at" => 1714187923820,
        //         "market" => "BTCUSDT",
        //         "market_type" => "FUTURES",
        //         "price" => "61000",
        //         "side" => "buy",
        //         "stop_id" => 136984426097,
        //         "trigger_direction" => "higher",
        //         "trigger_price" => "62000",
        //         "trigger_price_type" => "latest_price",
        //         "type" => "limit",
        //         "updated_at" => 1714187974363
        //     }
        //
        // Spot and Margin trigger fetchOpenOrders, fetchClosedOrders
        //
        //     {
        //         "stop_id" => 117586439530,
        //         "market" => "BTCUSDT",
        //         "market_type" => "SPOT",
        //         "ccy" => "BTC",
        //         "side" => "buy",
        //         "type" => "limit",
        //         "amount" => "0.0001",
        //         "price" => "51000",
        //         "trigger_price" => "52000",
        //         "trigger_direction" => "higher",
        //         "trigger_price_type" => "mark_price",
        //         "client_id" => "x-167673045-df61777094c69312",
        //         "created_at" => 1714551237335,
        //         "updated_at" => 1714551237335
        //     }
        //
        $rawStatus = $this->safe_string($order, 'status');
        $timestamp = $this->safe_integer($order, 'created_at');
        $updatedTimestamp = $this->safe_integer($order, 'updated_at');
        if ($updatedTimestamp === 0) {
            $updatedTimestamp = $timestamp;
        }
        $marketId = $this->safe_string($order, 'market');
        $defaultType = $this->safe_string($this->options, 'defaultType');
        $orderType = $this->safe_string_lower($order, 'market_type', $defaultType);
        if ($orderType === 'futures') {
            $orderType = 'swap';
        }
        $marketType = ($orderType === 'swap') ? 'swap' : 'spot';
        $market = $this->safe_market($marketId, $market, null, $marketType);
        $feeCurrencyId = $this->safe_string($order, 'fee_ccy');
        $feeCurrency = $this->safe_currency_code($feeCurrencyId);
        if ($feeCurrency === null) {
            $feeCurrency = $market['quote'];
        }
        $side = $this->safe_string($order, 'side');
        if ($side === 'long') {
            $side = 'buy';
        } elseif ($side === 'short') {
            $side = 'sell';
        }
        $clientOrderId = $this->safe_string($order, 'client_id');
        if ($clientOrderId === '') {
            $clientOrderId = null;
        }
        return $this->safe_order(array(
            'id' => $this->safe_string_n($order, array( 'position_id', 'order_id', 'stop_id' )),
            'clientOrderId' => $clientOrderId,
            'datetime' => $this->iso8601($timestamp),
            'timestamp' => $timestamp,
            'lastTradeTimestamp' => $updatedTimestamp,
            'status' => $this->parse_order_status($rawStatus),
            'symbol' => $market['symbol'],
            'type' => $this->safe_string($order, 'type'),
            'timeInForce' => null,
            'postOnly' => null,
            'reduceOnly' => null,
            'side' => $side,
            'price' => $this->safe_string($order, 'price'),
            'triggerPrice' => $this->safe_string($order, 'trigger_price'),
            'takeProfitPrice' => $this->safe_number($order, 'take_profit_price'),
            'stopLossPrice' => $this->safe_number($order, 'stop_loss_price'),
            'cost' => $this->safe_string($order, 'filled_value'),
            'average' => $this->safe_string($order, 'avg_entry_price'),
            'amount' => $this->safe_string($order, 'amount'),
            'filled' => $this->safe_string($order, 'filled_amount'),
            'remaining' => $this->safe_string($order, 'unfilled_amount'),
            'trades' => null,
            'fee' => array(
                'currency' => $feeCurrency,
                'cost' => $this->safe_string_2($order, 'quote_fee', 'fee'),
            ),
            'info' => $order,
        ), $market);
    }

    public function create_market_buy_order_with_cost(string $symbol, float $cost, $params = array ()) {
        return Async\async(function () use ($symbol, $cost, $params) {
            /**
             * create a $market buy order by providing the $symbol and $cost
             *
             * @see https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot003_trade003_market_order
             * @see https://docs.coinex.com/api/v2/spot/order/http/put-order
             *
             * @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 {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} an ~@link https://docs.ccxt.com/#/?id=order-structure order structure~
             */
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            if (!$market['spot']) {
                throw new NotSupported($this->id . ' createMarketBuyOrderWithCost() supports spot orders only');
            }
            $params['createMarketBuyOrderRequiresPrice'] = false;
            return Async\await($this->create_order($symbol, 'market', 'buy', $cost, null, $params));
        }) ();
    }

    public function create_order_request(string $symbol, string $type, string $side, float $amount, ?float $price = null, $params = array ()) {
        $market = $this->market($symbol);
        $swap = $market['swap'];
        $clientOrderId = $this->safe_string_2($params, 'client_id', 'clientOrderId');
        $triggerPrice = $this->safe_string_2($params, 'stopPrice', 'triggerPrice');
        $stopLossPrice = $this->safe_string($params, 'stopLossPrice');
        $takeProfitPrice = $this->safe_string($params, 'takeProfitPrice');
        $option = $this->safe_string($params, 'option');
        $isMarketOrder = $type === 'market';
        $postOnly = $this->is_post_only($isMarketOrder, $option === 'maker_only', $params);
        $timeInForceRaw = $this->safe_string_upper($params, 'timeInForce');
        $reduceOnly = $this->safe_bool($params, 'reduceOnly');
        if ($reduceOnly) {
            if (!$market['swap']) {
                throw new InvalidOrder($this->id . ' createOrder() does not support $reduceOnly for ' . $market['type'] . ' orders, $reduceOnly orders are supported for $swap markets only');
            }
        }
        $request = array(
            'market' => $market['id'],
        );
        if ($clientOrderId === null) {
            $defaultId = 'x-167673045';
            $brokerId = $this->safe_string($this->options, 'brokerId', $defaultId);
            $request['client_id'] = $brokerId . '-' . $this->uuid16();
        } else {
            $request['client_id'] = $clientOrderId;
        }
        if (($stopLossPrice === null) && ($takeProfitPrice === null)) {
            if (!$reduceOnly) {
                $request['side'] = $side;
            }
            $requestType = $type;
            if ($postOnly) {
                $requestType = 'maker_only';
            } elseif ($timeInForceRaw !== null) {
                if ($timeInForceRaw === 'IOC') {
                    $requestType = 'ioc';
                } elseif ($timeInForceRaw === 'FOK') {
                    $requestType = 'fok';
                }
            }
            if (!$isMarketOrder) {
                $request['price'] = $this->price_to_precision($symbol, $price);
            }
            $request['type'] = $requestType;
        }
        if ($swap) {
            $request['market_type'] = 'FUTURES';
            if ($stopLossPrice || $takeProfitPrice) {
                if ($stopLossPrice) {
                    $request['stop_loss_price'] = $this->price_to_precision($symbol, $stopLossPrice);
                    $request['stop_loss_type'] = $this->safe_string($params, 'stop_type', 'latest_price');
                } elseif ($takeProfitPrice) {
                    $request['take_profit_price'] = $this->price_to_precision($symbol, $takeProfitPrice);
                    $request['take_profit_type'] = $this->safe_string($params, 'stop_type', 'latest_price');
                }
            } else {
                $request['amount'] = $this->amount_to_precision($symbol, $amount);
                if ($triggerPrice !== null) {
                    $request['trigger_price'] = $this->price_to_precision($symbol, $triggerPrice);
                    $request['trigger_price_type'] = $this->safe_string($params, 'stop_type', 'latest_price');
                }
            }
        } else {
            $marginMode = null;
            list($marginMode, $params) = $this->handle_margin_mode_and_params('createOrder', $params);
            if ($marginMode !== null) {
                $request['market_type'] = 'MARGIN';
            } else {
                $request['market_type'] = 'SPOT';
            }
            if (($type === 'market') && ($side === 'buy')) {
                $createMarketBuyOrderRequiresPrice = true;
                list($createMarketBuyOrderRequiresPrice, $params) = $this->handle_option_and_params($params, 'createOrder', 'createMarketBuyOrderRequiresPrice', true);
                $cost = $this->safe_number($params, 'cost');
                $params = $this->omit($params, 'cost');
                if ($createMarketBuyOrderRequiresPrice) {
                    if (($price === null) && ($cost === null)) {
                        throw new InvalidOrder($this->id . ' createOrder() requires the $price argument for $market buy orders to calculate the total $cost to spend ($amount * $price), alternatively set the $createMarketBuyOrderRequiresPrice $option or param to false and pass the $cost to spend in the $amount argument');
                    } else {
                        $amountString = $this->number_to_string($amount);
                        $priceString = $this->number_to_string($price);
                        $quoteAmount = $this->parse_to_numeric(Precise::string_mul($amountString, $priceString));
                        $costRequest = ($cost !== null) ? $cost : $quoteAmount;
                        $request['amount'] = $this->cost_to_precision($symbol, $costRequest);
                    }
                } else {
                    $request['amount'] = $this->cost_to_precision($symbol, $amount);
                }
            } else {
                $request['amount'] = $this->amount_to_precision($symbol, $amount);
            }
            if ($triggerPrice !== null) {
                $request['trigger_price'] = $this->price_to_precision($symbol, $triggerPrice);
            }
        }
        $params = $this->omit($params, array( 'reduceOnly', 'timeInForce', 'postOnly', 'stopPrice', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice' ));
        return $this->extend($request, $params);
    }

    public function create_order(string $symbol, string $type, string $side, float $amount, ?float $price = null, $params = array ()) {
        return Async\async(function () use ($symbol, $type, $side, $amount, $price, $params) {
            /**
             * create a trade order
             *
             * @see https://docs.coinex.com/api/v2/spot/order/http/put-order
             * @see https://docs.coinex.com/api/v2/spot/order/http/put-stop-order
             * @see https://docs.coinex.com/api/v2/futures/order/http/put-order
             * @see https://docs.coinex.com/api/v2/futures/order/http/put-stop-order
             * @see https://docs.coinex.com/api/v2/futures/position/http/close-position
             * @see https://docs.coinex.com/api/v2/futures/position/http/set-position-stop-loss
             * @see https://docs.coinex.com/api/v2/futures/position/http/set-position-take-profit
             *
             * @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 you want to trade in units of the base currency
             * @param {float} [$price] the $price at which the order is to be fulfilled, in units of the quote currency, ignored in $market orders
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {float} [$params->triggerPrice] $price to trigger stop orders
             * @param {float} [$params->stopLossPrice] $price to trigger stop loss orders
             * @param {float} [$params->takeProfitPrice] $price to trigger take profit orders
             * @param {string} [$params->timeInForce] 'GTC', 'IOC', 'FOK', 'PO'
             * @param {boolean} [$params->postOnly] set to true if you wish to make a post only order
             * @param {boolean} [$params->reduceOnly] *contract only* indicates if this order is to reduce the size of a position
             * @return {array} an ~@link https://docs.ccxt.com/#/?id=order-structure order structure~
             */
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $reduceOnly = $this->safe_bool($params, 'reduceOnly');
            $triggerPrice = $this->safe_string_2($params, 'stopPrice', 'triggerPrice');
            $stopLossTriggerPrice = $this->safe_string($params, 'stopLossPrice');
            $takeProfitTriggerPrice = $this->safe_string($params, 'takeProfitPrice');
            $isTriggerOrder = $triggerPrice !== null;
            $isStopLossTriggerOrder = $stopLossTriggerPrice !== null;
            $isTakeProfitTriggerOrder = $takeProfitTriggerPrice !== null;
            $isStopLossOrTakeProfitTrigger = $isStopLossTriggerOrder || $isTakeProfitTriggerOrder;
            $request = $this->create_order_request($symbol, $type, $side, $amount, $price, $params);
            $response = null;
            if ($market['spot']) {
                if ($isTriggerOrder) {
                    $response = Async\await($this->v2PrivatePostSpotStopOrder ($request));
                    //
                    //     {
                    //         "code" => 0,
                    //         "data" => array(
                    //             "stop_id" => 117180138153
                    //         ),
                    //         "message" => "OK"
                    //     }
                    //
                } else {
                    $response = Async\await($this->v2PrivatePostSpotOrder ($request));
                    //
                    //     {
                    //         "code" => 0,
                    //         "data" => array(
                    //             "amount" => "0.0001",
                    //             "base_fee" => "0",
                    //             "ccy" => "BTC",
                    //             "client_id" => "x-167673045-a0a3c6461459a801",
                    //             "created_at" => 1714114386250,
                    //             "discount_fee" => "0",
                    //             "filled_amount" => "0",
                    //             "filled_value" => "0",
                    //             "last_fill_amount" => "0",
                    //             "last_fill_price" => "0",
                    //             "maker_fee_rate" => "0.002",
                    //             "market" => "BTCUSDT",
                    //             "market_type" => "SPOT",
                    //             "order_id" => 117178743547,
                    //             "price" => "61000",
                    //             "quote_fee" => "0",
                    //             "side" => "buy",
                    //             "taker_fee_rate" => "0.002",
                    //             "type" => "limit",
                    //             "unfilled_amount" => "0.0001",
                    //             "updated_at" => 1714114386250
                    //         ),
                    //         "message" => "OK"
                    //     }
                    //
                }
            } else {
                if ($isTriggerOrder) {
                    $response = Async\await($this->v2PrivatePostFuturesStopOrder ($request));
                    //
                    //     {
                    //         "code" => 0,
                    //         "data" => array(
                    //             "stop_id" => 136915460994
                    //         ),
                    //         "message" => "OK"
                    //     }
                    //
                } elseif ($isStopLossOrTakeProfitTrigger) {
                    if ($isStopLossTriggerOrder) {
                        $response = Async\await($this->v2PrivatePostFuturesSetPositionStopLoss ($request));
                        //
                        //     {
                        //         "code" => 0,
                        //         "data" => array(
                        //             "adl_level" => 1,
                        //             "ath_margin_size" => "2.14586666",
                        //             "ath_position_amount" => "0.0001",
                        //             "avg_entry_price" => "64376",
                        //             "bkr_price" => "0",
                        //             "close_avbl" => "0.0001",
                        //             "cml_position_value" => "6.4376",
                        //             "created_at" => 1714119054558,
                        //             "leverage" => "3",
                        //             "liq_price" => "0",
                        //             "maintenance_margin_rate" => "0.005",
                        //             "maintenance_margin_value" => "0.03218632",
                        //             "margin_avbl" => "2.14586666",
                        //             "margin_mode" => "cross",
                        //             "market" => "BTCUSDT",
                        //             "market_type" => "FUTURES",
                        //             "max_position_value" => "6.4376",
                        //             "open_interest" => "0.0001",
                        //             "position_id" => 303884204,
                        //             "position_margin_rate" => "3.10624785634397912265",
                        //             "realized_pnl" => "-0.0032188",
                        //             "settle_price" => "64376",
                        //             "settle_value" => "6.4376",
                        //             "side" => "long",
                        //             "stop_loss_price" => "62000",
                        //             "stop_loss_type" => "latest_price",
                        //             "take_profit_price" => "0",
                        //             "take_profit_type" => "",
                        //             "unrealized_pnl" => "0",
                        //             "updated_at" => 1714119054559
                        //         ),
                        //         "message" => "OK"
                        //     }
                        //
                    } elseif ($isTakeProfitTriggerOrder) {
                        $response = Async\await($this->v2PrivatePostFuturesSetPositionTakeProfit ($request));
                        //
                        //     {
                        //         "code" => 0,
                        //         "data" => array(
                        //             "adl_level" => 1,
                        //             "ath_margin_size" => "2.14586666",
                        //             "ath_position_amount" => "0.0001",
                        //             "avg_entry_price" => "64376",
                        //             "bkr_price" => "0",
                        //             "close_avbl" => "0.0001",
                        //             "cml_position_value" => "6.4376",
                        //             "created_at" => 1714119054558,
                        //             "leverage" => "3",
                        //             "liq_price" => "0",
                        //             "maintenance_margin_rate" => "0.005",
                        //             "maintenance_margin_value" => "0.03218632",
                        //             "margin_avbl" => "2.14586666",
                        //             "margin_mode" => "cross",
                        //             "market" => "BTCUSDT",
                        //             "market_type" => "FUTURES",
                        //             "max_position_value" => "6.4376",
                        //             "open_interest" => "0.0001",
                        //             "position_id" => 303884204,
                        //             "position_margin_rate" => "3.10624785634397912265",
                        //             "realized_pnl" => "-0.0032188",
                        //             "settle_price" => "64376",
                        //             "settle_value" => "6.4376",
                        //             "side" => "long",
                        //             "stop_loss_price" => "62000",
                        //             "stop_loss_type" => "latest_price",
                        //             "take_profit_price" => "70000",
                        //             "take_profit_type" => "latest_price",
                        //             "unrealized_pnl" => "0",
                        //             "updated_at" => 1714119054559
                        //         ),
                        //         "message" => "OK"
                        //     }
                        //
                    }
                } else {
                    if ($reduceOnly) {
                        $response = Async\await($this->v2PrivatePostFuturesClosePosition ($request));
                        //
                        //     {
                        //         "code" => 0,
                        //         "data" => array(
                        //             "amount" => "0.0001",
                        //             "client_id" => "x-167673045-4f264600c432ac06",
                        //             "created_at" => 1714119323764,
                        //             "fee" => "0.003221",
                        //             "fee_ccy" => "USDT",
                        //             "filled_amount" => "0.0001",
                        //             "filled_value" => "6.442017",
                        //             "last_filled_amount" => "0.0001",
                        //             "last_filled_price" => "64420.17",
                        //             "maker_fee_rate" => "0",
                        //             "market" => "BTCUSDT",
                        //             "market_type" => "FUTURES",
                        //             "order_id" => 136915813578,
                        //             "price" => "0",
                        //             "realized_pnl" => "0.004417",
                        //             "side" => "sell",
                        //             "taker_fee_rate" => "0.0005",
                        //             "type" => "market",
                        //             "unfilled_amount" => "0",
                        //             "updated_at" => 1714119323764
                        //         ),
                        //         "message" => "OK"
                        //     }
                        //
                    } else {
                        $response = Async\await($this->v2PrivatePostFuturesOrder ($request));
                        //
                        //     {
                        //         "code" => 0,
                        //         "data" => array(
                        //             "amount" => "0.0001",
                        //             "client_id" => "x-167673045-1471b81d747080a0",
                        //             "created_at" => 1714116769986,
                        //             "fee" => "0",
                        //             "fee_ccy" => "USDT",
                        //             "filled_amount" => "0",
                        //             "filled_value" => "0",
                        //             "last_filled_amount" => "0",
                        //             "last_filled_price" => "0",
                        //             "maker_fee_rate" => "0.0003",
                        //             "market" => "BTCUSDT",
                        //             "market_type" => "FUTURES",
                        //             "order_id" => 136913377780,
                        //             "price" => "61000.42",
                        //             "realized_pnl" => "0",
                        //             "side" => "buy",
                        //             "taker_fee_rate" => "0.0005",
                        //             "type" => "limit",
                        //             "unfilled_amount" => "0.0001",
                        //             "updated_at" => 1714116769986
                        //         ),
                        //         "message" => "OK"
                        //     }
                        //
                    }
                }
            }
            $data = $this->safe_dict($response, 'data', array());
            return $this->parse_order($data, $market);
        }) ();
    }

    public function create_orders(array $orders, $params = array ()): PromiseInterface {
        return Async\async(function () use ($orders, $params) {
            /**
             * create a list of trade $orders (all $orders should be of the same $symbol)
             *
             * @see https://docs.coinex.com/api/v2/spot/order/http/put-multi-$order
             * @see https://docs.coinex.com/api/v2/spot/order/http/put-multi-stop-$order
             * @see https://docs.coinex.com/api/v2/futures/order/http/put-multi-$order
             * @see https://docs.coinex.com/api/v2/futures/order/http/put-multi-stop-$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 {array} [$params] extra parameters specific to the api endpoint
             * @return {array} an ~@link https://docs.ccxt.com/#/?id=$order-structure $order structure~
             */
            Async\await($this->load_markets());
            $ordersRequests = array();
            $symbol = null;
            $reduceOnly = false;
            $isTriggerOrder = false;
            $isStopLossOrTakeProfitTrigger = false;
            for ($i = 0; $i < count($orders); $i++) {
                $rawOrder = $orders[$i];
                $marketId = $this->safe_string($rawOrder, 'symbol');
                if ($symbol === null) {
                    $symbol = $marketId;
                } else {
                    if ($symbol !== $marketId) {
                        throw new BadRequest($this->id . ' createOrders() requires all $orders to have the same symbol');
                    }
                }
                $type = $this->safe_string($rawOrder, 'type');
                $side = $this->safe_string($rawOrder, 'side');
                $amount = $this->safe_value($rawOrder, 'amount');
                $price = $this->safe_value($rawOrder, 'price');
                $orderParams = $this->safe_value($rawOrder, 'params', array());
                if ($type !== 'limit') {
                    throw new NotSupported($this->id . ' createOrders() does not support ' . $type . ' $orders, only limit $orders are accepted');
                }
                $reduceOnly = $this->safe_value($orderParams, 'reduceOnly');
                $triggerPrice = $this->safe_number_2($orderParams, 'stopPrice', 'triggerPrice');
                $stopLossTriggerPrice = $this->safe_number($orderParams, 'stopLossPrice');
                $takeProfitTriggerPrice = $this->safe_number($orderParams, 'takeProfitPrice');
                $isTriggerOrder = $triggerPrice !== null;
                $isStopLossTriggerOrder = $stopLossTriggerPrice !== null;
                $isTakeProfitTriggerOrder = $takeProfitTriggerPrice !== null;
                $isStopLossOrTakeProfitTrigger = $isStopLossTriggerOrder || $isTakeProfitTriggerOrder;
                $orderRequest = $this->create_order_request($marketId, $type, $side, $amount, $price, $orderParams);
                $ordersRequests[] = $orderRequest;
            }
            $market = $this->market($symbol);
            $request = array(
                'market' => $market['id'],
                'orders' => $ordersRequests,
            );
            $response = null;
            if ($market['spot']) {
                if ($isTriggerOrder) {
                    $response = Async\await($this->v2PrivatePostSpotBatchStopOrder ($request));
                    //
                    //     {
                    //         "code" => 0,
                    //         "data" => array(
                    //             array(
                    //                 "code" => 0,
                    //                 "data" => array(
                    //                     "stop_id" => 117186257510
                    //                 ),
                    //                 "message" => "OK"
                    //             ),
                    //         ),
                    //         "message" => "OK"
                    //     }
                    //
                } else {
                    $response = Async\await($this->v2PrivatePostSpotBatchOrder ($request));
                    //
                    //     {
                    //         "code" => 0,
                    //         "data" => array(
                    //             array(
                    //                 "amount" => "0.0001",
                    //                 "base_fee" => "0",
                    //                 "ccy" => "BTC",
                    //                 "client_id" => "x-167673045-f3651372049dab0d",
                    //                 "created_at" => 1714121403450,
                    //                 "discount_fee" => "0",
                    //                 "filled_amount" => "0",
                    //                 "filled_value" => "0",
                    //                 "last_fill_amount" => "0",
                    //                 "last_fill_price" => "0",
                    //                 "maker_fee_rate" => "0.002",
                    //                 "market" => "BTCUSDT",
                    //                 "market_type" => "SPOT",
                    //                 "order_id" => 117185362233,
                    //                 "price" => "61000",
                    //                 "quote_fee" => "0",
                    //                 "side" => "buy",
                    //                 "taker_fee_rate" => "0.002",
                    //                 "type" => "limit",
                    //                 "unfilled_amount" => "0.0001",
                    //                 "updated_at" => 1714121403450
                    //             ),
                    //             {
                    //                 "code" => 3109,
                    //                 "data" => null,
                    //                 "message" => "balance not enough"
                    //             }
                    //         ),
                    //         "message" => "OK"
                    //     }
                    //
                }
            } else {
                if ($isTriggerOrder) {
                    $response = Async\await($this->v2PrivatePostFuturesBatchStopOrder ($request));
                    //
                    //     {
                    //         "code" => 0,
                    //         "data" => array(
                    //             array(
                    //                 "code" => 0,
                    //                 "data" => array(
                    //                     "stop_id" => 136919625994
                    //                 ),
                    //                 "message" => "OK"
                    //             ),
                    //         ),
                    //         "message" => "OK"
                    //     }
                    //
                } elseif ($isStopLossOrTakeProfitTrigger) {
                    throw new NotSupported($this->id . ' createOrders() does not support stopLossPrice or takeProfitPrice orders');
                } else {
                    if ($reduceOnly) {
                        throw new NotSupported($this->id . ' createOrders() does not support $reduceOnly orders');
                    } else {
                        $response = Async\await($this->v2PrivatePostFuturesBatchOrder ($request));
                        //
                        //     {
                        //         "code" => 0,
                        //         "data" => array(
                        //             array(
                        //                 "code" => 0,
                        //                 "data" => array(
                        //                     "amount" => "0.0001",
                        //                     "client_id" => "x-167673045-2cb7436f3462a654",
                        //                     "created_at" => 1714122832493,
                        //                     "fee" => "0",
                        //                     "fee_ccy" => "USDT",
                        //                     "filled_amount" => "0",
                        //                     "filled_value" => "0",
                        //                     "last_filled_amount" => "0",
                        //                     "last_filled_price" => "0",
                        //                     "maker_fee_rate" => "0.0003",
                        //                     "market" => "BTCUSDT",
                        //                     "market_type" => "FUTURES",
                        //                     "order_id" => 136918835063,
                        //                     "price" => "61000",
                        //                     "realized_pnl" => "0",
                        //                     "side" => "buy",
                        //                     "taker_fee_rate" => "0.0005",
                        //                     "type" => "limit",
                        //                     "unfilled_amount" => "0.0001",
                        //                     "updated_at" => 1714122832493
                        //                 ),
                        //                 "message" => "OK"
                        //             ),
                        //         ),
                        //         "message" => "OK"
                        //     }
                        //
                    }
                }
            }
            $data = $this->safe_list($response, 'data', array());
            $results = array();
            for ($i = 0; $i < count($data); $i++) {
                $entry = $data[$i];
                $status = null;
                $code = $this->safe_integer($entry, 'code');
                if ($code !== null) {
                    if ($code !== 0) {
                        $status = 'rejected';
                    } else {
                        $status = 'open';
                    }
                }
                $innerData = $this->safe_dict($entry, 'data', array());
                $order = null;
                if ($market['spot'] && !$isTriggerOrder) {
                    $entry['status'] = $status;
                    $order = $this->parse_order($entry, $market);
                } else {
                    $innerData['status'] = $status;
                    $order = $this->parse_order($innerData, $market);
                }
                $results[] = $order;
            }
            return $results;
        }) ();
    }

    public function cancel_orders($ids, ?string $symbol = null, $params = array ()) {
        return Async\async(function () use ($ids, $symbol, $params) {
            /**
             * cancel multiple orders
             *
             * @see https://docs.coinex.com/api/v2/spot/order/http/cancel-batch-$order
             * @see https://docs.coinex.com/api/v2/spot/order/http/cancel-batch-stop-$order
             * @see https://docs.coinex.com/api/v2/futures/order/http/cancel-batch-$order
             * @see https://docs.coinex.com/api/v2/futures/order/http/cancel-batch-stop-$order
             *
             * @param {string[]} $ids $order $ids
             * @param {string} $symbol unified $market $symbol
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {boolean} [$params->trigger] set to true for canceling stop orders
             * @return {array} a list of ~@link https://docs.ccxt.com/#/?id=$order-structure $order structures~
             */
            if ($symbol === null) {
                throw new ArgumentsRequired($this->id . ' cancelOrders() requires a $symbol argument');
            }
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $request = array(
                'market' => $market['id'],
            );
            $trigger = $this->safe_bool_2($params, 'stop', 'trigger');
            $params = $this->omit($params, array( 'stop', 'trigger' ));
            $response = null;
            $requestIds = array();
            for ($i = 0; $i < count($ids); $i++) {
                $requestIds[] = intval($ids[$i]);
            }
            if ($trigger) {
                $request['stop_ids'] = $requestIds;
            } else {
                $request['order_ids'] = $requestIds;
            }
            if ($market['spot']) {
                if ($trigger) {
                    $response = Async\await($this->v2PrivatePostSpotCancelBatchStopOrder ($this->extend($request, $params)));
                    //
                    //     {
                    //         "code" => 0,
                    //         "data" => array(
                    //             array(
                    //                 "code" => 0,
                    //                 "data" => array(
                    //                     "amount" => "0.0001",
                    //                     "ccy" => "BTC",
                    //                     "client_id" => "x-167673045-8e33d6f4a4bcb022",
                    //                     "created_at" => 1714188827291,
                    //                     "market" => "BTCUSDT",
                    //                     "market_type" => "SPOT",
                    //                     "price" => "61000",
                    //                     "side" => "buy",
                    //                     "stop_id" => 117248845854,
                    //                     "trigger_direction" => "higher",
                    //                     "trigger_price" => "62000",
                    //                     "trigger_price_type" => "mark_price",
                    //                     "type" => "limit",
                    //                     "updated_at" => 1714188827291
                    //                 ),
                    //                 "message" => "OK"
                    //             ),
                    //         ),
                    //         "message" => "OK"
                    //     }
                    //
                } else {
                    $response = Async\await($this->v2PrivatePostSpotCancelBatchOrder ($this->extend($request, $params)));
                    //
                    //     {
                    //         "code" => 0,
                    //         "data" => array(
                    //             array(
                    //                 "code" => 0,
                    //                 "data" => array(
                    //                     "amount" => "0.0001",
                    //                     "base_fee" => "0",
                    //                     "ccy" => "BTC",
                    //                     "client_id" => "x-167673045-c1cc78e5b42d8c4e",
                    //                     "created_at" => 1714188449497,
                    //                     "discount_fee" => "0",
                    //                     "filled_amount" => "0",
                    //                     "filled_value" => "0",
                    //                     "last_fill_amount" => "0",
                    //                     "last_fill_price" => "0",
                    //                     "maker_fee_rate" => "0.002",
                    //                     "market" => "BTCUSDT",
                    //                     "market_type" => "SPOT",
                    //                     "order_id" => 117248494358,
                    //                     "price" => "60000",
                    //                     "quote_fee" => "0",
                    //                     "side" => "buy",
                    //                     "taker_fee_rate" => "0.002",
                    //                     "type" => "limit",
                    //                     "unfilled_amount" => "0.0001",
                    //                     "updated_at" => 1714188449497
                    //                 ),
                    //                 "message" => ""
                    //             ),
                    //         ),
                    //         "message" => "OK"
                    //     }
                    //
                }
            } else {
                $request['market_type'] = 'FUTURES';
                if ($trigger) {
                    $response = Async\await($this->v2PrivatePostFuturesCancelBatchStopOrder ($this->extend($request, $params)));
                    //
                    //     {
                    //         "code" => 0,
                    //         "data" => array(
                    //             array(
                    //                 "code" => 0,
                    //                 "data" => array(
                    //                     "amount" => "0.0001",
                    //                     "client_id" => "x-167673045-a7d7714c6478acf6",
                    //                     "created_at" => 1714187923820,
                    //                     "market" => "BTCUSDT",
                    //                     "market_type" => "FUTURES",
                    //                     "price" => "61000",
                    //                     "side" => "buy",
                    //                     "stop_id" => 136984426097,
                    //                     "trigger_direction" => "higher",
                    //                     "trigger_price" => "62000",
                    //                     "trigger_price_type" => "latest_price",
                    //                     "type" => "limit",
                    //                     "updated_at" => 1714187974363
                    //                 ),
                    //                 "message" => ""
                    //             ),
                    //         ),
                    //         "message" => "OK"
                    //     }
                    //
                } else {
                    $response = Async\await($this->v2PrivatePostFuturesCancelBatchOrder ($this->extend($request, $params)));
                    //
                    //     {
                    //         "code" => 0,
                    //         "data" => array(
                    //             array(
                    //                 "code" => 0,
                    //                 "data" => array(
                    //                     "amount" => "0.0001",
                    //                     "client_id" => "x-167673045-9f80fde284339a72",
                    //                     "created_at" => 1714187491784,
                    //                     "fee" => "0",
                    //                     "fee_ccy" => "USDT",
                    //                     "filled_amount" => "0",
                    //                     "filled_value" => "0",
                    //                     "last_filled_amount" => "0",
                    //                     "last_filled_price" => "0",
                    //                     "maker_fee_rate" => "0.0003",
                    //                     "market" => "BTCUSDT",
                    //                     "market_type" => "FUTURES",
                    //                     "order_id" => 136983851788,
                    //                     "price" => "61000",
                    //                     "realized_pnl" => "0",
                    //                     "side" => "buy",
                    //                     "taker_fee_rate" => "0.0005",
                    //                     "type" => "limit",
                    //                     "unfilled_amount" => "0.0001",
                    //                     "updated_at" => 1714187567079
                    //                 ),
                    //                 "message" => ""
                    //             ),
                    //         ),
                    //         "message" => "OK"
                    //     }
                    //
                }
            }
            $data = $this->safe_list($response, 'data', array());
            $results = array();
            for ($i = 0; $i < count($data); $i++) {
                $entry = $data[$i];
                $item = $this->safe_dict($entry, 'data', array());
                $order = $this->parse_order($item, $market);
                $results[] = $order;
            }
            return $results;
        }) ();
    }

    public function edit_order(string $id, string $symbol, string $type, string $side, ?float $amount = null, ?float $price = null, $params = array ()) {
        return Async\async(function () use ($id, $symbol, $type, $side, $amount, $price, $params) {
            /**
             * edit a trade order
             *
             * @see https://docs.coinex.com/api/v2/spot/order/http/edit-order
             * @see https://docs.coinex.com/api/v2/spot/order/http/edit-stop-order
             * @see https://docs.coinex.com/api/v2/futures/order/http/edit-order
             * @see https://docs.coinex.com/api/v2/futures/order/http/edit-stop-order
             *
             * @param {string} $id order $id
             * @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 the currency you want to trade in units of the base currency
             * @param {float} [$price] the $price at which the order is to be fulfilled, in units of the quote currency, ignored in $market orders
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {float} [$params->triggerPrice] the $price to trigger stop orders
             * @return {array} an ~@link https://docs.ccxt.com/#/?$id=order-structure order structure~
             */
            if ($symbol === null) {
                throw new ArgumentsRequired($this->id . ' editOrder() requires a $symbol argument');
            }
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $request = array(
                'market' => $market['id'],
            );
            if ($amount !== null) {
                $request['amount'] = $this->amount_to_precision($symbol, $amount);
            }
            if ($price !== null) {
                $request['price'] = $this->price_to_precision($symbol, $price);
            }
            $response = null;
            $triggerPrice = $this->safe_string_n($params, array( 'stopPrice', 'triggerPrice', 'trigger_price' ));
            $params = $this->omit($params, array( 'stopPrice', 'triggerPrice' ));
            $isTriggerOrder = $triggerPrice !== null;
            if ($isTriggerOrder) {
                $request['trigger_price'] = $this->price_to_precision($symbol, $triggerPrice);
                $request['stop_id'] = $this->parse_to_numeric($id);
            } else {
                $request['order_id'] = $this->parse_to_numeric($id);
            }
            $marginMode = null;
            list($marginMode, $params) = $this->handle_margin_mode_and_params('editOrder', $params);
            if ($market['spot']) {
                if ($marginMode !== null) {
                    $request['market_type'] = 'MARGIN';
                } else {
                    $request['market_type'] = 'SPOT';
                }
                if ($isTriggerOrder) {
                    $response = Async\await($this->v2PrivatePostSpotModifyStopOrder ($this->extend($request, $params)));
                    //
                    //     {
                    //         "code" => 0,
                    //         "data" => array(
                    //             "stop_id" => 117337235167
                    //         ),
                    //         "message" => "OK"
                    //     }
                    //
                } else {
                    $response = Async\await($this->v2PrivatePostSpotModifyOrder ($this->extend($request, $params)));
                    //
                    //     {
                    //         "code" => 0,
                    //         "data" => array(
                    //             "amount" => "0.0001",
                    //             "base_fee" => "0",
                    //             "ccy" => "BTC",
                    //             "client_id" => "x-167673045-87eb2bebf42882d8",
                    //             "created_at" => 1714290302047,
                    //             "discount_fee" => "0",
                    //             "filled_amount" => "0",
                    //             "filled_value" => "0",
                    //             "last_fill_amount" => "0",
                    //             "last_fill_price" => "0",
                    //             "maker_fee_rate" => "0.002",
                    //             "market" => "BTCUSDT",
                    //             "market_type" => "SPOT",
                    //             "order_id" => 117336922195,
                    //             "price" => "61000",
                    //             "quote_fee" => "0",
                    //             "side" => "buy",
                    //             "status" => "open",
                    //             "taker_fee_rate" => "0.002",
                    //             "type" => "limit",
                    //             "unfilled_amount" => "0.0001",
                    //             "updated_at" => 1714290191141
                    //         ),
                    //         "message" => "OK"
                    //     }
                    //
                }
            } else {
                $request['market_type'] = 'FUTURES';
                if ($isTriggerOrder) {
                    $response = Async\await($this->v2PrivatePostFuturesModifyStopOrder ($this->extend($request, $params)));
                    //
                    //     {
                    //         "code" => 0,
                    //         "data" => array(
                    //             "stop_id" => 137091875605
                    //         ),
                    //         "message" => "OK"
                    //     }
                    //
                } else {
                    $response = Async\await($this->v2PrivatePostFuturesModifyOrder ($this->extend($request, $params)));
                    //
                    //     {
                    //         "code" => 0,
                    //         "data" => array(
                    //             "amount" => "0.0001",
                    //             "client_id" => "x-167673045-3f2d09191462b207",
                    //             "created_at" => 1714290927630,
                    //             "fee" => "0",
                    //             "fee_ccy" => "USDT",
                    //             "filled_amount" => "0",
                    //             "filled_value" => "0",
                    //             "last_filled_amount" => "0",
                    //             "last_filled_price" => "0",
                    //             "maker_fee_rate" => "0.0003",
                    //             "market" => "BTCUSDT",
                    //             "market_type" => "FUTURES",
                    //             "order_id" => 137091566717,
                    //             "price" => "61000",
                    //             "realized_pnl" => "0",
                    //             "side" => "buy",
                    //             "taker_fee_rate" => "0.0005",
                    //             "type" => "limit",
                    //             "unfilled_amount" => "0.0001",
                    //             "updated_at" => 1714290927630
                    //         ),
                    //         "message" => "OK"
                    //     }
                    //
                }
            }
            $data = $this->safe_dict($response, 'data', array());
            return $this->parse_order($data, $market);
        }) ();
    }

    public function cancel_order(string $id, ?string $symbol = null, $params = array ()) {
        return Async\async(function () use ($id, $symbol, $params) {
            /**
             * cancels an open order
             *
             * @see https://docs.coinex.com/api/v2/spot/order/http/cancel-order
             * @see https://docs.coinex.com/api/v2/spot/order/http/cancel-stop-order
             * @see https://docs.coinex.com/api/v2/spot/order/http/cancel-order-by-client-$id
             * @see https://docs.coinex.com/api/v2/spot/order/http/cancel-stop-order-by-client-$id
             * @see https://docs.coinex.com/api/v2/futures/order/http/cancel-order
             * @see https://docs.coinex.com/api/v2/futures/order/http/cancel-stop-order
             * @see https://docs.coinex.com/api/v2/futures/order/http/cancel-order-by-client-$id
             * @see https://docs.coinex.com/api/v2/futures/order/http/cancel-stop-order-by-client-$id
             *
             * @param {string} $id order $id
             * @param {string} $symbol unified $symbol of the $market the order was made in
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {string} [$params->clientOrderId] client order $id, defaults to $id if not passed
             * @param {boolean} [$params->trigger] set to true for canceling a trigger order
             * @return {array} an ~@link https://docs.ccxt.com/#/?$id=order-structure order structure~
             */
            if ($symbol === null) {
                throw new ArgumentsRequired($this->id . ' cancelOrder() requires a $symbol argument');
            }
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $isTriggerOrder = $this->safe_bool_2($params, 'stop', 'trigger');
            $swap = $market['swap'];
            $request = array(
                'market' => $market['id'],
            );
            $marginMode = null;
            list($marginMode, $params) = $this->handle_margin_mode_and_params('cancelOrder', $params);
            if ($swap) {
                $request['market_type'] = 'FUTURES';
            } else {
                if ($marginMode !== null) {
                    $request['market_type'] = 'MARGIN';
                } else {
                    $request['market_type'] = 'SPOT';
                }
            }
            $clientOrderId = $this->safe_string_2($params, 'client_id', 'clientOrderId');
            $params = $this->omit($params, array( 'stop', 'trigger', 'clientOrderId' ));
            $response = null;
            if ($clientOrderId !== null) {
                $request['client_id'] = $clientOrderId;
                if ($isTriggerOrder) {
                    if ($swap) {
                        $response = Async\await($this->v2PrivatePostFuturesCancelStopOrderByClientId ($this->extend($request, $params)));
                        //     {
                        //         "code" => 0,
                        //         "data" => array(
                        //             {
                        //                 "code" => 0,
                        //                 "data" => array(
                        //                     "amount" => "0.0001",
                        //                     "client_id" => "client01",
                        //                     "created_at" => 1714368624473,
                        //                     "market" => "BTCUSDT",
                        //                     "market_type" => "FUTURES",
                        //                     "price" => "61000",
                        //                     "side" => "buy",
                        //                     "stop_id" => 137175823891,
                        //                     "trigger_direction" => "higher",
                        //                     "trigger_price" => "61500",
                        //                     "trigger_price_type" => "latest_price",
                        //                     "type" => "limit",
                        //                     "updated_at" => 1714368661444
                        //                 ),
                        //                 "message" => ""
                        //             }
                        //         ),
                        //         "message" => "OK"
                        //     }
                    } else {
                        $response = Async\await($this->v2PrivatePostSpotCancelStopOrderByClientId ($this->extend($request, $params)));
                        //     {
                        //         "code" :0,
                        //         "data" => array(
                        //             {
                        //                 "code" => 0,
                        //                 "data" => array(
                        //                     "amount" => "0.0001",
                        //                     "ccy" => "BTC",
                        //                     "client_id" => "client01",
                        //                     "created_at" => 1714366950279,
                        //                     "market" => "BTCUSDT",
                        //                     "market_type" => "SPOT",
                        //                     "price" => "61000",
                        //                     "side" => "buy",
                        //                     "stop_id" => 117402512706,
                        //                     "trigger_direction" => "higher",
                        //                     "trigger_price" => "61500",
                        //                     "trigger_price_type" => "mark_price",
                        //                     "type" => "limit",
                        //                     "updated_at" => 1714366950279
                        //                 ),
                        //                 "message" => "OK"
                        //             }
                        //         ),
                        //         "message" => "OK"
                        //     }
                    }
                } else {
                    if ($swap) {
                        $response = Async\await($this->v2PrivatePostFuturesCancelOrderByClientId ($this->extend($request, $params)));
                        //     {
                        //         "code" => 0,
                        //         "data" => array(
                        //             {
                        //                 "code" => 0,
                        //                 "data" => array(
                        //                     "amount" => "0.0001",
                        //                     "client_id" => "x-167673045-bf60e24bb437a3df",
                        //                     "created_at" => 1714368416437,
                        //                     "fee" => "0",
                        //                     "fee_ccy" => "USDT",
                        //                     "filled_amount" => "0",
                        //                     "filled_value" => "0",
                        //                     "last_filled_amount" => "0",
                        //                     "last_filled_price" => "0",
                        //                     "maker_fee_rate" => "0.0003",
                        //                     "market" => "BTCUSDT",
                        //                     "market_type" => "FUTURES",
                        //                     "order_id" => 137175616437,
                        //                     "price" => "61000",
                        //                     "realized_pnl" => "0",
                        //                     "side" => "buy",
                        //                     "taker_fee_rate" => "0.0005",
                        //                     "type" => "limit",
                        //                     "unfilled_amount" => "0.0001",
                        //                     "updated_at" => 1714368507174
                        //                 ),
                        //                 "message" => ""
                        //             }
                        //         ),
                        //         "message" => "OK"
                        //     }
                    } else {
                        $response = Async\await($this->v2PrivatePostSpotCancelOrderByClientId ($this->extend($request, $params)));
                        //     {
                        //         "code" => 0,
                        //         "data" => array(
                        //             {
                        //                 "code" => 0,
                        //                 "data" => array(
                        //                     "amount" => "0.0001",
                        //                     "base_fee" => "0",
                        //                     "ccy" => "BTC",
                        //                     "client_id" => "x-167673045-d49eaca5f412afc8",
                        //                     "created_at" => 1714366502807,
                        //                     "discount_fee" => "0",
                        //                     "filled_amount" => "0",
                        //                     "filled_value" => "0",
                        //                     "last_fill_amount" => "0",
                        //                     "last_fill_price" => "0",
                        //                     "maker_fee_rate" => "0.002",
                        //                     "market" => "BTCUSDT",
                        //                     "market_type" => "SPOT",
                        //                     "order_id" => 117402157490,
                        //                     "price" => "61000",
                        //                     "quote_fee" => "0",
                        //                     "side" => "buy",
                        //                     "taker_fee_rate" => "0.002",
                        //                     "type" => "limit",
                        //                     "unfilled_amount" => "0.0001",
                        //                     "updated_at" => 1714366502807
                        //                 ),
                        //                 "message" => "OK"
                        //             }
                        //         ),
                        //         "message" => "OK"
                        //     }
                    }
                }
            } else {
                if ($isTriggerOrder) {
                    $request['stop_id'] = $this->parse_to_numeric($id);
                    if ($swap) {
                        $response = Async\await($this->v2PrivatePostFuturesCancelStopOrder ($this->extend($request, $params)));
                        //     {
                        //         "code" => 0,
                        //         "data" => array(
                        //             "amount" => "0.0001",
                        //             "ccy" => "BTC",
                        //             "client_id" => "x-167673045-f21ecfd7542abf1f",
                        //             "created_at" => 1714366177334,
                        //             "market" => "BTCUSDT",
                        //             "market_type" => "SPOT",
                        //             "price" => "61000",
                        //             "side" => "buy",
                        //             "stop_id" => 117401897954,
                        //             "trigger_direction" => "higher",
                        //             "trigger_price" => "61500",
                        //             "trigger_price_type" => "mark_price",
                        //             "type" => "limit",
                        //             "updated_at" => 1714366177334
                        //         ),
                        //         "message" => "OK"
                        //     }
                    } else {
                        $response = Async\await($this->v2PrivatePostSpotCancelStopOrder ($this->extend($request, $params)));
                        //     {
                        //         "code" => 0,
                        //         "data" => array(
                        //             "amount" => "0.0001",
                        //             "ccy" => "BTC",
                        //             "client_id" => "x-167673045-f21ecfd7542abf1f",
                        //             "created_at" => 1714366177334,
                        //             "market" => "BTCUSDT",
                        //             "market_type" => "SPOT",
                        //             "price" => "61000",
                        //             "side" => "buy",
                        //             "stop_id" => 117401897954,
                        //             "trigger_direction" => "higher",
                        //             "trigger_price" => "61500",
                        //             "trigger_price_type" => "mark_price",
                        //             "type" => "limit",
                        //             "updated_at" => 1714366177334
                        //         ),
                        //         "message" => "OK"
                        //     }
                    }
                } else {
                    $request['order_id'] = $this->parse_to_numeric($id);
                    if ($swap) {
                        $response = Async\await($this->v2PrivatePostFuturesCancelOrder ($this->extend($request, $params)));
                        //     {
                        //         "code" => 0,
                        //         "data" => array(
                        //             "amount" => "0.0001",
                        //             "client_id" => "x-167673045-7f14381c74a98a85",
                        //             "created_at" => 1714367342024,
                        //             "fee" => "0",
                        //             "fee_ccy" => "USDT",
                        //             "filled_amount" => "0",
                        //             "filled_value" => "0",
                        //             "last_filled_amount" => "0",
                        //             "last_filled_price" => "0",
                        //             "maker_fee_rate" => "0.0003",
                        //             "market" => "BTCUSDT",
                        //             "market_type" => "FUTURES",
                        //             "order_id" => 137174472136,
                        //             "price" => "61000",
                        //             "realized_pnl" => "0",
                        //             "side" => "buy",
                        //             "taker_fee_rate" => "0.0005",
                        //             "type" => "limit",
                        //             "unfilled_amount" => "0.0001",
                        //             "updated_at" => 1714367515978
                        //         ),
                        //         "message" => "OK"
                        //     }
                    } else {
                        $response = Async\await($this->v2PrivatePostSpotCancelOrder ($this->extend($request, $params)));
                        //     {
                        //         "code" => 0,
                        //         "data" => array(
                        //             "amount" => "0.0001",
                        //             "base_fee" => "0",
                        //             "ccy" => "BTC",
                        //             "client_id" => "x-167673045-86fbe37b54a2aea3",
                        //             "created_at" => 1714365277437,
                        //             "discount_fee" => "0",
                        //             "filled_amount" => "0",
                        //             "filled_value" => "0",
                        //             "last_fill_amount" => "0",
                        //             "last_fill_price" => "0",
                        //             "maker_fee_rate" => "0.002",
                        //             "market" => "BTCUSDT",
                        //             "market_type" => "SPOT",
                        //             "order_id" => 117401168172,
                        //             "price" => "61000",
                        //             "quote_fee" => "0",
                        //             "side" => "buy",
                        //             "taker_fee_rate" => "0.002",
                        //             "type" => "limit",
                        //             "unfilled_amount" => "0.0001",
                        //             "updated_at" => 1714365277437
                        //         ),
                        //         "message" => "OK"
                        //     }
                    }
                }
            }
            $data = null;
            if ($clientOrderId !== null) {
                $rows = $this->safe_list($response, 'data', array());
                $data = $this->safe_dict($rows[0], 'data', array());
            } else {
                $data = $this->safe_dict($response, 'data', array());
            }
            return $this->parse_order($data, $market);
        }) ();
    }

    public function cancel_all_orders(?string $symbol = null, $params = array ()) {
        return Async\async(function () use ($symbol, $params) {
            /**
             * cancel all open orders in a $market
             *
             * @see https://docs.coinex.com/api/v2/spot/order/http/cancel-all-order
             * @see https://docs.coinex.com/api/v2/futures/order/http/cancel-all-order
             *
             * @param {string} $symbol unified $market $symbol of the $market to cancel orders in
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {string} [$params->marginMode] 'cross' or 'isolated' for canceling spot margin orders
             * @return {array[]} a list of ~@link https://docs.ccxt.com/#/?id=order-structure order structures~
             */
            if ($symbol === null) {
                throw new ArgumentsRequired($this->id . ' cancelAllOrders() requires a $symbol argument');
            }
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $request = array(
                'market' => $market['id'],
            );
            $response = null;
            if ($market['swap']) {
                $request['market_type'] = 'FUTURES';
                $response = Async\await($this->v2PrivatePostFuturesCancelAllOrder ($this->extend($request, $params)));
                //
                // array("code":0,"data":array(),"message":"OK")
                //
            } else {
                $marginMode = null;
                list($marginMode, $params) = $this->handle_margin_mode_and_params('cancelAllOrders', $params);
                if ($marginMode !== null) {
                    $request['market_type'] = 'MARGIN';
                } else {
                    $request['market_type'] = 'SPOT';
                }
                $response = Async\await($this->v2PrivatePostSpotCancelAllOrder ($this->extend($request, $params)));
                //
                // array("code":0,"data":array(),"message":"OK")
                //
            }
            return array(
                $this->safe_order(array(
                    'info' => $response,
                )),
            );
        }) ();
    }

    public function fetch_order(string $id, ?string $symbol = null, $params = array ()) {
        return Async\async(function () use ($id, $symbol, $params) {
            /**
             * fetches information on an order made by the user
             *
             * @see https://docs.coinex.com/api/v2/spot/order/http/get-order-status
             * @see https://docs.coinex.com/api/v2/futures/order/http/get-order-status
             *
             * @param {string} $id order $id
             * @param {string} $symbol unified $symbol of the $market the order was made in
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} An ~@link https://docs.ccxt.com/#/?$id=order-structure order structure~
             */
            if ($symbol === null) {
                throw new ArgumentsRequired($this->id . ' fetchOrder() requires a $symbol argument');
            }
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $request = array(
                'market' => $market['id'],
                'order_id' => $this->parse_to_numeric($id),
            );
            $response = null;
            if ($market['swap']) {
                $response = Async\await($this->v2PrivateGetFuturesOrderStatus ($this->extend($request, $params)));
                //
                //     {
                //         "code" => 0,
                //         "data" => array(
                //             "amount" => "0.0001",
                //             "client_id" => "x-167673045-da5f31dcd478a829",
                //             "created_at" => 1714460987164,
                //             "fee" => "0",
                //             "fee_ccy" => "USDT",
                //             "filled_amount" => "0",
                //             "filled_value" => "0",
                //             "last_filled_amount" => "0",
                //             "last_filled_price" => "0",
                //             "maker_fee_rate" => "0.0003",
                //             "market" => "BTCUSDT",
                //             "market_type" => "FUTURES",
                //             "order_id" => 137319868771,
                //             "price" => "61000",
                //             "realized_pnl" => "0",
                //             "side" => "buy",
                //             "status" => "open",
                //             "taker_fee_rate" => "0.0005",
                //             "type" => "limit",
                //             "unfilled_amount" => "0.0001",
                //             "updated_at" => 1714460987164
                //         ),
                //         "message" => "OK"
                //     }
                //
            } else {
                $response = Async\await($this->v2PrivateGetSpotOrderStatus ($this->extend($request, $params)));
                //
                //     {
                //         "code" => 0,
                //         "data" => array(
                //             "amount" => "0.0001",
                //             "base_fee" => "0",
                //             "ccy" => "BTC",
                //             "client_id" => "x-167673045-da918d6724e3af81",
                //             "created_at" => 1714461638958,
                //             "discount_fee" => "0",
                //             "filled_amount" => "0",
                //             "filled_value" => "0",
                //             "last_fill_amount" => "0",
                //             "last_fill_price" => "0",
                //             "maker_fee_rate" => "0.002",
                //             "market" => "BTCUSDT",
                //             "market_type" => "SPOT",
                //             "order_id" => 117492012985,
                //             "price" => "61000",
                //             "quote_fee" => "0",
                //             "side" => "buy",
                //             "status" => "open",
                //             "taker_fee_rate" => "0.002",
                //             "type" => "limit",
                //             "unfilled_amount" => "0.0001",
                //             "updated_at" => 1714461638958
                //         ),
                //         "message" => "OK"
                //     }
                //
            }
            $data = $this->safe_dict($response, 'data', array());
            return $this->parse_order($data, $market);
        }) ();
    }

    public function fetch_orders_by_status($status, ?string $symbol = null, ?int $since = null, ?int $limit = null, $params = array ()) {
        return Async\async(function () use ($status, $symbol, $since, $limit, $params) {
            /**
             * fetch a list of orders
             *
             * @see https://docs.coinex.com/api/v2/spot/order/http/list-finished-order
             * @see https://docs.coinex.com/api/v2/spot/order/http/list-finished-stop-order
             * @see https://docs.coinex.com/api/v2/futures/order/http/list-finished-order
             * @see https://docs.coinex.com/api/v2/futures/order/http/list-finished-stop-order
             *
             * @param {string} $status order $status to fetch for
             * @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 {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {boolean} [$params->trigger] set to true for fetching $trigger orders
             * @param {string} [$params->marginMode] 'cross' or 'isolated' for fetching spot margin orders
             * @return {Order[]} a list of ~@link https://docs.ccxt.com/#/?id=order-structure order structures~
             */
            Async\await($this->load_markets());
            $request = array();
            $market = null;
            if ($symbol !== null) {
                $market = $this->market($symbol);
                $request['market'] = $market['id'];
            }
            if ($limit !== null) {
                $request['limit'] = $limit;
            }
            $trigger = $this->safe_bool_2($params, 'stop', 'trigger');
            $params = $this->omit($params, array( 'stop', 'trigger' ));
            $marketType = null;
            list($marketType, $params) = $this->handle_market_type_and_params('fetchOrdersByStatus', $market, $params);
            $response = null;
            $isClosed = ($status === 'finished') || ($status === 'closed');
            $isOpen = ($status === 'pending') || ($status === 'open');
            if ($marketType === 'swap') {
                $request['market_type'] = 'FUTURES';
                if ($isClosed) {
                    if ($trigger) {
                        $response = Async\await($this->v2PrivateGetFuturesFinishedStopOrder ($this->extend($request, $params)));
                        //
                        //     {
                        //         "code" => 0,
                        //         "data" => array(
                        //             array(
                        //                 "stop_id" => 52431158859,
                        //                 "market" => "BTCUSDT",
                        //                 "market_type" => "FUTURES",
                        //                 "side" => "sell",
                        //                 "type" => "market",
                        //                 "amount" => "0.0005",
                        //                 "price" => "20599.64",
                        //                 "client_id" => "",
                        //                 "created_at" => 1667547909856,
                        //                 "updated_at" => 1667547909856,
                        //                 "trigger_price" => "20599.64",
                        //                 "trigger_price_type" => "latest_price",
                        //                 "trigger_direction" => ""
                        //             ),
                        //         ),
                        //         "message" => "OK",
                        //         "pagination" => {
                        //             "has_next" => false
                        //         }
                        //     }
                        //
                    } else {
                        $response = Async\await($this->v2PrivateGetFuturesFinishedOrder ($this->extend($request, $params)));
                        //
                        //     {
                        //         "code" => 0,
                        //         "data" => array(
                        //             array(
                        //                 "order_id" => 136915813578,
                        //                 "market" => "BTCUSDT",
                        //                 "market_type" => "FUTURES",
                        //                 "side" => "sell",
                        //                 "type" => "market",
                        //                 "amount" => "0.0001",
                        //                 "price" => "0",
                        //                 "client_id" => "x-167673045-4f264600c432ac06",
                        //                 "created_at" => 1714119323764,
                        //                 "updated_at" => 1714119323764,
                        //                 "unfilled_amount" => "0",
                        //                 "filled_amount" => "0.0001",
                        //                 "filled_value" => "6.442017",
                        //                 "fee" => "0.003221",
                        //                 "fee_ccy" => "USDT",
                        //                 "maker_fee_rate" => "0",
                        //                 "taker_fee_rate" => "0.0005"
                        //             ),
                        //         ),
                        //         "message" => "OK",
                        //         "pagination" => {
                        //             "has_next" => false
                        //         }
                        //     }
                        //
                    }
                } elseif ($isOpen) {
                    if ($trigger) {
                        $response = Async\await($this->v2PrivateGetFuturesPendingStopOrder ($this->extend($request, $params)));
                        //
                        //     {
                        //         "code" => 0,
                        //         "data" => array(
                        //             {
                        //                 "stop_id" => 137481469849,
                        //                 "market" => "BTCUSDT",
                        //                 "market_type" => "FUTURES",
                        //                 "side" => "buy",
                        //                 "type" => "limit",
                        //                 "amount" => "0.0001",
                        //                 "price" => "51000",
                        //                 "client_id" => "x-167673045-2b932341949fa2a1",
                        //                 "created_at" => 1714552257876,
                        //                 "updated_at" => 1714552257876,
                        //                 "trigger_price" => "52000",
                        //                 "trigger_price_type" => "latest_price",
                        //                 "trigger_direction" => "higher"
                        //             }
                        //         ),
                        //         "message" => "OK",
                        //         "pagination" => {
                        //             "total" => 1,
                        //             "has_next" => false
                        //         }
                        //     }
                        //
                    } else {
                        $response = Async\await($this->v2PrivateGetFuturesPendingOrder ($this->extend($request, $params)));
                        //
                        //     {
                        //         "code" => 0,
                        //         "data" => array(
                        //             {
                        //                 "order_id" => 137480580906,
                        //                 "market" => "BTCUSDT",
                        //                 "market_type" => "FUTURES",
                        //                 "side" => "buy",
                        //                 "type" => "limit",
                        //                 "amount" => "0.0001",
                        //                 "price" => "51000",
                        //                 "client_id" => "",
                        //                 "created_at" => 1714551877569,
                        //                 "updated_at" => 1714551877569,
                        //                 "unfilled_amount" => "0.0001",
                        //                 "filled_amount" => "0",
                        //                 "filled_value" => "0",
                        //                 "fee" => "0",
                        //                 "fee_ccy" => "USDT",
                        //                 "maker_fee_rate" => "0.0003",
                        //                 "taker_fee_rate" => "0.0005",
                        //                 "last_filled_amount" => "0",
                        //                 "last_filled_price" => "0",
                        //                 "realized_pnl" => "0"
                        //             }
                        //         ),
                        //         "message" => "OK",
                        //         "pagination" => {
                        //             "total" => 1,
                        //             "has_next" => false
                        //         }
                        //     }
                        //
                    }
                }
            } else {
                $marginMode = null;
                list($marginMode, $params) = $this->handle_margin_mode_and_params('fetchOrdersByStatus', $params);
                if ($marginMode !== null) {
                    $request['market_type'] = 'MARGIN';
                } else {
                    $request['market_type'] = 'SPOT';
                }
                if ($isClosed) {
                    if ($trigger) {
                        $response = Async\await($this->v2PrivateGetSpotFinishedStopOrder ($this->extend($request, $params)));
                        //
                        //     {
                        //         "code" => 0,
                        //         "data" => array(
                        //             {
                        //                 "stop_id" => 117654881420,
                        //                 "market" => "BTCUSDT",
                        //                 "market_type" => "SPOT",
                        //                 "ccy" => "USDT",
                        //                 "side" => "buy",
                        //                 "type" => "market",
                        //                 "amount" => "5.83325524",
                        //                 "price" => "0",
                        //                 "trigger_price" => "57418",
                        //                 "trigger_direction" => "lower",
                        //                 "trigger_price_type" => "mark_price",
                        //                 "client_id" => "",
                        //                 "created_at" => 1714618050597,
                        //                 "updated_at" => 0
                        //             }
                        //         ),
                        //         "message" => "OK",
                        //         "pagination" => {
                        //             "has_next" => false
                        //         }
                        //     }
                        //
                    } else {
                        $response = Async\await($this->v2PrivateGetSpotFinishedOrder ($this->extend($request, $params)));
                        //
                        //     {
                        //         "code" => 0,
                        //         "data" => array(
                        //             array(
                        //                 "order_id" => 117180532345,
                        //                 "market" => "BTCUSDT",
                        //                 "market_type" => "SPOT",
                        //                 "side" => "sell",
                        //                 "type" => "market",
                        //                 "ccy" => "BTC",
                        //                 "amount" => "0.00015484",
                        //                 "price" => "0",
                        //                 "client_id" => "",
                        //                 "created_at" => 1714116494219,
                        //                 "updated_at" => 0,
                        //                 "base_fee" => "0",
                        //                 "quote_fee" => "0.0199931699632",
                        //                 "discount_fee" => "0",
                        //                 "maker_fee_rate" => "0",
                        //                 "taker_fee_rate" => "0.002",
                        //                 "unfilled_amount" => "0",
                        //                 "filled_amount" => "0.00015484",
                        //                 "filled_value" => "9.9965849816"
                        //             ),
                        //         ),
                        //         "message" => "OK",
                        //         "pagination" => {
                        //             "has_next" => false
                        //         }
                        //     }
                        //
                    }
                } elseif ($status === 'pending') {
                    if ($trigger) {
                        $response = Async\await($this->v2PrivateGetSpotPendingStopOrder ($this->extend($request, $params)));
                        //
                        //     {
                        //         "code" => 0,
                        //         "data" => array(
                        //             {
                        //                 "stop_id" => 117586439530,
                        //                 "market" => "BTCUSDT",
                        //                 "market_type" => "SPOT",
                        //                 "ccy" => "BTC",
                        //                 "side" => "buy",
                        //                 "type" => "limit",
                        //                 "amount" => "0.0001",
                        //                 "price" => "51000",
                        //                 "trigger_price" => "52000",
                        //                 "trigger_direction" => "higher",
                        //                 "trigger_price_type" => "mark_price",
                        //                 "client_id" => "x-167673045-df61777094c69312",
                        //                 "created_at" => 1714551237335,
                        //                 "updated_at" => 1714551237335
                        //             }
                        //         ),
                        //         "message" => "OK",
                        //         "pagination" => {
                        //             "total" => 1,
                        //             "has_next" => false
                        //         }
                        //     }
                        //
                    } else {
                        $response = Async\await($this->v2PrivateGetSpotPendingOrder ($this->extend($request, $params)));
                        //
                        //     {
                        //         "code" => 0,
                        //         "data" => array(
                        //             {
                        //                 "order_id" => 117585921297,
                        //                 "market" => "BTCUSDT",
                        //                 "market_type" => "SPOT",
                        //                 "side" => "buy",
                        //                 "type" => "limit",
                        //                 "ccy" => "BTC",
                        //                 "amount" => "0.00011793",
                        //                 "price" => "52000",
                        //                 "client_id" => "",
                        //                 "created_at" => 1714550707486,
                        //                 "updated_at" => 1714550707486,
                        //                 "base_fee" => "0",
                        //                 "quote_fee" => "0",
                        //                 "discount_fee" => "0",
                        //                 "maker_fee_rate" => "0.002",
                        //                 "taker_fee_rate" => "0.002",
                        //                 "last_fill_amount" => "0",
                        //                 "last_fill_price" => "0",
                        //                 "unfilled_amount" => "0.00011793",
                        //                 "filled_amount" => "0",
                        //                 "filled_value" => "0"
                        //             }
                        //         ),
                        //         "message" => "OK",
                        //         "pagination" => {
                        //             "total" => 1,
                        //             "has_next" => false
                        //         }
                        //     }
                        //
                    }
                }
            }
            $data = $this->safe_list($response, 'data', array());
            return $this->parse_orders($data, $market, $since, $limit);
        }) ();
    }

    public function fetch_open_orders(?string $symbol = null, ?int $since = null, ?int $limit = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $since, $limit, $params) {
            /**
             * fetch all unfilled currently open orders
             *
             * @see https://docs.coinex.com/api/v2/spot/order/http/list-pending-order
             * @see https://docs.coinex.com/api/v2/spot/order/http/list-pending-stop-order
             * @see https://docs.coinex.com/api/v2/futures/order/http/list-pending-order
             * @see https://docs.coinex.com/api/v2/futures/order/http/list-pending-stop-order
             *
             * @param {string} $symbol unified market $symbol
             * @param {int} [$since] the earliest time in ms to fetch open orders for
             * @param {int} [$limit] the maximum number of open order structures to retrieve
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {boolean} [$params->trigger] set to true for fetching trigger orders
             * @param {string} [$params->marginMode] 'cross' or 'isolated' for fetching spot margin orders
             * @return {Order[]} a list of ~@link https://docs.ccxt.com/#/?id=order-structure order structures~
             */
            $openOrders = Async\await($this->fetch_orders_by_status('pending', $symbol, $since, $limit, $params));
            for ($i = 0; $i < count($openOrders); $i++) {
                $openOrders[$i]['status'] = 'open';
            }
            return $openOrders;
        }) ();
    }

    public function fetch_closed_orders(?string $symbol = null, ?int $since = null, ?int $limit = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $since, $limit, $params) {
            /**
             * fetches information on multiple closed orders made by the user
             *
             * @see https://docs.coinex.com/api/v2/spot/order/http/list-finished-order
             * @see https://docs.coinex.com/api/v2/spot/order/http/list-finished-stop-order
             * @see https://docs.coinex.com/api/v2/futures/order/http/list-finished-order
             * @see https://docs.coinex.com/api/v2/futures/order/http/list-finished-stop-order
             *
             * @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 {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {boolean} [$params->trigger] set to true for fetching trigger orders
             * @param {string} [$params->marginMode] 'cross' or 'isolated' for fetching spot margin orders
             * @return {Order[]} a list of ~@link https://docs.ccxt.com/#/?id=order-structure order structures~
             */
            return Async\await($this->fetch_orders_by_status('finished', $symbol, $since, $limit, $params));
        }) ();
    }

    public function create_deposit_address(string $code, $params = array ()): PromiseInterface {
        return Async\async(function () use ($code, $params) {
            /**
             * create a $currency deposit address
             *
             * @see https://docs.coinex.com/api/v2/assets/deposit-withdrawal/http/update-deposit-address
             *
             * @param {string} $code unified $currency $code of the $currency for the deposit address
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {string} [$params->network] the blockchain $network to create a deposit address on
             * @return {array} an ~@link https://docs.ccxt.com/#/?id=address-structure address structure~
             */
            Async\await($this->load_markets());
            $currency = $this->currency($code);
            $network = $this->safe_string_2($params, 'chain', 'network');
            if ($network === null) {
                throw new ArgumentsRequired($this->id . ' createDepositAddress() requires a $network parameter');
            }
            $params = $this->omit($params, 'network');
            $request = array(
                'ccy' => $currency['id'],
                'chain' => $this->network_code_to_id($network, $currency['code']),
            );
            $response = Async\await($this->v2PrivatePostAssetsRenewalDepositAddress ($this->extend($request, $params)));
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             "address" => "0x321bd6479355142334f45653ad5d8b76105a1234",
            //             "memo" => ""
            //         ),
            //         "message" => "OK"
            //     }
            //
            $data = $this->safe_dict($response, 'data', array());
            return $this->parse_deposit_address($data, $currency);
        }) ();
    }

    public function fetch_deposit_address(string $code, $params = array ()): PromiseInterface {
        return Async\async(function () use ($code, $params) {
            /**
             * fetch the deposit address for a $currency associated with this account
             *
             * @see https://docs.coinex.com/api/v2/assets/deposit-withdrawal/http/get-deposit-address
             *
             * @param {string} $code unified $currency $code
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {string} [$params->network] the blockchain network to create a deposit address on
             * @return {array} an ~@link https://docs.ccxt.com/#/?id=address-structure address structure~
             */
            Async\await($this->load_markets());
            $currency = $this->currency($code);
            $request = array(
                'ccy' => $currency['id'],
            );
            $networkCode = null;
            list($networkCode, $params) = $this->handle_network_code_and_params($params);
            if ($networkCode === null) {
                throw new ArgumentsRequired($this->id . ' fetchDepositAddress() requires a "network" parameter');
            }
            $request['chain'] = $this->network_code_to_id($networkCode); // required for on-chain, not required for inter-user transfer
            $response = Async\await($this->v2PrivateGetAssetsDepositAddress ($this->extend($request, $params)));
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             "address" => "0x321bd6479355142334f45653ad5d8b76105a1234",
            //             "memo" => ""
            //         ),
            //         "message" => "OK"
            //     }
            //
            $data = $this->safe_dict($response, 'data', array());
            return $this->parse_deposit_address($data, $currency);
        }) ();
    }

    public function parse_deposit_address($depositAddress, ?array $currency = null): array {
        //
        //     {
        //         "address" => "1P1JqozxioQwaqPwgMAQdNDYNyaVSqgARq",
        //         "memo" => ""
        //     }
        //
        $coinAddress = $this->safe_string($depositAddress, 'address');
        $parts = explode(':', $coinAddress);
        $address = null;
        $tag = null;
        $partsLength = count($parts);
        if ($partsLength > 1 && $parts[0] !== 'cfx') {
            $address = $parts[0];
            $tag = $parts[1];
        } else {
            $address = $coinAddress;
        }
        return array(
            'info' => $depositAddress,
            'currency' => $this->safe_currency_code(null, $currency),
            'network' => null,
            'address' => $address,
            'tag' => $this->safe_string($depositAddress, 'memo', $tag),
        );
    }

    public function fetch_my_trades(?string $symbol = null, ?int $since = null, ?int $limit = null, $params = array ()) {
        return Async\async(function () use ($symbol, $since, $limit, $params) {
            /**
             * fetch all trades made by the user
             *
             * @see https://docs.coinex.com/api/v2/spot/deal/http/list-user-deals
             * @see https://docs.coinex.com/api/v2/futures/deal/http/list-user-deals
             *
             * @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 trade structures to retrieve
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {int} [$params->until] timestamp in ms of the latest trades
             * @param {string} [$params->side] the side of the trades, either 'buy' or 'sell', required for swap
             * @return {Trade[]} a list of ~@link https://docs.ccxt.com/#/?id=trade-structure trade structures~
             */
            if ($symbol === null) {
                throw new ArgumentsRequired($this->id . ' fetchMyTrades() requires a $symbol argument');
            }
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $request = array(
                'market' => $market['id'],
            );
            if ($limit !== null) {
                $request['limit'] = $limit;
            }
            if ($since !== null) {
                $request['start_time'] = $since;
            }
            list($request, $params) = $this->handle_until_option('end_time', $request, $params);
            $response = null;
            if ($market['swap']) {
                $request['market_type'] = 'FUTURES';
                $response = Async\await($this->v2PrivateGetFuturesUserDeals ($this->extend($request, $params)));
                //
                //     {
                //         "code" => 0,
                //         "data" => array(
                //             {
                //                 "deal_id" => 1180222387,
                //                 "created_at" => 1714119054558,
                //                 "market" => "BTCUSDT",
                //                 "side" => "buy",
                //                 "order_id" => 136915589622,
                //                 "price" => "64376",
                //                 "amount" => "0.0001"
                //             }
                //         ),
                //         "message" => "OK",
                //         "pagination" => {
                //             "has_next" => true
                //         }
                //     }
                //
            } else {
                $marginMode = null;
                list($marginMode, $params) = $this->handle_margin_mode_and_params('fetchMyTrades', $params);
                if ($marginMode !== null) {
                    $request['market_type'] = 'MARGIN';
                } else {
                    $request['market_type'] = 'SPOT';
                }
                $response = Async\await($this->v2PrivateGetSpotUserDeals ($this->extend($request, $params)));
                //
                //     {
                //         "code" => 0,
                //         "data" => array(
                //             {
                //                 "amount" => "0.00010087",
                //                 "created_at" => 1714618087585,
                //                 "deal_id" => 4161200602,
                //                 "margin_market" => "",
                //                 "market" => "BTCUSDT",
                //                 "order_id" => 117654919342,
                //                 "price" => "57464.04",
                //                 "side" => "sell"
                //             }
                //         ),
                //         "message" => "OK",
                //         "pagination" => {
                //             "has_next" => true
                //         }
                //     }
                //
            }
            $data = $this->safe_list($response, 'data', array());
            return $this->parse_trades($data, $market, $since, $limit);
        }) ();
    }

    public function fetch_positions(?array $symbols = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbols, $params) {
            /**
             * fetch all open positions
             *
             * @see https://docs.coinex.com/api/v2/futures/position/http/list-pending-$position
             * @see https://docs.coinex.com/api/v2/futures/position/http/list-finished-$position
             *
             * @param {string[]} [$symbols] list of unified $market $symbols
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {string} [$params->method] the method to use 'v2PrivateGetFuturesPendingPosition' or 'v2PrivateGetFuturesFinishedPosition' default is 'v2PrivateGetFuturesPendingPosition'
             * @return {array[]} a list of ~@link https://docs.ccxt.com/#/?id=$position-structure $position structure~
             */
            Async\await($this->load_markets());
            $defaultMethod = null;
            list($defaultMethod, $params) = $this->handle_option_and_params($params, 'fetchPositions', 'method', 'v2PrivateGetFuturesPendingPosition');
            $symbols = $this->market_symbols($symbols);
            $request = array(
                'market_type' => 'FUTURES',
            );
            $market = null;
            if ($symbols !== null) {
                $symbol = null;
                if (gettype($symbols) === 'array' && array_keys($symbols) === array_keys(array_keys($symbols))) {
                    $symbolsLength = count($symbols);
                    if ($symbolsLength > 1) {
                        throw new BadRequest($this->id . ' fetchPositions() $symbols argument cannot contain more than 1 symbol');
                    }
                    $symbol = $symbols[0];
                } else {
                    $symbol = $symbols;
                }
                $market = $this->market($symbol);
                $request['market'] = $market['id'];
            }
            $response = null;
            if ($defaultMethod === 'v2PrivateGetFuturesPendingPosition') {
                $response = Async\await($this->v2PrivateGetFuturesPendingPosition ($this->extend($request, $params)));
            } else {
                $response = Async\await($this->v2PrivateGetFuturesFinishedPosition ($this->extend($request, $params)));
            }
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             {
            //                 "position_id" => 305891033,
            //                 "market" => "BTCUSDT",
            //                 "market_type" => "FUTURES",
            //                 "side" => "long",
            //                 "margin_mode" => "cross",
            //                 "open_interest" => "0.0001",
            //                 "close_avbl" => "0.0001",
            //                 "ath_position_amount" => "0.0001",
            //                 "unrealized_pnl" => "0",
            //                 "realized_pnl" => "-0.00311684",
            //                 "avg_entry_price" => "62336.8",
            //                 "cml_position_value" => "6.23368",
            //                 "max_position_value" => "6.23368",
            //                 "created_at" => 1715152208041,
            //                 "updated_at" => 1715152208041,
            //                 "take_profit_price" => "0",
            //                 "stop_loss_price" => "0",
            //                 "take_profit_type" => "",
            //                 "stop_loss_type" => "",
            //                 "settle_price" => "62336.8",
            //                 "settle_value" => "6.23368",
            //                 "leverage" => "3",
            //                 "margin_avbl" => "2.07789333",
            //                 "ath_margin_size" => "2.07789333",
            //                 "position_margin_rate" => "2.40545879023305655728",
            //                 "maintenance_margin_rate" => "0.005",
            //                 "maintenance_margin_value" => "0.03118094",
            //                 "liq_price" => "0",
            //                 "bkr_price" => "0",
            //                 "adl_level" => 1
            //             }
            //         ),
            //         "message" => "OK",
            //         "pagination" => {
            //             "has_next" => false
            //         }
            //     }
            //
            $position = $this->safe_list($response, 'data', array());
            $result = array();
            for ($i = 0; $i < count($position); $i++) {
                $result[] = $this->parse_position($position[$i], $market);
            }
            return $this->filter_by_array_positions($result, 'symbol', $symbols, false);
        }) ();
    }

    public function fetch_position(string $symbol, $params = array ()) {
        return Async\async(function () use ($symbol, $params) {
            /**
             * fetch $data on a single open contract trade position
             *
             * @see https://docs.coinex.com/api/v2/futures/position/http/list-pending-position
             *
             * @param {string} $symbol unified $market $symbol of the $market the position is held in
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=position-structure position structure~
             */
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $request = array(
                'market_type' => 'FUTURES',
                'market' => $market['id'],
            );
            $response = Async\await($this->v2PrivateGetFuturesPendingPosition ($this->extend($request, $params)));
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             {
            //                 "position_id" => 305891033,
            //                 "market" => "BTCUSDT",
            //                 "market_type" => "FUTURES",
            //                 "side" => "long",
            //                 "margin_mode" => "cross",
            //                 "open_interest" => "0.0001",
            //                 "close_avbl" => "0.0001",
            //                 "ath_position_amount" => "0.0001",
            //                 "unrealized_pnl" => "0",
            //                 "realized_pnl" => "-0.00311684",
            //                 "avg_entry_price" => "62336.8",
            //                 "cml_position_value" => "6.23368",
            //                 "max_position_value" => "6.23368",
            //                 "created_at" => 1715152208041,
            //                 "updated_at" => 1715152208041,
            //                 "take_profit_price" => "0",
            //                 "stop_loss_price" => "0",
            //                 "take_profit_type" => "",
            //                 "stop_loss_type" => "",
            //                 "settle_price" => "62336.8",
            //                 "settle_value" => "6.23368",
            //                 "leverage" => "3",
            //                 "margin_avbl" => "2.07789333",
            //                 "ath_margin_size" => "2.07789333",
            //                 "position_margin_rate" => "2.40545879023305655728",
            //                 "maintenance_margin_rate" => "0.005",
            //                 "maintenance_margin_value" => "0.03118094",
            //                 "liq_price" => "0",
            //                 "bkr_price" => "0",
            //                 "adl_level" => 1
            //             }
            //         ),
            //         "message" => "OK",
            //         "pagination" => {
            //             "has_next" => false
            //         }
            //     }
            //
            $data = $this->safe_list($response, 'data', array());
            return $this->parse_position($data[0], $market);
        }) ();
    }

    public function parse_position(array $position, ?array $market = null) {
        //
        //     {
        //         "position_id" => 305891033,
        //         "market" => "BTCUSDT",
        //         "market_type" => "FUTURES",
        //         "side" => "long",
        //         "margin_mode" => "cross",
        //         "open_interest" => "0.0001",
        //         "close_avbl" => "0.0001",
        //         "ath_position_amount" => "0.0001",
        //         "unrealized_pnl" => "0",
        //         "realized_pnl" => "-0.00311684",
        //         "avg_entry_price" => "62336.8",
        //         "cml_position_value" => "6.23368",
        //         "max_position_value" => "6.23368",
        //         "created_at" => 1715152208041,
        //         "updated_at" => 1715152208041,
        //         "take_profit_price" => "0",
        //         "stop_loss_price" => "0",
        //         "take_profit_type" => "",
        //         "stop_loss_type" => "",
        //         "settle_price" => "62336.8",
        //         "settle_value" => "6.23368",
        //         "leverage" => "3",
        //         "margin_avbl" => "2.07789333",
        //         "ath_margin_size" => "2.07789333",
        //         "position_margin_rate" => "2.40545879023305655728",
        //         "maintenance_margin_rate" => "0.005",
        //         "maintenance_margin_value" => "0.03118094",
        //         "liq_price" => "0",
        //         "bkr_price" => "0",
        //         "adl_level" => 1
        //     }
        //
        $marketId = $this->safe_string($position, 'market');
        $market = $this->safe_market($marketId, $market, null, 'swap');
        $timestamp = $this->safe_integer($position, 'created_at');
        return $this->safe_position(array(
            'info' => $position,
            'id' => $this->safe_integer($position, 'position_id'),
            'symbol' => $market['symbol'],
            'notional' => $this->safe_number($position, 'settle_value'),
            'marginMode' => $this->safe_string($position, 'margin_mode'),
            'liquidationPrice' => $this->safe_number($position, 'liq_price'),
            'entryPrice' => $this->safe_number($position, 'avg_entry_price'),
            'unrealizedPnl' => $this->safe_number($position, 'unrealized_pnl'),
            'realizedPnl' => $this->safe_number($position, 'realized_pnl'),
            'percentage' => null,
            'contracts' => $this->safe_number($position, 'close_avbl'),
            'contractSize' => $this->safe_number($market, 'contractSize'),
            'markPrice' => null,
            'lastPrice' => null,
            'side' => $this->safe_string($position, 'side'),
            'hedged' => null,
            'timestamp' => $timestamp,
            'datetime' => $this->iso8601($timestamp),
            'lastUpdateTimestamp' => $this->safe_integer($position, 'updated_at'),
            'maintenanceMargin' => $this->safe_number($position, 'maintenance_margin_value'),
            'maintenanceMarginPercentage' => $this->safe_number($position, 'maintenance_margin_rate'),
            'collateral' => $this->safe_number($position, 'margin_avbl'),
            'initialMargin' => null,
            'initialMarginPercentage' => null,
            'leverage' => $this->safe_number($position, 'leverage'),
            'marginRatio' => $this->safe_number($position, 'position_margin_rate'),
            'stopLossPrice' => $this->omit_zero($this->safe_string($position, 'stop_loss_price')),
            'takeProfitPrice' => $this->omit_zero($this->safe_string($position, 'take_profit_price')),
        ));
    }

    public function set_margin_mode(string $marginMode, ?string $symbol = null, $params = array ()) {
        return Async\async(function () use ($marginMode, $symbol, $params) {
            /**
             * set margin mode to 'cross' or 'isolated'
             *
             * @see https://docs.coinex.com/api/v2/futures/position/http/adjust-position-$leverage
             *
             * @param {string} $marginMode 'cross' or 'isolated'
             * @param {string} $symbol unified $market $symbol
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {int} $params->leverage the rate of $leverage
             * @return {array} response from the exchange
             */
            if ($symbol === null) {
                throw new ArgumentsRequired($this->id . ' setMarginMode() requires a $symbol argument');
            }
            $marginMode = strtolower($marginMode);
            if ($marginMode !== 'isolated' && $marginMode !== 'cross') {
                throw new BadRequest($this->id . ' setMarginMode() $marginMode argument should be isolated or cross');
            }
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            if ($market['type'] !== 'swap') {
                throw new BadSymbol($this->id . ' setMarginMode() supports swap contracts only');
            }
            $leverage = $this->safe_integer($params, 'leverage');
            $maxLeverage = $this->safe_integer($market['limits']['leverage'], 'max', 100);
            if ($leverage === null) {
                throw new ArgumentsRequired($this->id . ' setMarginMode() requires a $leverage parameter');
            }
            if (($leverage < 1) || ($leverage > $maxLeverage)) {
                throw new BadRequest($this->id . ' setMarginMode() $leverage should be between 1 and ' . (string) $maxLeverage . ' for ' . $symbol);
            }
            $request = array(
                'market' => $market['id'],
                'market_type' => 'FUTURES',
                'margin_mode' => $marginMode,
                'leverage' => $leverage,
            );
            return Async\await($this->v2PrivatePostFuturesAdjustPositionLeverage ($this->extend($request, $params)));
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             "leverage" => 1,
            //             "margin_mode" => "isolated"
            //         ),
            //         "message" => "OK"
            //     }
            //
        }) ();
    }

    public function set_leverage(int $leverage, ?string $symbol = null, $params = array ()) {
        return Async\async(function () use ($leverage, $symbol, $params) {
            /**
             *
             * @see https://docs.coinex.com/api/v2/futures/position/http/adjust-position-$leverage
             *
             * set the level of $leverage for a $market
             * @param {float} $leverage the rate of $leverage
             * @param {string} $symbol unified $market $symbol
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {string} [$params->marginMode] 'cross' or 'isolated' (default is 'cross')
             * @return {array} response from the exchange
             */
            if ($symbol === null) {
                throw new ArgumentsRequired($this->id . ' setLeverage() requires a $symbol argument');
            }
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            if (!$market['swap']) {
                throw new BadSymbol($this->id . ' setLeverage() supports swap contracts only');
            }
            $marginMode = null;
            list($marginMode, $params) = $this->handle_margin_mode_and_params('setLeverage', $params, 'cross');
            $minLeverage = $this->safe_integer($market['limits']['leverage'], 'min', 1);
            $maxLeverage = $this->safe_integer($market['limits']['leverage'], 'max', 100);
            if (($leverage < $minLeverage) || ($leverage > $maxLeverage)) {
                throw new BadRequest($this->id . ' setLeverage() $leverage should be between ' . (string) $minLeverage . ' and ' . (string) $maxLeverage . ' for ' . $symbol);
            }
            $request = array(
                'market' => $market['id'],
                'market_type' => 'FUTURES',
                'margin_mode' => $marginMode,
                'leverage' => $leverage,
            );
            return Async\await($this->v2PrivatePostFuturesAdjustPositionLeverage ($this->extend($request, $params)));
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             "leverage" => 1,
            //             "margin_mode" => "isolated"
            //         ),
            //         "message" => "OK"
            //     }
            //
        }) ();
    }

    public function fetch_leverage_tiers(?array $symbols = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbols, $params) {
            /**
             * retrieve information on the maximum leverage, and maintenance margin for trades of varying trade sizes
             *
             * @see https://docs.coinex.com/api/v2/futures/market/http/list-market-position-level
             *
             * @param {string[]|null} $symbols list of unified market $symbols
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} a dictionary of ~@link https://docs.ccxt.com/#/?id=leverage-tiers-structure leverage tiers structures~, indexed by market $symbols
             */
            Async\await($this->load_markets());
            $request = array();
            if ($symbols !== null) {
                $marketIds = $this->market_ids($symbols);
                $request['market'] = implode(',', $marketIds);
            }
            $response = Async\await($this->v2PublicGetFuturesPositionLevel ($this->extend($request, $params)));
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             array(
            //                 "level" => array(
            //                     array(
            //                         "amount" => "20001",
            //                         "leverage" => "20",
            //                         "maintenance_margin_rate" => "0.02",
            //                         "min_initial_margin_rate" => "0.05"
            //                     ),
            //                     array(
            //                         "amount" => "50001",
            //                         "leverage" => "10",
            //                         "maintenance_margin_rate" => "0.04",
            //                         "min_initial_margin_rate" => "0.1"
            //                     ),
            //                 ),
            //                 "market" => "MINAUSDT"
            //             ),
            //         ),
            //         "message" => "OK"
            //     }
            //
            $data = $this->safe_list($response, 'data', array());
            return $this->parse_leverage_tiers($data, $symbols, 'market');
        }) ();
    }

    public function parse_market_leverage_tiers($info, ?array $market = null): array {
        $tiers = array();
        $brackets = $this->safe_list($info, 'level', array());
        $minNotional = 0;
        for ($i = 0; $i < count($brackets); $i++) {
            $tier = $brackets[$i];
            $marketId = $this->safe_string($info, 'market');
            $market = $this->safe_market($marketId, $market, null, 'swap');
            $maxNotional = $this->safe_number($tier, 'amount');
            $tiers[] = array(
                'tier' => $this->sum($i, 1),
                'symbol' => $this->safe_symbol($marketId, $market, null, 'swap'),
                'currency' => $market['linear'] ? $market['base'] : $market['quote'],
                'minNotional' => $minNotional,
                'maxNotional' => $maxNotional,
                'maintenanceMarginRate' => $this->safe_number($tier, 'maintenance_margin_rate'),
                'maxLeverage' => $this->safe_integer($tier, 'leverage'),
                'info' => $tier,
            );
            $minNotional = $maxNotional;
        }
        return $tiers;
    }

    public function modify_margin_helper(string $symbol, $amount, $addOrReduce, $params = array ()) {
        return Async\async(function () use ($symbol, $amount, $addOrReduce, $params) {
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $rawAmount = $this->amount_to_precision($symbol, $amount);
            $requestAmount = $rawAmount;
            if ($addOrReduce === 'reduce') {
                $requestAmount = Precise::string_neg($rawAmount);
            }
            $request = array(
                'market' => $market['id'],
                'market_type' => 'FUTURES',
                'amount' => $requestAmount,
            );
            $response = Async\await($this->v2PrivatePostFuturesAdjustPositionMargin ($this->extend($request, $params)));
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             "adl_level" => 1,
            //             "ath_margin_size" => "2.034928",
            //             "ath_position_amount" => "0.0001",
            //             "avg_entry_price" => "61047.84",
            //             "bkr_price" => "30698.5600000000000004142",
            //             "close_avbl" => "0.0001",
            //             "cml_position_value" => "6.104784",
            //             "created_at" => 1715488472908,
            //             "leverage" => "3",
            //             "liq_price" => "30852.82412060301507579316",
            //             "maintenance_margin_rate" => "0.005",
            //             "maintenance_margin_value" => "0.03051465",
            //             "margin_avbl" => "3.034928",
            //             "margin_mode" => "isolated",
            //             "market" => "BTCUSDT",
            //             "market_type" => "FUTURES",
            //             "max_position_value" => "6.104784",
            //             "open_interest" => "0.0001",
            //             "position_id" => 306458800,
            //             "position_margin_rate" => "0.49713929272518077625",
            //             "realized_pnl" => "-0.003052392",
            //             "settle_price" => "61047.84",
            //             "settle_value" => "6.104784",
            //             "side" => "long",
            //             "stop_loss_price" => "0",
            //             "stop_loss_type" => "",
            //             "take_profit_price" => "0",
            //             "take_profit_type" => "",
            //             "unrealized_pnl" => "0",
            //             "updated_at" => 1715488805563
            //         ),
            //         "message" => "OK"
            //     }
            //
            $data = $this->safe_dict($response, 'data');
            $status = $this->safe_string_lower($response, 'message');
            $type = ($addOrReduce === 'reduce') ? 'reduce' : 'add';
            return $this->extend($this->parse_margin_modification($data, $market), array(
                'type' => $type,
                'amount' => $this->parse_number($amount),
                'status' => $status,
            ));
        }) ();
    }

    public function parse_margin_modification(array $data, ?array $market = null): array {
        //
        // addMargin/reduceMargin
        //
        //     {
        //         "adl_level" => 1,
        //         "ath_margin_size" => "2.034928",
        //         "ath_position_amount" => "0.0001",
        //         "avg_entry_price" => "61047.84",
        //         "bkr_price" => "30698.5600000000000004142",
        //         "close_avbl" => "0.0001",
        //         "cml_position_value" => "6.104784",
        //         "created_at" => 1715488472908,
        //         "leverage" => "3",
        //         "liq_price" => "30852.82412060301507579316",
        //         "maintenance_margin_rate" => "0.005",
        //         "maintenance_margin_value" => "0.03051465",
        //         "margin_avbl" => "3.034928",
        //         "margin_mode" => "isolated",
        //         "market" => "BTCUSDT",
        //         "market_type" => "FUTURES",
        //         "max_position_value" => "6.104784",
        //         "open_interest" => "0.0001",
        //         "position_id" => 306458800,
        //         "position_margin_rate" => "0.49713929272518077625",
        //         "realized_pnl" => "-0.003052392",
        //         "settle_price" => "61047.84",
        //         "settle_value" => "6.104784",
        //         "side" => "long",
        //         "stop_loss_price" => "0",
        //         "stop_loss_type" => "",
        //         "take_profit_price" => "0",
        //         "take_profit_type" => "",
        //         "unrealized_pnl" => "0",
        //         "updated_at" => 1715488805563
        //     }
        //
        // fetchMarginAdjustmentHistory
        //
        //     {
        //         "bkr_pirce" => "24698.56000000000000005224",
        //         "created_at" => 1715489978697,
        //         "leverage" => "3",
        //         "liq_price" => "24822.67336683417085432386",
        //         "margin_avbl" => "3.634928",
        //         "margin_change" => "-1.5",
        //         "margin_mode" => "isolated",
        //         "market" => "BTCUSDT",
        //         "market_type" => "FUTURES",
        //         "open_interest" => "0.0001",
        //         "position_id" => 306458800,
        //         "settle_price" => "61047.84"
        //     }
        //
        $marketId = $this->safe_string($data, 'market');
        $timestamp = $this->safe_integer_2($data, 'updated_at', 'created_at');
        $change = $this->safe_string($data, 'margin_change');
        return array(
            'info' => $data,
            'symbol' => $this->safe_symbol($marketId, $market, null, 'swap'),
            'type' => null,
            'marginMode' => 'isolated',
            'amount' => $this->parse_number(Precise::string_abs($change)),
            'total' => $this->safe_number($data, 'margin_avbl'),
            'code' => $market['quote'],
            'status' => null,
            'timestamp' => $timestamp,
            'datetime' => $this->iso8601($timestamp),
        );
    }

    public function add_margin(string $symbol, float $amount, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $amount, $params) {
            /**
             * add margin
             *
             * @see https://docs.coinex.com/api/v2/futures/position/http/adjust-position-margin
             *
             * @param {string} $symbol unified market $symbol
             * @param {float} $amount amount of margin to add
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=add-margin-structure margin structure~
             */
            return Async\await($this->modify_margin_helper($symbol, $amount, 'add', $params));
        }) ();
    }

    public function reduce_margin(string $symbol, float $amount, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $amount, $params) {
            /**
             * remove margin from a position
             *
             * @see https://docs.coinex.com/api/v2/futures/position/http/adjust-position-margin
             *
             * @param {string} $symbol unified market $symbol
             * @param {float} $amount the $amount of margin to remove
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=reduce-margin-structure margin structure~
             */
            return Async\await($this->modify_margin_helper($symbol, $amount, 'reduce', $params));
        }) ();
    }

    public function fetch_funding_history(?string $symbol = null, ?int $since = null, ?int $limit = null, $params = array ()) {
        return Async\async(function () use ($symbol, $since, $limit, $params) {
            /**
             * fetch the history of funding fee payments paid and received on this account
             *
             * @see https://docs.coinex.com/api/v2/futures/position/http/list-position-funding-history
             *
             * @param {string} $symbol unified $market $symbol
             * @param {int} [$since] the earliest time in ms to fetch funding history for
             * @param {int} [$limit] the maximum number of funding history structures to retrieve
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=funding-history-structure funding history structure~
             */
            if ($symbol === null) {
                throw new ArgumentsRequired($this->id . ' fetchFundingHistory() requires a $symbol argument');
            }
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $request = array(
                'market' => $market['id'],
                'market_type' => 'FUTURES',
            );
            list($request, $params) = $this->handle_until_option('end_time', $request, $params);
            if ($since !== null) {
                $request['start_time'] = $since;
            }
            if ($limit !== null) {
                $request['limit'] = $limit;
            }
            $response = Async\await($this->v2PrivateGetFuturesPositionFundingHistory ($this->extend($request, $params)));
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             array(
            //                 "ccy" => "USDT",
            //                 "created_at" => 1715673620183,
            //                 "funding_rate" => "0",
            //                 "funding_value" => "0",
            //                 "market" => "BTCUSDT",
            //                 "market_type" => "FUTURES",
            //                 "position_id" => 306458800,
            //                 "side" => "long"
            //             ),
            //         ),
            //         "message" => "OK",
            //         "pagination" => {
            //             "has_next" => true
            //         }
            //     }
            //
            $data = $this->safe_list($response, 'data', array());
            $result = array();
            for ($i = 0; $i < count($data); $i++) {
                $entry = $data[$i];
                $timestamp = $this->safe_integer($entry, 'created_at');
                $currencyId = $this->safe_string($entry, 'ccy');
                $code = $this->safe_currency_code($currencyId);
                $result[] = array(
                    'info' => $entry,
                    'symbol' => $symbol,
                    'code' => $code,
                    'timestamp' => $timestamp,
                    'datetime' => $this->iso8601($timestamp),
                    'id' => $this->safe_number($entry, 'position_id'),
                    'amount' => $this->safe_number($entry, 'funding_value'),
                );
            }
            return $result;
        }) ();
    }

    public function fetch_funding_rate(string $symbol, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $params) {
            /**
             * fetch the current funding rate
             *
             * @see https://docs.coinex.com/api/v2/futures/market/http/list-$market-funding-rate
             *
             * @param {string} $symbol unified $market $symbol
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=funding-rate-structure funding rate structure~
             */
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            if (!$market['swap']) {
                throw new BadSymbol($this->id . ' fetchFundingRate() supports swap contracts only');
            }
            $request = array(
                'market' => $market['id'],
            );
            $response = Async\await($this->v2PublicGetFuturesFundingRate ($this->extend($request, $params)));
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             {
            //                 "latest_funding_rate" => "0",
            //                 "latest_funding_time" => 1715731200000,
            //                 "mark_price" => "61602.22",
            //                 "market" => "BTCUSDT",
            //                 "max_funding_rate" => "0.00375",
            //                 "min_funding_rate" => "-0.00375",
            //                 "next_funding_rate" => "0.00021074",
            //                 "next_funding_time" => 1715760000000
            //             }
            //         ),
            //         "message" => "OK"
            //     }
            //
            $data = $this->safe_list($response, 'data', array());
            $first = $this->safe_dict($data, 0, array());
            return $this->parse_funding_rate($first, $market);
        }) ();
    }

    public function fetch_funding_interval(string $symbol, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $params) {
            /**
             * fetch the current funding rate interval
             *
             * @see https://docs.coinex.com/api/v2/futures/market/http/list-market-funding-rate
             *
             * @param {string} $symbol unified market $symbol
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=funding-rate-structure funding rate structure~
             */
            return Async\await($this->fetch_funding_rate($symbol, $params));
        }) ();
    }

    public function parse_funding_rate($contract, ?array $market = null): array {
        //
        // fetchFundingRate, fetchFundingRates, fetchFundingInterval
        //
        //     {
        //         "latest_funding_rate" => "0",
        //         "latest_funding_time" => 1715731200000,
        //         "mark_price" => "61602.22",
        //         "market" => "BTCUSDT",
        //         "max_funding_rate" => "0.00375",
        //         "min_funding_rate" => "-0.00375",
        //         "next_funding_rate" => "0.00021074",
        //         "next_funding_time" => 1715760000000
        //     }
        //
        $currentFundingTimestamp = $this->safe_integer($contract, 'latest_funding_time');
        $futureFundingTimestamp = $this->safe_integer($contract, 'next_funding_time');
        $fundingTimeString = $this->safe_string($contract, 'latest_funding_time');
        $nextFundingTimeString = $this->safe_string($contract, 'next_funding_time');
        $millisecondsInterval = Precise::string_sub($nextFundingTimeString, $fundingTimeString);
        $marketId = $this->safe_string($contract, 'market');
        return array(
            'info' => $contract,
            'symbol' => $this->safe_symbol($marketId, $market, null, 'swap'),
            'markPrice' => $this->safe_number($contract, 'mark_price'),
            'indexPrice' => null,
            'interestRate' => null,
            'estimatedSettlePrice' => null,
            'timestamp' => null,
            'datetime' => null,
            'fundingRate' => $this->safe_number($contract, 'latest_funding_rate'),
            'fundingTimestamp' => $currentFundingTimestamp,
            'fundingDatetime' => $this->iso8601($currentFundingTimestamp),
            'nextFundingRate' => $this->safe_number($contract, 'next_funding_rate'),
            'nextFundingTimestamp' => $futureFundingTimestamp,
            'nextFundingDatetime' => $this->iso8601($futureFundingTimestamp),
            'previousFundingRate' => null,
            'previousFundingTimestamp' => null,
            'previousFundingDatetime' => null,
            'interval' => $this->parse_funding_interval($millisecondsInterval),
        );
    }

    public function parse_funding_interval($interval) {
        $intervals = array(
            '3600000' => '1h',
            '14400000' => '4h',
            '28800000' => '8h',
            '57600000' => '16h',
            '86400000' => '24h',
        );
        return $this->safe_string($intervals, $interval, $interval);
    }

    public function fetch_funding_rates(?array $symbols = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbols, $params) {
            /**
             * fetch the current funding rates for multiple markets
             *
             * @see https://docs.coinex.com/api/v2/futures/market/http/list-$market-funding-rate
             *
             * @param {string[]} $symbols unified $market $symbols
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array[]} an array of ~@link https://docs.ccxt.com/#/?id=funding-rate-structure funding rate structures~
             */
            Async\await($this->load_markets());
            $symbols = $this->market_symbols($symbols);
            $request = array();
            $market = null;
            if ($symbols !== null) {
                $symbol = $this->safe_value($symbols, 0);
                $market = $this->market($symbol);
                if (!$market['swap']) {
                    throw new BadSymbol($this->id . ' fetchFundingRates() supports swap contracts only');
                }
                $marketIds = $this->market_ids($symbols);
                $request['market'] = implode(',', $marketIds);
            }
            $response = Async\await($this->v2PublicGetFuturesFundingRate ($this->extend($request, $params)));
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             {
            //                 "latest_funding_rate" => "0",
            //                 "latest_funding_time" => 1715731200000,
            //                 "mark_price" => "61602.22",
            //                 "market" => "BTCUSDT",
            //                 "max_funding_rate" => "0.00375",
            //                 "min_funding_rate" => "-0.00375",
            //                 "next_funding_rate" => "0.00021074",
            //                 "next_funding_time" => 1715760000000
            //             }
            //         ),
            //         "message" => "OK"
            //     }
            //
            $data = $this->safe_list($response, 'data', array());
            return $this->parse_funding_rates($data, $symbols);
        }) ();
    }

    public function withdraw(string $code, float $amount, string $address, ?string $tag = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($code, $amount, $address, $tag, $params) {
            /**
             * make a withdrawal
             *
             * @see https://docs.coinex.com/api/v2/assets/deposit-withdrawal/http/withdrawal
             *
             * @param {string} $code unified $currency $code
             * @param {float} $amount the $amount to withdraw
             * @param {string} $address the $address to withdraw to
             * @param {string} [$tag] memo
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {string} [$params->network] unified network $code
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=$transaction-structure $transaction structure~
             */
            list($tag, $params) = $this->handle_withdraw_tag_and_params($tag, $params);
            $this->check_address($address);
            Async\await($this->load_markets());
            $currency = $this->currency($code);
            $request = array(
                'ccy' => $currency['id'],
                'to_address' => $address, // must be authorized, inter-user transfer by a registered mobile phone number or an email $address is supported
                'amount' => $this->currency_to_precision($code, $amount), // the actual $amount without fees, https://www.coinex.com/fees
            );
            if ($tag !== null) {
                $request['memo'] = $tag;
            }
            $networkCode = null;
            list($networkCode, $params) = $this->handle_network_code_and_params($params);
            if ($networkCode !== null) {
                $request['chain'] = $this->network_code_to_id($networkCode); // required for on-chain, not required for inter-user transfer
            }
            $response = Async\await($this->v2PrivatePostAssetsWithdraw ($this->extend($request, $params)));
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             "withdraw_id" => 31193755,
            //             "created_at" => 1716874165038,
            //             "withdraw_method" => "ON_CHAIN",
            //             "ccy" => "USDT",
            //             "amount" => "17.3",
            //             "actual_amount" => "15",
            //             "chain" => "TRC20",
            //             "tx_fee" => "2.3",
            //             "fee_asset" => "USDT",
            //             "fee_amount" => "2.3",
            //             "to_address" => "TY5vq3MT6b5cQVAHWHtpGyPg1ERcQgi3UN",
            //             "memo" => "",
            //             "tx_id" => "",
            //             "confirmations" => 0,
            //             "explorer_address_url" => "https://tronscan.org/#/address/TY5vq3MT6b5cQVAHWHtpGyPg1ERcQgi3UN",
            //             "explorer_tx_url" => "https://tronscan.org/#/transaction/",
            //             "remark" => "",
            //             "status" => "audit_required"
            //         ),
            //         "message" => "OK"
            //     }
            //
            $transaction = $this->safe_dict($response, 'data', array());
            return $this->parse_transaction($transaction, $currency);
        }) ();
    }

    public function parse_transaction_status(?string $status) {
        $statuses = array(
            'audit' => 'pending',
            'pass' => 'pending',
            'audit_required' => 'pending',
            'processing' => 'pending',
            'confirming' => 'pending',
            'not_pass' => 'failed',
            'cancel' => 'canceled',
            'finish' => 'ok',
            'finished' => 'ok',
            'fail' => 'failed',
        );
        return $this->safe_string($statuses, $status, $status);
    }

    public function fetch_funding_rate_history(?string $symbol = null, ?int $since = null, ?int $limit = null, $params = array ()) {
        return Async\async(function () use ($symbol, $since, $limit, $params) {
            /**
             * fetches historical funding rate prices
             *
             * @see https://docs.coinex.com/api/v2/futures/market/http/list-$market-funding-rate-history
             *
             * @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 ~@link https://docs.ccxt.com/#/?id=funding-rate-history-structure funding rate structures~ to fetch
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {boolean} [$params->paginate] default false, when true will automatically $paginate by calling this endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-$params)
             * @param {int} [$params->until] $timestamp in ms of the latest funding rate
             * @return {array[]} a list of ~@link https://docs.ccxt.com/#/?id=funding-rate-history-structure funding rate structures~
             */
            if ($symbol === null) {
                throw new ArgumentsRequired($this->id . ' fetchFundingRateHistory() requires a $symbol argument');
            }
            Async\await($this->load_markets());
            $paginate = false;
            list($paginate, $params) = $this->handle_option_and_params($params, 'fetchFundingRateHistory', 'paginate');
            if ($paginate) {
                return Async\await($this->fetch_paginated_call_deterministic('fetchFundingRateHistory', $symbol, $since, $limit, '8h', $params, 1000));
            }
            $market = $this->market($symbol);
            $request = array(
                'market' => $market['id'],
            );
            if ($since !== null) {
                $request['start_time'] = $since;
            }
            if ($limit !== null) {
                $request['limit'] = $limit;
            }
            list($request, $params) = $this->handle_until_option('end_time', $request, $params);
            $response = Async\await($this->v2PublicGetFuturesFundingRateHistory ($this->extend($request, $params)));
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             array(
            //                 "actual_funding_rate" => "0",
            //                 "funding_time" => 1715731221761,
            //                 "market" => "BTCUSDT",
            //                 "theoretical_funding_rate" => "0"
            //             ),
            //         ),
            //         "message" => "OK",
            //         "pagination" => {
            //             "has_next" => true
            //         }
            //     }
            //
            $data = $this->safe_list($response, 'data', array());
            $rates = array();
            for ($i = 0; $i < count($data); $i++) {
                $entry = $data[$i];
                $marketId = $this->safe_string($entry, 'market');
                $symbolInner = $this->safe_symbol($marketId, $market, null, 'swap');
                $timestamp = $this->safe_integer($entry, 'funding_time');
                $rates[] = array(
                    'info' => $entry,
                    'symbol' => $symbolInner,
                    'fundingRate' => $this->safe_number($entry, 'actual_funding_rate'),
                    'timestamp' => $timestamp,
                    'datetime' => $this->iso8601($timestamp),
                );
            }
            $sorted = $this->sort_by($rates, 'timestamp');
            return $this->filter_by_symbol_since_limit($sorted, $market['symbol'], $since, $limit);
        }) ();
    }

    public function parse_transaction(array $transaction, ?array $currency = null): array {
        //
        // fetchDeposits
        //
        //     {
        //         "deposit_id" => 5173806,
        //         "created_at" => 1714021652557,
        //         "tx_id" => "d9f47d2550397c635cb89a8963118f8fe78ef048bc8b6f0caaeaa7dc6",
        //         "tx_id_display" => "",
        //         "ccy" => "USDT",
        //         "chain" => "TRC20",
        //         "deposit_method" => "ON_CHAIN",
        //         "amount" => "30",
        //         "actual_amount" => "",
        //         "to_address" => "TYewD2pVWDUwfNr9A",
        //         "confirmations" => 20,
        //         "status" => "FINISHED",
        //         "tx_explorer_url" => "https://tronscan.org/#/transaction",
        //         "to_addr_explorer_url" => "https://tronscan.org/#/address",
        //         "remark" => ""
        //     }
        //
        // fetchWithdrawals and withdraw
        //
        //     {
        //         "withdraw_id" => 259364,
        //         "created_at" => 1701323541548,
        //         "withdraw_method" => "ON_CHAIN",
        //         "ccy" => "USDT",
        //         "amount" => "23.845744",
        //         "actual_amount" => "22.445744",
        //         "chain" => "TRC20",
        //         "tx_fee" => "1.4",
        //         "fee_asset" => "USDT",
        //         "fee_amount" => "1.4",
        //         "to_address" => "T8t5i2454dhdhnnnGdi49vMbihvY",
        //         "memo" => "",
        //         "tx_id" => "1237623941964de9954ed2e36640228d78765c1026",
        //         "confirmations" => 18,
        //         "explorer_address_url" => "https://tronscan.org/#/address",
        //         "explorer_tx_url" => "https://tronscan.org/#/transaction",
        //         "remark" => "",
        //         "status" => "finished"
        //     }
        //
        $address = $this->safe_string($transaction, 'to_address');
        $tag = $this->safe_string($transaction, 'memo');
        if ($tag !== null) {
            if (strlen($tag) < 1) {
                $tag = null;
            }
        }
        $remark = $this->safe_string($transaction, 'remark');
        if ($remark !== null) {
            if (strlen($remark) < 1) {
                $remark = null;
            }
        }
        $txid = $this->safe_string($transaction, 'tx_id');
        if ($txid !== null) {
            if (strlen($txid) < 1) {
                $txid = null;
            }
        }
        $currencyId = $this->safe_string($transaction, 'ccy');
        $code = $this->safe_currency_code($currencyId, $currency);
        $timestamp = $this->safe_integer($transaction, 'created_at');
        $type = (is_array($transaction) && array_key_exists('withdraw_id', $transaction)) ? 'withdrawal' : 'deposit';
        $networkId = $this->safe_string($transaction, 'chain');
        $feeCost = $this->safe_string($transaction, 'tx_fee');
        $transferMethod = $this->safe_string_lower_2($transaction, 'withdraw_method', 'deposit_method');
        $internal = $transferMethod === 'local';
        $amount = $this->safe_number($transaction, 'actual_amount');
        if ($amount === null) {
            $amount = $this->safe_number($transaction, 'amount');
        }
        if ($type === 'deposit') {
            $feeCost = '0';
        }
        $feeCurrencyId = $this->safe_string($transaction, 'fee_asset');
        $fee = array(
            'cost' => $this->parse_number($feeCost),
            'currency' => $this->safe_currency_code($feeCurrencyId),
        );
        return array(
            'info' => $transaction,
            'id' => $this->safe_string_2($transaction, 'withdraw_id', 'deposit_id'),
            'txid' => $txid,
            'timestamp' => $timestamp,
            'datetime' => $this->iso8601($timestamp),
            'network' => $this->network_id_to_code($networkId),
            'address' => $address,
            'addressTo' => $address,
            'addressFrom' => null,
            'tag' => $tag,
            'tagTo' => null,
            'tagFrom' => null,
            'type' => $type,
            'amount' => $amount,
            'currency' => $code,
            'status' => $this->parse_transaction_status($this->safe_string($transaction, 'status')),
            'updated' => null,
            'fee' => $fee,
            'comment' => $remark,
            'internal' => $internal,
        );
    }

    public function transfer(string $code, float $amount, string $fromAccount, string $toAccount, $params = array ()): PromiseInterface {
        return Async\async(function () use ($code, $amount, $fromAccount, $toAccount, $params) {
            /**
             * transfer $currency internally between wallets on the same account
             *
             * @see https://docs.coinex.com/api/v2/assets/transfer/http/transfer
             *
             * @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 {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {string} [$params->symbol] unified ccxt $symbol, required when either the $fromAccount or $toAccount is margin
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=transfer-structure transfer structure~
             */
            Async\await($this->load_markets());
            $currency = $this->currency($code);
            $amountToPrecision = $this->currency_to_precision($code, $amount);
            $accountsByType = $this->safe_dict($this->options, 'accountsByType', array());
            $fromId = $this->safe_string($accountsByType, $fromAccount, $fromAccount);
            $toId = $this->safe_string($accountsByType, $toAccount, $toAccount);
            $request = array(
                'ccy' => $currency['id'],
                'amount' => $amountToPrecision,
                'from_account_type' => $fromId,
                'to_account_type' => $toId,
            );
            if (($fromAccount === 'margin') || ($toAccount === 'margin')) {
                $symbol = $this->safe_string($params, 'symbol');
                if ($symbol === null) {
                    throw new ArgumentsRequired($this->id . ' transfer() the $symbol parameter must be defined for a margin account');
                }
                $params = $this->omit($params, 'symbol');
                $request['market'] = $this->market_id($symbol);
            }
            if (($fromAccount !== 'spot') && ($toAccount !== 'spot')) {
                throw new BadRequest($this->id . ' transfer() can only be between spot and swap, or spot and margin, either the $fromAccount or $toAccount must be spot');
            }
            $response = Async\await($this->v2PrivatePostAssetsTransfer ($this->extend($request, $params)));
            //
            //     {
            //         "code" => 0,
            //         "data" => array(),
            //         "message" => "OK"
            //     }
            //
            return $this->extend($this->parse_transfer($response, $currency), array(
                'amount' => $this->parse_number($amountToPrecision),
                'fromAccount' => $fromAccount,
                'toAccount' => $toAccount,
            ));
        }) ();
    }

    public function parse_transfer_status($status) {
        $statuses = array(
            '0' => 'ok',
            'SUCCESS' => 'ok',
            'OK' => 'ok',
            'finished' => 'ok',
            'FINISHED' => 'ok',
        );
        return $this->safe_string($statuses, $status, $status);
    }

    public function parse_transfer(array $transfer, ?array $currency = null): array {
        $timestamp = $this->safe_integer($transfer, 'created_at');
        $currencyId = $this->safe_string($transfer, 'ccy');
        $fromId = $this->safe_string($transfer, 'from_account_type');
        $toId = $this->safe_string($transfer, 'to_account_type');
        $accountsById = $this->safe_value($this->options, 'accountsById', array());
        return array(
            'id' => null,
            'timestamp' => $timestamp,
            'datetime' => $this->iso8601($timestamp),
            'currency' => $this->safe_currency_code($currencyId, $currency),
            'amount' => $this->safe_number($transfer, 'amount'),
            'fromAccount' => $this->safe_string($accountsById, $fromId, $fromId),
            'toAccount' => $this->safe_string($accountsById, $toId, $toId),
            'status' => $this->parse_transfer_status($this->safe_string_2($transfer, 'code', 'status')),
        );
    }

    public function fetch_transfers(?string $code = null, ?int $since = null, ?int $limit = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($code, $since, $limit, $params) {
            /**
             * fetch a history of internal transfers made on an account
             *
             * @see https://docs.coinex.com/api/v2/assets/transfer/http/list-transfer-history
             *
             * @param {string} $code unified $currency $code of the $currency transferred
             * @param {int} [$since] the earliest time in ms to fetch transfers for
             * @param {int} [$limit] the maximum number of transfer structures to retrieve
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {string} [$params->marginMode] 'cross' or 'isolated' for fetching transfers to and from your margin account
             * @return {array[]} a list of ~@link https://docs.ccxt.com/#/?id=transfer-structure transfer structures~
             */
            Async\await($this->load_markets());
            if ($code === null) {
                throw new ArgumentsRequired($this->id . ' fetchTransfers() requires a $code argument');
            }
            $currency = $this->currency($code);
            $request = array(
                'ccy' => $currency['id'],
            );
            $marginMode = null;
            list($marginMode, $params) = $this->handle_margin_mode_and_params('fetchTransfers', $params);
            if ($marginMode !== null) {
                $request['transfer_type'] = 'MARGIN';
            } else {
                $request['transfer_type'] = 'FUTURES';
            }
            if ($since !== null) {
                $request['start_time'] = $since;
            }
            if ($limit !== null) {
                $request['limit'] = $limit;
            }
            list($request, $params) = $this->handle_until_option('end_time', $request, $params);
            $response = Async\await($this->v2PrivateGetAssetsTransferHistory ($this->extend($request, $params)));
            //
            //     {
            //         "data" => array(
            //             array(
            //                 "created_at" => 1715848480646,
            //                 "from_account_type" => "SPOT",
            //                 "to_account_type" => "FUTURES",
            //                 "ccy" => "USDT",
            //                 "amount" => "10",
            //                 "status" => "finished"
            //             ),
            //         ),
            //         "pagination" => array(
            //             "total" => 8,
            //             "has_next" => false
            //         ),
            //         "code" => 0,
            //         "message" => "OK"
            //     }
            //
            $data = $this->safe_list($response, 'data', array());
            return $this->parse_transfers($data, $currency, $since, $limit);
        }) ();
    }

    public function fetch_withdrawals(?string $code = null, ?int $since = null, ?int $limit = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($code, $since, $limit, $params) {
            /**
             * fetch all withdrawals made from an account
             *
             * @see https://docs.coinex.com/api/v2/assets/deposit-withdrawal/http/list-withdrawal-history
             *
             * @param {string} [$code] unified $currency $code
             * @param {int} [$since] the earliest time in ms to fetch withdrawals for
             * @param {int} [$limit] the maximum number of withdrawal structures to retrieve
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array[]} a list of ~@link https://docs.ccxt.com/#/?id=transaction-structure transaction structures~
             */
            Async\await($this->load_markets());
            $request = array();
            $currency = null;
            if ($code !== null) {
                $currency = $this->currency($code);
                $request['ccy'] = $currency['id'];
            }
            if ($limit !== null) {
                $request['limit'] = $limit;
            }
            $response = Async\await($this->v2PrivateGetAssetsWithdraw ($this->extend($request, $params)));
            //
            //     {
            //         "data" => array(
            //             array(
            //                 "withdraw_id" => 259364,
            //                 "created_at" => 1701323541548,
            //                 "withdraw_method" => "ON_CHAIN",
            //                 "ccy" => "USDT",
            //                 "amount" => "23.845744",
            //                 "actual_amount" => "22.445744",
            //                 "chain" => "TRC20",
            //                 "tx_fee" => "1.4",
            //                 "fee_asset" => "USDT",
            //                 "fee_amount" => "1.4",
            //                 "to_address" => "T8t5i2454dhdhnnnGdi49vMbihvY",
            //                 "memo" => "",
            //                 "tx_id" => "1237623941964de9954ed2e36640228d78765c1026",
            //                 "confirmations" => 18,
            //                 "explorer_address_url" => "https://tronscan.org/#/address",
            //                 "explorer_tx_url" => "https://tronscan.org/#/transaction",
            //                 "remark" => "",
            //                 "status" => "finished"
            //             ),
            //         ),
            //         "pagination" => array(
            //             "total" => 9,
            //             "has_next" => true
            //         ),
            //         "code" => 0,
            //         "message" => "OK"
            //     }
            //
            $data = $this->safe_list($response, 'data', array());
            return $this->parse_transactions($data, $currency, $since, $limit);
        }) ();
    }

    public function fetch_deposits(?string $code = null, ?int $since = null, ?int $limit = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($code, $since, $limit, $params) {
            /**
             * fetch all deposits made to an account
             *
             * @see https://docs.coinex.com/api/v2/assets/deposit-withdrawal/http/list-deposit-history
             *
             * @param {string} [$code] unified $currency $code
             * @param {int} [$since] the earliest time in ms to fetch deposits for
             * @param {int} [$limit] the maximum number of deposit structures to retrieve
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array[]} a list of ~@link https://docs.ccxt.com/#/?id=transaction-structure transaction structures~
             */
            Async\await($this->load_markets());
            $request = array();
            $currency = null;
            if ($code !== null) {
                $currency = $this->currency($code);
                $request['ccy'] = $currency['id'];
            }
            if ($limit !== null) {
                $request['limit'] = $limit;
            }
            $response = Async\await($this->v2PrivateGetAssetsDepositHistory ($this->extend($request, $params)));
            //
            //     {
            //         "data" => array(
            //             array(
            //                 "deposit_id" => 5173806,
            //                 "created_at" => 1714021652557,
            //                 "tx_id" => "d9f47d2550397c635cb89a8963118f8fe78ef048bc8b6f0caaeaa7dc6",
            //                 "tx_id_display" => "",
            //                 "ccy" => "USDT",
            //                 "chain" => "TRC20",
            //                 "deposit_method" => "ON_CHAIN",
            //                 "amount" => "30",
            //                 "actual_amount" => "",
            //                 "to_address" => "TYewD2pVWDUwfNr9A",
            //                 "confirmations" => 20,
            //                 "status" => "FINISHED",
            //                 "tx_explorer_url" => "https://tronscan.org/#/transaction",
            //                 "to_addr_explorer_url" => "https://tronscan.org/#/address",
            //                 "remark" => ""
            //             ),
            //         ),
            //         "paginatation" => array(
            //             "total" => 8,
            //             "has_next" => true
            //         ),
            //         "code" => 0,
            //         "message" => "OK"
            //     }
            //
            $data = $this->safe_list($response, 'data', array());
            return $this->parse_transactions($data, $currency, $since, $limit);
        }) ();
    }

    public function parse_isolated_borrow_rate(array $info, ?array $market = null): array {
        //
        //     {
        //         "market" => "BTCUSDT",
        //         "ccy" => "USDT",
        //         "leverage" => 10,
        //         "min_amount" => "60",
        //         "max_amount" => "500000",
        //         "daily_interest_rate" => "0.001"
        //     }
        //
        $marketId = $this->safe_string($info, 'market');
        $market = $this->safe_market($marketId, $market, null, 'spot');
        $currency = $this->safe_string($info, 'ccy');
        $rate = $this->safe_number($info, 'daily_interest_rate');
        $baseRate = null;
        $quoteRate = null;
        if ($currency === $market['baseId']) {
            $baseRate = $rate;
        } elseif ($currency === $market['quoteId']) {
            $quoteRate = $rate;
        }
        return array(
            'symbol' => $market['symbol'],
            'base' => $market['base'],
            'baseRate' => $baseRate,
            'quote' => $market['quote'],
            'quoteRate' => $quoteRate,
            'period' => 86400000,
            'timestamp' => null,
            'datetime' => null,
            'info' => $info,
        );
    }

    public function fetch_isolated_borrow_rate(string $symbol, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $params) {
            /**
             * fetch the rate of interest to borrow a $currency for margin trading
             *
             * @see https://docs.coinex.com/api/v2/assets/loan-flat/http/list-margin-interest-limit
             *
             * @param {string} $symbol unified $symbol of the $market to fetch the borrow rate for
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {string} $params->code unified $currency $code
             * @return {array} an ~@link https://docs.ccxt.com/#/?id=isolated-borrow-rate-structure isolated borrow rate structure~
             */
            Async\await($this->load_markets());
            $code = $this->safe_string($params, 'code');
            if ($code === null) {
                throw new ArgumentsRequired($this->id . ' fetchIsolatedBorrowRate() requires a $code parameter');
            }
            $params = $this->omit($params, 'code');
            $currency = $this->currency($code);
            $market = $this->market($symbol);
            $request = array(
                'market' => $market['id'],
                'ccy' => $currency['id'],
            );
            $response = Async\await($this->v2PrivateGetAssetsMarginInterestLimit ($this->extend($request, $params)));
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             "market" => "BTCUSDT",
            //             "ccy" => "USDT",
            //             "leverage" => 10,
            //             "min_amount" => "60",
            //             "max_amount" => "500000",
            //             "daily_interest_rate" => "0.001"
            //         ),
            //         "message" => "OK"
            //     }
            //
            $data = $this->safe_dict($response, 'data', array());
            return $this->parse_isolated_borrow_rate($data, $market);
        }) ();
    }

    public function fetch_borrow_interest(?string $code = null, ?string $symbol = null, ?int $since = null, ?int $limit = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($code, $symbol, $since, $limit, $params) {
            /**
             * fetch the $interest owed by the user for borrowing currency for margin trading
             *
             * @see https://docs.coinex.com/api/v2/assets/loan-flat/http/list-margin-borrow-history
             *
             * @param {string} [$code] unified currency $code
             * @param {string} [$symbol] unified $market $symbol when fetch $interest in isolated markets
             * @param {int} [$since] the earliest time in ms to fetch borrrow $interest for
             * @param {int} [$limit] the maximum number of structures to retrieve
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array[]} a list of ~@link https://docs.ccxt.com/#/?id=borrow-$interest-structure borrow $interest structures~
             */
            Async\await($this->load_markets());
            $request = array();
            $market = null;
            if ($symbol !== null) {
                $market = $this->market($symbol);
                $request['market'] = $market['id'];
            }
            if ($limit !== null) {
                $request['limit'] = $limit;
            }
            $response = Async\await($this->v2PrivateGetAssetsMarginBorrowHistory ($this->extend($request, $params)));
            //
            //     {
            //         "data" => array(
            //             array(
            //                 "borrow_id" => 2642934,
            //                 "created_at" => 1654761016000,
            //                 "market" => "BTCUSDT",
            //                 "ccy" => "USDT",
            //                 "daily_interest_rate" => "0.001",
            //                 "expired_at" => 1655625016000,
            //                 "borrow_amount" => "100",
            //                 "to_repaied_amount" => "0",
            //                 "is_auto_renew" => false,
            //                 "status" => "finish"
            //             ),
            //         ),
            //         "pagination" => array(
            //             "total" => 4,
            //             "has_next" => true
            //         ),
            //         "code" => 0,
            //         "message" => "OK"
            //     }
            //
            $rows = $this->safe_value($response, 'data', array());
            $interest = $this->parse_borrow_interests($rows, $market);
            return $this->filter_by_currency_since_limit($interest, $code, $since, $limit);
        }) ();
    }

    public function parse_borrow_interest(array $info, ?array $market = null): array {
        //
        //     {
        //         "borrow_id" => 2642934,
        //         "created_at" => 1654761016000,
        //         "market" => "BTCUSDT",
        //         "ccy" => "USDT",
        //         "daily_interest_rate" => "0.001",
        //         "expired_at" => 1655625016000,
        //         "borrow_amount" => "100",
        //         "to_repaied_amount" => "0",
        //         "is_auto_renew" => false,
        //         "status" => "finish"
        //     }
        //
        $marketId = $this->safe_string($info, 'market');
        $market = $this->safe_market($marketId, $market, null, 'spot');
        $timestamp = $this->safe_integer($info, 'expired_at');
        return array(
            'info' => $info,
            'symbol' => $market['symbol'],
            'currency' => $this->safe_currency_code($this->safe_string($info, 'ccy')),
            'interest' => $this->safe_number($info, 'to_repaied_amount'),
            'interestRate' => $this->safe_number($info, 'daily_interest_rate'),
            'amountBorrowed' => $this->safe_number($info, 'borrow_amount'),
            'marginMode' => 'isolated',
            'timestamp' => $timestamp,  // expiry time
            'datetime' => $this->iso8601($timestamp),
        );
    }

    public function borrow_isolated_margin(string $symbol, string $code, float $amount, $params = array ()) {
        return Async\async(function () use ($symbol, $code, $amount, $params) {
            /**
             * create a loan to borrow margin
             *
             * @see https://docs.coinex.com/api/v2/assets/loan-flat/http/margin-borrow
             *
             * @param {string} $symbol unified $market $symbol, required for coinex
             * @param {string} $code unified $currency $code of the $currency to borrow
             * @param {float} $amount the $amount to borrow
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {boolean} [$params->isAutoRenew] whether to renew the margin loan automatically or not, default is false
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=margin-loan-structure margin loan structure~
             */
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $currency = $this->currency($code);
            $isAutoRenew = $this->safe_bool_2($params, 'isAutoRenew', 'is_auto_renew', false);
            $params = $this->omit($params, 'isAutoRenew');
            $request = array(
                'market' => $market['id'],
                'ccy' => $currency['id'],
                'borrow_amount' => $this->currency_to_precision($code, $amount),
                'is_auto_renew' => $isAutoRenew,
            );
            $response = Async\await($this->v2PrivatePostAssetsMarginBorrow ($this->extend($request, $params)));
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             "borrow_id" => 13784021,
            //             "market" => "BTCUSDT",
            //             "ccy" => "USDT",
            //             "daily_interest_rate" => "0.001",
            //             "expired_at" => 1717299948340,
            //             "borrow_amount" => "60",
            //             "to_repaied_amount" => "60.0025",
            //             "status" => "loan"
            //         ),
            //         "message" => "OK"
            //     }
            //
            $data = $this->safe_dict($response, 'data', array());
            $transaction = $this->parse_margin_loan($data, $currency);
            return $this->extend($transaction, array(
                'amount' => $amount,
                'symbol' => $symbol,
            ));
        }) ();
    }

    public function repay_isolated_margin(string $symbol, string $code, $amount, $params = array ()) {
        return Async\async(function () use ($symbol, $code, $amount, $params) {
            /**
             * repay borrowed margin and interest
             *
             * @see https://docs.coinex.com/api/v2/assets/loan-flat/http/margin-repay
             *
             * @param {string} $symbol unified $market $symbol, required for coinex
             * @param {string} $code unified $currency $code of the $currency to repay
             * @param {float} $amount the $amount to repay
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {string} [$params->borrow_id] extra parameter that is not required
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=margin-loan-structure margin loan structure~
             */
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $currency = $this->currency($code);
            $request = array(
                'market' => $market['id'],
                'ccy' => $currency['id'],
                'amount' => $this->currency_to_precision($code, $amount),
            );
            $response = Async\await($this->v2PrivatePostAssetsMarginRepay ($this->extend($request, $params)));
            //
            //     {
            //         "code" => 0,
            //         "data" => array(),
            //         "message" => "OK"
            //     }
            //
            $data = $this->safe_dict($response, 'data', array());
            $transaction = $this->parse_margin_loan($data, $currency);
            return $this->extend($transaction, array(
                'amount' => $amount,
                'symbol' => $symbol,
            ));
        }) ();
    }

    public function parse_margin_loan($info, ?array $currency = null) {
        //
        //     {
        //         "borrow_id" => 13784021,
        //         "market" => "BTCUSDT",
        //         "ccy" => "USDT",
        //         "daily_interest_rate" => "0.001",
        //         "expired_at" => 1717299948340,
        //         "borrow_amount" => "60",
        //         "to_repaied_amount" => "60.0025",
        //         "status" => "loan"
        //     }
        //
        $currencyId = $this->safe_string($info, 'ccy');
        $marketId = $this->safe_string($info, 'market');
        $timestamp = $this->safe_integer($info, 'expired_at');
        return array(
            'id' => $this->safe_integer($info, 'borrow_id'),
            'currency' => $this->safe_currency_code($currencyId, $currency),
            'amount' => $this->safe_string($info, 'borrow_amount'),
            'symbol' => $this->safe_symbol($marketId, null, null, 'spot'),
            'timestamp' => $timestamp,
            'datetime' => $this->iso8601($timestamp),
            'info' => $info,
        );
    }

    public function fetch_deposit_withdraw_fee(string $code, $params = array ()) {
        return Async\async(function () use ($code, $params) {
            /**
             * fetch the fee for deposits and withdrawals
             *
             * @see https://docs.coinex.com/api/v2/assets/deposit-withdrawal/http/get-deposit-withdrawal-config
             *
             * @param {string} $code unified $currency $code
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=fee-structure fee structure~
             */
            Async\await($this->load_markets());
            $currency = $this->currency($code);
            $request = array(
                'ccy' => $currency['id'],
            );
            $response = Async\await($this->v2PublicGetAssetsDepositWithdrawConfig ($this->extend($request, $params)));
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             "asset" => array(
            //                 "ccy" => "USDT",
            //                 "deposit_enabled" => true,
            //                 "withdraw_enabled" => true,
            //                 "inter_transfer_enabled" => true,
            //                 "is_st" => false
            //             ),
            //             "chains" => array(
            //                 array(
            //                     "chain" => "TRC20",
            //                     "min_deposit_amount" => "2.4",
            //                     "min_withdraw_amount" => "2.4",
            //                     "deposit_enabled" => true,
            //                     "withdraw_enabled" => true,
            //                     "deposit_delay_minutes" => 0,
            //                     "safe_confirmations" => 10,
            //                     "irreversible_confirmations" => 20,
            //                     "deflation_rate" => "0",
            //                     "withdrawal_fee" => "2.4",
            //                     "withdrawal_precision" => 6,
            //                     "memo" => "",
            //                     "is_memo_required_for_deposit" => false,
            //                     "explorer_asset_url" => "https://tronscan.org/#/token20/TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"
            //                 ),
            //             )
            //         ),
            //         "message" => "OK"
            //     }
            //
            $data = $this->safe_dict($response, 'data', array());
            return $this->parse_deposit_withdraw_fee($data, $currency);
        }) ();
    }

    public function fetch_deposit_withdraw_fees(?array $codes = null, $params = array ()) {
        return Async\async(function () use ($codes, $params) {
            /**
             * fetch the fees for deposits and withdrawals
             *
             * @see https://docs.coinex.com/api/v2/assets/deposit-withdrawal/http/list-all-deposit-withdrawal-config
             *
             * @param $codes
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @return {array} a dictionary of ~@link https://docs.ccxt.com/#/?id=fee-structure fee structures~
             */
            Async\await($this->load_markets());
            $response = Async\await($this->v2PublicGetAssetsAllDepositWithdrawConfig ($params));
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             {
            //                 "asset" => array(
            //                     "ccy" => "CET",
            //                     "deposit_enabled" => true,
            //                     "withdraw_enabled" => true,
            //                     "inter_transfer_enabled" => true,
            //                     "is_st" => false
            //                 ),
            //                 "chains" => array(
            //                     array(
            //                         "chain" => "CSC",
            //                         "min_deposit_amount" => "0.8",
            //                         "min_withdraw_amount" => "8",
            //                         "deposit_enabled" => true,
            //                         "withdraw_enabled" => true,
            //                         "deposit_delay_minutes" => 0,
            //                         "safe_confirmations" => 10,
            //                         "irreversible_confirmations" => 20,
            //                         "deflation_rate" => "0",
            //                         "withdrawal_fee" => "0.026",
            //                         "withdrawal_precision" => 8,
            //                         "memo" => "",
            //                         "is_memo_required_for_deposit" => false,
            //                         "explorer_asset_url" => ""
            //                     ),
            //                 )
            //             }
            //         ),
            //         "message" => "OK"
            //     }
            //
            $data = $this->safe_list($response, 'data', array());
            $result = array();
            for ($i = 0; $i < count($data); $i++) {
                $item = $data[$i];
                $asset = $this->safe_dict($item, 'asset', array());
                $currencyId = $this->safe_string($asset, 'ccy');
                if ($currencyId === null) {
                    continue;
                }
                $code = $this->safe_currency_code($currencyId);
                if ($codes === null || $this->in_array($code, $codes)) {
                    $result[$code] = $this->parse_deposit_withdraw_fee($item);
                }
            }
            return $result;
        }) ();
    }

    public function parse_deposit_withdraw_fee($fee, ?array $currency = null) {
        //
        //     {
        //         "asset" => array(
        //             "ccy" => "USDT",
        //             "deposit_enabled" => true,
        //             "withdraw_enabled" => true,
        //             "inter_transfer_enabled" => true,
        //             "is_st" => false
        //         ),
        //         "chains" => array(
        //             array(
        //                 "chain" => "TRC20",
        //                 "min_deposit_amount" => "2.4",
        //                 "min_withdraw_amount" => "2.4",
        //                 "deposit_enabled" => true,
        //                 "withdraw_enabled" => true,
        //                 "deposit_delay_minutes" => 0,
        //                 "safe_confirmations" => 10,
        //                 "irreversible_confirmations" => 20,
        //                 "deflation_rate" => "0",
        //                 "withdrawal_fee" => "2.4",
        //                 "withdrawal_precision" => 6,
        //                 "memo" => "",
        //                 "is_memo_required_for_deposit" => false,
        //                 "explorer_asset_url" => "https://tronscan.org/#/token20/TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"
        //             ),
        //         )
        //     }
        //
        $result = array(
            'info' => $fee,
            'withdraw' => array(
                'fee' => null,
                'percentage' => null,
            ),
            'deposit' => array(
                'fee' => null,
                'percentage' => null,
            ),
            'networks' => array(),
        );
        $chains = $this->safe_list($fee, 'chains', array());
        $asset = $this->safe_dict($fee, 'asset', array());
        for ($i = 0; $i < count($chains); $i++) {
            $entry = $chains[$i];
            $isWithdrawEnabled = $this->safe_bool($entry, 'withdraw_enabled');
            if ($isWithdrawEnabled) {
                $result['withdraw']['fee'] = $this->safe_number($entry, 'withdrawal_fee');
                $result['withdraw']['percentage'] = false;
                $networkId = $this->safe_string($entry, 'chain');
                if ($networkId) {
                    $networkCode = $this->network_id_to_code($networkId, $this->safe_string($asset, 'ccy'));
                    $result['networks'][$networkCode] = array(
                        'withdraw' => array(
                            'fee' => $this->safe_number($entry, 'withdrawal_fee'),
                            'percentage' => false,
                        ),
                        'deposit' => array(
                            'fee' => null,
                            'percentage' => null,
                        ),
                    );
                }
            }
        }
        return $result;
    }

    public function fetch_leverage(string $symbol, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $params) {
            /**
             * fetch the set leverage for a $market
             *
             * @see https://docs.coinex.com/api/v2/assets/loan-flat/http/list-margin-interest-limit
             *
             * @param {string} $symbol unified $market $symbol
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {string} $params->code unified $currency $code
             * @return {array} a ~@link https://docs.ccxt.com/#/?id=leverage-structure leverage structure~
             */
            Async\await($this->load_markets());
            $code = $this->safe_string($params, 'code');
            if ($code === null) {
                throw new ArgumentsRequired($this->id . ' fetchLeverage() requires a $code parameter');
            }
            $params = $this->omit($params, 'code');
            $currency = $this->currency($code);
            $market = $this->market($symbol);
            $request = array(
                'market' => $market['id'],
                'ccy' => $currency['id'],
            );
            $response = Async\await($this->v2PrivateGetAssetsMarginInterestLimit ($this->extend($request, $params)));
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             "market" => "BTCUSDT",
            //             "ccy" => "USDT",
            //             "leverage" => 10,
            //             "min_amount" => "50",
            //             "max_amount" => "500000",
            //             "daily_interest_rate" => "0.001"
            //         ),
            //         "message" => "OK"
            //     }
            //
            $data = $this->safe_dict($response, 'data', array());
            return $this->parse_leverage($data, $market);
        }) ();
    }

    public function parse_leverage(array $leverage, ?array $market = null): array {
        //
        //     {
        //         "market" => "BTCUSDT",
        //         "ccy" => "USDT",
        //         "leverage" => 10,
        //         "min_amount" => "50",
        //         "max_amount" => "500000",
        //         "daily_interest_rate" => "0.001"
        //     }
        //
        $marketId = $this->safe_string($leverage, 'market');
        $leverageValue = $this->safe_integer($leverage, 'leverage');
        return array(
            'info' => $leverage,
            'symbol' => $this->safe_symbol($marketId, $market, null, 'spot'),
            'marginMode' => 'isolated',
            'longLeverage' => $leverageValue,
            'shortLeverage' => $leverageValue,
        );
    }

    public function fetch_position_history(string $symbol, ?int $since = null, ?int $limit = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $since, $limit, $params) {
            /**
             * fetches historical $positions
             *
             * @see https://docs.coinex.com/api/v2/futures/position/http/list-finished-position
             *
             * @param {string} $symbol unified contract $symbol
             * @param {int} [$since] the earliest time in ms to fetch $positions for
             * @param {int} [$limit] the maximum amount of $records to fetch, default is 10
             * @param {array} [$params] extra parameters specific to the exchange api endpoint
             * @param {int} [$params->until] the latest time in ms to fetch $positions for
             * @return {array[]} a list of ~@link https://docs.ccxt.com/#/?id=position-structure position structures~
             */
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $request = array(
                'market_type' => 'FUTURES',
                'market' => $market['id'],
            );
            if ($limit !== null) {
                $request['limit'] = $limit;
            }
            if ($since !== null) {
                $request['start_time'] = $since;
            }
            list($request, $params) = $this->handle_until_option('end_time', $request, $params);
            $response = Async\await($this->v2PrivateGetFuturesFinishedPosition ($this->extend($request, $params)));
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             {
            //                 "position_id" => 305891033,
            //                 "market" => "BTCUSDT",
            //                 "market_type" => "FUTURES",
            //                 "side" => "long",
            //                 "margin_mode" => "cross",
            //                 "open_interest" => "0.0001",
            //                 "close_avbl" => "0.0001",
            //                 "ath_position_amount" => "0.0001",
            //                 "unrealized_pnl" => "0",
            //                 "realized_pnl" => "-0.00311684",
            //                 "avg_entry_price" => "62336.8",
            //                 "cml_position_value" => "6.23368",
            //                 "max_position_value" => "6.23368",
            //                 "created_at" => 1715152208041,
            //                 "updated_at" => 1715152208041,
            //                 "take_profit_price" => "0",
            //                 "stop_loss_price" => "0",
            //                 "take_profit_type" => "",
            //                 "stop_loss_type" => "",
            //                 "settle_price" => "62336.8",
            //                 "settle_value" => "6.23368",
            //                 "leverage" => "3",
            //                 "margin_avbl" => "2.07789333",
            //                 "ath_margin_size" => "2.07789333",
            //                 "position_margin_rate" => "2.40545879023305655728",
            //                 "maintenance_margin_rate" => "0.005",
            //                 "maintenance_margin_value" => "0.03118094",
            //                 "liq_price" => "0",
            //                 "bkr_price" => "0",
            //                 "adl_level" => 1
            //             }
            //         ),
            //         "message" => "OK",
            //         "pagination" => {
            //             "has_next" => false
            //         }
            //     }
            //
            $records = $this->safe_list($response, 'data', array());
            $positions = $this->parse_positions($records);
            return $this->filter_by_symbol_since_limit($positions, $symbol, $since, $limit);
        }) ();
    }

    public function close_position(string $symbol, ?string $side = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $side, $params) {
            /**
             * closes an open position for a $market
             *
             * @see https://docs.coinex.com/api/v2/futures/position/http/close-position
             *
             * @param {string} $symbol unified CCXT $market $symbol
             * @param {string} [$side] buy or sell, not used by coinex
             * @param {array} [$params] extra parameters specific to the exchange API endpoint
             * @param {string} $params->type required by coinex, one of => limit, $market, maker_only, ioc or fok, default is *$market*
             * @param {string} [$params->price] the price to fulfill the order, ignored in $market orders
             * @param {string} [$params->amount] the amount to trade in units of the base currency
             * @param {string} [$params->clientOrderId] the client id of the order
             * @return {array} an ~@link https://docs.ccxt.com/#/?id=order-structure order structure~
             */
            Async\await($this->load_markets());
            $market = $this->market($symbol);
            $type = $this->safe_string($params, 'type', 'market');
            $request = array(
                'market' => $market['id'],
                'market_type' => 'FUTURES',
                'type' => $type,
            );
            $clientOrderId = $this->safe_string_2($params, 'client_id', 'clientOrderId');
            if ($clientOrderId !== null) {
                $request['client_id'] = $clientOrderId;
            }
            $params = $this->omit($params, 'clientOrderId');
            $response = Async\await($this->v2PrivatePostFuturesClosePosition ($this->extend($request, $params)));
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             "amount" => "0.0001",
            //             "client_id" => "",
            //             "created_at" => 1729666043969,
            //             "fee" => "0.00335858",
            //             "fee_ccy" => "USDT",
            //             "filled_amount" => "0.0001",
            //             "filled_value" => "6.717179",
            //             "last_filled_amount" => "0.0001",
            //             "last_filled_price" => "67171.79",
            //             "maker_fee_rate" => "0",
            //             "market" => "BTCUSDT",
            //             "market_type" => "FUTURES",
            //             "order_id" => 155477479761,
            //             "price" => "0",
            //             "realized_pnl" => "-0.001823",
            //             "side" => "sell",
            //             "taker_fee_rate" => "0.0005",
            //             "type" => "market",
            //             "unfilled_amount" => "0",
            //             "updated_at" => 1729666043969
            //         ),
            //         "message" => "OK"
            //     }
            //
            $data = $this->safe_dict($response, 'data', array());
            return $this->parse_order($data, $market);
        }) ();
    }

    public function handle_margin_mode_and_params($methodName, $params = array (), $defaultValue = null) {
        /**
         * @ignore
         * $marginMode specified by $params["marginMode"], $this->options["marginMode"], $this->options["defaultMarginMode"], $params["margin"] = true or $this->options["defaultType"] = 'margin'
         * @param {array} $params extra parameters specific to the exchange api endpoint
         * @return {Array} the $marginMode in lowercase
         */
        $defaultType = $this->safe_string($this->options, 'defaultType');
        $isMargin = $this->safe_bool($params, 'margin', false);
        $marginMode = null;
        list($marginMode, $params) = parent::handle_margin_mode_and_params($methodName, $params, $defaultValue);
        if ($marginMode === null) {
            if (($defaultType === 'margin') || ($isMargin === true)) {
                $marginMode = 'isolated';
            }
        }
        return array( $marginMode, $params );
    }

    public function nonce() {
        return $this->milliseconds();
    }

    public function sign($path, $api = [], $method = 'GET', $params = array (), $headers = null, $body = null) {
        $path = $this->implode_params($path, $params);
        $version = $api[0];
        $requestUrl = $api[1];
        $url = $this->urls['api'][$requestUrl] . '/' . $version . '/' . $path;
        $query = $this->omit($params, $this->extract_params($path));
        $nonce = (string) $this->nonce();
        if ($method === 'POST') {
            $parts = explode('/', $path);
            $firstPart = $this->safe_string($parts, 0, '');
            $numParts = count($parts);
            $lastPart = $this->safe_string($parts, $numParts - 1, '');
            $lastWords = explode('_', $lastPart);
            $numWords = count($lastWords);
            $lastWord = $this->safe_string($lastWords, $numWords - 1, '');
            if (($firstPart === 'order') && ($lastWord === 'limit' || $lastWord === 'market')) {
                // inject in implicit API calls
                // POST /order/limit - Place limit orders
                // POST /order/market - Place market orders
                // POST /order/stop/limit - Place stop limit orders
                // POST /order/stop/market - Place stop market orders
                // POST /perpetual/v1/order/put_limit - Place limit orders
                // POST /perpetual/v1/order/put_market - Place market orders
                // POST /perpetual/v1/order/put_stop_limit - Place stop limit orders
                // POST /perpetual/v1/order/put_stop_market - Place stop market orders
                $clientOrderId = $this->safe_string($params, 'client_id');
                if ($clientOrderId === null) {
                    $defaultId = 'x-167673045';
                    $brokerId = $this->safe_value($this->options, 'brokerId', $defaultId);
                    $query['client_id'] = $brokerId . '_' . $this->uuid16();
                }
            }
        }
        if ($requestUrl === 'perpetualPrivate') {
            $this->check_required_credentials();
            $query = $this->extend(array(
                'access_id' => $this->apiKey,
                'timestamp' => $nonce,
            ), $query);
            $query = $this->keysort($query);
            $urlencoded = $this->rawencode($query);
            $signature = $this->hash($this->encode($urlencoded . '&secret_key=' . $this->secret), 'sha256');
            $headers = array(
                'Authorization' => strtolower($signature),
                'AccessId' => $this->apiKey,
            );
            if (($method === 'GET') || ($method === 'PUT')) {
                $url .= '?' . $urlencoded;
            } else {
                $headers['Content-Type'] = 'application/x-www-form-urlencoded';
                $body = $urlencoded;
            }
        } elseif ($requestUrl === 'public' || $requestUrl === 'perpetualPublic') {
            if ($query) {
                $url .= '?' . $this->urlencode($query);
            }
        } else {
            if ($version === 'v1') {
                $this->check_required_credentials();
                $query = $this->extend(array(
                    'access_id' => $this->apiKey,
                    'tonce' => $nonce,
                ), $query);
                $query = $this->keysort($query);
                $urlencoded = $this->rawencode($query);
                $signature = $this->hash($this->encode($urlencoded . '&secret_key=' . $this->secret), 'md5');
                $headers = array(
                    'Authorization' => strtoupper($signature),
                    'Content-Type' => 'application/json',
                );
                if (($method === 'GET') || ($method === 'DELETE') || ($method === 'PUT')) {
                    $url .= '?' . $urlencoded;
                } else {
                    $body = $this->json($query);
                }
            } elseif ($version === 'v2') {
                $this->check_required_credentials();
                $query = $this->keysort($query);
                $urlencoded = $this->rawencode($query);
                $preparedString = $method . '/' . $version . '/' . $path;
                if ($method === 'POST') {
                    $body = $this->json($query);
                    $preparedString .= $body;
                } elseif ($urlencoded) {
                    $preparedString .= '?' . $urlencoded;
                }
                $preparedString .= $nonce . $this->secret;
                $signature = $this->hash($this->encode($preparedString), 'sha256');
                $headers = array(
                    'Content-Type' => 'application/json',
                    'Accept' => 'application/json',
                    'X-COINEX-KEY' => $this->apiKey,
                    'X-COINEX-SIGN' => $signature,
                    'X-COINEX-TIMESTAMP' => $nonce,
                );
                if ($method !== 'POST') {
                    if ($urlencoded) {
                        $url .= '?' . $urlencoded;
                    }
                }
            }
        }
        return array( 'url' => $url, 'method' => $method, 'body' => $body, 'headers' => $headers );
    }

    public function handle_errors(int $httpCode, string $reason, string $url, string $method, array $headers, string $body, $response, $requestHeaders, $requestBody) {
        if ($response === null) {
            return null;
        }
        $code = $this->safe_string($response, 'code');
        $data = $this->safe_value($response, 'data');
        $message = $this->safe_string($response, 'message');
        if (($code !== '0') || (($message !== 'Success') && ($message !== 'Succeeded') && (strtolower($message) !== 'ok') && !$data)) {
            $feedback = $this->id . ' ' . $message;
            $this->throw_broadly_matched_exception($this->exceptions['broad'], $message, $feedback);
            $this->throw_exactly_matched_exception($this->exceptions['exact'], $code, $feedback);
            throw new ExchangeError($feedback);
        }
        return null;
    }

    public function fetch_margin_adjustment_history(?string $symbol = null, ?string $type = null, ?float $since = null, ?float $limit = null, $params = array ()): PromiseInterface {
        return Async\async(function () use ($symbol, $type, $since, $limit, $params) {
            /**
             * fetches the history of margin added or reduced from contract isolated positions
             *
             * @see https://docs.coinex.com/api/v2/futures/position/http/list-position-margin-history
             *
             * @param {string} $symbol unified $market $symbol
             * @param {string} [$type] not used by coinex fetchMarginAdjustmentHistory
             * @param {int} [$since] timestamp in ms of the earliest change to fetch
             * @param {int} [$limit] the maximum amount of changes to fetch, default is 10
             * @param {array} $params extra parameters specific to the exchange api endpoint
             * @param {int} [$params->until] timestamp in ms of the latest change to fetch
             * @param {int} [$params->positionId] the id of the position that you want to retrieve margin adjustment history for
             * @return {array[]} a list of ~@link https://docs.ccxt.com/#/?id=margin-loan-structure margin structures~
             */
            Async\await($this->load_markets());
            if ($symbol === null) {
                throw new ArgumentsRequired($this->id . ' fetchMarginAdjustmentHistory() requires a $symbol argument');
            }
            $positionId = $this->safe_integer_2($params, 'positionId', 'position_id');
            $params = $this->omit($params, 'positionId');
            if ($positionId === null) {
                throw new ArgumentsRequired($this->id . ' fetchMarginAdjustmentHistory() requires a $positionId parameter');
            }
            $market = $this->market($symbol);
            $request = array(
                'market' => $market['id'],
                'market_type' => 'FUTURES',
                'position_id' => $positionId,
            );
            list($request, $params) = $this->handle_until_option('end_time', $request, $params);
            if ($since !== null) {
                $request['start_time'] = $since;
            }
            if ($limit !== null) {
                $request['limit'] = $limit;
            }
            $response = Async\await($this->v2PrivateGetFuturesPositionMarginHistory ($this->extend($request, $params)));
            //
            //     {
            //         "code" => 0,
            //         "data" => array(
            //             array(
            //                 "bkr_pirce" => "24698.56000000000000005224",
            //                 "created_at" => 1715489978697,
            //                 "leverage" => "3",
            //                 "liq_price" => "24822.67336683417085432386",
            //                 "margin_avbl" => "3.634928",
            //                 "margin_change" => "-1.5",
            //                 "margin_mode" => "isolated",
            //                 "market" => "BTCUSDT",
            //                 "market_type" => "FUTURES",
            //                 "open_interest" => "0.0001",
            //                 "position_id" => 306458800,
            //                 "settle_price" => "61047.84"
            //             ),
            //         ),
            //         "message" => "OK",
            //         "pagination" => {
            //             "has_next" => true
            //         }
            //     }
            //
            $data = $this->safe_list($response, 'data', array());
            $modifications = $this->parse_margin_modifications($data, null, 'market', 'swap');
            return $this->filter_by_symbol_since_limit($modifications, $symbol, $since, $limit);
        }) ();
    }
}
