# -*- coding: utf-8 -*-

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

from ccxt_zagrava.base.exchange import Exchange
from ccxt_zagrava.abstract.xt import ImplicitAPI
import hashlib
from ccxt_zagrava.base.types import Currencies, Currency, Int, LeverageTier, MarginModification, Market, Num, Order, OrderSide, OrderType, Str, Tickers, Transaction, TransferEntry
from typing import List
from ccxt_zagrava.base.errors import ExchangeError
from ccxt_zagrava.base.errors import AuthenticationError
from ccxt_zagrava.base.errors import PermissionDenied
from ccxt_zagrava.base.errors import ArgumentsRequired
from ccxt_zagrava.base.errors import BadRequest
from ccxt_zagrava.base.errors import BadSymbol
from ccxt_zagrava.base.errors import InsufficientFunds
from ccxt_zagrava.base.errors import InvalidOrder
from ccxt_zagrava.base.errors import NotSupported
from ccxt_zagrava.base.errors import NetworkError
from ccxt_zagrava.base.errors import RateLimitExceeded
from ccxt_zagrava.base.errors import OnMaintenance
from ccxt_zagrava.base.errors import RequestTimeout
from ccxt_zagrava.base.decimal_to_precision import TICK_SIZE
from ccxt_zagrava.base.precise import Precise


class xt(Exchange, ImplicitAPI):

    def describe(self):
        return self.deep_extend(super(xt, self).describe(), {
            'id': 'xt',
            'name': 'XT',
            'countries': ['SC'],  # Seychelles
            # spot api ratelimits are None, 10/s/ip, 50/s/ip, 100/s/ip or 200/s/ip
            # futures 3 requests per second => 1000ms / (100 * 3.33) = 3.003(get assets -> fetchMarkets & fetchCurrencies)
            # futures 10 requests per second => 1000ms / (100 * 1) = 10(all other)
            # futures 1000 times per minute for each single IP -> Otherwise account locked for 10min
            'rateLimit': 100,
            'version': 'v4',
            'certified': False,
            'pro': True,
            'has': {
                'CORS': False,
                'spot': True,
                'margin': True,
                'swap': True,
                'future': True,
                'option': False,
                'addMargin': True,
                'borrowMargin': False,
                'cancelAllOrders': True,
                'cancelOrder': True,
                'cancelOrders': True,
                'createDepositAddress': False,
                'createMarketBuyOrderWithCost': True,
                'createMarketSellOrderWithCost': False,
                'createOrder': True,
                'createPostOnlyOrder': False,
                'createReduceOnlyOrder': True,
                'editOrder': False,
                'fetchAccounts': False,
                'fetchBalance': True,
                'fetchBidsAsks': True,
                'fetchBorrowInterest': False,
                'fetchBorrowRate': False,
                'fetchBorrowRateHistories': False,
                'fetchBorrowRateHistory': False,
                'fetchBorrowRatesPerSymbol': False,
                'fetchCanceledOrders': True,
                'fetchClosedOrders': True,
                'fetchCurrencies': True,
                'fetchDeposit': False,
                'fetchDepositAddress': True,
                'fetchDeposits': True,
                'fetchDepositWithdrawals': False,
                'fetchDepositWithdrawFee': False,
                'fetchDepositWithdrawFees': False,
                'fetchFundingHistory': True,
                'fetchFundingRate': True,
                'fetchFundingRateHistory': True,
                'fetchFundingRates': False,
                'fetchIndexOHLCV': False,
                'fetchL3OrderBook': False,
                'fetchLedger': True,
                'fetchLedgerEntry': False,
                'fetchLeverage': False,
                'fetchLeverageTiers': True,
                'fetchMarketLeverageTiers': True,
                'fetchMarkets': True,
                'fetchMarkOHLCV': False,
                'fetchMyTrades': True,
                'fetchOHLCV': True,
                'fetchOpenInterest': False,
                'fetchOpenInterestHistory': False,
                'fetchOpenOrders': True,
                'fetchOrder': True,
                'fetchOrderBook': True,
                'fetchOrderBooks': False,
                'fetchOrders': True,
                'fetchOrdersByStatus': True,
                'fetchOrderTrades': False,
                'fetchPosition': True,
                'fetchPositions': True,
                'fetchPremiumIndexOHLCV': False,
                'fetchSettlementHistory': False,
                'fetchStatus': False,
                'fetchTicker': True,
                'fetchTickers': True,
                'fetchTime': True,
                'fetchTrades': True,
                'fetchTradingFee': False,
                'fetchTradingFees': False,
                'fetchTradingLimits': False,
                'fetchTransactionFee': False,
                'fetchTransactionFees': False,
                'fetchTransactions': False,
                'fetchTransfer': False,
                'fetchTransfers': False,
                'fetchWithdrawal': False,
                'fetchWithdrawals': True,
                'fetchWithdrawalWhitelist': False,
                'reduceMargin': True,
                'repayMargin': False,
                'setLeverage': True,
                'setMargin': False,
                'setMarginMode': False,
                'setPositionMode': False,
                'signIn': False,
                'transfer': True,
                'withdraw': True,
            },
            'precisionMode': TICK_SIZE,
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/14319357/232636712-466df2fc-560a-4ca4-aab2-b1d954a58e24.jpg',
                'api': {
                    'spot': 'https://sapi.xt.com',
                    'linear': 'https://fapi.xt.com',
                    'inverse': 'https://dapi.xt.com',
                    'user': 'https://api.xt.com',
                },
                'www': 'https://xt.com',
                'referral': 'https://www.xt.com/en/accounts/register?ref=9PTM9VW',
                'doc': [
                    'https://doc.xt.com/',
                    'https://github.com/xtpub/api-doc',
                ],
                'fees': 'https://www.xt.com/en/rate',
            },
            'api': {
                'public': {
                    'spot': {
                        'get': {
                            'currencies': 1,
                            'depth': 0.05,
                            'kline': 0.1,
                            'symbol': 1,  # 0.1 for a single symbol
                            'ticker': 1,  # 0.1 for a single symbol
                            'ticker/book': 1,  # 0.1 for a single symbol
                            'ticker/price': 1,  # 0.1 for a single symbol
                            'ticker/24h': 1,  # 0.1 for a single symbol
                            'time': 1,
                            'trade/history': 0.1,
                            'trade/recent': 0.1,
                            'wallet/support/currency': 1,
                        },
                    },
                    'linear': {
                        'get': {
                            'future/market/v1/public/contract/risk-balance': 1,
                            'future/market/v1/public/contract/open-interest': 1,
                            'future/market/v1/public/leverage/bracket/detail': 1,
                            'future/market/v1/public/leverage/bracket/list': 1,
                            'future/market/v1/public/q/agg-ticker': 1,
                            'future/market/v1/public/q/agg-tickers': 1,
                            'future/market/v1/public/q/deal': 1,
                            'future/market/v1/public/q/depth': 1,
                            'future/market/v1/public/q/funding-rate': 1,
                            'future/market/v1/public/q/funding-rate-record': 1,
                            'future/market/v1/public/q/index-price': 1,
                            'future/market/v1/public/q/kline': 1,
                            'future/market/v1/public/q/mark-price': 1,
                            'future/market/v1/public/q/symbol-index-price': 1,
                            'future/market/v1/public/q/symbol-mark-price': 1,
                            'future/market/v1/public/q/ticker': 1,
                            'future/market/v1/public/q/tickers': 1,
                            'future/market/v1/public/symbol/coins': 3.33,
                            'future/market/v1/public/symbol/detail': 3.33,
                            'future/market/v1/public/symbol/list': 1,
                        },
                    },
                    'inverse': {
                        'get': {
                            'future/market/v1/public/contract/risk-balance': 1,
                            'future/market/v1/public/contract/open-interest': 1,
                            'future/market/v1/public/leverage/bracket/detail': 1,
                            'future/market/v1/public/leverage/bracket/list': 1,
                            'future/market/v1/public/q/agg-ticker': 1,
                            'future/market/v1/public/q/agg-tickers': 1,
                            'future/market/v1/public/q/deal': 1,
                            'future/market/v1/public/q/depth': 1,
                            'future/market/v1/public/q/funding-rate': 1,
                            'future/market/v1/public/q/funding-rate-record': 1,
                            'future/market/v1/public/q/index-price': 1,
                            'future/market/v1/public/q/kline': 1,
                            'future/market/v1/public/q/mark-price': 1,
                            'future/market/v1/public/q/symbol-index-price': 1,
                            'future/market/v1/public/q/symbol-mark-price': 1,
                            'future/market/v1/public/q/ticker': 1,
                            'future/market/v1/public/q/tickers': 1,
                            'future/market/v1/public/symbol/coins': 3.33,
                            'future/market/v1/public/symbol/detail': 3.33,
                            'future/market/v1/public/symbol/list': 1,
                        },
                    },
                },
                'private': {
                    'spot': {
                        'get': {
                            'balance': 1,
                            'balances': 1,
                            'batch-order': 1,
                            'deposit/address': 1,
                            'deposit/history': 1,
                            'history-order': 1,
                            'open-order': 1,
                            'order': 1,
                            'order/{orderId}': 1,
                            'trade': 1,
                            'withdraw/history': 1,
                        },
                        'post': {
                            'order': 0.2,
                            'withdraw': 1,
                            'balance/transfer': 1,
                            'balance/account/transfer': 1,
                            'ws-token': 1,
                        },
                        'delete': {
                            'batch-order': 1,
                            'open-order': 1,
                            'order/{orderId}': 1,
                        },
                    },
                    'linear': {
                        'get': {
                            'future/trade/v1/entrust/plan-detail': 1,
                            'future/trade/v1/entrust/plan-list': 1,
                            'future/trade/v1/entrust/plan-list-history': 1,
                            'future/trade/v1/entrust/profit-detail': 1,
                            'future/trade/v1/entrust/profit-list': 1,
                            'future/trade/v1/order/detail': 1,
                            'future/trade/v1/order/list': 1,
                            'future/trade/v1/order/list-history': 1,
                            'future/trade/v1/order/trade-list': 1,
                            'future/user/v1/account/info': 1,
                            'future/user/v1/balance/bills': 1,
                            'future/user/v1/balance/detail': 1,
                            'future/user/v1/balance/funding-rate-list': 1,
                            'future/user/v1/balance/list': 1,
                            'future/user/v1/position/adl': 1,
                            'future/user/v1/position/list': 1,
                            'future/user/v1/user/collection/list': 1,
                            'future/user/v1/user/listen-key': 1,
                        },
                        'post': {
                            'future/trade/v1/entrust/cancel-all-plan': 1,
                            'future/trade/v1/entrust/cancel-all-profit-stop': 1,
                            'future/trade/v1/entrust/cancel-plan': 1,
                            'future/trade/v1/entrust/cancel-profit-stop': 1,
                            'future/trade/v1/entrust/create-plan': 1,
                            'future/trade/v1/entrust/create-profit': 1,
                            'future/trade/v1/entrust/update-profit-stop': 1,
                            'future/trade/v1/order/cancel': 1,
                            'future/trade/v1/order/cancel-all': 1,
                            'future/trade/v1/order/create': 1,
                            'future/trade/v1/order/create-batch': 1,
                            'future/user/v1/account/open': 1,
                            'future/user/v1/position/adjust-leverage': 1,
                            'future/user/v1/position/auto-margin': 1,
                            'future/user/v1/position/close-all': 1,
                            'future/user/v1/position/margin': 1,
                            'future/user/v1/user/collection/add': 1,
                            'future/user/v1/user/collection/cancel': 1,
                        },
                    },
                    'inverse': {
                        'get': {
                            'future/trade/v1/entrust/plan-detail': 1,
                            'future/trade/v1/entrust/plan-list': 1,
                            'future/trade/v1/entrust/plan-list-history': 1,
                            'future/trade/v1/entrust/profit-detail': 1,
                            'future/trade/v1/entrust/profit-list': 1,
                            'future/trade/v1/order/detail': 1,
                            'future/trade/v1/order/list': 1,
                            'future/trade/v1/order/list-history': 1,
                            'future/trade/v1/order/trade-list': 1,
                            'future/user/v1/account/info': 1,
                            'future/user/v1/balance/bills': 1,
                            'future/user/v1/balance/detail': 1,
                            'future/user/v1/balance/funding-rate-list': 1,
                            'future/user/v1/balance/list': 1,
                            'future/user/v1/position/adl': 1,
                            'future/user/v1/position/list': 1,
                            'future/user/v1/user/collection/list': 1,
                            'future/user/v1/user/listen-key': 1,
                        },
                        'post': {
                            'future/trade/v1/entrust/cancel-all-plan': 1,
                            'future/trade/v1/entrust/cancel-all-profit-stop': 1,
                            'future/trade/v1/entrust/cancel-plan': 1,
                            'future/trade/v1/entrust/cancel-profit-stop': 1,
                            'future/trade/v1/entrust/create-plan': 1,
                            'future/trade/v1/entrust/create-profit': 1,
                            'future/trade/v1/entrust/update-profit-stop': 1,
                            'future/trade/v1/order/cancel': 1,
                            'future/trade/v1/order/cancel-all': 1,
                            'future/trade/v1/order/create': 1,
                            'future/trade/v1/order/create-batch': 1,
                            'future/user/v1/account/open': 1,
                            'future/user/v1/position/adjust-leverage': 1,
                            'future/user/v1/position/auto-margin': 1,
                            'future/user/v1/position/close-all': 1,
                            'future/user/v1/position/margin': 1,
                            'future/user/v1/user/collection/add': 1,
                            'future/user/v1/user/collection/cancel': 1,
                        },
                    },
                    'user': {
                        'get': {
                            'user/account': 1,
                            'user/account/api-key': 1,
                        },
                        'post': {
                            'user/account': 1,
                            'user/account/api-key': 1,
                        },
                        'put': {
                            'user/account/api-key': 1,
                        },
                        'delete': {
                            'user/account/{apikeyId}': 1,
                        },
                    },
                },
            },
            'fees': {
                'spot': {
                    'tierBased': True,
                    'percentage': True,
                    'maker': self.parse_number('0.002'),
                    'taker': self.parse_number('0.002'),
                    'tiers': {
                        'maker': [
                            [self.parse_number('0'), self.parse_number('0.002')],
                            [self.parse_number('5000'), self.parse_number('0.0018')],
                            [self.parse_number('10000'), self.parse_number('0.0016')],
                            [self.parse_number('20000'), self.parse_number('0.0014')],
                            [self.parse_number('50000'), self.parse_number('0.0012')],
                            [self.parse_number('150000'), self.parse_number('0.0010')],
                            [self.parse_number('300000'), self.parse_number('0.0008')],
                            [self.parse_number('600000'), self.parse_number('0.0007')],
                            [self.parse_number('1200000'), self.parse_number('0.0006')],
                            [self.parse_number('2500000'), self.parse_number('0.0005')],
                            [self.parse_number('6000000'), self.parse_number('0.0004')],
                            [self.parse_number('15000000'), self.parse_number('0.0003')],
                            [self.parse_number('30000000'), self.parse_number('0.0002')],
                        ],
                        'taker': [
                            [self.parse_number('0'), self.parse_number('0.002')],
                            [self.parse_number('5000'), self.parse_number('0.0018')],
                            [self.parse_number('10000'), self.parse_number('0.0016')],
                            [self.parse_number('20000'), self.parse_number('0.0014')],
                            [self.parse_number('50000'), self.parse_number('0.0012')],
                            [self.parse_number('150000'), self.parse_number('0.0010')],
                            [self.parse_number('300000'), self.parse_number('0.0008')],
                            [self.parse_number('600000'), self.parse_number('0.0007')],
                            [self.parse_number('1200000'), self.parse_number('0.0006')],
                            [self.parse_number('2500000'), self.parse_number('0.0005')],
                            [self.parse_number('6000000'), self.parse_number('0.0004')],
                            [self.parse_number('15000000'), self.parse_number('0.0003')],
                            [self.parse_number('30000000'), self.parse_number('0.0002')],
                        ],
                    },
                },
                'contract': {
                    'tierBased': True,
                    'percentage': True,
                    'maker': self.parse_number('0.0004'),
                    'taker': self.parse_number('0.0006'),
                    'tiers': {
                        'maker': [
                            [self.parse_number('0'), self.parse_number('0.0004')],
                            [self.parse_number('200000'), self.parse_number('0.00038')],
                            [self.parse_number('1000000'), self.parse_number('0.00036')],
                            [self.parse_number('5000000'), self.parse_number('0.00034')],
                            [self.parse_number('10000000'), self.parse_number('0.00032')],
                            [self.parse_number('15000000'), self.parse_number('0.00028')],
                            [self.parse_number('30000000'), self.parse_number('0.00024')],
                            [self.parse_number('50000000'), self.parse_number('0.0002')],
                            [self.parse_number('100000000'), self.parse_number('0.00016')],
                            [self.parse_number('300000000'), self.parse_number('0.00012')],
                            [self.parse_number('500000000'), self.parse_number('0.00008')],
                        ],
                        'taker': [
                            [self.parse_number('0'), self.parse_number('0.0006')],
                            [self.parse_number('200000'), self.parse_number('0.000588')],
                            [self.parse_number('1000000'), self.parse_number('0.00057')],
                            [self.parse_number('5000000'), self.parse_number('0.00054')],
                            [self.parse_number('10000000'), self.parse_number('0.00051')],
                            [self.parse_number('15000000'), self.parse_number('0.00048')],
                            [self.parse_number('30000000'), self.parse_number('0.00045')],
                            [self.parse_number('50000000'), self.parse_number('0.00045')],
                            [self.parse_number('100000000'), self.parse_number('0.00036')],
                            [self.parse_number('300000000'), self.parse_number('0.00033')],
                            [self.parse_number('500000000'), self.parse_number('0.0003')],
                        ],
                    },
                },
            },
            'exceptions': {
                'exact': {
                    '400': NetworkError,  # {"returnCode":1,"msgInfo":"failure","error":{"code":"400","msg":"Connection refused: /10.0.26.71:8080"},"result":null}
                    '404': ExchangeError,  # interface does not exist
                    '429': RateLimitExceeded,  # The request is too frequent, please control the request rate according to the speed limit requirement
                    '500': ExchangeError,  # Service exception
                    '502': ExchangeError,  # Gateway exception
                    '503': OnMaintenance,  # Service unavailable, please try again later
                    'AUTH_001': AuthenticationError,  # missing request header xt-validate-appkey
                    'AUTH_002': AuthenticationError,  # missing request header xt-validate-timestamp
                    'AUTH_003': AuthenticationError,  # missing request header xt-validate-recvwindow
                    'AUTH_004': AuthenticationError,  # bad request header xt-validate-recvwindow
                    'AUTH_005': AuthenticationError,  # missing request header xt-validate-algorithms
                    'AUTH_006': AuthenticationError,  # bad request header xt-validate-algorithms
                    'AUTH_007': AuthenticationError,  # missing request header xt-validate-signature
                    'AUTH_101': AuthenticationError,  # ApiKey does not exist
                    'AUTH_102': AuthenticationError,  # ApiKey is not activated
                    'AUTH_103': AuthenticationError,  # Signature error, {"rc":1,"mc":"AUTH_103","ma":[],"result":null}
                    'AUTH_104': AuthenticationError,  # Unbound IP request
                    'AUTH_105': AuthenticationError,  # outdated message
                    'AUTH_106': PermissionDenied,  # Exceeded apikey permission
                    'SYMBOL_001': BadSymbol,  # Symbol not exist
                    'SYMBOL_002': BadSymbol,  # Symbol offline
                    'SYMBOL_003': BadSymbol,  # Symbol suspend trading
                    'SYMBOL_004': BadSymbol,  # Symbol country disallow trading
                    'SYMBOL_005': BadSymbol,  # The symbol does not support trading via API
                    'ORDER_001': InvalidOrder,  # Platform rejection
                    'ORDER_002': InsufficientFunds,  # insufficient funds
                    'ORDER_003': InvalidOrder,  # Trading Pair Suspended
                    'ORDER_004': InvalidOrder,  # no transaction
                    'ORDER_005': InvalidOrder,  # Order not exist
                    'ORDER_006': InvalidOrder,  # Too many open orders
                    'ORDER_007': PermissionDenied,  # The sub-account has no transaction authority
                    'ORDER_F0101': InvalidOrder,  # Trigger Price Filter - Min
                    'ORDER_F0102': InvalidOrder,  # Trigger Price Filter - Max
                    'ORDER_F0103': InvalidOrder,  # Trigger Price Filter - Step Value
                    'ORDER_F0201': InvalidOrder,  # Trigger Quantity Filter - Min
                    'ORDER_F0202': InvalidOrder,  # Trigger Quantity Filter - Max
                    'ORDER_F0203': InvalidOrder,  # Trigger Quantity Filter - Step Value
                    'ORDER_F0301': InvalidOrder,  # Trigger QUOTE_QTY Filter - Min Value
                    'ORDER_F0401': InvalidOrder,  # Trigger PROTECTION_ONLINE Filter
                    'ORDER_F0501': InvalidOrder,  # Trigger PROTECTION_LIMIT Filter - Buy Max Deviation
                    'ORDER_F0502': InvalidOrder,  # Trigger PROTECTION_LIMIT Filter - Sell Max Deviation
                    'ORDER_F0601': InvalidOrder,  # Trigger PROTECTION_MARKET Filter
                    'COMMON_001': ExchangeError,  # The user does not exist
                    'COMMON_002': ExchangeError,  # System busy, please try it later
                    'COMMON_003': BadRequest,  # Operation failed, please try it later
                    'CURRENCY_001': BadRequest,  # Information of currency is abnormal
                    'DEPOSIT_001': BadRequest,  # Deposit is not open
                    'DEPOSIT_002': PermissionDenied,  # The current account security level is low, please bind any two security verifications in mobile phone/email/Google Authenticator before deposit
                    'DEPOSIT_003': BadRequest,  # The format of address is incorrect, please enter again
                    'DEPOSIT_004': BadRequest,  # The address is already exists, please enter again
                    'DEPOSIT_005': BadRequest,  # Can not find the address of offline wallet
                    'DEPOSIT_006': BadRequest,  # No deposit address, please try it later
                    'DEPOSIT_007': BadRequest,  # Address is being generated, please try it later
                    'DEPOSIT_008': BadRequest,  # Deposit is not available
                    'WITHDRAW_001': BadRequest,  # Withdraw is not open
                    'WITHDRAW_002': BadRequest,  # The withdrawal address is invalid
                    'WITHDRAW_003': PermissionDenied,  # The current account security level is low, please bind any two security verifications in mobile phone/email/Google Authenticator before withdraw
                    'WITHDRAW_004': BadRequest,  # The withdrawal address is not added
                    'WITHDRAW_005': BadRequest,  # The withdrawal address cannot be empty
                    'WITHDRAW_006': BadRequest,  # Memo cannot be empty
                    'WITHDRAW_008': PermissionDenied,  # Risk control is triggered, withdraw of self currency is not currently supported
                    'WITHDRAW_009': PermissionDenied,  # Withdraw failed, some hasattr(self, assets) withdraw are restricted by T+1 withdraw
                    'WITHDRAW_010': BadRequest,  # The precision of withdrawal is invalid
                    'WITHDRAW_011': InsufficientFunds,  # free balance is not enough
                    'WITHDRAW_012': PermissionDenied,  # Withdraw failed, your remaining withdrawal limit today is not enough
                    'WITHDRAW_013': PermissionDenied,  # Withdraw failed, your remaining withdrawal limit today is not enough, the withdrawal amount can be increased by completing a higher level of real-name authentication
                    'WITHDRAW_014': BadRequest,  # This withdrawal address cannot be used in the internal transfer function, please cancel the internal transfer function before submitting
                    'WITHDRAW_015': BadRequest,  # The withdrawal amount is not enough to deduct the handling fee
                    'WITHDRAW_016': BadRequest,  # This withdrawal address is already exists
                    'WITHDRAW_017': BadRequest,  # This withdrawal has been processed and cannot be canceled
                    'WITHDRAW_018': BadRequest,  # Memo must be a number
                    'WITHDRAW_019': BadRequest,  # Memo is incorrect, please enter again
                    'WITHDRAW_020': PermissionDenied,  # Your withdrawal amount has reached the upper limit for today, please try it tomorrow
                    'WITHDRAW_021': PermissionDenied,  # Your withdrawal amount has reached the upper limit for today, you can only withdraw up to {0} self time
                    'WITHDRAW_022': BadRequest,  # Withdrawal amount must be greater than {0}
                    'WITHDRAW_023': BadRequest,  # Withdrawal amount must be less than {0}
                    'WITHDRAW_024': BadRequest,  # Withdraw is not supported
                    'WITHDRAW_025': BadRequest,  # Please create a FIO address in the deposit page
                    'FUND_001': BadRequest,  # Duplicate request(a bizId can only be requested once)
                    'FUND_002': InsufficientFunds,  # Insufficient account balance
                    'FUND_003': BadRequest,  # Transfer operations are not supported(for example, sub-accounts do not support financial transfers)
                    'FUND_004': ExchangeError,  # Unfreeze failed
                    'FUND_005': PermissionDenied,  # Transfer prohibited
                    'FUND_014': BadRequest,  # The transfer-in account id and transfer-out account ID cannot be the same
                    'FUND_015': BadRequest,  # From and to business types cannot be the same
                    'FUND_016': BadRequest,  # Leverage transfer, symbol cannot be empty
                    'FUND_017': BadRequest,  # Parameter error
                    'FUND_018': BadRequest,  # Invalid freeze record
                    'FUND_019': BadRequest,  # Freeze users not equal
                    'FUND_020': BadRequest,  # Freeze currency are not equal
                    'FUND_021': BadRequest,  # Operation not supported
                    'FUND_022': BadRequest,  # Freeze record does not exist
                    'FUND_044': BadRequest,  # The maximum length of the amount is 113 and cannot exceed the limit
                    'TRANSFER_001': BadRequest,  # Duplicate request(a bizId can only be requested once)
                    'TRANSFER_002': InsufficientFunds,  # Insufficient account balance
                    'TRANSFER_003': BadRequest,  # User not registered
                    'TRANSFER_004': PermissionDenied,  # The currency is not allowed to be transferred
                    'TRANSFER_005': PermissionDenied,  # The user’s currency is not allowed to be transferred
                    'TRANSFER_006': PermissionDenied,  # Transfer prohibited
                    'TRANSFER_007': RequestTimeout,  # Request timed out
                    'TRANSFER_008': BadRequest,  # Transferring to a leveraged account is abnormal
                    'TRANSFER_009': BadRequest,  # Departing from a leveraged account is abnormal
                    'TRANSFER_010': PermissionDenied,  # Leverage cleared, transfer prohibited
                    'TRANSFER_011': PermissionDenied,  # Leverage with borrowing, transfer prohibited
                    'TRANSFER_012': PermissionDenied,  # Currency transfer prohibited
                    'symbol_not_support_trading_via_api': BadSymbol,  # {"returnCode":1,"msgInfo":"failure","error":{"code":"symbol_not_support_trading_via_api","msg":"The symbol does not support trading via API"},"result":null}
                    'open_order_min_nominal_value_limit': InvalidOrder,  # {"returnCode":1,"msgInfo":"failure","error":{"code":"open_order_min_nominal_value_limit","msg":"Exceeds the minimum notional value of a single order"},"result":null}
                },
                'broad': {
                    'The symbol does not support trading via API': BadSymbol,  # {"returnCode":1,"msgInfo":"failure","error":{"code":"symbol_not_support_trading_via_api","msg":"The symbol does not support trading via API"},"result":null}
                    'Exceeds the minimum notional value of a single order': InvalidOrder,  # {"returnCode":1,"msgInfo":"failure","error":{"code":"open_order_min_nominal_value_limit","msg":"Exceeds the minimum notional value of a single order"},"result":null}
                },
            },
            'timeframes': {
                '1m': '1m',
                '5m': '5m',
                '15m': '15m',
                '30m': '30m',
                '1h': '1h',  # spot only
                '2h': '2h',  # spot only
                '4h': '4h',
                '6h': '6h',  # spot only
                '8h': '8h',  # spot only
                '1d': '1d',
                '3d': '3d',  # spot only
                '1w': '1w',
                '1M': '1M',  # spot only
            },
            'commonCurrencies': {},
            'options': {
                'adjustForTimeDifference': False,
                'timeDifference': 0,
                'accountsById': {
                    'spot': 'SPOT',
                    'leverage': 'LEVER',
                    'finance': 'FINANCE',
                    'swap': 'FUTURES_U',
                    'future': 'FUTURES_U',
                    'linear': 'FUTURES_U',
                    'inverse': 'FUTURES_C',
                },
                'networks': {
                    'ERC20': 'Ethereum',
                    'TRC20': 'Tron',
                    'BEP20': 'BNB Smart Chain',
                    'BEP2': 'BNB-BEP2',
                    'ETH': 'Ethereum',
                    'TRON': 'Tron',
                    'BNB': 'BNB Smart Chain',
                    'AVAX': 'AVAX C-Chain',
                    'GAL': 'GAL(FT)',
                    'ALEO': 'ALEO(IOU)',
                    'BTC': 'Bitcoin',
                    'XT': 'XT Smart Chain',
                    'ETC': 'Ethereum Classic',
                    'MATIC': 'Polygon',
                    'LTC': 'Litecoin',
                    'BTS': 'BitShares',
                    'XRP': 'Ripple',
                    'XLM': 'Stellar Network',
                    'ADA': 'Cardano',
                    'XWC': 'XWC-XWC',
                    'DOGE': 'dogecoin',
                    'DCR': 'Decred',
                    'SC': 'Siacoin',
                    'XTZ': 'Tezos',
                    'ZEC': 'Zcash',
                    'XMR': 'Monero',
                    'LSK': 'Lisk',
                    'ATOM': 'Cosmos',
                    'ONT': 'Ontology',
                    'ALGO': 'Algorand',
                    'SOL': 'SOL-SOL',
                    'DOT': 'Polkadot',
                    'ZEN': 'Horizen',
                    'FIL': 'Filecoin',
                    'CHZ': 'chz',
                    'ICP': 'Internet Computer',
                    'KSM': 'Kusama',
                    'LUNA': 'Terra',
                    'THETA': 'Theta Token',
                    'FTM': 'Fantom',
                    'VET': 'VeChain',
                    'NEAR': 'NEAR Protocol',
                    'ONE': 'Harmony',
                    'KLAY': 'Klaytn',
                    'AR': 'Arweave',
                    'CELT': 'OKT',
                    'EGLD': 'Elrond eGold',
                    'CRO': 'CRO-CRONOS',
                    'BCH': 'Bitcoin Cash',
                    'GLMR': 'Moonbeam',
                    'LOOP': 'LOOP-LRC',
                    'REI': 'REI Network',
                    'ASTR': 'Astar Network',
                    'OP': 'OPT',
                    'MMT': 'MMT-MMT',
                    'TBC': 'TBC-TBC',
                    'OMAX': 'OMAX-OMAX CHAIN',
                    'GMMT': 'GMMT chain',
                    'ZIL': 'Zilliqa',
                },
                'networksById': {
                    'Ethereum': 'ERC20',
                    'Tron': 'TRC20',
                    'BNB Smart Chain': 'BEP20',
                    'BNB-BEP2': 'BEP2',
                    'Bitcoin': 'BTC',
                    'XT Smart Chain': 'XT',
                    'Ethereum Classic': 'ETC',
                    'Polygon': 'MATIC',
                    'Litecoin': 'LTC',
                    'BitShares': 'BTS',
                    'Ripple': 'XRP',
                    'Stellar Network': 'XLM',
                    'Cardano': 'ADA',
                    'XWC-XWC': 'XWC',
                    'dogecoin': 'DOGE',
                    'Decred': 'DCR',
                    'Siacoin': 'SC',
                    'Tezos': 'XTZ',
                    'Zcash': 'ZEC',
                    'Monero': 'XMR',
                    'Lisk': 'LSK',
                    'Cosmos': 'ATOM',
                    'Ontology': 'ONT',
                    'Algorand': 'ALGO',
                    'SOL-SOL': 'SOL',
                    'Polkadot': 'DOT',
                    'Horizen': 'ZEN',
                    'Filecoin': 'FIL',
                    'chz': 'CHZ',
                    'Internet Computer': 'ICP',
                    'Kusama': 'KSM',
                    'Terra': 'LUNA',
                    'Theta Token': 'THETA',
                    'Fantom': 'FTM',
                    'VeChain': 'VET',
                    'AVAX C-Chain': 'AVAX',
                    'NEAR Protocol': 'NEAR',
                    'Harmony': 'ONE',
                    'Klaytn': 'KLAY',
                    'Arweave': 'AR',
                    'OKT': 'CELT',
                    'Elrond eGold': 'EGLD',
                    'CRO-CRONOS': 'CRO',
                    'Bitcoin Cash': 'BCH',
                    'Moonbeam': 'GLMR',
                    'LOOP-LRC': 'LOOP',
                    'REI Network': 'REI',
                    'Astar Network': 'ASTR',
                    'GAL(FT)': 'GAL',
                    'ALEO(IOU)': 'ALEO',
                    'OPT': 'OP',
                    'MMT-MMT': 'MMT',
                    'TBC-TBC': 'TBC',
                    'OMAX-OMAX CHAIN': 'OMAX',
                    'GMMT chain': 'GMMT',
                    'Zilliqa': 'ZIL',
                },
                'createMarketBuyOrderRequiresPrice': True,
                'recvWindow': '5000',  # in milliseconds, spot only
            },
        })

    def nonce(self):
        return self.milliseconds() - self.options['timeDifference']

    def fetch_time(self, params={}):
        """
        fetches the current integer timestamp in milliseconds from the xt server
        :see: https://doc.xt.com/#market1serverInfo
        :param dict params: extra parameters specific to the xt api endpoint
        :returns int: the current integer timestamp in milliseconds from the xt server
        """
        response = self.publicSpotGetTime(params)
        #
        #     {
        #         "rc": 0,
        #         "mc": "SUCCESS",
        #         "ma": [],
        #         "result": {
        #             "serverTime": 1677823301643
        #         }
        #     }
        #
        data = self.safe_value(response, 'result')
        return self.safe_integer(data, 'serverTime')

    def fetch_currencies(self, params={}) -> Currencies:
        """
        fetches all available currencies on an exchange
        :see: https://doc.xt.com/#deposit_withdrawalsupportedCurrenciesGet
        :param dict params: extra parameters specific to the xt api endpoint
        :returns dict: an associative dictionary of currencies
        """
        promisesRaw = [self.publicSpotGetWalletSupportCurrency(params), self.publicSpotGetCurrencies(params)]
        chainsResponse, currenciesResponse = promisesRaw
        #
        # currencies
        #
        #    {
        #        "time": "1686626116145",
        #        "version": "5dbbb2f2527c22b2b2e3b47187ef13d1",
        #        "currencies": [
        #            {
        #                "id": "2",
        #                "currency": "btc",
        #                "fullName": "Bitcoin",
        #                "logo": "https://a.static-global.com/1/currency/btc.png",
        #                "cmcLink": "https://coinmarketcap.com/currencies/bitcoin/",
        #                "weight": "99999",
        #                "maxPrecision": "10",
        #                "depositStatus": "1",
        #                "withdrawStatus": "1",
        #                "convertEnabled": "1",
        #                "transferEnabled": "1",
        #                "isChainExist": "1",
        #                "plates": [152]
        #            },
        #        ],
        #    }
        #
        #
        # chains
        #
        #     {
        #         "rc": 0,
        #         "mc": "SUCCESS",
        #         "ma": [],
        #         "result": [
        #             {
        #                 "currency": "btc",
        #                 "supportChains": [
        #                     {
        #                         "chain": "Bitcoin",
        #                         "depositEnabled": True,
        #                         "withdrawEnabled": True,
        #                         "withdrawFeeAmount": 0.0009,
        #                         "withdrawMinAmount": 0.0005,
        #                         "depositFeeRate": 0
        #                     },
        #                 ]
        #             },
        #         ]
        #     }
        #
        # note: individual network's full data is available on per-currency endpoint: https://www.xt.com/sapi/v4/balance/public/currency/11
        #
        chainsData = self.safe_value(chainsResponse, 'result', [])
        currenciesResult = self.safe_value(currenciesResponse, 'result', [])
        currenciesData = self.safe_value(currenciesResult, 'currencies', [])
        chainsDataIndexed = self.index_by(chainsData, 'currency')
        result = {}
        for i in range(0, len(currenciesData)):
            entry = currenciesData[i]
            currencyId = self.safe_string(entry, 'currency')
            code = self.safe_currency_code(currencyId)
            minPrecision = self.parse_number(self.parse_precision(self.safe_string(entry, 'maxPrecision')))
            networkEntry = self.safe_value(chainsDataIndexed, currencyId, {})
            rawNetworks = self.safe_value(networkEntry, 'supportChains', [])
            networks = {}
            minWithdrawString = None
            minWithdrawFeeString = None
            active = False
            deposit = False
            withdraw = False
            for j in range(0, len(rawNetworks)):
                rawNetwork = rawNetworks[j]
                networkId = self.safe_string(rawNetwork, 'chain')
                network = self.network_id_to_code(networkId)
                depositEnabled = self.safe_value(rawNetwork, 'depositEnabled')
                deposit = depositEnabled if (depositEnabled) else deposit
                withdrawEnabled = self.safe_value(rawNetwork, 'withdrawEnabled')
                withdraw = withdrawEnabled if (withdrawEnabled) else withdraw
                networkActive = depositEnabled and withdrawEnabled
                active = networkActive if (networkActive) else active
                withdrawFeeString = self.safe_string(rawNetwork, 'withdrawFeeAmount')
                if withdrawFeeString is not None:
                    minWithdrawFeeString = withdrawFeeString if (minWithdrawFeeString is None) else Precise.string_min(withdrawFeeString, minWithdrawFeeString)
                minNetworkWithdrawString = self.safe_string(rawNetwork, 'withdrawMinAmount')
                if minNetworkWithdrawString is not None:
                    minWithdrawString = minNetworkWithdrawString if (minWithdrawString is None) else Precise.string_min(minNetworkWithdrawString, minWithdrawString)
                networks[network] = {
                    'info': rawNetwork,
                    'id': networkId,
                    'network': network,
                    'name': None,
                    'active': networkActive,
                    'fee': self.parse_number(withdrawFeeString),
                    'precision': minPrecision,
                    'deposit': depositEnabled,
                    'withdraw': withdrawEnabled,
                    'limits': {
                        'amount': {
                            'min': None,
                            'max': None,
                        },
                        'withdraw': {
                            'min': self.parse_number(minNetworkWithdrawString),
                            'max': None,
                        },
                        'deposit': {
                            'min': None,
                            'max': None,
                        },
                    },
                }
            result[code] = {
                'info': entry,
                'id': currencyId,
                'code': code,
                'name': self.safe_string(entry, 'fullName'),
                'active': active,
                'fee': self.parse_number(minWithdrawFeeString),
                'precision': minPrecision,
                'deposit': deposit,
                'withdraw': withdraw,
                'networks': networks,
                'limits': {
                    'amount': {
                        'min': None,
                        'max': None,
                    },
                    'withdraw': {
                        'min': self.parse_number(minWithdrawString),
                        'max': None,
                    },
                    'deposit': {
                        'min': None,
                        'max': None,
                    },
                },
            }
        return result

    def fetch_markets(self, params={}) -> List[Market]:
        """
        retrieves data on all markets for xt
        :see: https://doc.xt.com/#market2symbol
        :see: https://doc.xt.com/#futures_quotesgetSymbols
        :param dict params: extra parameters specific to the xt api endpoint
        :returns dict[]: an array of objects representing market data
        """
        if self.options['adjustForTimeDifference']:
            self.load_time_difference()
        promisesUnresolved = [
            self.fetch_spot_markets(params),
            self.fetch_swap_and_future_markets(params),
        ]
        promises = promisesUnresolved
        spotMarkets = promises[0]
        swapAndFutureMarkets = promises[1]
        return self.array_concat(spotMarkets, swapAndFutureMarkets)

    def fetch_spot_markets(self, params={}):
        response = self.publicSpotGetSymbol(params)
        #
        #     {
        #         "rc": 0,
        #         "mc": "SUCCESS",
        #         "ma": [],
        #         "result": {
        #             "time": 1677881368812,
        #             "version": "abb101d1543e54bee40687b135411ba0",
        #             "symbols": [
        #                 {
        #                     "id": 640,
        #                     "symbol": "xt_usdt",
        #                     "state": "ONLINE",
        #                     "stateTime": 1554048000000,
        #                     "tradingEnabled": True,
        #                     "openapiEnabled": True,
        #                     "nextStateTime": null,
        #                     "nextState": null,
        #                     "depthMergePrecision": 5,
        #                     "baseCurrency": "xt",
        #                     "baseCurrencyPrecision": 8,
        #                     "baseCurrencyId": 128,
        #                     "quoteCurrency": "usdt",
        #                     "quoteCurrencyPrecision": 8,
        #                     "quoteCurrencyId": 11,
        #                     "pricePrecision": 4,
        #                     "quantityPrecision": 2,
        #                     "orderTypes": ["LIMIT","MARKET"],
        #                     "timeInForces": ["GTC","IOC"],
        #                     "displayWeight": 10002,
        #                     "displayLevel": "FULL",
        #                     "plates": [],
        #                     "filters":[
        #                         {
        #                             "filter": "QUOTE_QTY",
        #                             "min": "1"
        #                         },
        #                         {
        #                             "filter": "PROTECTION_LIMIT",
        #                             "buyMaxDeviation": "0.8",
        #                             "sellMaxDeviation": "4"
        #                         },
        #                         {
        #                             "filter": "PROTECTION_MARKET",
        #                             "maxDeviation": "0.02"
        #                         }
        #                     ]
        #                 },
        #             ]
        #         }
        #     }
        #
        data = self.safe_value(response, 'result', {})
        symbols = self.safe_value(data, 'symbols', [])
        return self.parse_markets(symbols)

    def fetch_swap_and_future_markets(self, params={}):
        markets = [self.publicLinearGetFutureMarketV1PublicSymbolList(params), self.publicInverseGetFutureMarketV1PublicSymbolList(params)]
        #
        #     {
        #         "returnCode": 0,
        #         "msgInfo": "success",
        #         "error": null,
        #         "result": [
        #             {
        #                 "id": 52,
        #                 "symbolGroupId": 71,
        #                 "symbol": "xt_usdt",
        #                 "pair": "xt_usdt",
        #                 "contractType": "PERPETUAL",
        #                 "productType": "perpetual",
        #                 "predictEventType": null,
        #                 "underlyingType": "U_BASED",
        #                 "contractSize": "1",
        #                 "tradeSwitch": True,
        #                 "isDisplay": True,
        #                 "isOpenApi": False,
        #                 "state": 0,
        #                 "initLeverage": 20,
        #                 "initPositionType": "CROSSED",
        #                 "baseCoin": "xt",
        #                 "quoteCoin": "usdt",
        #                 "baseCoinPrecision": 8,
        #                 "baseCoinDisplayPrecision": 4,
        #                 "quoteCoinPrecision": 8,
        #                 "quoteCoinDisplayPrecision": 4,
        #                 "quantityPrecision": 0,
        #                 "pricePrecision": 4,
        #                 "supportOrderType": "LIMIT,MARKET",
        #                 "supportTimeInForce": "GTC,FOK,IOC,GTX",
        #                 "supportEntrustType": "TAKE_PROFIT,STOP,TAKE_PROFIT_MARKET,STOP_MARKET,TRAILING_STOP_MARKET",
        #                 "supportPositionType": "CROSSED,ISOLATED",
        #                 "minQty": "1",
        #                 "minNotional": "5",
        #                 "maxNotional": "20000000",
        #                 "multiplierDown": "0.1",
        #                 "multiplierUp": "0.1",
        #                 "maxOpenOrders": 200,
        #                 "maxEntrusts": 200,
        #                 "makerFee": "0.0004",
        #                 "takerFee": "0.0006",
        #                 "liquidationFee": "0.01",
        #                 "marketTakeBound": "0.1",
        #                 "depthPrecisionMerge": 5,
        #                 "labels": ["HOT"],
        #                 "onboardDate": 1657101601000,
        #                 "enName": "XTUSDT ",
        #                 "cnName": "XTUSDT",
        #                 "minStepPrice": "0.0001",
        #                 "minPrice": null,
        #                 "maxPrice": null,
        #                 "deliveryDate": 1669879634000,
        #                 "deliveryPrice": null,
        #                 "deliveryCompletion": False,
        #                 "cnDesc": null,
        #                 "enDesc": null
        #             },
        #         ]
        #     }
        #
        swapAndFutureMarkets = self.array_concat(self.safe_value(markets[0], 'result', []), self.safe_value(markets[1], 'result', []))
        return self.parse_markets(swapAndFutureMarkets)

    def parse_markets(self, markets):
        result = []
        for i in range(0, len(markets)):
            result.append(self.parse_market(markets[i]))
        return result

    def parse_market(self, market: dict) -> Market:
        #
        # spot
        #
        #     {
        #         "id": 640,
        #         "symbol": "xt_usdt",
        #         "state": "ONLINE",
        #         "stateTime": 1554048000000,
        #         "tradingEnabled": True,
        #         "openapiEnabled": True,
        #         "nextStateTime": null,
        #         "nextState": null,
        #         "depthMergePrecision": 5,
        #         "baseCurrency": "xt",
        #         "baseCurrencyPrecision": 8,
        #         "baseCurrencyId": 128,
        #         "quoteCurrency": "usdt",
        #         "quoteCurrencyPrecision": 8,
        #         "quoteCurrencyId": 11,
        #         "pricePrecision": 4,
        #         "quantityPrecision": 2,
        #         "orderTypes": ["LIMIT","MARKET"],
        #         "timeInForces": ["GTC","IOC"],
        #         "displayWeight": 10002,
        #         "displayLevel": "FULL",
        #         "plates": [],
        #         "filters":[
        #             {
        #                 "filter": "QUOTE_QTY",
        #                 "min": "1"
        #             },
        #             {
        #                 "filter": "PRICE",
        #                 "min": null,
        #                 "max": null,
        #                 "tickSize": null
        #             },
        #             {
        #                 "filter": "QUANTITY",
        #                 "min": null,
        #                 "max": null,
        #                 "tickSize": null
        #             },
        #             {
        #                 "filter": "PROTECTION_LIMIT",
        #                 "buyMaxDeviation": "0.8",
        #                 "sellMaxDeviation": "4"
        #             },
        #             {
        #                 "filter": "PROTECTION_MARKET",
        #                 "maxDeviation": "0.02"
        #             },
        #             {
        #                  "filter": "PROTECTION_ONLINE",
        #                  "durationSeconds": "300",
        #                  "maxPriceMultiple": "5"
        #             },
        #         ]
        #     }
        #
        # swap and future
        #
        #     {
        #         "id": 52,
        #         "symbolGroupId": 71,
        #         "symbol": "xt_usdt",
        #         "pair": "xt_usdt",
        #         "contractType": "PERPETUAL",
        #         "productType": "perpetual",
        #         "predictEventType": null,
        #         "underlyingType": "U_BASED",
        #         "contractSize": "1",
        #         "tradeSwitch": True,
        #         "isDisplay": True,
        #         "isOpenApi": False,
        #         "state": 0,
        #         "initLeverage": 20,
        #         "initPositionType": "CROSSED",
        #         "baseCoin": "xt",
        #         "quoteCoin": "usdt",
        #         "baseCoinPrecision": 8,
        #         "baseCoinDisplayPrecision": 4,
        #         "quoteCoinPrecision": 8,
        #         "quoteCoinDisplayPrecision": 4,
        #         "quantityPrecision": 0,
        #         "pricePrecision": 4,
        #         "supportOrderType": "LIMIT,MARKET",
        #         "supportTimeInForce": "GTC,FOK,IOC,GTX",
        #         "supportEntrustType": "TAKE_PROFIT,STOP,TAKE_PROFIT_MARKET,STOP_MARKET,TRAILING_STOP_MARKET",
        #         "supportPositionType": "CROSSED,ISOLATED",
        #         "minQty": "1",
        #         "minNotional": "5",
        #         "maxNotional": "20000000",
        #         "multiplierDown": "0.1",
        #         "multiplierUp": "0.1",
        #         "maxOpenOrders": 200,
        #         "maxEntrusts": 200,
        #         "makerFee": "0.0004",
        #         "takerFee": "0.0006",
        #         "liquidationFee": "0.01",
        #         "marketTakeBound": "0.1",
        #         "depthPrecisionMerge": 5,
        #         "labels": ["HOT"],
        #         "onboardDate": 1657101601000,
        #         "enName": "XTUSDT ",
        #         "cnName": "XTUSDT",
        #         "minStepPrice": "0.0001",
        #         "minPrice": null,
        #         "maxPrice": null,
        #         "deliveryDate": 1669879634000,
        #         "deliveryPrice": null,
        #         "deliveryCompletion": False,
        #         "cnDesc": null,
        #         "enDesc": null
        #     }
        #
        id = self.safe_string(market, 'symbol')
        baseId = self.safe_string_2(market, 'baseCurrency', 'baseCoin')
        quoteId = self.safe_string_2(market, 'quoteCurrency', 'quoteCoin')
        base = self.safe_currency_code(baseId)
        quote = self.safe_currency_code(quoteId)
        state = self.safe_string(market, 'state')
        symbol = base + '/' + quote
        filters = self.safe_value(market, 'filters', [])
        minAmount = None
        maxAmount = None
        minCost = None
        maxCost = None
        minPrice = None
        maxPrice = None
        for i in range(0, len(filters)):
            entry = filters[i]
            filter = self.safe_string(entry, 'filter')
            if filter == 'QUANTITY':
                minAmount = self.safe_number(entry, 'min')
                maxAmount = self.safe_number(entry, 'max')
            if filter == 'QUOTE_QTY':
                minCost = self.safe_number(entry, 'min')
            if filter == 'PRICE':
                minPrice = self.safe_number(entry, 'min')
                maxPrice = self.safe_number(entry, 'max')
        underlyingType = self.safe_string(market, 'underlyingType')
        linear = None
        inverse = None
        settleId = None
        settle = None
        expiry = None
        future = False
        swap = False
        contract = False
        spot = True
        type = 'spot'
        if underlyingType == 'U_BASED':
            symbol = symbol + ':' + quote
            settleId = baseId
            settle = quote
            linear = True
            inverse = False
        elif underlyingType == 'COIN_BASED':
            symbol = symbol + ':' + base
            settleId = baseId
            settle = base
            linear = False
            inverse = True
        if underlyingType is not None:
            expiry = self.safe_integer(market, 'deliveryDate')
            productType = self.safe_string(market, 'productType')
            if productType != 'perpetual':
                symbol = symbol + '-' + self.yymmdd(expiry)
                type = 'future'
                future = True
            else:
                type = 'swap'
                swap = True
            minAmount = self.safe_number(market, 'minQty')
            minCost = self.safe_number(market, 'minNotional')
            maxCost = self.safe_number(market, 'maxNotional')
            minPrice = self.safe_number(market, 'minPrice')
            maxPrice = self.safe_number(market, 'maxPrice')
            contract = True
            spot = False
        isActive = False
        if contract:
            isActive = self.safe_value(market, 'isOpenApi', False)
        else:
            if (state == 'ONLINE') and (self.safe_value(market, 'tradingEnabled')) and (self.safe_value(market, 'openapiEnabled')):
                isActive = True
        return self.safe_market_structure({
            'id': id,
            'symbol': symbol,
            'base': base,
            'quote': quote,
            'settle': settle,
            'baseId': baseId,
            'quoteId': quoteId,
            'settleId': settleId,
            'type': type,
            'spot': spot,
            'margin': None,
            'swap': swap,
            'future': future,
            'option': False,
            'active': isActive,
            'contract': contract,
            'linear': linear,
            'inverse': inverse,
            'taker': self.safe_number(market, 'takerFee'),
            'maker': self.safe_number(market, 'makerFee'),
            'contractSize': self.safe_number(market, 'contractSize'),
            'expiry': expiry,
            'expiryDatetime': self.iso8601(expiry),
            'strike': None,
            'optionType': None,
            'precision': {
                'price': self.parse_number(self.parse_precision(self.safe_string(market, 'pricePrecision'))),
                'amount': self.parse_number(self.parse_precision(self.safe_string(market, 'quantityPrecision'))),
                'base': self.parse_number(self.parse_precision(self.safe_string(market, 'baseCoinPrecision'))),
                'quote': self.parse_number(self.parse_precision(self.safe_string(market, 'quoteCoinPrecision'))),
            },
            'limits': {
                'leverage': {
                    'min': self.parse_number('1'),
                    'max': None,
                },
                'amount': {
                    'min': minAmount,
                    'max': maxAmount,
                },
                'price': {
                    'min': minPrice,
                    'max': maxPrice,
                },
                'cost': {
                    'min': minCost,
                    'max': maxCost,
                },
            },
            'info': market,
        })

    def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}):
        """
        fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
        :see: https://doc.xt.com/#market4kline
        :see: https://doc.xt.com/#futures_quotesgetKLine
        :param str symbol: unified symbol of the market to fetch OHLCV data for
        :param str 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 dict params: extra parameters specific to the xt api endpoint
        :returns int[][]: A list of candles ordered, open, high, low, close, volume
        """
        self.load_markets()
        market = self.market(symbol)
        request = {
            'symbol': market['id'],
            'interval': self.safe_string(self.timeframes, timeframe, timeframe),
        }
        if since is not None:
            request['startTime'] = since
        if limit is not None:
            request['limit'] = limit
        response = None
        if market['linear']:
            response = self.publicLinearGetFutureMarketV1PublicQKline(self.extend(request, params))
        elif market['inverse']:
            response = self.publicInverseGetFutureMarketV1PublicQKline(self.extend(request, params))
        else:
            response = self.publicSpotGetKline(self.extend(request, params))
        #
        # spot
        #
        #     {
        #         "rc": 0,
        #         "mc": "SUCCESS",
        #         "ma": [],
        #         "result": [
        #             {
        #                 "t": 1678167720000,
        #                 "o": "22467.85",
        #                 "c": "22465.87",
        #                 "h": "22468.86",
        #                 "l": "22465.21",
        #                 "q": "1.316656",
        #                 "v": "29582.73018498"
        #             },
        #         ]
        #     }
        #
        # swap and future
        #
        #     {
        #         "returnCode": 0,
        #         "msgInfo": "success",
        #         "error": null,
        #         "result": [
        #             {
        #                 "s": "btc_usdt",
        #                 "p": "btc_usdt",
        #                 "t": 1678168020000,
        #                 "o": "22450.0",
        #                 "c": "22441.5",
        #                 "h": "22450.0",
        #                 "l": "22441.5",
        #                 "a": "312931",
        #                 "v": "702461.58895"
        #             },
        #         ]
        #     }
        #
        ohlcvs = self.safe_value(response, 'result', [])
        return self.parse_ohlcvs(ohlcvs, market, timeframe, since, limit)

    def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
        #
        # spot
        #
        #     {
        #         "t": 1678167720000,
        #         "o": "22467.85",
        #         "c": "22465.87",
        #         "h": "22468.86",
        #         "l": "22465.21",
        #         "q": "1.316656",
        #         "v": "29582.73018498"
        #     }
        #
        # swap and future
        #
        #     {
        #         "s": "btc_usdt",
        #         "p": "btc_usdt",
        #         "t": 1678168020000,
        #         "o": "22450.0",
        #         "c": "22441.5",
        #         "h": "22450.0",
        #         "l": "22441.5",
        #         "a": "312931",
        #         "v": "702461.58895"
        #     }
        #
        volumeIndex = 'v' if (market['inverse']) else 'a'
        return [
            self.safe_integer(ohlcv, 't'),
            self.safe_number(ohlcv, 'o'),
            self.safe_number(ohlcv, 'h'),
            self.safe_number(ohlcv, 'l'),
            self.safe_number(ohlcv, 'c'),
            self.safe_number_2(ohlcv, volumeIndex, 'v'),
        ]

    def fetch_order_book(self, symbol: str, limit: Int = None, params={}):
        """
        :see: https://doc.xt.com/#market3depth
        :see: https://doc.xt.com/#futures_quotesgetDepth
        fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
        :param str symbol: unified market symbol to fetch the order book for
        :param int [limit]: the maximum amount of order book entries to return
        :param dict params: extra parameters specific to the xt api endpoint
        :returns dict: A dictionary of `order book structures <https://docs.ccxt_zagrava.com/en/latest/manual.html#order-book-structure>` indexed by market symbols
        """
        self.load_markets()
        market = self.market(symbol)
        request = {
            'symbol': market['id'],
        }
        response = None
        if market['spot']:
            if limit is not None:
                request['limit'] = min(limit, 500)
            response = self.publicSpotGetDepth(self.extend(request, params))
        else:
            if limit is not None:
                request['level'] = min(limit, 50)
            else:
                request['level'] = 50
            if market['linear']:
                response = self.publicLinearGetFutureMarketV1PublicQDepth(self.extend(request, params))
            elif market['inverse']:
                response = self.publicInverseGetFutureMarketV1PublicQDepth(self.extend(request, params))
        #
        # spot
        #
        #     {
        #         "rc": 0,
        #         "mc": "SUCCESS",
        #         "ma": [],
        #         "result": {
        #             "timestamp": 1678169975184,
        #             "lastUpdateId": 1675333221812,
        #             "bids": [
        #                 ["22444.51", "0.129887"],
        #                 ["22444.49", "0.114245"],
        #                 ["22444.30", "0.225956"]
        #             ],
        #             "asks": [
        #                 ["22446.19", "0.095330"],
        #                 ["22446.24", "0.224413"],
        #                 ["22446.28", "0.329095"]
        #             ]
        #         }
        #     }
        #
        # swap and future
        #
        #     {
        #         "returnCode": 0,
        #         "msgInfo": "success",
        #         "error": null,
        #         "result": {
        #             "t": 1678170311005,
        #             "s": "btc_usdt",
        #             "u": 471694545627,
        #             "b": [
        #                 ["22426", "198623"],
        #                 ["22423.5", "80295"],
        #                 ["22423", "163580"]
        #             ],
        #             "a": [
        #                 ["22427", "3417"],
        #                 ["22428.5", "43532"],
        #                 ["22429", "119"]
        #             ]
        #         }
        #     }
        #
        orderBook = self.safe_value(response, 'result', {})
        timestamp = self.safe_integer_2(orderBook, 'timestamp', 't')
        if market['spot']:
            ob = self.parse_order_book(orderBook, symbol, timestamp)
            ob['nonce'] = self.safe_integer(orderBook, 'lastUpdateId')
            return ob
        swapOb = self.parse_order_book(orderBook, symbol, timestamp, 'b', 'a')
        swapOb['nonce'] = self.safe_integer_2(orderBook, 'u', 'lastUpdateId')
        return swapOb

    def fetch_ticker(self, symbol: str, params={}):
        """
        fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
        :see: https://doc.xt.com/#market10ticker24h
        :see: https://doc.xt.com/#futures_quotesgetAggTicker
        :param str symbol: unified market symbol to fetch the ticker for
        :param dict params: extra parameters specific to the xt api endpoint
        :returns dict: a `ticker structure <https://docs.ccxt_zagrava.com/en/latest/manual.html#ticker-structure>`
        """
        self.load_markets()
        market = self.market(symbol)
        request = {
            'symbol': market['id'],
        }
        response = None
        if market['linear']:
            response = self.publicLinearGetFutureMarketV1PublicQAggTicker(self.extend(request, params))
        elif market['inverse']:
            response = self.publicInverseGetFutureMarketV1PublicQAggTicker(self.extend(request, params))
        else:
            response = self.publicSpotGetTicker24h(self.extend(request, params))
        #
        # spot
        #
        #     {
        #         "rc": 0,
        #         "mc": "SUCCESS",
        #         "ma": [],
        #         "result": [
        #             {
        #                 "s": "btc_usdt",
        #                 "t": 1678172693931,
        #                 "cv": "34.00",
        #                 "cr": "0.0015",
        #                 "o": "22398.05",
        #                 "l": "22323.72",
        #                 "h": "22600.50",
        #                 "c": "22432.05",
        #                 "q": "7962.256931",
        #                 "v": "178675209.47416856"
        #             }
        #         ]
        #     }
        #
        # swap and future
        #
        #     {
        #         "returnCode": 0,
        #         "msgInfo": "success",
        #         "error": null,
        #         "result": {
        #             "t": 1678172848572,
        #             "s": "btc_usdt",
        #             "c": "22415.5",
        #             "h": "22590.0",
        #             "l": "22310.0",
        #             "a": "623654031",
        #             "v": "1399166074.31675",
        #             "o": "22381.5",
        #             "r": "0.0015",
        #             "i": "22424.5",
        #             "m": "22416.5",
        #             "bp": "22415",
        #             "ap": "22415.5"
        #         }
        #     }
        #
        ticker = self.safe_value(response, 'result')
        if market['spot']:
            return self.parse_ticker(ticker[0], market)
        return self.parse_ticker(ticker, market)

    def fetch_tickers(self, symbols: List[str] = None, params={}) -> Tickers:
        """
        fetches price tickers for multiple markets, statistical calculations with the information calculated over the past 24 hours each market
        :see: https://doc.xt.com/#market10ticker24h
        :see: https://doc.xt.com/#futures_quotesgetAggTickers
        :param str [symbols]: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
        :param dict params: extra parameters specific to the xt api endpoint
        :returns dict: an array of `ticker structures <https://docs.ccxt_zagrava.com/en/latest/manual.html#ticker-structure>`
        """
        self.load_markets()
        market = None
        if symbols is not None:
            symbols = self.market_symbols(symbols)
            market = self.market(symbols[0])
        request = {}
        type = None
        subType = None
        response = None
        type, params = self.handle_market_type_and_params('fetchTickers', market, params)
        subType, params = self.handle_sub_type_and_params('fetchTickers', market, params)
        if subType == 'inverse':
            response = self.publicInverseGetFutureMarketV1PublicQAggTickers(self.extend(request, params))
        elif (subType == 'linear') or (type == 'swap') or (type == 'future'):
            response = self.publicLinearGetFutureMarketV1PublicQAggTickers(self.extend(request, params))
        else:
            response = self.publicSpotGetTicker24h(self.extend(request, params))
        #
        # spot
        #
        #     {
        #         "rc": 0,
        #         "mc": "SUCCESS",
        #         "ma": [],
        #         "result": [
        #             {
        #                 "s": "btc_usdt",
        #                 "t": 1678172693931,
        #                 "cv": "34.00",
        #                 "cr": "0.0015",
        #                 "o": "22398.05",
        #                 "l": "22323.72",
        #                 "h": "22600.50",
        #                 "c": "22432.05",
        #                 "q": "7962.256931",
        #                 "v": "178675209.47416856"
        #             }
        #         ]
        #     }
        #
        # swap and future
        #
        #     {
        #         "returnCode": 0,
        #         "msgInfo": "success",
        #         "error": null,
        #         "result": [
        #             {
        #                 "t": 1680738775108,
        #                 "s": "badger_usdt",
        #                 "c": "2.7176",
        #                 "h": "2.7917",
        #                 "l": "2.6818",
        #                 "a": "88332",
        #                 "v": "242286.3520",
        #                 "o": "2.7422",
        #                 "r": "-0.0089",
        #                 "i": "2.7155",
        #                 "m": "2.7161",
        #                 "bp": "2.7152",
        #                 "ap": "2.7176"
        #             },
        #         ]
        #     }
        #
        tickers = self.safe_value(response, 'result', [])
        result = {}
        for i in range(0, len(tickers)):
            ticker = self.parse_ticker(tickers[i], market)
            symbol = ticker['symbol']
            result[symbol] = ticker
        return self.filter_by_array(result, 'symbol', symbols)

    def fetch_bids_asks(self, symbols: List[str] = None, params={}):
        """
        fetches the bid and ask price and volume for multiple markets
        :see: https://doc.xt.com/#market9tickerBook
        :param str [symbols]: unified symbols of the markets to fetch the bids and asks for, all markets are returned if not assigned
        :param dict params: extra parameters specific to the xt api endpoint
        :returns dict: a dictionary of `ticker structures <https://docs.ccxt_zagrava.com/en/latest/manual.html#ticker-structure>`
        """
        self.load_markets()
        symbols = self.market_symbols(symbols)
        request = {}
        market = None
        if symbols is not None:
            market = self.market(symbols[0])
        subType = None
        subType, params = self.handle_sub_type_and_params('fetchBidsAsks', market, params)
        if subType is not None:
            raise NotSupported(self.id + ' fetchBidsAsks() is not available for swap and future markets, only spot markets are supported')
        response = self.publicSpotGetTickerBook(self.extend(request, params))
        #
        #     {
        #         "rc": 0,
        #         "mc": "SUCCESS",
        #         "ma": [],
        #         "result": [
        #             {
        #                 "s": "kas_usdt",
        #                 "t": 1679539891853,
        #                 "ap": "0.016298",
        #                 "aq": "5119.09",
        #                 "bp": "0.016290",
        #                 "bq": "135.37"
        #             },
        #         ]
        #     }
        #
        tickers = self.safe_value(response, 'result', [])
        return self.parse_tickers(tickers, symbols)

    def parse_ticker(self, ticker, market=None):
        #
        # spot: fetchTicker, fetchTickers
        #
        #     {
        #         "s": "btc_usdt",
        #         "t": 1678172693931,
        #         "cv": "34.00",
        #         "cr": "0.0015",
        #         "o": "22398.05",
        #         "l": "22323.72",
        #         "h": "22600.50",
        #         "c": "22432.05",
        #         "q": "7962.256931",
        #         "v": "178675209.47416856"
        #     }
        #
        # swap and future: fetchTicker, fetchTickers
        #
        #     {
        #         "t": 1678172848572,
        #         "s": "btc_usdt",
        #         "c": "22415.5",
        #         "h": "22590.0",
        #         "l": "22310.0",
        #         "a": "623654031",
        #         "v": "1399166074.31675",
        #         "o": "22381.5",
        #         "r": "0.0015",
        #         "i": "22424.5",
        #         "m": "22416.5",
        #         "bp": "22415",
        #         "ap": "22415.5"
        #     }
        #
        # fetchBidsAsks
        #
        #     {
        #         "s": "kas_usdt",
        #         "t": 1679539891853,
        #         "ap": "0.016298",
        #         "aq": "5119.09",
        #         "bp": "0.016290",
        #         "bq": "135.37"
        #     }
        #
        marketId = self.safe_string(ticker, 's')
        marketType = market['type'] if (market is not None) else None
        hasSpotKeys = ('cv' in ticker) or ('aq' in ticker)
        if marketType is None:
            marketType = 'spot' if hasSpotKeys else 'contract'
        market = self.safe_market(marketId, market, '_', marketType)
        symbol = market['symbol']
        timestamp = self.safe_integer(ticker, 't')
        return self.safe_ticker({
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': self.iso8601(timestamp),
            'high': self.safe_number(ticker, 'h'),
            'low': self.safe_number(ticker, 'l'),
            'bid': self.safe_number(ticker, 'bp'),
            'bidVolume': self.safe_number(ticker, 'bq'),
            'ask': self.safe_number(ticker, 'ap'),
            'askVolume': self.safe_number(ticker, 'aq'),
            'vwap': None,
            'open': self.safe_string(ticker, 'o'),
            'close': self.safe_string(ticker, 'c'),
            'last': self.safe_string(ticker, 'c'),
            'previousClose': None,
            'change': self.safe_number(ticker, 'cv'),
            'percentage': self.safe_number_2(ticker, 'cr', 'r'),
            'average': None,
            'baseVolume': None,
            'quoteVolume': self.safe_number_2(ticker, 'a', 'v'),
            'info': ticker,
        }, market)

    def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}):
        """
        get the list of most recent trades for a particular symbol
        :see: https://doc.xt.com/#market5tradeRecent
        :see: https://doc.xt.com/#futures_quotesgetDeal
        :param str symbol: unified market symbol 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 dict params: extra parameters specific to the xt api endpoint
        :returns dict[]: a list of `trade structures <https://docs.ccxt_zagrava.com/en/latest/manual.html?#public-trades>`
        """
        self.load_markets()
        market = self.market(symbol)
        request = {
            'symbol': market['id'],
        }
        response = None
        if market['spot']:
            if limit is not None:
                request['limit'] = limit
            response = self.publicSpotGetTradeRecent(self.extend(request, params))
        else:
            if limit is not None:
                request['num'] = limit
            if market['linear']:
                response = self.publicLinearGetFutureMarketV1PublicQDeal(self.extend(request, params))
            elif market['inverse']:
                response = self.publicInverseGetFutureMarketV1PublicQDeal(self.extend(request, params))
        #
        # spot
        #
        #     {
        #         "rc": 0,
        #         "mc": "SUCCESS",
        #         "ma": [],
        #         "result": [
        #             {
        #                 "i": 203530723141917063,
        #                 "t": 1678227505815,
        #                 "p": "22038.81",
        #                 "q": "0.000978",
        #                 "v": "21.55395618",
        #                 "b": True
        #             },
        #         ]
        #     }
        #
        # swap and future
        #
        #     {
        #         "returnCode": 0,
        #         "msgInfo": "success",
        #         "error": null,
        #         "result": [
        #             {
        #                 "t": 1678227683897,
        #                 "s": "btc_usdt",
        #                 "p": "22031",
        #                 "a": "1067",
        #                 "m": "BID"
        #             },
        #         ]
        #     }
        #
        trades = self.safe_value(response, 'result', [])
        return self.parse_trades(trades, market)

    def fetch_my_trades(self, symbol: str = None, since: Int = None, limit: Int = None, params={}):
        """
        fetch all trades made by the user
        :see: https://doc.xt.com/#tradetradeGet
        :see: https://doc.xt.com/#futures_ordergetTrades
        :param str [symbol]: unified market symbol 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 dict params: extra parameters specific to the xt api endpoint
        :returns dict[]: a list of `trade structures <https://docs.ccxt_zagrava.com/en/latest/manual.html?#public-trades>`
        """
        self.load_markets()
        request = {}
        market = None
        if symbol is not None:
            market = self.market(symbol)
            request['symbol'] = market['id']
        if since is not None:
            request['startTime'] = since
        type = None
        subType = None
        response = None
        type, params = self.handle_market_type_and_params('fetchMyTrades', market, params)
        subType, params = self.handle_sub_type_and_params('fetchMyTrades', market, params)
        if (subType is not None) or (type == 'swap') or (type == 'future'):
            if limit is not None:
                request['size'] = limit
            if subType == 'inverse':
                response = self.privateInverseGetFutureTradeV1OrderTradeList(self.extend(request, params))
            else:
                response = self.privateLinearGetFutureTradeV1OrderTradeList(self.extend(request, params))
        else:
            marginMode = None
            marginMode, params = self.handle_margin_mode_and_params('fetchMyTrades', params)
            marginOrSpotRequest = 'LEVER' if (marginMode is not None) else 'SPOT'
            request['bizType'] = marginOrSpotRequest
            if limit is not None:
                request['limit'] = limit
            response = self.privateSpotGetTrade(self.extend(request, params))
        #
        # spot and margin
        #
        #     {
        #         "rc": 0,
        #         "mc": "SUCCESS",
        #         "ma": [],
        #         "result": {
        #             "hasPrev": False,
        #             "hasNext": False,
        #             "items": [
        #                 {
        #                     "symbol": "btc_usdt",
        #                     "tradeId": "206906233569974658",
        #                     "orderId": "206906233178463488",
        #                     "orderSide": "SELL",
        #                     "orderType": "MARKET",
        #                     "bizType": "SPOT",
        #                     "time": 1679032290215,
        #                     "price": "25703.46",
        #                     "quantity": "0.000099",
        #                     "quoteQty": "2.54464254",
        #                     "baseCurrency": "btc",
        #                     "quoteCurrency": "usdt",
        #                     "fee": "0.00508929",
        #                     "feeCurrency": "usdt",
        #                     "takerMaker": "TAKER"
        #                 },
        #             ]
        #         }
        #     }
        #
        # swap and future
        #
        #     {
        #         "returnCode": 0,
        #         "msgInfo": "success",
        #         "error": null,
        #         "result": {
        #             "page": 1,
        #             "ps": 10,
        #             "total": 2,
        #             "items": [
        #                 {
        #                     "orderId": "207260566170987200",
        #                     "execId": "207260566790603265",
        #                     "symbol": "btc_usdt",
        #                     "quantity": "13",
        #                     "price": "27368",
        #                     "fee": "0.02134704",
        #                     "feeCoin": "usdt",
        #                     "timestamp": 1679116769838,
        #                     "takerMaker": "TAKER"
        #                 },
        #             ]
        #         }
        #     }
        #
        data = self.safe_value(response, 'result', {})
        trades = self.safe_value(data, 'items', [])
        return self.parse_trades(trades, market, since, limit)

    def parse_trade(self, trade, market=None):
        #
        # spot: fetchTrades
        #
        #     {
        #         "i": 203530723141917063,
        #         "t": 1678227505815,
        #         "p": "22038.81",
        #         "q": "0.000978",
        #         "v": "21.55395618",
        #         "b": True
        #     }
        #
        # spot: watchMyTrades
        #
        #    {
        #        "s": "btc_usdt",                # symbol
        #        "t": 1656043204763,             # time
        #        "i": "6316559590087251233",     # tradeId
        #        "oi": "6216559590087220004",    # orderId
        #        "p": "30000",                   # trade price
        #        "q": "3",                       # qty quantity
        #        "v": "90000"                    # volume trade amount
        #    }
        #
        # spot: watchTrades
        #
        #    {
        #        s: 'btc_usdt',
        #        i: '228825383103928709',
        #        t: 1684258222702,
        #        p: '27003.65',
        #        q: '0.000796',
        #        b: True
        #    }
        #
        # swap and future: fetchTrades
        #
        #     {
        #         "t": 1678227683897,
        #         "s": "btc_usdt",
        #         "p": "22031",
        #         "a": "1067",
        #         "m": "BID"
        #     }
        #
        # spot: fetchMyTrades
        #
        #     {
        #         "symbol": "btc_usdt",
        #         "tradeId": "206906233569974658",
        #         "orderId": "206906233178463488",
        #         "orderSide": "SELL",
        #         "orderType": "MARKET",
        #         "bizType": "SPOT",
        #         "time": 1679032290215,
        #         "price": "25703.46",
        #         "quantity": "0.000099",
        #         "quoteQty": "2.54464254",
        #         "baseCurrency": "btc",
        #         "quoteCurrency": "usdt",
        #         "fee": "0.00508929",
        #         "feeCurrency": "usdt",
        #         "takerMaker": "TAKER"
        #     }
        #
        # swap and future: fetchMyTrades
        #
        #     {
        #         "orderId": "207260566170987200",
        #         "execId": "207260566790603265",
        #         "symbol": "btc_usdt",
        #         "quantity": "13",
        #         "price": "27368",
        #         "fee": "0.02134704",
        #         "feeCoin": "usdt",
        #         "timestamp": 1679116769838,
        #         "takerMaker": "TAKER"
        #     }
        #
        # contract watchMyTrades
        #
        #    {
        #        "symbol": 'btc_usdt',
        #        "orderSide": 'SELL',
        #        "positionSide": 'LONG',
        #        "orderId": '231485367663419328',
        #        "price": '27152.7',
        #        "quantity": '33',
        #        "marginUnfrozen": '2.85318000',
        #        "timestamp": 1684892412565
        #    }
        #
        # watchMyTrades(ws, swap)
        #
        #    {
        #        'fee': '0.04080840',
        #        'isMaker': False,
        #        'marginUnfrozen': '0.75711984',
        #        'orderId': '376172779053188416',
        #        'orderSide': 'BUY',
        #        'positionSide': 'LONG',
        #        'price': '3400.70',
        #        'quantity': '2',
        #        'symbol': 'eth_usdt',
        #        'timestamp': 1719388579622
        #    }
        #
        marketId = self.safe_string_2(trade, 's', 'symbol')
        marketType = market['type'] if (market is not None) else None
        hasSpotKeys = ('b' in trade) or ('bizType' in trade) or ('oi' in trade)
        if marketType is None:
            marketType = 'spot' if hasSpotKeys else 'contract'
        market = self.safe_market(marketId, market, '_', marketType)
        bidOrAsk = self.safe_string(trade, 'm')
        side = self.safe_string_lower(trade, 'orderSide')
        if bidOrAsk is not None:
            side = 'buy' if (bidOrAsk == 'BID') else 'sell'
        buyerMaker = self.safe_value(trade, 'b')
        if buyerMaker is not None:
            side = 'buy'
        takerOrMaker = self.safe_string_lower(trade, 'takerMaker')
        if buyerMaker is not None:
            takerOrMaker = 'maker' if buyerMaker else 'taker'
        isMaker = self.safe_bool(trade, 'isMaker')
        if isMaker is not None:
            takerOrMaker = 'maker' if isMaker else 'taker'
        timestamp = self.safe_integer_n(trade, ['t', 'time', 'timestamp'])
        quantity = self.safe_string_2(trade, 'q', 'quantity')
        amount = None
        if marketType == 'spot':
            amount = quantity
        else:
            if quantity is None:
                amount = Precise.string_mul(self.safe_string(trade, 'a'), self.number_to_string(market['contractSize']))
            else:
                amount = Precise.string_mul(quantity, self.number_to_string(market['contractSize']))
        return self.safe_trade({
            'info': trade,
            'id': self.safe_string_n(trade, ['i', 'tradeId', 'execId']),
            'timestamp': timestamp,
            'datetime': self.iso8601(timestamp),
            'symbol': market['symbol'],
            'order': self.safe_string_2(trade, 'orderId', 'oi'),
            'type': self.safe_string_lower(trade, 'orderType'),
            'side': side,
            'takerOrMaker': takerOrMaker,
            'price': self.safe_string_2(trade, 'p', 'price'),
            'amount': amount,
            'cost': None,
            'fee': {
                'currency': self.safe_currency_code(self.safe_string_2(trade, 'feeCurrency', 'feeCoin')),
                'cost': self.safe_string(trade, 'fee'),
                'rate': None,
            },
        }, market)

    def fetch_balance(self, params={}):
        """
        query for balance and get the amount of funds available for trading or funds locked in orders
        :see: https://doc.xt.com/#balancebalancesGet
        :see: https://doc.xt.com/#futures_usergetBalances
        :param dict params: extra parameters specific to the xt api endpoint
        :returns dict: a `balance structure <https://docs.ccxt_zagrava.com/en/latest/manual.html?#balance-structure>`
        """
        self.load_markets()
        type = None
        subType = None
        response = None
        type, params = self.handle_market_type_and_params('fetchBalance', None, params)
        subType, params = self.handle_sub_type_and_params('fetchBalance', None, params)
        isContractWallet = ((type == 'swap') or (type == 'future'))
        if subType == 'inverse':
            response = self.privateInverseGetFutureUserV1BalanceList(params)
        elif (subType == 'linear') or isContractWallet:
            response = self.privateLinearGetFutureUserV1BalanceList(params)
        else:
            response = self.privateSpotGetBalances(params)
        #
        # spot
        #
        #     {
        #         "rc": 0,
        #         "mc": "SUCCESS",
        #         "ma": [],
        #         "result": {
        #             "totalUsdtAmount": "31.75931133",
        #             "totalBtcAmount": "0.00115951",
        #             "assets": [
        #                 {
        #                     "currency": "usdt",
        #                     "currencyId": 11,
        #                     "frozenAmount": "0.03834082",
        #                     "availableAmount": "31.70995965",
        #                     "totalAmount": "31.74830047",
        #                     "convertBtcAmount": "0.00115911",
        #                     "convertUsdtAmount": "31.74830047"
        #                 },
        #             ]
        #         }
        #     }
        #
        # swap and future
        #
        #     {
        #         "returnCode": 0,
        #         "msgInfo": "success",
        #         "error": null,
        #         "result": [
        #             {
        #                 "coin": "usdt",
        #                 "walletBalance": "19.29849875",
        #                 "openOrderMarginFrozen": "0",
        #                 "isolatedMargin": "0.709475",
        #                 "crossedMargin": "0",
        #                 "availableBalance": "18.58902375",
        #                 "bonus": "0",
        #                 "coupon":"0"
        #             }
        #         ]
        #     }
        #
        balances = None
        if (subType is not None) or isContractWallet:
            balances = self.safe_value(response, 'result', [])
        else:
            data = self.safe_value(response, 'result', {})
            balances = self.safe_value(data, 'assets', [])
        return self.parse_balance(balances)

    def parse_balance(self, response):
        #
        # spot
        #
        #     {
        #         "currency": "usdt",
        #         "currencyId": 11,
        #         "frozenAmount": "0.03834082",
        #         "availableAmount": "31.70995965",
        #         "totalAmount": "31.74830047",
        #         "convertBtcAmount": "0.00115911",
        #         "convertUsdtAmount": "31.74830047"
        #     }
        #
        # swap and future
        #
        #     {
        #         "coin": "usdt",
        #         "walletBalance": "19.29849875",
        #         "openOrderMarginFrozen": "0",
        #         "isolatedMargin": "0.709475",
        #         "crossedMargin": "0",
        #         "availableBalance": "18.58902375",
        #         "bonus": "0",
        #         "coupon":"0"
        #     }
        #
        result = {'info': response}
        for i in range(0, len(response)):
            balance = response[i]
            currencyId = self.safe_string_2(balance, 'currency', 'coin')
            code = self.safe_currency_code(currencyId)
            account = self.account()
            free = self.safe_string_2(balance, 'availableAmount', 'availableBalance')
            used = self.safe_string(balance, 'frozenAmount')
            total = self.safe_string_2(balance, 'totalAmount', 'walletBalance')
            if used is None:
                crossedAndIsolatedMargin = Precise.string_add(self.safe_string(balance, 'crossedMargin'), self.safe_string(balance, 'isolatedMargin'))
                used = Precise.string_add(self.safe_string(balance, 'openOrderMarginFrozen'), crossedAndIsolatedMargin)
            account['free'] = free
            account['used'] = used
            account['total'] = total
            result[code] = account
        return self.safe_balance(result)

    def create_market_buy_order_with_cost(self, symbol: str, cost: float, params={}):
        """
        :see: https://doc.xt.com/#orderorderPost
        create a market buy order by providing the symbol and cost
        :param str 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 dict [params]: extra parameters specific to the exchange API endpoint
        :returns dict: an `order structure <https://docs.ccxt_zagrava.com/#/?id=order-structure>`
        """
        self.load_markets()
        market = self.market(symbol)
        if not market['spot']:
            raise NotSupported(self.id + ' createMarketBuyOrderWithCost() supports spot orders only')
        return self.create_order(symbol, 'market', 'buy', cost, 1, params)

    def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
        """
        create a trade order
        :see: https://doc.xt.com/#orderorderPost
        :see: https://doc.xt.com/#futures_ordercreate
        :see: https://doc.xt.com/#futures_entrustcreatePlan
        :see: https://doc.xt.com/#futures_entrustcreateProfit
        :param str symbol: unified symbol of the market to create an order in
        :param str type: 'market' or 'limit'
        :param str side: 'buy' or 'sell'
        :param float amount: how much you want to trade in units of the base currency
        :param float [price]: the price to fulfill the order, in units of the quote currency, can be ignored in market orders
        :param dict params: extra parameters specific to the xt api endpoint
        :param str [params.timeInForce]: 'GTC', 'IOC', 'FOK' or 'GTX'
        :param str [params.entrustType]: 'TAKE_PROFIT', 'STOP', 'TAKE_PROFIT_MARKET', 'STOP_MARKET', 'TRAILING_STOP_MARKET', required if stopPrice is defined, currently isn't functioning on xt's side
        :param str [params.triggerPriceType]: 'INDEX_PRICE', 'MARK_PRICE', 'LATEST_PRICE', required if stopPrice is defined
        :param float [params.stopPrice]: price to trigger a stop order
        :param float [params.stopLoss]: price to set a stop-loss on an open position
        :param float [params.takeProfit]: price to set a take-profit on an open position
        :returns dict: an `order structure <https://docs.ccxt_zagrava.com/en/latest/manual.html#order-structure>`
        """
        self.load_markets()
        market = self.market(symbol)
        symbol = market['symbol']
        if market['spot']:
            return self.create_spot_order(symbol, type, side, amount, price, params)
        else:
            return self.create_contract_order(symbol, type, side, amount, price, params)

    def create_spot_order(self, symbol: str, type, side, amount, price=None, params={}):
        self.load_markets()
        market = self.market(symbol)
        request = {
            'symbol': market['id'],
            'side': side.upper(),
            'type': type.upper(),
        }
        timeInForce = None
        marginMode = None
        marginMode, params = self.handle_margin_mode_and_params('createOrder', params)
        marginOrSpotRequest = 'LEVER' if (marginMode is not None) else 'SPOT'
        request['bizType'] = marginOrSpotRequest
        if type == 'market':
            timeInForce = self.safe_string_upper(params, 'timeInForce', 'FOK')
            if side == 'buy':
                cost = self.safe_string(params, 'cost')
                params = self.omit(params, 'cost')
                createMarketBuyOrderRequiresPrice = self.safe_bool(self.options, 'createMarketBuyOrderRequiresPrice', True)
                if createMarketBuyOrderRequiresPrice:
                    if price is None and (cost is None):
                        raise InvalidOrder(self.id + ' createOrder() requires a price argument or cost in params for market buy orders on spot markets to calculate the total amount to spend(amount * price), alternatively set the createMarketBuyOrderRequiresPrice option to False and pass in the cost to spend into the amount parameter')
                    else:
                        amountString = self.number_to_string(amount)
                        priceString = self.number_to_string(price)
                        costCalculated: Str = None
                        if price is not None:
                            costCalculated = Precise.string_mul(amountString, priceString)
                        else:
                            costCalculated = cost
                        request['quoteQty'] = self.cost_to_precision(symbol, costCalculated)
                else:
                    amountCost = cost if (cost is not None) else amount
                    request['quoteQty'] = self.cost_to_precision(symbol, amountCost)
        else:
            timeInForce = self.safe_string_upper(params, 'timeInForce', 'GTC')
            request['price'] = self.price_to_precision(symbol, price)
        if (side == 'sell') or (type == 'limit'):
            request['quantity'] = self.amount_to_precision(symbol, amount)
        request['timeInForce'] = timeInForce
        response = self.privateSpotPostOrder(self.extend(request, params))
        #
        #     {
        #         "rc": 0,
        #         "mc": "SUCCESS",
        #         "ma": [],
        #         "result": {
        #             "orderId": "204371980095156544"
        #         }
        #     }
        #
        order = self.safe_value(response, 'result', {})
        return self.parse_order(order, market)

    def create_contract_order(self, symbol: str, type, side, amount, price=None, params={}):
        self.load_markets()
        market = self.market(symbol)
        request = {
            'symbol': market['id'],
            'origQty': self.amount_to_precision(symbol, amount),
        }
        timeInForce = self.safe_string_upper(params, 'timeInForce')
        if timeInForce is not None:
            request['timeInForce'] = timeInForce
        reduceOnly = self.safe_value(params, 'reduceOnly', False)
        if side == 'buy':
            requestType = 'SHORT' if (reduceOnly) else 'LONG'
            request['positionSide'] = requestType
        else:
            requestType = 'LONG' if (reduceOnly) else 'SHORT'
            request['positionSide'] = requestType
        response = None
        triggerPrice = self.safe_number_2(params, 'triggerPrice', 'stopPrice')
        stopLoss = self.safe_number_2(params, 'stopLoss', 'triggerStopPrice')
        takeProfit = self.safe_number_2(params, 'takeProfit', 'triggerProfitPrice')
        isTrigger = (triggerPrice is not None)
        isStopLoss = (stopLoss is not None)
        isTakeProfit = (takeProfit is not None)
        if price is not None:
            if not (isStopLoss) and not (isTakeProfit):
                request['price'] = self.price_to_precision(symbol, price)
        if isTrigger:
            request['timeInForce'] = self.safe_string_upper(params, 'timeInForce', 'GTC')
            request['triggerPriceType'] = self.safe_string(params, 'triggerPriceType', 'LATEST_PRICE')
            request['orderSide'] = side.upper()
            request['stopPrice'] = self.price_to_precision(symbol, triggerPrice)
            entrustType = 'STOP_MARKET' if (type == 'market') else 'STOP'
            request['entrustType'] = entrustType
            params = self.omit(params, 'triggerPrice')
            if market['linear']:
                response = self.privateLinearPostFutureTradeV1EntrustCreatePlan(self.extend(request, params))
            elif market['inverse']:
                response = self.privateInversePostFutureTradeV1EntrustCreatePlan(self.extend(request, params))
        elif isStopLoss or isTakeProfit:
            if isStopLoss:
                request['triggerStopPrice'] = self.price_to_precision(symbol, stopLoss)
            else:
                request['triggerProfitPrice'] = self.price_to_precision(symbol, takeProfit)
            params = self.omit(params, ['stopLoss', 'takeProfit'])
            if market['linear']:
                response = self.privateLinearPostFutureTradeV1EntrustCreateProfit(self.extend(request, params))
            elif market['inverse']:
                response = self.privateInversePostFutureTradeV1EntrustCreateProfit(self.extend(request, params))
        else:
            request['orderSide'] = side.upper()
            request['orderType'] = type.upper()
            if market['linear']:
                response = self.privateLinearPostFutureTradeV1OrderCreate(self.extend(request, params))
            elif market['inverse']:
                response = self.privateInversePostFutureTradeV1OrderCreate(self.extend(request, params))
        #
        #     {
        #         "returnCode": 0,
        #         "msgInfo": "success",
        #         "error": null,
        #         "result": "206410760006650176"
        #     }
        #
        return self.parse_order(response, market)

    def fetch_order(self, id: str, symbol: str = None, params={}):
        """
        fetches information on an order made by the user
        :see: https://doc.xt.com/#orderorderGet
        :see: https://doc.xt.com/#futures_ordergetById
        :see: https://doc.xt.com/#futures_entrustgetPlanById
        :see: https://doc.xt.com/#futures_entrustgetProfitById
        :param str id: order id
        :param str [symbol]: unified symbol of the market the order was made in
        :param dict params: extra parameters specific to the xt api endpoint
        :param bool [params.stop]: if the order is a stop trigger order or not
        :param bool [params.stopLossTakeProfit]: if the order is a stop-loss or take-profit order
        :returns dict: An `order structure <https://docs.ccxt_zagrava.com/en/latest/manual.html#order-structure>`
        """
        self.load_markets()
        market = None
        if symbol is not None:
            market = self.market(symbol)
        request = {}
        type = None
        subType = None
        response = None
        type, params = self.handle_market_type_and_params('fetchOrder', market, params)
        subType, params = self.handle_sub_type_and_params('fetchOrder', market, params)
        stop = self.safe_value(params, 'stop')
        stopLossTakeProfit = self.safe_value(params, 'stopLossTakeProfit')
        if stop:
            request['entrustId'] = id
        elif stopLossTakeProfit:
            request['profitId'] = id
        else:
            request['orderId'] = id
        if stop:
            params = self.omit(params, 'stop')
            if subType == 'inverse':
                response = self.privateInverseGetFutureTradeV1EntrustPlanDetail(self.extend(request, params))
            else:
                response = self.privateLinearGetFutureTradeV1EntrustPlanDetail(self.extend(request, params))
        elif stopLossTakeProfit:
            params = self.omit(params, 'stopLossTakeProfit')
            if subType == 'inverse':
                response = self.privateInverseGetFutureTradeV1EntrustProfitDetail(self.extend(request, params))
            else:
                response = self.privateLinearGetFutureTradeV1EntrustProfitDetail(self.extend(request, params))
        elif subType == 'inverse':
            response = self.privateInverseGetFutureTradeV1OrderDetail(self.extend(request, params))
        elif (subType == 'linear') or (type == 'swap') or (type == 'future'):
            response = self.privateLinearGetFutureTradeV1OrderDetail(self.extend(request, params))
        else:
            response = self.privateSpotGetOrderOrderId(self.extend(request, params))
        #
        # spot
        #
        #     {
        #         "rc": 0,
        #         "mc": "SUCCESS",
        #         "ma": [],
        #         "result": {
        #             "symbol": "btc_usdt",
        #             "orderId": "207505997850909952",
        #             "clientOrderId": null,
        #             "baseCurrency": "btc",
        #             "quoteCurrency": "usdt",
        #             "side": "BUY",
        #             "type": "LIMIT",
        #             "timeInForce": "GTC",
        #             "price": "20000.00",
        #             "origQty": "0.001000",
        #             "origQuoteQty": "20.00",
        #             "executedQty": "0.000000",
        #             "leavingQty": "0.001000",
        #             "tradeBase": "0.000000",
        #             "tradeQuote": "0.00",
        #             "avgPrice": null,
        #             "fee": null,
        #             "feeCurrency": null,
        #             "closed": False,
        #             "state": "NEW",
        #             "time": 1679175285162,
        #             "updatedTime": 1679175285255
        #         }
        #     }
        #
        # swap and future
        #
        #     {
        #         "returnCode": 0,
        #         "msgInfo": "success",
        #         "error": null,
        #         "result": {
        #             "orderId": "211451874783183936",
        #             "clientOrderId": null,
        #             "symbol": "btc_usdt",
        #             "orderType": "LIMIT",
        #             "orderSide": "BUY",
        #             "positionSide": "LONG",
        #             "timeInForce": "GTC",
        #             "closePosition": False,
        #             "price": "20000",
        #             "origQty": "10",
        #             "avgPrice": "0",
        #             "executedQty": "0",
        #             "marginFrozen": "1.34533334",
        #             "remark": null,
        #             "triggerProfitPrice": null,
        #             "triggerStopPrice": null,
        #             "sourceId": null,
        #             "sourceType": "DEFAULT",
        #             "forceClose": False,
        #             "closeProfit": null,
        #             "state": "NEW",
        #             "createdTime": 1680116055693,
        #             "updatedTime": 1680116055693
        #         }
        #     }
        #
        # trigger
        #
        #     {
        #         "returnCode": 0,
        #         "msgInfo": "success",
        #         "error": null,
        #         "result": {
        #             "entrustId": "216300248132756992",
        #             "symbol": "btc_usdt",
        #             "entrustType": "STOP",
        #             "orderSide": "SELL",
        #             "positionSide": "SHORT",
        #             "timeInForce": "GTC",
        #             "closePosition": null,
        #             "price": "20000",
        #             "origQty": "1",
        #             "stopPrice": "19000",
        #             "triggerPriceType": "LATEST_PRICE",
        #             "state": "NOT_TRIGGERED",
        #             "marketOrderLevel": null,
        #             "createdTime": 1681271998064,
        #             "updatedTime": 1681271998064,
        #             "ordinary": False
        #         }
        #     }
        #
        # stop-loss and take-profit
        #
        #     {
        #         "returnCode": 0,
        #         "msgInfo": "success",
        #         "error": null,
        #         "result": {
        #             "profitId": "216306213226230400",
        #             "symbol": "btc_usdt",
        #             "positionSide": "LONG",
        #             "origQty": "1",
        #             "triggerPriceType": "LATEST_PRICE",
        #             "triggerProfitPrice": null,
        #             "triggerStopPrice": "20000",
        #             "entryPrice": null,
        #             "positionSize": null,
        #             "isolatedMargin": null,
        #             "executedQty": null,
        #             "avgPrice": null,
        #             "positionType": "ISOLATED",
        #             "state": "NOT_TRIGGERED",
        #             "createdTime": 1681273420039
        #         }
        #     }
        #
        order = self.safe_value(response, 'result', {})
        return self.parse_order(order, market)

    def fetch_orders(self, symbol: str = None, since: Int = None, limit: Int = None, params={}):
        """
        fetches information on multiple orders made by the user
        :see: https://doc.xt.com/#orderhistoryOrderGet
        :see: https://doc.xt.com/#futures_ordergetHistory
        :see: https://doc.xt.com/#futures_entrustgetPlanHistory
        :param str [symbol]: unified market symbol of the market the orders were made in
        :param int [since]: timestamp in ms of the earliest order
        :param int [limit]: the maximum number of order structures to retrieve
        :param dict params: extra parameters specific to the xt api endpoint
        :param bool [params.stop]: if the order is a stop trigger order or not
        :returns dict[]: a list of `order structures <https://docs.ccxt_zagrava.com/en/latest/manual.html#order-structure>`
        """
        self.load_markets()
        request = {}
        market = None
        if symbol is not None:
            market = self.market(symbol)
            request['symbol'] = market['id']
        if since is not None:
            request['startTime'] = since
        if limit is not None:
            request['limit'] = limit
        type = None
        subType = None
        response = None
        type, params = self.handle_market_type_and_params('fetchOrders', market, params)
        subType, params = self.handle_sub_type_and_params('fetchOrders', market, params)
        stop = self.safe_value(params, 'stop')
        if stop:
            params = self.omit(params, 'stop')
            if subType == 'inverse':
                response = self.privateInverseGetFutureTradeV1EntrustPlanListHistory(self.extend(request, params))
            else:
                response = self.privateLinearGetFutureTradeV1EntrustPlanListHistory(self.extend(request, params))
        elif subType == 'inverse':
            response = self.privateInverseGetFutureTradeV1OrderListHistory(self.extend(request, params))
        elif (subType == 'linear') or (type == 'swap') or (type == 'future'):
            response = self.privateLinearGetFutureTradeV1OrderListHistory(self.extend(request, params))
        else:
            marginMode = None
            marginMode, params = self.handle_margin_mode_and_params('fetchOrders', params)
            marginOrSpotRequest = 'LEVER' if (marginMode is not None) else 'SPOT'
            request['bizType'] = marginOrSpotRequest
            response = self.privateSpotGetHistoryOrder(self.extend(request, params))
        #
        #  spot and margin
        #
        #     {
        #         "rc": 0,
        #         "mc": "SUCCESS",
        #         "ma": [],
        #         "result": {
        #             "hasPrev": False,
        #             "hasNext": True,
        #             "items": [
        #                 {
        #                     "symbol": "btc_usdt",
        #                     "orderId": "207505997850909952",
        #                     "clientOrderId": null,
        #                     "baseCurrency": "btc",
        #                     "quoteCurrency": "usdt",
        #                     "side": "BUY",
        #                     "type": "LIMIT",
        #                     "timeInForce": "GTC",
        #                     "price": "20000.00",
        #                     "origQty": "0.001000",
        #                     "origQuoteQty": "20.00",
        #                     "executedQty": "0.000000",
        #                     "leavingQty": "0.000000",
        #                     "tradeBase": "0.000000",
        #                     "tradeQuote": "0.00",
        #                     "avgPrice": null,
        #                     "fee": null,
        #                     "feeCurrency": null,
        #                     "closed": True,
        #                     "state": "CANCELED",
        #                     "time": 1679175285162,
        #                     "updatedTime": 1679175488492
        #                 },
        #             ]
        #         }
        #     }
        #
        # swap and future
        #
        #     {
        #         "returnCode": 0,
        #         "msgInfo": "success",
        #         "error": null,
        #         "result": {
        #             "hasPrev": False,
        #             "hasNext": True,
        #             "items": [
        #                 {
        #                     "orderId": "207519546930995456",
        #                     "clientOrderId": null,
        #                     "symbol": "btc_usdt",
        #                     "orderType": "LIMIT",
        #                     "orderSide": "BUY",
        #                     "positionSide": "LONG",
        #                     "timeInForce": "GTC",
        #                     "closePosition": False,
        #                     "price": "20000",
        #                     "origQty": "100",
        #                     "avgPrice": "0",
        #                     "executedQty": "0",
        #                     "marginFrozen": "4.12",
        #                     "remark": null,
        #                     "triggerProfitPrice": null,
        #                     "triggerStopPrice": null,
        #                     "sourceId": null,
        #                     "sourceType": "DEFAULT",
        #                     "forceClose": False,
        #                     "closeProfit": null,
        #                     "state": "CANCELED",
        #                     "createdTime": 1679178515689,
        #                     "updatedTime": 1679180096172
        #                 },
        #             ]
        #         }
        #     }
        #
        # stop
        #
        #     {
        #         "returnCode": 0,
        #         "msgInfo": "success",
        #         "error": null,
        #         "result": {
        #             "hasPrev": False,
        #             "hasNext": False,
        #             "items": [
        #                 {
        #                     "entrustId": "216300248132756992",
        #                     "symbol": "btc_usdt",
        #                     "entrustType": "STOP",
        #                     "orderSide": "SELL",
        #                     "positionSide": "SHORT",
        #                     "timeInForce": "GTC",
        #                     "closePosition": null,
        #                     "price": "20000",
        #                     "origQty": "1",
        #                     "stopPrice": "19000",
        #                     "triggerPriceType": "LATEST_PRICE",
        #                     "state": "USER_REVOCATION",
        #                     "marketOrderLevel": null,
        #                     "createdTime": 1681271998064,
        #                     "updatedTime": 1681273188674,
        #                     "ordinary": False
        #                 },
        #             ]
        #         }
        #     }
        #
        data = self.safe_value(response, 'result', {})
        orders = self.safe_value(data, 'items', [])
        return self.parse_orders(orders, market, since, limit)

    def fetch_orders_by_status(self, status, symbol: str = None, since: Int = None, limit: Int = None, params={}):
        self.load_markets()
        request = {}
        market = None
        if symbol is not None:
            market = self.market(symbol)
            request['symbol'] = market['id']
        type = None
        subType = None
        response = None
        type, params = self.handle_market_type_and_params('fetchOrdersByStatus', market, params)
        subType, params = self.handle_sub_type_and_params('fetchOrdersByStatus', market, params)
        stop = self.safe_value(params, 'stop')
        stopLossTakeProfit = self.safe_value(params, 'stopLossTakeProfit')
        if status == 'open':
            if stop or stopLossTakeProfit:
                request['state'] = 'NOT_TRIGGERED'
            elif subType is not None:
                request['state'] = 'NEW'
        elif status == 'closed':
            if stop or stopLossTakeProfit:
                request['state'] = 'TRIGGERED'
            else:
                request['state'] = 'FILLED'
        elif status == 'canceled':
            if stop or stopLossTakeProfit:
                request['state'] = 'USER_REVOCATION'
            else:
                request['state'] = 'CANCELED'
        else:
            request['state'] = status
        if stop or stopLossTakeProfit or (subType is not None) or (type == 'swap') or (type == 'future'):
            if since is not None:
                request['startTime'] = since
            if limit is not None:
                request['size'] = limit
        if stop:
            params = self.omit(params, 'stop')
            if subType == 'inverse':
                response = self.privateInverseGetFutureTradeV1EntrustPlanList(self.extend(request, params))
            else:
                response = self.privateLinearGetFutureTradeV1EntrustPlanList(self.extend(request, params))
        elif stopLossTakeProfit:
            params = self.omit(params, 'stopLossTakeProfit')
            if subType == 'inverse':
                response = self.privateInverseGetFutureTradeV1EntrustProfitList(self.extend(request, params))
            else:
                response = self.privateLinearGetFutureTradeV1EntrustProfitList(self.extend(request, params))
        elif (subType is not None) or (type == 'swap') or (type == 'future'):
            if subType == 'inverse':
                response = self.privateInverseGetFutureTradeV1OrderList(self.extend(request, params))
            else:
                response = self.privateLinearGetFutureTradeV1OrderList(self.extend(request, params))
        else:
            marginMode = None
            marginMode, params = self.handle_margin_mode_and_params('fetchOrdersByStatus', params)
            marginOrSpotRequest = 'LEVER' if (marginMode is not None) else 'SPOT'
            request['bizType'] = marginOrSpotRequest
            if status != 'open':
                if since is not None:
                    request['startTime'] = since
                if limit is not None:
                    request['limit'] = limit
                response = self.privateSpotGetHistoryOrder(self.extend(request, params))
            else:
                response = self.privateSpotGetOpenOrder(self.extend(request, params))
        #
        # spot and margin
        #
        #     {
        #         "rc": 0,
        #         "mc": "SUCCESS",
        #         "ma": [],
        #         "result": {
        #             "hasPrev": False,
        #             "hasNext": True,
        #             "items": [
        #                 {
        #                     "symbol": "btc_usdt",
        #                     "orderId": "207505997850909952",
        #                     "clientOrderId": null,
        #                     "baseCurrency": "btc",
        #                     "quoteCurrency": "usdt",
        #                     "side": "BUY",
        #                     "type": "LIMIT",
        #                     "timeInForce": "GTC",
        #                     "price": "20000.00",
        #                     "origQty": "0.001000",
        #                     "origQuoteQty": "20.00",
        #                     "executedQty": "0.000000",
        #                     "leavingQty": "0.000000",
        #                     "tradeBase": "0.000000",
        #                     "tradeQuote": "0.00",
        #                     "avgPrice": null,
        #                     "fee": null,
        #                     "feeCurrency": null,
        #                     "closed": True,
        #                     "state": "CANCELED",
        #                     "time": 1679175285162,
        #                     "updatedTime": 1679175488492
        #                 },
        #             ]
        #         }
        #     }
        #
        # spot and margin: fetchOpenOrders
        #
        #     {
        #         "rc": 0,
        #         "mc": "SUCCESS",
        #         "ma": [],
        #         "result": [
        #             {
        #                 "symbol": "eth_usdt",
        #                 "orderId": "208249323222264320",
        #                 "clientOrderId": null,
        #                 "baseCurrency": "eth",
        #                 "quoteCurrency": "usdt",
        #                 "side": "BUY",
        #                 "type": "LIMIT",
        #                 "timeInForce": "GTC",
        #                 "price": "1300.00",
        #                 "origQty": "0.0032",
        #                 "origQuoteQty": "4.16",
        #                 "executedQty": "0.0000",
        #                 "leavingQty": "0.0032",
        #                 "tradeBase": "0.0000",
        #                 "tradeQuote": "0.00",
        #                 "avgPrice": null,
        #                 "fee": null,
        #                 "feeCurrency": null,
        #                 "closed": False,
        #                 "state": "NEW",
        #                 "time": 1679352507741,
        #                 "updatedTime": 1679352507869
        #             },
        #         ]
        #     }
        #
        # swap and future
        #
        #     {
        #         "returnCode": 0,
        #         "msgInfo": "success",
        #         "error": null,
        #         "result": {
        #             "page": 1,
        #             "ps": 10,
        #             "total": 25,
        #             "items": [
        #                 {
        #                     "orderId": "207519546930995456",
        #                     "clientOrderId": null,
        #                     "symbol": "btc_usdt",
        #                     "orderType": "LIMIT",
        #                     "orderSide": "BUY",
        #                     "positionSide": "LONG",
        #                     "timeInForce": "GTC",
        #                     "closePosition": False,
        #                     "price": "20000",
        #                     "origQty": "100",
        #                     "avgPrice": "0",
        #                     "executedQty": "0",
        #                     "marginFrozen": "4.12",
        #                     "remark": null,
        #                     "triggerProfitPrice": null,
        #                     "triggerStopPrice": null,
        #                     "sourceId": null,
        #                     "sourceType": "DEFAULT",
        #                     "forceClose": False,
        #                     "closeProfit": null,
        #                     "state": "CANCELED",
        #                     "createdTime": 1679178515689,
        #                     "updatedTime": 1679180096172
        #                 },
        #             ]
        #         }
        #     }
        #
        # stop
        #
        #     {
        #         "returnCode": 0,
        #         "msgInfo": "success",
        #         "error": null,
        #         "result": {
        #             "page": 1,
        #             "ps": 3,
        #             "total": 8,
        #             "items": [
        #                 {
        #                     "entrustId": "216300248132756992",
        #                     "symbol": "btc_usdt",
        #                     "entrustType": "STOP",
        #                     "orderSide": "SELL",
        #                     "positionSide": "SHORT",
        #                     "timeInForce": "GTC",
        #                     "closePosition": null,
        #                     "price": "20000",
        #                     "origQty": "1",
        #                     "stopPrice": "19000",
        #                     "triggerPriceType": "LATEST_PRICE",
        #                     "state": "USER_REVOCATION",
        #                     "marketOrderLevel": null,
        #                     "createdTime": 1681271998064,
        #                     "updatedTime": 1681273188674,
        #                     "ordinary": False
        #                 },
        #             ]
        #         }
        #     }
        #
        # stop-loss and take-profit
        #
        #     {
        #         "returnCode": 0,
        #         "msgInfo": "success",
        #         "error": null,
        #         "result": {
        #             "page": 1,
        #             "ps": 3,
        #             "total": 2,
        #             "items": [
        #                 {
        #                     "profitId": "216306213226230400",
        #                     "symbol": "btc_usdt",
        #                     "positionSide": "LONG",
        #                     "origQty": "1",
        #                     "triggerPriceType": "LATEST_PRICE",
        #                     "triggerProfitPrice": null,
        #                     "triggerStopPrice": "20000",
        #                     "entryPrice": "0",
        #                     "positionSize": "0",
        #                     "isolatedMargin": "0",
        #                     "executedQty": "0",
        #                     "avgPrice": null,
        #                     "positionType": "ISOLATED",
        #                     "state": "USER_REVOCATION",
        #                     "createdTime": 1681273420039
        #                 },
        #             ]
        #         }
        #     }
        #
        isSpotOpenOrders = ((status == 'open') and (subType is None))
        data = self.safe_value(response, 'result', {})
        orders = self.safe_value(response, 'result', []) if isSpotOpenOrders else self.safe_value(data, 'items', [])
        return self.parse_orders(orders, market, since, limit)

    def fetch_open_orders(self, symbol: str = None, since: Int = None, limit: Int = None, params={}):
        """
        fetch all unfilled currently open orders
        :see: https://doc.xt.com/#orderopenOrderGet
        :see: https://doc.xt.com/#futures_ordergetOrders
        :see: https://doc.xt.com/#futures_entrustgetPlan
        :see: https://doc.xt.com/#futures_entrustgetProfit
        :param str [symbol]: unified market symbol of the market the orders were made in
        :param int [since]: timestamp in ms of the earliest order
        :param int [limit]: the maximum number of open order structures to retrieve
        :param dict params: extra parameters specific to the xt api endpoint
        :param bool [params.stop]: if the order is a stop trigger order or not
        :param bool [params.stopLossTakeProfit]: if the order is a stop-loss or take-profit order
        :returns dict[]: a list of `order structures <https://docs.ccxt_zagrava.com/en/latest/manual.html#order-structure>`
        """
        return self.fetch_orders_by_status('open', symbol, since, limit, params)

    def fetch_closed_orders(self, symbol: str = None, since: Int = None, limit: Int = None, params={}):
        """
        fetches information on multiple closed orders made by the user
        :see: https://doc.xt.com/#orderhistoryOrderGet
        :see: https://doc.xt.com/#futures_ordergetOrders
        :see: https://doc.xt.com/#futures_entrustgetPlan
        :see: https://doc.xt.com/#futures_entrustgetProfit
        :param str [symbol]: unified market symbol of the market the orders were made in
        :param int [since]: timestamp in ms of the earliest order
        :param int [limit]: the maximum number of order structures to retrieve
        :param dict params: extra parameters specific to the xt api endpoint
        :param bool [params.stop]: if the order is a stop trigger order or not
        :param bool [params.stopLossTakeProfit]: if the order is a stop-loss or take-profit order
        :returns dict[]: a list of `order structures <https://docs.ccxt_zagrava.com/en/latest/manual.html#order-structure>`
        """
        return self.fetch_orders_by_status('closed', symbol, since, limit, params)

    def fetch_canceled_orders(self, symbol: str = None, since: Int = None, limit: Int = None, params={}):
        """
        fetches information on multiple canceled orders made by the user
        :see: https://doc.xt.com/#orderhistoryOrderGet
        :see: https://doc.xt.com/#futures_ordergetOrders
        :see: https://doc.xt.com/#futures_entrustgetPlan
        :see: https://doc.xt.com/#futures_entrustgetProfit
        :param str [symbol]: unified market symbol of the market the orders were made in
        :param int [since]: timestamp in ms of the earliest order
        :param int [limit]: the maximum number of order structures to retrieve
        :param dict params: extra parameters specific to the xt api endpoint
        :param bool [params.stop]: if the order is a stop trigger order or not
        :param bool [params.stopLossTakeProfit]: if the order is a stop-loss or take-profit order
        :returns dict: a list of `order structures <https://docs.ccxt_zagrava.com/en/latest/manual.html#order-structure>`
        """
        return self.fetch_orders_by_status('canceled', symbol, since, limit, params)

    def cancel_order(self, id: str, symbol: str = None, params={}):
        """
        cancels an open order
        :see: https://doc.xt.com/#orderorderDel
        :see: https://doc.xt.com/#futures_ordercancel
        :see: https://doc.xt.com/#futures_entrustcancelPlan
        :see: https://doc.xt.com/#futures_entrustcancelProfit
        :param str id: order id
        :param str [symbol]: unified symbol of the market the order was made in
        :param dict params: extra parameters specific to the xt api endpoint
        :param bool [params.stop]: if the order is a stop trigger order or not
        :param bool [params.stopLossTakeProfit]: if the order is a stop-loss or take-profit order
        :returns dict: An `order structure <https://docs.ccxt_zagrava.com/en/latest/manual.html#order-structure>`
        """
        self.load_markets()
        market = None
        if symbol is not None:
            market = self.market(symbol)
        request = {}
        type = None
        subType = None
        response = None
        type, params = self.handle_market_type_and_params('cancelOrder', market, params)
        subType, params = self.handle_sub_type_and_params('cancelOrder', market, params)
        stop = self.safe_value(params, 'stop')
        stopLossTakeProfit = self.safe_value(params, 'stopLossTakeProfit')
        if stop:
            request['entrustId'] = id
        elif stopLossTakeProfit:
            request['profitId'] = id
        else:
            request['orderId'] = id
        if stop:
            params = self.omit(params, 'stop')
            if subType == 'inverse':
                response = self.privateInversePostFutureTradeV1EntrustCancelPlan(self.extend(request, params))
            else:
                response = self.privateLinearPostFutureTradeV1EntrustCancelPlan(self.extend(request, params))
        elif stopLossTakeProfit:
            params = self.omit(params, 'stopLossTakeProfit')
            if subType == 'inverse':
                response = self.privateInversePostFutureTradeV1EntrustCancelProfitStop(self.extend(request, params))
            else:
                response = self.privateLinearPostFutureTradeV1EntrustCancelProfitStop(self.extend(request, params))
        elif subType == 'inverse':
            response = self.privateInversePostFutureTradeV1OrderCancel(self.extend(request, params))
        elif (subType == 'linear') or (type == 'swap') or (type == 'future'):
            response = self.privateLinearPostFutureTradeV1OrderCancel(self.extend(request, params))
        else:
            response = self.privateSpotDeleteOrderOrderId(self.extend(request, params))
        #
        # spot
        #
        #     {
        #         "rc": 0,
        #         "mc": "SUCCESS",
        #         "ma": [],
        #         "result": {
        #             "cancelId": "208322474307982720"
        #         }
        #     }
        #
        # swap and future
        #
        #     {
        #         "returnCode": 0,
        #         "msgInfo": "success",
        #         "error": null,
        #         "result": "208319789679471616"
        #     }
        #
        isContractResponse = ((subType is not None) or (type == 'swap') or (type == 'future'))
        order = response if isContractResponse else self.safe_value(response, 'result', {})
        return self.parse_order(order, market)

    def cancel_all_orders(self, symbol: str = None, params={}):
        """
        cancel all open orders in a market
        :see: https://doc.xt.com/#orderopenOrderDel
        :see: https://doc.xt.com/#futures_ordercancelBatch
        :see: https://doc.xt.com/#futures_entrustcancelPlanBatch
        :see: https://doc.xt.com/#futures_entrustcancelProfitBatch
        :param str [symbol]: unified market symbol of the market to cancel orders in
        :param dict params: extra parameters specific to the xt api endpoint
        :param bool [params.stop]: if the order is a stop trigger order or not
        :param bool [params.stopLossTakeProfit]: if the order is a stop-loss or take-profit order
        :returns dict[]: a list of `order structures <https://docs.ccxt_zagrava.com/en/latest/manual.html#order-structure>`
        """
        self.load_markets()
        request = {}
        market = None
        if symbol is not None:
            market = self.market(symbol)
            request['symbol'] = market['id']
        type = None
        subType = None
        response = None
        type, params = self.handle_market_type_and_params('cancelAllOrders', market, params)
        subType, params = self.handle_sub_type_and_params('cancelAllOrders', market, params)
        stop = self.safe_value(params, 'stop')
        stopLossTakeProfit = self.safe_value(params, 'stopLossTakeProfit')
        if stop:
            params = self.omit(params, 'stop')
            if subType == 'inverse':
                response = self.privateInversePostFutureTradeV1EntrustCancelAllPlan(self.extend(request, params))
            else:
                response = self.privateLinearPostFutureTradeV1EntrustCancelAllPlan(self.extend(request, params))
        elif stopLossTakeProfit:
            params = self.omit(params, 'stopLossTakeProfit')
            if subType == 'inverse':
                response = self.privateInversePostFutureTradeV1EntrustCancelAllProfitStop(self.extend(request, params))
            else:
                response = self.privateLinearPostFutureTradeV1EntrustCancelAllProfitStop(self.extend(request, params))
        elif subType == 'inverse':
            response = self.privateInversePostFutureTradeV1OrderCancelAll(self.extend(request, params))
        elif (subType == 'linear') or (type == 'swap') or (type == 'future'):
            response = self.privateLinearPostFutureTradeV1OrderCancelAll(self.extend(request, params))
        else:
            marginMode = None
            marginMode, params = self.handle_margin_mode_and_params('cancelAllOrders', params)
            marginOrSpotRequest = 'LEVER' if (marginMode is not None) else 'SPOT'
            request['bizType'] = marginOrSpotRequest
            response = self.privateSpotDeleteOpenOrder(self.extend(request, params))
        #
        # spot and margin
        #
        #     {
        #         "rc": 0,
        #         "mc": "SUCCESS",
        #         "ma": [],
        #         "result": null
        #     }
        #
        # swap and future
        #
        #     {
        #         "returnCode": 0,
        #         "msgInfo": "success",
        #         "error": null,
        #         "result": True
        #     }
        #
        return [
            self.safe_order(response),
        ]

    def cancel_orders(self, ids: List[str], symbol: str = None, params={}) -> List[Order]:
        """
        cancel multiple orders
        :see: https://doc.xt.com/#orderbatchOrderDel
        :param str[] ids: order ids
        :param str [symbol]: unified market symbol of the market to cancel orders in
        :param dict params: extra parameters specific to the xt api endpoint
        :returns dict[]: a list of `order structures <https://docs.ccxt_zagrava.com/en/latest/manual.html#order-structure>`
        """
        self.load_markets()
        request = {
            'orderIds': ids,
        }
        market = None
        if symbol is not None:
            market = self.market(symbol)
        subType = None
        subType, params = self.handle_sub_type_and_params('cancelOrders', market, params)
        if subType is not None:
            raise NotSupported(self.id + ' cancelOrders() does not support swap and future orders, only spot orders are accepted')
        response = self.privateSpotDeleteBatchOrder(self.extend(request, params))
        #
        # spot
        #
        #     {
        #         "rc": 0,
        #         "mc": "SUCCESS",
        #         "ma": [],
        #         "result": null
        #     }
        #
        return [
            self.safe_order(response),
        ]

    def parse_order(self, order, market=None):
        #
        # spot: createOrder
        #
        #     {
        #         "orderId": "204371980095156544"
        #     }
        #
        # spot: cancelOrder
        #
        #     {
        #         "cancelId": "208322474307982720"
        #     }
        #
        # swap and future: createOrder, cancelOrder
        #
        #     {
        #         "returnCode": 0,
        #         "msgInfo": "success",
        #         "error": null,
        #         "result": "206410760006650176"
        #     }
        #
        # spot: fetchOrder, fetchOrders, fetchOpenOrders, fetchClosedOrders, fetchCanceledOrders, fetchOrdersByStatus
        #
        #     {
        #         "symbol": "btc_usdt",
        #         "orderId": "207505997850909952",
        #         "clientOrderId": null,
        #         "baseCurrency": "btc",
        #         "quoteCurrency": "usdt",
        #         "side": "BUY",
        #         "type": "LIMIT",
        #         "timeInForce": "GTC",
        #         "price": "20000.00",
        #         "origQty": "0.001000",
        #         "origQuoteQty": "20.00",
        #         "executedQty": "0.000000",
        #         "leavingQty": "0.001000",
        #         "tradeBase": "0.000000",
        #         "tradeQuote": "0.00",
        #         "avgPrice": null,
        #         "fee": null,
        #         "feeCurrency": null,
        #         "closed": False,
        #         "state": "NEW",
        #         "time": 1679175285162,
        #         "updatedTime": 1679175285255
        #     }
        #
        # swap and future: fetchOrder, fetchOrders, fetchOpenOrders, fetchClosedOrders, fetchCanceledOrders, fetchOrdersByStatus
        #
        #     {
        #         "orderId": "207519546930995456",
        #         "clientOrderId": null,
        #         "symbol": "btc_usdt",
        #         "orderType": "LIMIT",
        #         "orderSide": "BUY",
        #         "positionSide": "LONG",
        #         "timeInForce": "GTC",
        #         "closePosition": False,
        #         "price": "20000",
        #         "origQty": "100",
        #         "avgPrice": "0",
        #         "executedQty": "0",
        #         "marginFrozen": "4.12",
        #         "remark": null,
        #         "triggerProfitPrice": null,
        #         "triggerStopPrice": null,
        #         "sourceId": null,
        #         "sourceType": "DEFAULT",
        #         "forceClose": False,
        #         "closeProfit": null,
        #         "state": "CANCELED",
        #         "createdTime": 1679178515689,
        #         "updatedTime": 1679180096172
        #     }
        #
        # trigger: fetchOrder, fetchOrders, fetchOpenOrders, fetchClosedOrders, fetchCanceledOrders, fetchOrdersByStatus
        #
        #     {
        #         "entrustId": "216300248132756992",
        #         "symbol": "btc_usdt",
        #         "entrustType": "STOP",
        #         "orderSide": "SELL",
        #         "positionSide": "SHORT",
        #         "timeInForce": "GTC",
        #         "closePosition": null,
        #         "price": "20000",
        #         "origQty": "1",
        #         "stopPrice": "19000",
        #         "triggerPriceType": "LATEST_PRICE",
        #         "state": "NOT_TRIGGERED",
        #         "marketOrderLevel": null,
        #         "createdTime": 1681271998064,
        #         "updatedTime": 1681271998064,
        #         "ordinary": False
        #     }
        #
        # stop-loss and take-profit: fetchOrder, fetchOpenOrders, fetchClosedOrders, fetchCanceledOrders, fetchOrdersByStatus
        #
        #     {
        #         "profitId": "216306213226230400",
        #         "symbol": "btc_usdt",
        #         "positionSide": "LONG",
        #         "origQty": "1",
        #         "triggerPriceType": "LATEST_PRICE",
        #         "triggerProfitPrice": null,
        #         "triggerStopPrice": "20000",
        #         "entryPrice": null,
        #         "positionSize": null,
        #         "isolatedMargin": null,
        #         "executedQty": null,
        #         "avgPrice": null,
        #         "positionType": "ISOLATED",
        #         "state": "NOT_TRIGGERED",
        #         "createdTime": 1681273420039
        #     }
        #
        marketId = self.safe_string(order, 'symbol')
        marketType = ('result' in order) or 'contract' if ('positionSide' in order) else 'spot'
        market = self.safe_market(marketId, market, None, marketType)
        symbol = self.safe_symbol(marketId, market, None, marketType)
        timestamp = self.safe_integer_2(order, 'time', 'createdTime')
        quantity = self.safe_number(order, 'origQty')
        amount = quantity if (marketType == 'spot') else Precise.string_mul(self.number_to_string(quantity), self.number_to_string(market['contractSize']))
        filledQuantity = self.safe_number(order, 'executedQty')
        filled = filledQuantity if (marketType == 'spot') else Precise.string_mul(self.number_to_string(filledQuantity), self.number_to_string(market['contractSize']))
        lastUpdatedTimestamp = self.safe_integer(order, 'updatedTime')
        return self.safe_order({
            'info': order,
            'id': self.safe_string_n(order, ['orderId', 'result', 'cancelId', 'entrustId', 'profitId']),
            'clientOrderId': self.safe_string(order, 'clientOrderId'),
            'timestamp': timestamp,
            'datetime': self.iso8601(timestamp),
            'lastTradeTimestamp': lastUpdatedTimestamp,
            'lastUpdateTimestamp': lastUpdatedTimestamp,
            'symbol': symbol,
            'type': self.safe_string_lower_2(order, 'type', 'orderType'),
            'timeInForce': self.safe_string(order, 'timeInForce'),
            'postOnly': None,
            'side': self.safe_string_lower_2(order, 'side', 'orderSide'),
            'price': self.safe_number(order, 'price'),
            'stopPrice': self.safe_number(order, 'stopPrice'),
            'stopLoss': self.safe_number(order, 'triggerStopPrice'),
            'takeProfit': self.safe_number(order, 'triggerProfitPrice'),
            'amount': amount,
            'filled': filled,
            'remaining': self.safe_number(order, 'leavingQty'),
            'cost': None,
            'average': self.safe_number(order, 'avgPrice'),
            'status': self.parse_order_status(self.safe_string(order, 'state')),
            'fee': {
                'currency': self.safe_currency_code(self.safe_string(order, 'feeCurrency')),
                'cost': self.safe_number(order, 'fee'),
            },
            'trades': None,
        }, market)

    def parse_order_status(self, status):
        statuses = {
            'NEW': 'open',
            'PARTIALLY_FILLED': 'open',
            'FILLED': 'closed',
            'CANCELED': 'canceled',
            'REJECTED': 'rejected',
            'EXPIRED': 'expired',
            'UNFINISHED': 'open',
            'NOT_TRIGGERED': 'open',
            'TRIGGERING': 'open',
            'TRIGGERED': 'closed',
            'USER_REVOCATION': 'canceled',
            'PLATFORM_REVOCATION': 'rejected',
            'HISTORY': 'expired',
        }
        return self.safe_string(statuses, status, status)

    def fetch_ledger(self, code: str = None, since: Int = None, limit: Int = None, params={}):
        """
        fetch the history of changes, actions done by the user or operations that altered the balance of the user
        :see: https://doc.xt.com/#futures_usergetBalanceBill
        :param str [code]: unified currency code
        :param int [since]: timestamp in ms of the earliest ledger entry
        :param int [limit]: max number of ledger entries to return
        :param dict params: extra parameters specific to the xt api endpoint
        :returns dict: a `ledger structure <https://docs.ccxt_zagrava.com/en/latest/manual.html#ledger-structure>`
        """
        self.load_markets()
        request = {}
        currency = None
        if code is not None:
            currency = self.currency(code)
        if since is not None:
            request['startTime'] = since
        if limit is not None:
            request['limit'] = limit
        type = None
        subType = None
        response = None
        type, params = self.handle_market_type_and_params('fetchLedger', None, params)
        subType, params = self.handle_sub_type_and_params('fetchLedger', None, params)
        if subType == 'inverse':
            response = self.privateInverseGetFutureUserV1BalanceBills(self.extend(request, params))
        elif (subType == 'linear') or (type == 'swap') or (type == 'future'):
            response = self.privateLinearGetFutureUserV1BalanceBills(self.extend(request, params))
        else:
            raise NotSupported(self.id + ' fetchLedger() does not support spot transactions, only swap and future wallet transactions are supported')
        #
        #     {
        #         "returnCode": 0,
        #         "msgInfo": "success",
        #         "error": null,
        #         "result": {
        #             "hasPrev": False,
        #             "hasNext": False,
        #             "items": [
        #                 {
        #                     "id": "207260567109387524",
        #                     "coin": "usdt",
        #                     "symbol": "btc_usdt",
        #                     "type": "FEE",
        #                     "amount": "-0.0213",
        #                     "side": "SUB",
        #                     "afterAmount": null,
        #                     "createdTime": 1679116769914
        #                 },
        #             ]
        #         }
        #     }
        #
        data = self.safe_value(response, 'result', {})
        ledger = self.safe_value(data, 'items', [])
        return self.parse_ledger(ledger, currency, since, limit)

    def parse_ledger_entry(self, item, currency=None):
        #
        #     {
        #         "id": "207260567109387524",
        #         "coin": "usdt",
        #         "symbol": "btc_usdt",
        #         "type": "FEE",
        #         "amount": "-0.0213",
        #         "side": "SUB",
        #         "afterAmount": null,
        #         "createdTime": 1679116769914
        #     }
        #
        side = self.safe_string(item, 'side')
        direction = 'in' if (side == 'ADD') else 'out'
        currencyId = self.safe_string(item, 'coin')
        timestamp = self.safe_integer(item, 'createdTime')
        return {
            'id': self.safe_string(item, 'id'),
            'direction': direction,
            'account': None,
            'referenceId': None,
            'referenceAccount': None,
            'type': self.parse_ledger_entry_type(self.safe_string(item, 'type')),
            'currency': self.safe_currency_code(currencyId, currency),
            'amount': self.safe_number(item, 'amount'),
            'timestamp': timestamp,
            'datetime': self.iso8601(timestamp),
            'before': None,
            'after': self.safe_number(item, 'afterAmount'),
            'status': None,
            'fee': {
                'currency': None,
                'cost': None,
            },
            'info': item,
        }

    def parse_ledger_entry_type(self, type):
        ledgerType = {
            'EXCHANGE': 'transfer',
            'CLOSE_POSITION': 'trade',
            'TAKE_OVER': 'trade',
            'MERGE': 'trade',
            'QIANG_PING_MANAGER': 'fee',
            'FUND': 'fee',
            'FEE': 'fee',
            'ADL': 'auto-deleveraging',
        }
        return self.safe_string(ledgerType, type, type)

    def fetch_deposit_address(self, code: str, params={}):
        """
        fetch the deposit address for a currency associated with self account
        :see: https://doc.xt.com/#deposit_withdrawaldepositAddressGet
        :param str code: unified currency code
        :param dict params: extra parameters specific to the xt api endpoint
        :param str params['network']: required network id
        :returns dict: an `address structure <https://docs.ccxt_zagrava.com/en/latest/manual.html#address-structure>`
        """
        self.load_markets()
        networkCode = None
        networkCode, params = self.handle_network_code_and_params(params)
        currency = self.currency(code)
        networkId = self.network_code_to_id(networkCode, code)
        self.check_required_argument('fetchDepositAddress', networkId, 'network')
        request = {
            'currency': currency['id'],
            'chain': networkId,
        }
        response = self.privateSpotGetDepositAddress(self.extend(request, params))
        #
        #     {
        #         "rc": 0,
        #         "mc": "SUCCESS",
        #         "ma": [],
        #         "result": {
        #             "address": "0x7f7173cf29d3846d20ca5a3aec1120b93dbd157a",
        #             "memo": ""
        #         }
        #     }
        #
        result = self.safe_value(response, 'result', {})
        return self.parse_deposit_address(result, currency)

    def parse_deposit_address(self, depositAddress, currency=None):
        #
        #     {
        #         "address": "0x7f7173cf29d3846d20ca5a3aec1120b93dbd157a",
        #         "memo": ""
        #     }
        #
        address = self.safe_string(depositAddress, 'address')
        self.check_address(address)
        return {
            'currency': self.safe_currency_code(None, currency),
            'address': address,
            'tag': self.safe_string(depositAddress, 'memo'),
            'network': None,
            'info': depositAddress,
        }

    def fetch_deposits(self, code: str = None, since: Int = None, limit: Int = None, params={}):
        """
        fetch all deposits made to an account
        :see: https://doc.xt.com/#deposit_withdrawalhistoryDepositGet
        :param str [code]: unified currency code
        :param int [since]: the earliest time in ms to fetch deposits for
        :param int [limit]: the maximum number of transaction structures to retrieve
        :param dict params: extra parameters specific to the xt api endpoint
        :returns dict[]: a list of `transaction structures <https://docs.ccxt_zagrava.com/en/latest/manual.html#transaction-structure>`
        """
        self.load_markets()
        request = {}
        currency = None
        if code is not None:
            currency = self.currency(code)
            request['currency'] = currency['id']
        if since is not None:
            request['startTime'] = since
        if limit is not None:
            request['limit'] = limit  # default 10, max 200
        response = self.privateSpotGetDepositHistory(self.extend(request, params))
        #
        #     {
        #         "rc": 0,
        #         "mc": "SUCCESS",
        #         "ma": [],
        #         "result": {
        #             "hasPrev": False,
        #             "hasNext": False,
        #             "items": [
        #                 {
        #                     "id": 170368702,
        #                     "currency": "usdt",
        #                     "chain": "Ethereum",
        #                     "memo": "",
        #                     "status": "SUCCESS",
        #                     "amount": "31.792528",
        #                     "confirmations": 12,
        #                     "transactionId": "0x90b8487c258b81b85e15e461b1839c49d4d8e6e9de4c1adb658cd47d4f5c5321",
        #                     "address": "0x7f7172cf29d3846d30ca5a3aec1120b92dbd150b",
        #                     "fromAddr": "0x7830c87c02e56aff27fa9ab1241711331fa86f58",
        #                     "createdTime": 1678491442000
        #                 },
        #             ]
        #         }
        #     }
        #
        data = self.safe_value(response, 'result', {})
        deposits = self.safe_value(data, 'items', [])
        return self.parse_transactions(deposits, currency, since, limit, params)

    def fetch_withdrawals(self, code: str = None, since: Int = None, limit: Int = None, params={}):
        """
        fetch all withdrawals made from an account
        :see: https://doc.xt.com/#deposit_withdrawalwithdrawHistory
        :param str [code]: unified currency code
        :param int [since]: the earliest time in ms to fetch withdrawals for
        :param int [limit]: the maximum number of transaction structures to retrieve
        :param dict params: extra parameters specific to the xt api endpoint
        :returns dict[]: a list of `transaction structures <https://docs.ccxt_zagrava.com/en/latest/manual.html#transaction-structure>`
        """
        self.load_markets()
        request = {}
        currency = None
        if code is not None:
            currency = self.currency(code)
            request['currency'] = currency['id']
        if since is not None:
            request['startTime'] = since
        if limit is not None:
            request['limit'] = limit  # default 10, max 200
        response = self.privateSpotGetWithdrawHistory(self.extend(request, params))
        #
        #     {
        #         "rc": 0,
        #         "mc": "SUCCESS",
        #         "ma": [],
        #         "result": {
        #             "hasPrev": False,
        #             "hasNext": False,
        #             "items": [
        #                 {
        #                     "id": 950898,
        #                     "currency": "usdt",
        #                     "chain": "Tron",
        #                     "address": "TGB2vxTjiqraVZBy7YHXF8V3CSMVhQKcaf",
        #                     "memo": "",
        #                     "status": "SUCCESS",
        #                     "amount": "5",
        #                     "fee": "2",
        #                     "confirmations": 6,
        #                     "transactionId": "c36e230b879842b1d7afd19d15ee1a866e26eaa0626e367d6f545d2932a15156",
        #                     "createdTime": 1680049062000
        #                 }
        #             ]
        #         }
        #     }
        #
        data = self.safe_value(response, 'result', {})
        withdrawals = self.safe_value(data, 'items', [])
        return self.parse_transactions(withdrawals, currency, since, limit, params)

    def withdraw(self, code: str, amount: float, address: str, tag=None, params={}):
        """
        make a withdrawal
        :see: https://doc.xt.com/#deposit_withdrawalwithdraw
        :param str code: unified currency code
        :param float amount: the amount to withdraw
        :param str address: the address to withdraw to
        :param str [tag]:
        :param dict params: extra parameters specific to the xt api endpoint
        :returns dict: a `transaction structure <https://docs.ccxt_zagrava.com/en/latest/manual.html#transaction-structure>`
        """
        self.check_address(address)
        self.load_markets()
        currency = self.currency(code)
        tag, params = self.handle_withdraw_tag_and_params(tag, params)
        networkCode = None
        networkCode, params = self.handle_network_code_and_params(params)
        networkIdsByCodes = self.safe_value(self.options, 'networks', {})
        networkId = self.safe_string_2(networkIdsByCodes, networkCode, code, code)
        request = {
            'currency': currency['id'],
            'chain': networkId,
            'amount': self.currency_to_precision(code, amount),
            'address': address,
        }
        if tag is not None:
            request['memo'] = tag
        response = self.privateSpotPostWithdraw(self.extend(request, params))
        #
        #     {
        #         "rc": 0,
        #         "mc": "SUCCESS",
        #         "ma": [],
        #         "result": {
        #             "id": 950898
        #         }
        #     }
        #
        result = self.safe_value(response, 'result', {})
        return self.parse_transaction(result, currency)

    def parse_transaction(self, transaction: dict, currency: Currency = None) -> Transaction:
        #
        # fetchDeposits
        #
        #     {
        #         "id": 170368702,
        #         "currency": "usdt",
        #         "chain": "Ethereum",
        #         "memo": "",
        #         "status": "SUCCESS",
        #         "amount": "31.792528",
        #         "confirmations": 12,
        #         "transactionId": "0x90b8487c258b81b85e15e461b1839c49d4d8e6e9de4c1adb658cd47d4f5c5321",
        #         "address": "0x7f7172cf29d3846d30ca5a3aec1120b92dbd150b",
        #         "fromAddr": "0x7830c87c02e56aff27fa9ab1241711331fa86f58",
        #         "createdTime": 1678491442000
        #     }
        #
        # fetchWithdrawals
        #
        #     {
        #         "id": 950898,
        #         "currency": "usdt",
        #         "chain": "Tron",
        #         "address": "TGB2vxTjiqraVZBy7YHXF8V3CSMVhQKcaf",
        #         "memo": "",
        #         "status": "SUCCESS",
        #         "amount": "5",
        #         "fee": "2",
        #         "confirmations": 6,
        #         "transactionId": "c36e230b879842b1d7afd19d15ee1a866e26eaa0626e367d6f545d2932a15156",
        #         "createdTime": 1680049062000
        #     }
        #
        # withdraw
        #
        #     {
        #         "id": 950898
        #     }
        #
        type = 'deposit' if ('fromAddr' in transaction) else 'withdraw'
        timestamp = self.safe_integer(transaction, 'createdTime')
        address = self.safe_string(transaction, 'address')
        memo = self.safe_string(transaction, 'memo')
        currencyCode = self.safe_currency_code(self.safe_string(transaction, 'currency'), currency)
        fee = self.safe_number(transaction, 'fee')
        feeCurrency = currencyCode if (fee is not None) else None
        networkId = self.safe_string(transaction, 'chain')
        return {
            'info': transaction,
            'id': self.safe_string(transaction, 'id'),
            'txid': self.safe_string(transaction, 'transactionId'),
            'timestamp': timestamp,
            'datetime': self.iso8601(timestamp),
            'updated': None,
            'addressFrom': self.safe_string(transaction, 'fromAddr'),
            'addressTo': address,
            'address': address,
            'tagFrom': None,
            'tagTo': None,
            'tag': memo,
            'type': type,
            'amount': self.safe_number(transaction, 'amount'),
            'currency': currencyCode,
            'network': self.network_id_to_code(networkId, currencyCode),
            'status': self.parse_transaction_status(self.safe_string(transaction, 'status')),
            'comment': memo,
            'fee': {
                'currency': feeCurrency,
                'cost': fee,
                'rate': None,
            },
            'internal': None,
        }

    def parse_transaction_status(self, status):
        statuses = {
            'SUBMIT': 'pending',
            'REVIEW': 'pending',
            'AUDITED': 'pending',
            'PENDING': 'pending',
            'CANCEL': 'canceled',
            'FAIL': 'failed',
            'SUCCESS': 'ok',
        }
        return self.safe_string(statuses, status, status)

    def set_leverage(self, leverage: Int, symbol: str = None, params={}):
        """
        set the level of leverage for a market
        :see: https://doc.xt.com/#futures_useradjustLeverage
        :param float leverage: the rate of leverage
        :param str symbol: unified market symbol
        :param dict params: extra parameters specific to the xt api endpoint
        :param str params['positionSide']: 'LONG' or 'SHORT'
        :returns dict: response from the exchange
        """
        if symbol is None:
            raise ArgumentsRequired(self.id + ' setLeverage() requires a symbol argument')
        positionSide = self.safe_string(params, 'positionSide')
        self.check_required_argument('setLeverage', positionSide, 'positionSide', ['LONG', 'SHORT'])
        if (leverage < 1) or (leverage > 125):
            raise BadRequest(self.id + ' setLeverage() leverage should be between 1 and 125')
        self.load_markets()
        market = self.market(symbol)
        if not (market['contract']):
            raise BadSymbol(self.id + ' setLeverage() supports contract markets only')
        request = {
            'symbol': market['id'],
            'positionSide': positionSide,
            'leverage': leverage,
        }
        subType = None
        subType, params = self.handle_sub_type_and_params('setLeverage', market, params)
        response = None
        if subType == 'inverse':
            response = self.privateInversePostFutureUserV1PositionAdjustLeverage(self.extend(request, params))
        else:
            response = self.privateLinearPostFutureUserV1PositionAdjustLeverage(self.extend(request, params))
        #
        #     {
        #         "returnCode": 0,
        #         "msgInfo": "success",
        #         "error": null,
        #         "result": null
        #     }
        #
        return response

    def add_margin(self, symbol: str, amount: float, params={}):
        """
        add margin to a position
        :see: https://doc.xt.com/#futures_useradjustMargin
        :param str symbol: unified market symbol
        :param float amount: amount of margin to add
        :param dict params: extra parameters specific to the xt api endpoint
        :param str params['positionSide']: 'LONG' or 'SHORT'
        :returns dict: a `margin structure <https://docs.ccxt_zagrava.com/#/?id=add-margin-structure>`
        """
        return self.modify_margin_helper(symbol, amount, 'ADD', params)

    def reduce_margin(self, symbol: str, amount: float, params={}):
        """
        remove margin from a position
        :see: https://doc.xt.com/#futures_useradjustMargin
        :param str symbol: unified market symbol
        :param float amount: the amount of margin to remove
        :param dict params: extra parameters specific to the xt api endpoint
        :param str params['positionSide']: 'LONG' or 'SHORT'
        :returns dict: a `margin structure <https://docs.ccxt_zagrava.com/#/?id=reduce-margin-structure>`
        """
        return self.modify_margin_helper(symbol, amount, 'SUB', params)

    def modify_margin_helper(self, symbol: str, amount, addOrReduce, params={}) -> MarginModification:
        positionSide = self.safe_string(params, 'positionSide')
        self.check_required_argument('setLeverage', positionSide, 'positionSide', ['LONG', 'SHORT'])
        self.load_markets()
        market = self.market(symbol)
        request = {
            'symbol': market['id'],
            'margin': amount,
            'type': addOrReduce,
            'positionSide': positionSide,
        }
        subType = None
        subType, params = self.handle_sub_type_and_params('modifyMarginHelper', market, params)
        response = None
        if subType == 'inverse':
            response = self.privateInversePostFutureUserV1PositionMargin(self.extend(request, params))
        else:
            response = self.privateLinearPostFutureUserV1PositionMargin(self.extend(request, params))
        #
        #     {
        #         "returnCode": 0,
        #         "msgInfo": "success",
        #         "error": null,
        #         "result": null
        #     }
        #
        return self.parse_margin_modification(response, market)

    def parse_margin_modification(self, data, market=None) -> MarginModification:
        return {
            'info': data,
            'type': None,
            'amount': None,
            'code': None,
            'symbol': self.safe_symbol(None, market),
            'status': None,
            'marginMode': None,
            'total': None,
            'timestamp': None,
            'datetime': None,
        }

    def fetch_leverage_tiers(self, symbols: List[str] = None, params={}):
        """
        :see: https://doc.xt.com/#futures_quotesgetLeverageBrackets
        retrieve information on the maximum leverage for different trade sizes
        :param str [symbols]: a list of unified market symbols
        :param dict params: extra parameters specific to the xt api endpoint
        :returns dict: a dictionary of `leverage tiers structures <https://docs.ccxt_zagrava.com/#/?id=leverage-tiers-structure>`
        """
        self.load_markets()
        subType = None
        subType, params = self.handle_sub_type_and_params('fetchLeverageTiers', None, params)
        response = None
        if subType == 'inverse':
            response = self.publicInverseGetFutureMarketV1PublicLeverageBracketList(params)
        else:
            response = self.publicLinearGetFutureMarketV1PublicLeverageBracketList(params)
        #
        #     {
        #         "returnCode": 0,
        #         "msgInfo": "success",
        #         "error": null,
        #         "result": [
        #             {
        #                 "symbol": "rad_usdt",
        #                 "leverageBrackets": [
        #                     {
        #                         "symbol": "rad_usdt",
        #                         "bracket": 1,
        #                         "maxNominalValue": "5000",
        #                         "maintMarginRate": "0.025",
        #                         "startMarginRate": "0.05",
        #                         "maxStartMarginRate": null,
        #                         "maxLeverage": "20",
        #                         "minLeverage": "1"
        #                     },
        #                 ]
        #             },
        #         ]
        #     }
        #
        data = self.safe_value(response, 'result', [])
        symbols = self.market_symbols(symbols)
        return self.parse_leverage_tiers(data, symbols, 'symbol')

    def parse_leverage_tiers(self, response, symbols=None, marketIdKey=None):
        #
        #     {
        #         "symbol": "rad_usdt",
        #         "leverageBrackets": [
        #             {
        #                 "symbol": "rad_usdt",
        #                 "bracket": 1,
        #                 "maxNominalValue": "5000",
        #                 "maintMarginRate": "0.025",
        #                 "startMarginRate": "0.05",
        #                 "maxStartMarginRate": null,
        #                 "maxLeverage": "20",
        #                 "minLeverage": "1"
        #             },
        #         ]
        #     }
        #
        result = {}
        for i in range(0, len(response)):
            entry = response[i]
            marketId = self.safe_string(entry, 'symbol')
            market = self.safe_market(marketId, None, '_', 'contract')
            symbol = self.safe_symbol(marketId, market)
            if symbols is not None:
                if self.in_array(symbol, symbols):
                    result[symbol] = self.parse_market_leverage_tiers(entry, market)
            else:
                result[symbol] = self.parse_market_leverage_tiers(response[i], market)
        return result

    def fetch_market_leverage_tiers(self, symbol: str, params={}) -> List[LeverageTier]:
        """
        :see: https://doc.xt.com/#futures_quotesgetLeverageBracket
        retrieve information on the maximum leverage for different trade sizes of a single market
        :param str symbol: unified market symbol
        :param dict params: extra parameters specific to the xt api endpoint
        :returns dict: a `leverage tiers structure <https://docs.ccxt_zagrava.com/#/?id=leverage-tiers-structure>`
        """
        self.load_markets()
        market = self.market(symbol)
        request = {
            'symbol': market['id'],
        }
        subType = None
        subType, params = self.handle_sub_type_and_params('fetchMarketLeverageTiers', market, params)
        response = None
        if subType == 'inverse':
            response = self.publicInverseGetFutureMarketV1PublicLeverageBracketDetail(self.extend(request, params))
        else:
            response = self.publicLinearGetFutureMarketV1PublicLeverageBracketDetail(self.extend(request, params))
        #
        #     {
        #         "returnCode": 0,
        #         "msgInfo": "success",
        #         "error": null,
        #         "result": {
        #             "symbol": "btc_usdt",
        #             "leverageBrackets": [
        #                 {
        #                     "symbol": "btc_usdt",
        #                     "bracket": 1,
        #                     "maxNominalValue": "500000",
        #                     "maintMarginRate": "0.004",
        #                     "startMarginRate": "0.008",
        #                     "maxStartMarginRate": null,
        #                     "maxLeverage": "125",
        #                     "minLeverage": "1"
        #                 },
        #             ]
        #         }
        #     }
        #
        data = self.safe_value(response, 'result', {})
        return self.parse_market_leverage_tiers(data, market)

    def parse_market_leverage_tiers(self, info, market=None):
        #
        #     {
        #         "symbol": "rad_usdt",
        #         "leverageBrackets": [
        #             {
        #                 "symbol": "rad_usdt",
        #                 "bracket": 1,
        #                 "maxNominalValue": "5000",
        #                 "maintMarginRate": "0.025",
        #                 "startMarginRate": "0.05",
        #                 "maxStartMarginRate": null,
        #                 "maxLeverage": "20",
        #                 "minLeverage": "1"
        #             },
        #         ]
        #     }
        #
        tiers = []
        brackets = self.safe_value(info, 'leverageBrackets', [])
        for i in range(0, len(brackets)):
            tier = brackets[i]
            marketId = self.safe_string(info, 'symbol')
            market = self.safe_market(marketId, market, '_', 'contract')
            tiers.append({
                'tier': self.safe_integer(tier, 'bracket'),
                'currency': market['settle'],
                'minNotional': self.safe_number(brackets[i - 1], 'maxNominalValue', 0),
                'maxNotional': self.safe_number(tier, 'maxNominalValue'),
                'maintenanceMarginRate': self.safe_number(tier, 'maintMarginRate'),
                'maxLeverage': self.safe_number(tier, 'maxLeverage'),
                'info': tier,
            })
        return tiers

    def fetch_funding_rate_history(self, symbol: str = None, since: Int = None, limit: Int = None, params={}):
        """
        fetches historical funding rates
        :see: https://doc.xt.com/#futures_quotesgetFundingRateRecord
        :param str [symbol]: unified symbol of the market to fetch the funding rate history for
        :param int [since]: timestamp in ms of the earliest funding rate to fetch
        :param int [limit]: the maximum amount of [funding rate structures] to fetch
        :param dict params: extra parameters specific to the xt api endpoint
        :returns dict[]: a list of `funding rate structures <https://docs.ccxt_zagrava.com/en/latest/manual.html?#funding-rate-history-structure>`
        """
        if symbol is None:
            raise ArgumentsRequired(self.id + ' fetchFundingRateHistory() requires a symbol argument')
        self.load_markets()
        market = self.market(symbol)
        if not market['swap']:
            raise BadSymbol(self.id + ' fetchFundingRateHistory() supports swap contracts only')
        request = {
            'symbol': market['id'],
        }
        if limit is not None:
            request['limit'] = limit
        subType = None
        subType, params = self.handle_sub_type_and_params('fetchFundingRateHistory', market, params)
        response = None
        if subType == 'inverse':
            response = self.publicInverseGetFutureMarketV1PublicQFundingRateRecord(self.extend(request, params))
        else:
            response = self.publicLinearGetFutureMarketV1PublicQFundingRateRecord(self.extend(request, params))
        #
        #     {
        #         "returnCode": 0,
        #         "msgInfo": "success",
        #         "error": null,
        #         "result": {
        #             "hasPrev": False,
        #             "hasNext": True,
        #             "items": [
        #                 {
        #                     "id": "210441653482221888",
        #                     "symbol": "btc_usdt",
        #                     "fundingRate": "0.000057",
        #                     "createdTime": 1679875200000,
        #                     "collectionInternal": 28800
        #                 },
        #             ]
        #         }
        #     }
        #
        result = self.safe_value(response, 'result', {})
        items = self.safe_value(result, 'items', [])
        rates = []
        for i in range(0, len(items)):
            entry = items[i]
            marketId = self.safe_string(entry, 'symbol')
            symbolInner = self.safe_symbol(marketId, market)
            timestamp = self.safe_integer(entry, 'createdTime')
            rates.append({
                'info': entry,
                'symbol': symbolInner,
                'fundingRate': self.safe_number(entry, 'fundingRate'),
                'timestamp': timestamp,
                'datetime': self.iso8601(timestamp),
            })
        sorted = self.sort_by(rates, 'timestamp')
        return self.filter_by_symbol_since_limit(sorted, market['symbol'], since, limit)

    def fetch_funding_rate(self, symbol: str, params={}):
        """
        fetch the current funding rate
        :see: https://doc.xt.com/#futures_quotesgetFundingRate
        :param str symbol: unified market symbol
        :param dict params: extra parameters specific to the xt api endpoint
        :returns dict: a `funding rate structure <https://docs.ccxt_zagrava.com/#/?id=funding-rate-structure>`
        """
        self.load_markets()
        market = self.market(symbol)
        if not market['swap']:
            raise BadSymbol(self.id + ' fetchFundingRate() supports swap contracts only')
        request = {
            'symbol': market['id'],
        }
        subType = None
        subType, params = self.handle_sub_type_and_params('fetchFundingRate', market, params)
        response = None
        if subType == 'inverse':
            response = self.publicInverseGetFutureMarketV1PublicQFundingRate(self.extend(request, params))
        else:
            response = self.publicLinearGetFutureMarketV1PublicQFundingRate(self.extend(request, params))
        #
        #     {
        #         "returnCode": 0,
        #         "msgInfo": "success",
        #         "error": null,
        #         "result": {
        #             "symbol": "btc_usdt",
        #             "fundingRate": "0.000086",
        #             "nextCollectionTime": 1680307200000,
        #             "collectionInternal": 8
        #         }
        #     }
        #
        result = self.safe_value(response, 'result', {})
        return self.parse_funding_rate(result, market)

    def parse_funding_rate(self, contract, market=None):
        #
        #     {
        #         "symbol": "btc_usdt",
        #         "fundingRate": "0.000086",
        #         "nextCollectionTime": 1680307200000,
        #         "collectionInternal": 8
        #     }
        #
        marketId = self.safe_string(contract, 'symbol')
        symbol = self.safe_symbol(marketId, market, '_', 'swap')
        timestamp = self.safe_integer(contract, 'nextCollectionTime')
        return {
            'info': contract,
            'symbol': symbol,
            'markPrice': None,
            'indexPrice': None,
            'interestRate': None,
            'estimatedSettlePrice': None,
            'timestamp': None,
            'datetime': None,
            'fundingRate': self.safe_number(contract, 'fundingRate'),
            'fundingTimestamp': timestamp,
            'fundingDatetime': self.iso8601(timestamp),
            'nextFundingRate': None,
            'nextFundingTimestamp': None,
            'nextFundingDatetime': None,
            'previousFundingRate': None,
            'previousFundingTimestamp': None,
            'previousFundingDatetime': None,
        }

    def fetch_funding_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
        """
        fetch the funding history
        :see: https://doc.xt.com/#futures_usergetFunding
        :param str symbol: unified market symbol
        :param int [since]: the starting timestamp in milliseconds
        :param int [limit]: the number of entries to return
        :param dict params: extra parameters specific to the xt api endpoint
        :returns dict[]: a list of `funding history structures <https://docs.ccxt_zagrava.com/#/?id=funding-history-structure>`
        """
        self.load_markets()
        market = self.market(symbol)
        if not market['swap']:
            raise BadSymbol(self.id + ' fetchFundingHistory() supports swap contracts only')
        request = {
            'symbol': market['id'],
        }
        if since is not None:
            request['startTime'] = since
        if limit is not None:
            request['limit'] = limit
        subType = None
        subType, params = self.handle_sub_type_and_params('fetchFundingHistory', market, params)
        response = None
        if subType == 'inverse':
            response = self.privateInverseGetFutureUserV1BalanceFundingRateList(self.extend(request, params))
        else:
            response = self.privateLinearGetFutureUserV1BalanceFundingRateList(self.extend(request, params))
        #
        #     {
        #         "returnCode": 0,
        #         "msgInfo": "success",
        #         "error": null,
        #         "result": {
        #             "hasPrev": False,
        #             "hasNext": False,
        #             "items": [
        #                 {
        #                     "id": "210804044057280512",
        #                     "symbol": "btc_usdt",
        #                     "cast": "-0.0013",
        #                     "coin": "usdt",
        #                     "positionSide": "SHORT",
        #                     "createdTime": 1679961600653
        #                 },
        #             ]
        #         }
        #     }
        #
        data = self.safe_value(response, 'result', {})
        items = self.safe_value(data, 'items', [])
        result = []
        for i in range(0, len(items)):
            entry = items[i]
            result.append(self.parse_funding_history(entry, market))
        sorted = self.sort_by(result, 'timestamp')
        return self.filter_by_since_limit(sorted, since, limit)

    def parse_funding_history(self, contract, market=None):
        #
        #     {
        #         "id": "210804044057280512",
        #         "symbol": "btc_usdt",
        #         "cast": "-0.0013",
        #         "coin": "usdt",
        #         "positionSide": "SHORT",
        #         "createdTime": 1679961600653
        #     }
        #
        marketId = self.safe_string(contract, 'symbol')
        symbol = self.safe_symbol(marketId, market, '_', 'swap')
        currencyId = self.safe_string(contract, 'coin')
        code = self.safe_currency_code(currencyId)
        timestamp = self.safe_integer(contract, 'createdTime')
        return {
            'info': contract,
            'symbol': symbol,
            'code': code,
            'timestamp': timestamp,
            'datetime': self.iso8601(timestamp),
            'id': self.safe_string(contract, 'id'),
            'amount': self.safe_number(contract, 'cast'),
        }

    def fetch_position(self, symbol: str, params={}):
        """
        fetch data on a single open contract trade position
        :see: https://doc.xt.com/#futures_usergetPosition
        :param str symbol: unified market symbol of the market the position is held in
        :param dict params: extra parameters specific to the xt api endpoint
        :returns dict: a `position structure <https://docs.ccxt_zagrava.com/#/?id=position-structure>`
        """
        self.load_markets()
        market = self.market(symbol)
        request = {
            'symbol': market['id'],
        }
        subType = None
        subType, params = self.handle_sub_type_and_params('fetchPosition', market, params)
        response = None
        if subType == 'inverse':
            response = self.privateInverseGetFutureUserV1PositionList(self.extend(request, params))
        else:
            response = self.privateLinearGetFutureUserV1PositionList(self.extend(request, params))
        #
        #     {
        #         "returnCode": 0,
        #         "msgInfo": "success",
        #         "error": null,
        #         "result": [
        #             {
        #                 "symbol": "btc_usdt",
        #                 "positionType": "ISOLATED",
        #                 "positionSide": "SHORT",
        #                 "contractType": "PERPETUAL",
        #                 "positionSize": "10",
        #                 "closeOrderSize": "0",
        #                 "availableCloseSize": "10",
        #                 "entryPrice": "27060",
        #                 "openOrderSize": "0",
        #                 "isolatedMargin": "1.0824",
        #                 "openOrderMarginFrozen": "0",
        #                 "realizedProfit": "-0.00130138",
        #                 "autoMargin": False,
        #                 "leverage": 25
        #             },
        #         ]
        #     }
        #
        positions = self.safe_value(response, 'result', [])
        for i in range(0, len(positions)):
            entry = positions[i]
            marketId = self.safe_string(entry, 'symbol')
            marketInner = self.safe_market(marketId, None, None, 'contract')
            positionSize = self.safe_string(entry, 'positionSize')
            if positionSize != '0':
                return self.parse_position(entry, marketInner)
        return None

    def fetch_positions(self, symbols: List[str] = None, params={}):
        """
        fetch all open positions
        :see: https://doc.xt.com/#futures_usergetPosition
        :param str [symbols]: list of unified market symbols, not supported with xt
        :param dict params: extra parameters specific to the xt api endpoint
        :returns dict[]: a list of `position structure <https://docs.ccxt_zagrava.com/#/?id=position-structure>`
        """
        self.load_markets()
        subType = None
        subType, params = self.handle_sub_type_and_params('fetchPositions', None, params)
        response = None
        if subType == 'inverse':
            response = self.privateInverseGetFutureUserV1PositionList(params)
        else:
            response = self.privateLinearGetFutureUserV1PositionList(params)
        #
        #     {
        #         "returnCode": 0,
        #         "msgInfo": "success",
        #         "error": null,
        #         "result": [
        #             {
        #                 "symbol": "btc_usdt",
        #                 "positionType": "ISOLATED",
        #                 "positionSide": "SHORT",
        #                 "contractType": "PERPETUAL",
        #                 "positionSize": "10",
        #                 "closeOrderSize": "0",
        #                 "availableCloseSize": "10",
        #                 "entryPrice": "27060",
        #                 "openOrderSize": "0",
        #                 "isolatedMargin": "1.0824",
        #                 "openOrderMarginFrozen": "0",
        #                 "realizedProfit": "-0.00130138",
        #                 "autoMargin": False,
        #                 "leverage": 25
        #             },
        #         ]
        #     }
        #
        positions = self.safe_value(response, 'result', [])
        result = []
        for i in range(0, len(positions)):
            entry = positions[i]
            marketId = self.safe_string(entry, 'symbol')
            marketInner = self.safe_market(marketId, None, None, 'contract')
            result.append(self.parse_position(entry, marketInner))
        return self.filter_by_array_positions(result, 'symbol', symbols, False)

    def parse_position(self, position, market=None):
        #
        #     {
        #         "symbol": "btc_usdt",
        #         "positionType": "ISOLATED",
        #         "positionSide": "SHORT",
        #         "contractType": "PERPETUAL",
        #         "positionSize": "10",
        #         "closeOrderSize": "0",
        #         "availableCloseSize": "10",
        #         "entryPrice": "27060",
        #         "openOrderSize": "0",
        #         "isolatedMargin": "1.0824",
        #         "openOrderMarginFrozen": "0",
        #         "realizedProfit": "-0.00130138",
        #         "autoMargin": False,
        #         "leverage": 25
        #     }
        #
        marketId = self.safe_string(position, 'symbol')
        market = self.safe_market(marketId, market, None, 'contract')
        symbol = self.safe_symbol(marketId, market, None, 'contract')
        positionType = self.safe_string(position, 'positionType')
        marginMode = 'cross' if (positionType == 'CROSSED') else 'isolated'
        collateral = self.safe_number(position, 'isolatedMargin')
        return self.safe_position({
            'info': position,
            'id': None,
            'symbol': symbol,
            'timestamp': None,
            'datetime': None,
            'hedged': None,
            'side': self.safe_string_lower(position, 'positionSide'),
            'contracts': self.safe_number(position, 'positionSize'),
            'contractSize': market['contractSize'],
            'entryPrice': self.safe_number(position, 'entryPrice'),
            'markPrice': None,
            'notional': None,
            'leverage': self.safe_integer(position, 'leverage'),
            'collateral': collateral,
            'initialMargin': collateral,
            'maintenanceMargin': None,
            'initialMarginPercentage': None,
            'maintenanceMarginPercentage': None,
            'unrealizedPnl': None,
            'liquidationPrice': None,
            'marginMode': marginMode,
            'percentage': None,
            'marginRatio': None,
        })

    def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
        """
        transfer currency internally between wallets on the same account
        :see: https://doc.xt.com/#transfersubTransferPost
        :param str code: unified currency code
        :param float amount: amount to transfer
        :param str fromAccount: account to transfer from -  spot, swap, leverage, finance
        :param str toAccount: account to transfer to - spot, swap, leverage, finance
        :param dict params: extra parameters specific to the whitebit api endpoint
        :returns dict: a `transfer structure <https://docs.ccxt_zagrava.com/#/?id=transfer-structure>`
        """
        self.load_markets()
        currency = self.currency(code)
        accountsByType = self.safe_value(self.options, 'accountsById')
        fromAccountId = self.safe_string(accountsByType, fromAccount, fromAccount)
        toAccountId = self.safe_string(accountsByType, toAccount, toAccount)
        amountString = self.currency_to_precision(code, amount)
        request = {
            'bizId': self.uuid(),
            'currency': currency['id'],
            'amount': amountString,
            'from': fromAccountId,
            'to': toAccountId,
        }
        response = self.privateSpotPostBalanceTransfer(self.extend(request, params))
        #
        #   {
        #       info: {rc: '0', mc: 'SUCCESS', ma: [], result: '226971333791398656'},
        #       id: '226971333791398656',
        #       timestamp: None,
        #       datetime: None,
        #       currency: None,
        #       amount: None,
        #       fromAccount: None,
        #       toAccount: None,
        #       status: None
        #   }
        #
        return self.parse_transfer(response, currency)

    def parse_transfer(self, transfer, currency=None):
        return {
            'info': transfer,
            'id': self.safe_string(transfer, 'result'),
            'timestamp': None,
            'datetime': None,
            'currency': None,
            'amount': None,
            'fromAccount': None,
            'toAccount': None,
            'status': None,
        }

    def handle_errors(self, code, reason, url, method, headers, body, response, requestHeaders, requestBody):
        #
        # spot: error
        #
        #     {
        #         "rc": 1,
        #         "mc": "AUTH_103",
        #         "ma": [],
        #         "result": null
        #     }
        #
        # spot: success
        #
        #     {
        #         "returnCode": 0,
        #         "msgInfo": "success",
        #         "error": null,
        #         "result": []
        #     }
        #
        # swap and future: error
        #
        #     {
        #         "returnCode": 1,
        #         "msgInfo": "failure",
        #         "error": {
        #             "code": "403",
        #             "msg": "invalid signature"
        #         },
        #         "result": null
        #     }
        #
        # swap and future: success
        #
        #     {
        #         "returnCode": 0,
        #         "msgInfo": "success",
        #         "error": null,
        #         "result": null
        #     }
        #
        # other:
        #
        #     {
        #         "rc": 0,
        #         "mc": "SUCCESS",
        #         "ma": [],
        #         "result": {}
        #     }
        #
        status = self.safe_string_upper_2(response, 'msgInfo', 'mc')
        if status is not None and status != 'SUCCESS':
            feedback = self.id + ' ' + body
            error = self.safe_value(response, 'error', {})
            spotErrorCode = self.safe_string(response, 'mc')
            errorCode = self.safe_string(error, 'code', spotErrorCode)
            spotMessage = self.safe_string(response, 'msgInfo')
            message = self.safe_string(error, 'msg', spotMessage)
            self.throw_exactly_matched_exception(self.exceptions['exact'], errorCode, feedback)
            self.throw_broadly_matched_exception(self.exceptions['broad'], message, feedback)
            raise ExchangeError(feedback)
        return None

    def sign(self, path, api=[], method='GET', params={}, headers=None, body=None):
        signed = api[0] == 'private'
        endpoint = api[1]
        request = '/' + self.implode_params(path, params)
        payload = None
        if (endpoint == 'spot') or (endpoint == 'user'):
            if signed:
                payload = '/' + self.version + request
            else:
                payload = '/' + self.version + '/public' + request
        else:
            payload = request
        url = self.urls['api'][endpoint] + payload
        query = self.omit(params, self.extract_params(path))
        urlencoded = self.urlencode(self.keysort(query))
        headers = {
            'Content-Type': 'application/json',
        }
        if signed:
            self.check_required_credentials()
            defaultRecvWindow = self.safe_string(self.options, 'recvWindow')
            recvWindow = self.safe_string(query, 'recvWindow', defaultRecvWindow)
            timestamp = self.number_to_string(self.nonce())
            body = query
            if (payload == '/v4/order') or (payload == '/future/trade/v1/order/create') or (payload == '/future/trade/v1/entrust/create-plan') or (payload == '/future/trade/v1/entrust/create-profit') or (payload == '/future/trade/v1/order/create-batch'):
                id = 'ccxt_zagrava'
                if payload.find('future') > -1:
                    body['clientMedia'] = id
                else:
                    body['media'] = id
            isUndefinedBody = ((method == 'GET') or (path == 'order/{orderId}') or (path == 'ws-token'))
            body = None if isUndefinedBody else self.json(body)
            payloadString = None
            if (endpoint == 'spot') or (endpoint == 'user'):
                payloadString = 'xt-validate-algorithms=HmacSHA256&xt-validate-appkey=' + self.apiKey + '&xt-validate-recvwindow=' + recvWindow + '&xt-validate-t' + 'imestamp=' + timestamp
                if isUndefinedBody:
                    if urlencoded:
                        url += '?' + urlencoded
                        payloadString += '#' + method + '#' + payload + '#' + self.rawencode(self.keysort(query))
                    else:
                        payloadString += '#' + method + '#' + payload
                else:
                    payloadString += '#' + method + '#' + payload + '#' + body
                headers['xt-validate-algorithms'] = 'HmacSHA256'
                headers['xt-validate-recvwindow'] = recvWindow
            else:
                payloadString = 'xt-validate-appkey=' + self.apiKey + '&xt-validate-t' + 'imestamp=' + timestamp  # we can't glue timestamp, breaks in php
                if method == 'GET':
                    if urlencoded:
                        url += '?' + urlencoded
                        payloadString += '#' + payload + '#' + urlencoded
                    else:
                        payloadString += '#' + payload
                else:
                    payloadString += '#' + payload + '#' + body
            signature = self.hmac(self.encode(payloadString), self.encode(self.secret), hashlib.sha256)
            headers['xt-validate-appkey'] = self.apiKey
            headers['xt-validate-timestamp'] = timestamp
            headers['xt-validate-signature'] = signature
        else:
            if urlencoded:
                url += '?' + urlencoded
        return {'url': url, 'method': method, 'body': body, 'headers': headers}
