text: # -*- coding: utf-8 -*-
  
  # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
  # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
  
  from ccxt.async_support.base.exchange import Exchange
  
  # -----------------------------------------------------------------------------
  
  try:
      basestring  # Python 3
  except NameError:
      basestring = str  # Python 2
  import hashlib
  from ccxt.base.errors import ExchangeError
  from ccxt.base.errors import AuthenticationError
  from ccxt.base.errors import PermissionDenied
  from ccxt.base.errors import AccountNotEnabled
  from ccxt.base.errors import ArgumentsRequired
  from ccxt.base.errors import BadRequest
  from ccxt.base.errors import BadSymbol
  from ccxt.base.errors import InsufficientFunds
  from ccxt.base.errors import InvalidAddress
  from ccxt.base.errors import InvalidOrder
  from ccxt.base.errors import OrderNotFound
  from ccxt.base.errors import NotSupported
  from ccxt.base.errors import NetworkError
  from ccxt.base.errors import RateLimitExceeded
  from ccxt.base.errors import ExchangeNotAvailable
  from ccxt.base.errors import OnMaintenance
  from ccxt.base.errors import RequestTimeout
  from ccxt.base.decimal_to_precision import TRUNCATE
  from ccxt.base.decimal_to_precision import TICK_SIZE
  from ccxt.base.precise import Precise
  
  
  class huobi(Exchange):
  
      def describe(self):
          return self.deep_extend(super(huobi, self).describe(), {
              'id': 'huobi',
              'name': 'Huobi',
              'countries': ['CN'],
              'rateLimit': 100,
              'userAgent': self.userAgents['chrome39'],
              'certified': True,
              'version': 'v1',
              'accounts': None,
              'accountsById': None,
              'hostname': 'api.huobi.pro',  # api.testnet.huobi.pro
              'pro': True,
              'has': {
                  'CORS': None,
                  'spot': True,
                  'margin': True,
                  'swap': True,
                  'future': True,
                  'option': None,
                  'addMargin': None,
                  'cancelAllOrders': True,
                  'cancelOrder': True,
                  'cancelOrders': True,
                  'createDepositAddress': None,
                  'createOrder': True,
                  'createReduceOnlyOrder': False,
                  'deposit': None,
                  'fetchAccounts': True,
                  'fetchAllTradingFees': None,
                  'fetchBalance': True,
                  'fetchBidsAsks': None,
                  'fetchBorrowRate': True,
                  'fetchBorrowRateHistories': None,
                  'fetchBorrowRateHistory': None,
                  'fetchBorrowRates': True,
                  'fetchBorrowRatesPerSymbol': True,
                  'fetchCanceledOrders': None,
                  'fetchClosedOrder': None,
                  'fetchClosedOrders': True,
                  'fetchCurrencies': True,
                  'fetchDeposit': None,
                  'fetchDepositAddress': True,
                  'fetchDepositAddresses': None,
                  'fetchDepositAddressesByNetwork': True,
                  'fetchDeposits': True,
                  'fetchFundingFee': None,
                  'fetchFundingFees': None,
                  'fetchFundingHistory': True,
                  'fetchFundingRate': True,
                  'fetchFundingRateHistory': True,
                  'fetchFundingRates': True,
                  'fetchIndexOHLCV': True,
                  'fetchIsolatedPositions': False,
                  'fetchL3OrderBook': None,
                  'fetchLedger': True,
                  'fetchLedgerEntry': None,
                  'fetchLeverage': False,
                  'fetchMarkets': True,
                  'fetchMarkOHLCV': True,
                  'fetchMyBuys': None,
                  'fetchMySells': None,
                  'fetchMyTrades': True,
                  'fetchOHLCV': True,
                  'fetchOpenOrder': None,
                  'fetchOpenOrders': True,
                  'fetchOrder': True,
                  'fetchOrderBook': True,
                  'fetchOrderBooks': None,
                  'fetchOrders': True,
                  'fetchOrderTrades': True,
                  'fetchPosition': True,
                  'fetchPositions': True,
                  'fetchPositionsRisk': False,
                  'fetchPremiumIndexOHLCV': True,
                  'fetchStatus': None,
                  'fetchTicker': True,
                  'fetchTickers': True,
                  'fetchTime': True,
                  'fetchTrades': True,
                  'fetchTradingFee': True,
                  'fetchTradingFees': None,
                  'fetchTradingLimits': True,
                  'fetchTransactions': None,
                  'fetchTransfers': None,
                  'fetchWithdrawAddressesByNetwork': True,
                  'fetchWithdrawal': None,
                  'fetchWithdrawals': True,
                  'fetchWithdrawalWhitelist': None,
                  'loadLeverageBrackets': None,
                  'reduceMargin': None,
                  'setLeverage': True,
                  'setMarginMode': False,
                  'setPositionMode': False,
                  'signIn': None,
                  'transfer': True,
                  'withdraw': True,
              },
              'timeframes': {
                  '1m': '1min',
                  '5m': '5min',
                  '15m': '15min',
                  '30m': '30min',
                  '1h': '60min',
                  '4h': '4hour',
                  '1d': '1day',
                  '1w': '1week',
                  '1M': '1mon',
                  '1y': '1year',
              },
              'urls': {
                  # 'test': {
                  #     'market': 'https://api.testnet.huobi.pro',
                  #     'public': 'https://api.testnet.huobi.pro',
                  #     'private': 'https://api.testnet.huobi.pro',
                  # },
                  'logo': 'https://user-images.githubusercontent.com/1294454/76137448-22748a80-604e-11ea-8069-6e389271911d.jpg',
                  'hostnames': {
                      'contract': 'api.hbdm.com',
                      'spot': 'api.huobi.pro',
                      # recommended for AWS
                      # 'contract': 'api.hbdm.vn',
                      # 'spot': 'api-aws.huobi.pro',
                  },
                  'api': {
                      'contract': 'https://{hostname}',
                      'spot': 'https://{hostname}',
                      'market': 'https://{hostname}',
                      'public': 'https://{hostname}',
                      'private': 'https://{hostname}',
                      'v2Public': 'https://{hostname}',
                      'v2Private': 'https://{hostname}',
                  },
                  'www': 'https://www.huobi.com',
                  'referral': {
                      'url': 'https://www.huobi.com/en-us/topic/double-reward/?invite_code=6rmm2223',
                      'discount': 0.15,
                  },
                  'doc': [
                      'https://huobiapi.github.io/docs/spot/v1/cn/',
                      'https://huobiapi.github.io/docs/dm/v1/cn/',
                      'https://huobiapi.github.io/docs/coin_margined_swap/v1/cn/',
                      'https://huobiapi.github.io/docs/usdt_swap/v1/cn/',
                      'https://huobiapi.github.io/docs/option/v1/cn/',
                  ],
                  'fees': 'https://www.huobi.com/about/fee/',
              },
              'api': {
                  # ------------------------------------------------------------
                  # old api definitions
                  'v2Public': {
                      'get': {
                          'reference/currencies': 1,  # 币链参考信息
                          'market-status': 1,  # 获取当前市场状态
                      },
                  },
                  'v2Private': {
                      'get': {
                          'account/ledger': 1,
                          'account/withdraw/quota': 1,
                          'account/withdraw/address': 1,  # 提币地址查询(限母用户可用)
                          'account/deposit/address': 1,
                          'account/repayment': 5,  # 还币交易记录查询
                          'reference/transact-fee-rate': 1,
                          'account/asset-valuation': 0.2,  # 获取账户资产估值
                          'point/account': 5,  # 点卡余额查询
                          'sub-user/user-list': 1,  # 获取子用户列表
                          'sub-user/user-state': 1,  # 获取特定子用户的用户状态
                          'sub-user/account-list': 1,  # 获取特定子用户的账户列表
                          'sub-user/deposit-address': 1,  # 子用户充币地址查询
                          'sub-user/query-deposit': 1,  # 子用户充币记录查询
                          'user/api-key': 1,  # 母子用户API key信息查询
                          'user/uid': 1,  # 母子用户获取用户UID
                          'algo-orders/opening': 1,  # 查询未触发OPEN策略委托
                          'algo-orders/history': 1,  # 查询策略委托历史
                          'algo-orders/specific': 1,  # 查询特定策略委托
                          'c2c/offers': 1,  # 查询借入借出订单
                          'c2c/offer': 1,  # 查询特定借入借出订单及其交易记录
                          'c2c/transactions': 1,  # 查询借入借出交易记录
                          'c2c/repayment': 1,  # 查询还币交易记录
                          'c2c/account': 1,  # 查询账户余额
                          'etp/reference': 1,  # 基础参考信息
                          'etp/transactions': 5,  # 获取杠杆ETP申赎记录
                          'etp/transaction': 5,  # 获取特定杠杆ETP申赎记录
                          'etp/rebalance': 1,  # 获取杠杆ETP调仓记录
                          'etp/limit': 1,  # 获取ETP持仓限额
                      },
                      'post': {
                          'account/transfer': 1,
                          'account/repayment': 5,  # 归还借币（全仓逐仓通用）
                          'point/transfer': 5,  # 点卡划转
                          'sub-user/management': 1,  # 冻结/解冻子用户
                          'sub-user/creation': 1,  # 子用户创建
                          'sub-user/tradable-market': 1,  # 设置子用户交易权限
                          'sub-user/transferability': 1,  # 设置子用户资产转出权限
                          'sub-user/api-key-generation': 1,  # 子用户API key创建
                          'sub-user/api-key-modification': 1,  # 修改子用户API key
                          'sub-user/api-key-deletion': 1,  # 删除子用户API key
                          'sub-user/deduct-mode': 1,  # 设置子用户手续费抵扣模式
                          'algo-orders': 1,  # 策略委托下单
                          'algo-orders/cancel-all-after': 1,  # 自动撤销订单
                          'algo-orders/cancellation': 1,  # 策略委托（触发前）撤单
                          'c2c/offer': 1,  # 借入借出下单
                          'c2c/cancellation': 1,  # 借入借出撤单
                          'c2c/cancel-all': 1,  # 撤销所有借入借出订单
                          'c2c/repayment': 1,  # 还币
                          'c2c/transfer': 1,  # 资产划转
                          'etp/creation': 5,  # 杠杆ETP换入
                          'etp/redemption': 5,  # 杠杆ETP换出
                          'etp/{transactId}/cancel': 10,  # 杠杆ETP单个撤单
                          'etp/batch-cancel': 50,  # 杠杆ETP批量撤单
                      },
                  },
                  'market': {
                      'get': {
                          'history/kline': 1,  # 获取K线数据
                          'detail/merged': 1,  # 获取聚合行情(Ticker)
                          'depth': 1,  # 获取 Market Depth 数据
                          'trade': 1,  # 获取 Trade Detail 数据
                          'history/trade': 1,  # 批量获取最近的交易记录
                          'detail': 1,  # 获取 Market Detail 24小时成交量数据
                          'tickers': 1,
                          'etp': 1,  # 获取杠杆ETP实时净值
                      },
                  },
                  'public': {
                      'get': {
                          'common/symbols': 1,  # 查询系统支持的所有交易对
                          'common/currencys': 1,  # 查询系统支持的所有币种
                          'common/timestamp': 1,  # 查询系统当前时间
                          'common/exchange': 1,  # order limits
                          'settings/currencys': 1,  # ?language=en-US
                      },
                  },
                  'private': {
                      'get': {
                          'account/accounts': 0.2,  # 查询当前用户的所有账户(即account-id)
                          'account/accounts/{id}/balance': 0.2,  # 查询指定账户的余额
                          'account/accounts/{sub-uid}': 1,
                          'account/history': 4,
                          'cross-margin/loan-info': 1,
                          'margin/loan-info': 1,  # 查询借币币息率及额度
                          'fee/fee-rate/get': 1,
                          'order/openOrders': 0.4,
                          'order/orders': 0.4,
                          'order/orders/{id}': 0.4,  # 查询某个订单详情
                          'order/orders/{id}/matchresults': 0.4,  # 查询某个订单的成交明细
                          'order/orders/getClientOrder': 0.4,
                          'order/history': 1,  # 查询当前委托、历史委托
                          'order/matchresults': 1,  # 查询当前成交、历史成交
                          # 'dw/withdraw-virtual/addresses',  # 查询虚拟币提现地址（Deprecated）
                          'query/deposit-withdraw': 1,
                          # 'margin/loan-info',  # duplicate
                          'margin/loan-orders': 0.2,  # 借贷订单
                          'margin/accounts/balance': 0.2,  # 借贷账户详情
                          'cross-margin/loan-orders': 1,  # 查询借币订单
                          'cross-margin/accounts/balance': 1,  # 借币账户详情
                          'points/actions': 1,
                          'points/orders': 1,
                          'subuser/aggregate-balance': 10,
                          'stable-coin/exchange_rate': 1,
                          'stable-coin/quote': 1,
                      },
                      'post': {
                          'account/transfer': 1,  # 资产划转(该节点为母用户和子用户进行资产划转的通用接口。)
                          'futures/transfer': 1,
                          'order/batch-orders': 0.4,
                          'order/orders/place': 0.2,  # 创建并执行一个新订单(一步下单， 推荐使用)
                          'order/orders/submitCancelClientOrder': 0.2,
                          'order/orders/batchCancelOpenOrders': 0.4,
                          # 'order/orders',  # 创建一个新的订单请求 （仅创建订单，不执行下单）
                          # 'order/orders/{id}/place',  # 执行一个订单 （仅执行已创建的订单）
                          'order/orders/{id}/submitcancel': 0.2,  # 申请撤销一个订单请求
                          'order/orders/batchcancel': 0.4,  # 批量撤销订单
                          # 'dw/balance/transfer',  # 资产划转
                          'dw/withdraw/api/create': 1,  # 申请提现虚拟币
                          # 'dw/withdraw-virtual/create',  # 申请提现虚拟币
                          # 'dw/withdraw-virtual/{id}/place',  # 确认申请虚拟币提现（Deprecated）
                          'dw/withdraw-virtual/{id}/cancel': 1,  # 申请取消提现虚拟币
                          'dw/transfer-in/margin': 10,  # 现货账户划入至借贷账户
                          'dw/transfer-out/margin': 10,  # 借贷账户划出至现货账户
                          'margin/orders': 10,  # 申请借贷
                          'margin/orders/{id}/repay': 10,  # 归还借贷
                          'cross-margin/transfer-in': 1,  # 资产划转
                          'cross-margin/transfer-out': 1,  # 资产划转
                          'cross-margin/orders': 1,  # 申请借币
                          'cross-margin/orders/{id}/repay': 1,  # 归还借币
                          'stable-coin/exchange': 1,
                          'subuser/transfer': 10,
                      },
                  },
                  # ------------------------------------------------------------
                  # new api definitions
                  # 'https://status.huobigroup.com/api/v2/summary.json': 1,
                  # 'https://status-dm.huobigroup.com/api/v2/summary.json': 1,
                  # 'https://status-swap.huobigroup.com/api/v2/summary.json': 1,
                  # 'https://status-linear-swap.huobigroup.com/api/v2/summary.json': 1,
                  'spot': {
                      'public': {
                          'get': {
                              'v2/market-status': 1,
                              'v1/common/symbols': 1,
                              'v1/common/currencys': 1,
                              'v2/reference/currencies': 1,
                              'v1/common/timestamp': 1,
                              'v1/common/exchange': 1,  # order limits
                              # Market Data
                              'market/history/kline': 1,
                              'market/detail/merged': 1,
                              'market/tickers': 1,
                              'market/depth': 1,
                              'market/trade': 1,
                              'market/history/trade': 1,
                              'market/detail/': 1,
                              'market/etp': 1,
                              # ETP
                              'v2/etp/reference': 1,
                              'v2/etp/rebalance': 1,
                          },
                      },
                      'private': {
                          'get': {
                              # Account
                              'v1/account/accounts': 0.2,
                              'v1/account/accounts/{account-id}/balance': 0.2,
                              'v2/account/valuation': 1,
                              'v2/account/asset-valuation': 0.2,
                              'v1/account/history': 4,
                              'v2/account/ledger': 1,
                              'v2/point/account': 5,
                              # Wallet(Deposit and Withdraw)
                              'v2/account/deposit/address': 1,
                              'v2/account/withdraw/quota': 1,
                              'v2/account/withdraw/address': 1,
                              'v2/reference/currencies': 1,
                              'v1/query/deposit-withdraw': 1,
                              # Sub user management
                              'v2/user/api-key': 1,
                              'v2/user/uid': 1,
                              'v2/sub-user/user-list': 1,
                              'v2/sub-user/user-state': 1,
                              'v2/sub-user/account-list': 1,
                              'v2/sub-user/deposit-address': 1,
                              'v2/sub-user/query-deposit': 1,
                              'v1/subuser/aggregate-balance': 10,
                              'v1/account/accounts/{sub-uid}': 1,
                              # Trading
                              'v1/order/openOrders': 0.4,
                              'v1/order/orders/{order-id}': 0.4,
                              'v1/order/orders/getClientOrder': 0.4,
                              'v1/order/orders/{order-id}/matchresults': 0.4,
                              'v1/order/orders': 0.4,
                              'v1/order/history': 1,
                              'v1/order/matchresults': 1,
                              'v2/reference/transact-fee-rate': 1,
                              # Conditional Order
                              'v2/algo-orders/opening': 1,
                              'v2/algo-orders/history': 1,
                              'v2/algo-orders/specific': 1,
                              # Margin Loan(Cross/Isolated)
                              'v1/margin/loan-info': 1,
                              'v1/margin/loan-orders': 0.2,
                              'v1/margin/accounts/balance': 0.2,
                              'v1/cross-margin/loan-info': 1,
                              'v1/cross-margin/loan-orders': 1,
                              'v1/cross-margin/accounts/balance': 1,
                              'v2/account/repayment': 5,
                              # Stable Coin Exchange
                              'v1/stable-coin/quote': 1,
                              # ETP
                              'v2/etp/transactions': 5,
                              'v2/etp/transaction': 5,
                              'v2/etp/limit': 1,
                          },
                          'post': {
                              # Account
                              'v1/account/transfer': 1,
                              'v1/futures/transfer': 1,  # future transfers
                              'v2/point/transfer': 5,
                              'v2/account/transfer': 1,  # swap transfers
                              # Wallet(Deposit and Withdraw)
                              'v1/dw/withdraw/api/create': 1,
                              'v1/dw/withdraw-virtual/{withdraw-id}/cancel': 1,
                              # Sub user management
                              'v2/sub-user/deduct-mode': 1,
                              'v2/sub-user/creation': 1,
                              'v2/sub-user/management': 1,
                              'v2/sub-user/tradable-market': 1,
                              'v2/sub-user/transferability': 1,
                              'v2/sub-user/api-key-generation': 1,
                              'v2/sub-user/api-key-modification': 1,
                              'v2/sub-user/api-key-deletion': 1,
                              'v1/subuser/transfer': 10,
                              # Trading
                              'v1/order/orders/place': 0.2,
                              'v1/order/batch-orders': 0.4,
                              'v1/order/orders/{order-id}/submitcancel': 0.2,
                              'v1/order/orders/submitCancelClientOrder': 0.2,
                              'v1/order/orders/batchCancelOpenOrders': 0.4,
                              'v1/order/orders/batchcancel': 0.4,
                              'v2/algo-orders/cancel-all-after': 1,
                              # Conditional Order
                              'v2/algo-orders': 1,
                              'v2/algo-orders/cancellation': 1,
                              # Margin Loan(Cross/Isolated)
                              'v2/account/repayment': 5,
                              'v1/dw/transfer-in/margin': 10,
                              'v1/dw/transfer-out/margin': 10,
                              'v1/margin/orders': 10,
                              'v1/margin/orders/{order-id}/repay': 10,
                              'v1/cross-margin/transfer-in': 1,
                              'v1/cross-margin/transfer-out': 1,
                              'v1/cross-margin/orders': 1,
                              'v1/cross-margin/orders/{order-id}/repay': 1,
                              # Stable Coin Exchange
                              'v1/stable-coin/exchange': 1,
                              # ETP
                              'v2/etp/creation': 5,
                              'v2/etp/redemption': 5,
                              'v2/etp/{transactId}/cancel': 10,
                              'v2/etp/batch-cancel': 50,
                          },
                      },
                  },
                  'contract': {
                      'public': {
                          'get': {
                              'api/v1/timestamp': 1,
                              # Future Market Data interface
                              'api/v1/contract_contract_info': 1,
                              'api/v1/contract_index': 1,
                              'api/v1/contract_price_limit': 1,
                              'api/v1/contract_open_interest': 1,
                              'api/v1/contract_delivery_price': 1,
                              'market/depth': 1,
                              'market/bbo': 1,
                              'market/history/kline': 1,
                              'index/market/history/mark_price_kline': 1,
                              'market/detail/merged': 1,
                              'market/detail/batch_merged': 1,
                              'market/trade': 1,
                              'market/history/trade': 1,
                              'api/v1/contract_risk_info': 1,
                              'api/v1/contract_insurance_fund': 1,
                              'api/v1/contract_adjustfactor': 1,
                              'api/v1/contract_his_open_interest': 1,
                              'api/v1/contract_ladder_margin': 1,
                              'api/v1/contract_api_state': 1,
                              'api/v1/contract_elite_account_ratio': 1,
                              'api/v1/contract_elite_position_ratio': 1,
                              'api/v1/contract_liquidation_orders': 1,
                              'api/v1/contract_settlement_records': 1,
                              'index/market/history/index': 1,
                              'index/market/history/basis': 1,
                              'api/v1/contract_estimated_settlement_price': 1,
                              # Swap Market Data interface
                              'swap-api/v1/swap_contract_info': 1,
                              'swap-api/v1/swap_index': 1,
                              'swap-api/v1/swap_price_limit': 1,
                              'swap-api/v1/swap_open_interest': 1,
                              'swap-ex/market/depth': 1,
                              'swap-ex/market/bbo': 1,
                              'swap-ex/market/history/kline': 1,
                              'index/market/history/swap_mark_price_kline': 1,
                              'swap-ex/market/detail/merged': 1,
                              'swap-ex/market/detail/batch_merged': 1,
                              'swap-ex/market/trade': 1,
                              'swap-ex/market/history/trade': 1,
                              'swap-api/v1/swap_risk_info': 1,
                              'swap-api/v1/swap_insurance_fund': 1,
                              'swap-api/v1/swap_adjustfactor': 1,
                              'swap-api/v1/swap_his_open_interest': 1,
                              'swap-api/v1/swap_ladder_margin': 1,
                              'swap-api/v1/swap_api_state': 1,
                              'swap-api/v1/swap_elite_account_ratio': 1,
                              'swap-api/v1/swap_elite_position_ratio': 1,
                              'swap-api/v1/swap_estimated_settlement_price': 1,
                              'swap-api/v1/swap_liquidation_orders': 1,
                              'swap-api/v1/swap_settlement_records': 1,
                              'swap-api/v1/swap_funding_rate': 1,
                              'swap-api/v1/swap_batch_funding_rate': 1,
                              'swap-api/v1/swap_historical_funding_rate': 1,
                              'index/market/history/swap_premium_index_kline': 1,
                              'index/market/history/swap_estimated_rate_kline': 1,
                              'index/market/history/swap_basis': 1,
                              # Swap Market Data interface
                              'linear-swap-api/v1/swap_contract_info': 1,
                              'linear-swap-api/v1/swap_index': 1,
                              'linear-swap-api/v1/swap_price_limit': 1,
                              'linear-swap-api/v1/swap_open_interest': 1,
                              'linear-swap-ex/market/depth': 1,
                              'linear-swap-ex/market/bbo': 1,
                              'linear-swap-ex/market/history/kline': 1,
                              'index/market/history/linear_swap_mark_price_kline': 1,
                              'linear-swap-ex/market/detail/merged': 1,
                              'linear-swap-ex/market/detail/batch_merged': 1,
                              'linear-swap-ex/market/trade': 1,
                              'linear-swap-ex/market/history/trade': 1,
                              'linear-swap-api/v1/swap_risk_info': 1,
                              'swap-api/v1/linear-swap-api/v1/swap_insurance_fund': 1,
                              'linear-swap-api/v1/swap_adjustfactor': 1,
                              'linear-swap-api/v1/swap_cross_adjustfactor': 1,
                              'linear-swap-api/v1/swap_his_open_interest': 1,
                              'linear-swap-api/v1/swap_ladder_margin': 1,
                              'linear-swap-api/v1/swap_cross_ladder_margin': 1,
                              'linear-swap-api/v1/swap_api_state': 1,
                              'linear-swap-api/v1/swap_cross_transfer_state': 1,
                              'linear-swap-api/v1/swap_cross_trade_state': 1,
                              'linear-swap-api/v1/swap_elite_account_ratio': 1,
                              'linear-swap-api/v1/swap_elite_position_ratio': 1,
                              'linear-swap-api/v1/swap_liquidation_orders': 1,
                              'linear-swap-api/v1/swap_settlement_records': 1,
                              'linear-swap-api/v1/swap_funding_rate': 1,
                              'linear-swap-api/v1/swap_batch_funding_rate': 1,
                              'linear-swap-api/v1/swap_historical_funding_rate': 1,
                              'index/market/history/linear_swap_premium_index_kline': 1,
                              'index/market/history/linear_swap_estimated_rate_kline': 1,
                              'index/market/history/linear_swap_basis': 1,
                              'linear-swap-api/v1/swap_estimated_settlement_price': 1,
                          },
                      },
                      'private': {
                          'get': {
                              # Future Account Interface
                              'api/v1/contract_api_trading_status': 1,
                              # Swap Account Interface
                              'swap-api/v1/swap_api_trading_status': 1,
                              # Swap Account Interface
                              'linear-swap-api/v1/swap_api_trading_status': 1,
                          },
                          'post': {
                              # Future Account Interface
                              'api/v1/contract_balance_valuation': 1,
                              'api/v1/contract_account_info': 1,
                              'api/v1/contract_position_info': 1,
                              'api/v1/contract_sub_auth': 1,
                              'api/v1/contract_sub_account_list': 1,
                              'api/v1/contract_sub_account_info_list': 1,
                              'api/v1/contract_sub_account_info': 1,
                              'api/v1/contract_sub_position_info': 1,
                              'api/v1/contract_financial_record': 1,
                              'api/v1/contract_financial_record_exact': 1,
                              'api/v1/contract_user_settlement_records': 1,
                              'api/v1/contract_order_limit': 1,
                              'api/v1/contract_fee': 1,
                              'api/v1/contract_transfer_limit': 1,
                              'api/v1/contract_position_limit': 1,
                              'api/v1/contract_account_position_info': 1,
                              'api/v1/contract_master_sub_transfer': 1,
                              'api/v1/contract_master_sub_transfer_record': 1,
                              'api/v1/contract_available_level_rate': 1,
                              # Future Trade Interface
                              'api/v1/contract_order': 1,
                              'v1/contract_batchorder': 1,
                              'api/v1/contract_cancel': 1,
                              'api/v1/contract_cancelall': 1,
                              'api/v1/contract_switch_lever_rate': 1,
                              'api/v1/lightning_close_position': 1,
                              'api/v1/contract_order_info': 1,
                              'api/v1/contract_order_detail': 1,
                              'api/v1/contract_openorders': 1,
                              'api/v1/contract_hisorders': 1,
                              'api/v1/contract_hisorders_exact': 1,
                              'api/v1/contract_matchresults': 1,
                              'api/v1/contract_matchresults_exact': 1,
                              # Contract Strategy Order Interface
                              'api/v1/contract_trigger_order': 1,
                              'api/v1/contract_trigger_cancel': 1,
                              'api/v1/contract_trigger_cancelall': 1,
                              'api/v1/contract_trigger_openorders': 1,
                              'api/v1/contract_trigger_hisorders': 1,
                              'api/v1/contract_tpsl_order': 1,
                              'api/v1/contract_tpsl_cancel': 1,
                              'api/v1/contract_tpsl_cancelall': 1,
                              'api/v1/contract_tpsl_openorders': 1,
                              'api/v1/contract_tpsl_hisorders': 1,
                              'api/v1/contract_relation_tpsl_order': 1,
                              'api/v1/contract_track_order': 1,
                              'api/v1/contract_track_cancel': 1,
                              'api/v1/contract_track_cancelall': 1,
                              'api/v1/contract_track_openorders': 1,
                              'api/v1/contract_track_hisorders': 1,
                              # Swap Account Interface
                              'swap-api/v1/swap_balance_valuation': 1,
                              'swap-api/v1/swap_account_info': 1,
                              'swap-api/v1/swap_position_info': 1,
                              'swap-api/v1/swap_account_position_info': 1,
                              'swap-api/v1/swap_sub_auth': 1,
                              'swap-api/v1/swap_sub_account_list': 1,
                              'swap-api/v1/swap_sub_account_info_list': 1,
                              'swap-api/v1/swap_sub_account_info': 1,
                              'swap-api/v1/swap_sub_position_info': 1,
                              'swap-api/v1/swap_financial_record': 1,
                              'swap-api/v1/swap_financial_record_exact': 1,
                              'swap-api/v1/swap_user_settlement_records': 1,
                              'swap-api/v1/swap_available_level_rate': 1,
                              'swap-api/v1/swap_order_limit': 1,
                              'swap-api/v1/swap_fee': 1,
                              'swap-api/v1/swap_transfer_limit': 1,
                              'swap-api/v1/swap_position_limit': 1,
                              'swap-api/v1/swap_master_sub_transfer': 1,
                              'swap-api/v1/swap_master_sub_transfer_record': 1,
                              # Swap Trade Interface
                              'swap-api/v1/swap_order': 1,
                              'swap-api/v1/swap_batchorder': 1,
                              'swap-api/v1/swap_cancel': 1,
                              'swap-api/v1/swap_cancelall': 1,
                              'swap-api/v1/swap_lightning_close_position': 1,
                              'swap-api/v1/swap_switch_lever_rate': 1,
                              'swap-api/v1/swap_order_info': 1,
                              'swap-api/v1/swap_order_detail': 1,
                              'swap-api/v1/swap_openorders': 1,
                              'swap-api/v1/swap_hisorders': 1,
                              'swap-api/v1/swap_hisorders_exact': 1,
                              'swap-api/v1/swap_matchresults': 1,
                              'swap-api/v1/swap_matchresults_exact': 1,
                              # Swap Strategy Order Interface
                              'swap-api/v1/swap_trigger_order': 1,
                              'swap-api/v1/swap_trigger_cancel': 1,
                              'swap-api/v1/swap_trigger_cancelall': 1,
                              'swap-api/v1/swap_trigger_openorders': 1,
                              'swap-api/v1/swap_trigger_hisorders': 1,
                              'swap-api/v1/swap_tpsl_order': 1,
                              'swap-api/v1/swap_tpsl_cancel': 1,
                              'swap-api/v1/swap_tpsl_cancelall': 1,
                              'swap-api/v1/swap_tpsl_openorders': 1,
                              'swap-api/v1/swap_tpsl_hisorders': 1,
                              'swap-api/v1/swap_relation_tpsl_order': 1,
                              'swap-api/v1/swap_track_order': 1,
                              'swap-api/v1/swap_track_cancel': 1,
                              'swap-api/v1/swap_track_cancelall': 1,
                              'swap-api/v1/swap_track_openorders': 1,
                              'swap-api/v1/swap_track_hisorders': 1,
                              # Swap Account Interface
                              'linear-swap-api/v1/swap_balance_valuation': 1,
                              'linear-swap-api/v1/swap_account_info': 1,
                              'linear-swap-api/v1/swap_cross_account_info': 1,
                              'linear-swap-api/v1/swap_position_info': 1,
                              'linear-swap-api/v1/swap_cross_position_info': 1,
                              'linear-swap-api/v1/swap_account_position_info': 1,
                              'linear-swap-api/v1/swap_cross_account_position_info': 1,
                              'linear-swap-api/v1/swap_sub_auth': 1,
                              'linear-swap-api/v1/swap_sub_account_list': 1,
                              'linear-swap-api/v1/swap_cross_sub_account_list': 1,
                              'linear-swap-api/v1/swap_sub_account_info_list': 1,
                              'linear-swap-api/v1/swap_cross_sub_account_info_list': 1,
                              'linear-swap-api/v1/swap_sub_account_info': 1,
                              'linear-swap-api/v1/swap_cross_sub_account_info': 1,
                              'linear-swap-api/v1/swap_sub_position_info': 1,
                              'linear-swap-api/v1/swap_cross_sub_position_info': 1,
                              'linear-swap-api/v1/swap_financial_record': 1,
                              'linear-swap-api/v1/swap_financial_record_exact': 1,
                              'linear-swap-api/v1/swap_user_settlement_records': 1,
                              'linear-swap-api/v1/swap_cross_user_settlement_records': 1,
                              'linear-swap-api/v1/swap_available_level_rate': 1,
                              'linear-swap-api/v1/swap_cross_available_level_rate': 1,
                              'linear-swap-api/v1/swap_order_limit': 1,
                              'linear-swap-api/v1/swap_fee': 1,
                              'linear-swap-api/v1/swap_transfer_limit': 1,
                              'linear-swap-api/v1/swap_cross_transfer_limit': 1,
                              'linear-swap-api/v1/swap_position_limit': 1,
                              'linear-swap-api/v1/swap_cross_position_limit': 1,
                              'linear-swap-api/v1/swap_master_sub_transfer': 1,
                              'linear-swap-api/v1/swap_master_sub_transfer_record': 1,
                              'linear-swap-api/v1/swap_transfer_inner': 1,
                              # Swap Trade Interface
                              'linear-swap-api/v1/swap_order': 1,
                              'linear-swap-api/v1/swap_cross_order': 1,
                              'linear-swap-api/v1/swap_batchorder': 1,
                              'linear-swap-api/v1/swap_cross_batchorder': 1,
                              'linear-swap-api/v1/swap_cancel': 1,
                              'linear-swap-api/v1/swap_cross_cancel': 1,
                              'linear-swap-api/v1/swap_cancelall': 1,
                              'linear-swap-api/v1/swap_cross_cancelall': 1,
                              'linear-swap-api/v1/swap_switch_lever_rate': 1,
                              'linear-swap-api/v1/swap_cross_switch_lever_rate': 1,
                              'linear-swap-api/v1/swap_lightning_close_position': 1,
                              'linear-swap-api/v1/swap_cross_lightning_close_position': 1,
                              'linear-swap-api/v1/swap_order_info': 1,
                              'linear-swap-api/v1/swap_cross_order_info': 1,
                              'linear-swap-api/v1/swap_order_detail': 1,
                              'linear-swap-api/v1/swap_cross_order_detail': 1,
                              'linear-swap-api/v1/swap_openorders': 1,
                              'linear-swap-api/v1/swap_cross_openorders': 1,
                              'linear-swap-api/v1/swap_hisorders': 1,
                              'linear-swap-api/v1/swap_cross_hisorders': 1,
                              'linear-swap-api/v1/swap_hisorders_exact': 1,
                              'linear-swap-api/v1/swap_cross_hisorders_exact': 1,
                              'linear-swap-api/v1/swap_matchresults': 1,
                              'linear-swap-api/v1/swap_cross_matchresults': 1,
                              'linear-swap-api/v1/swap_matchresults_exact': 1,
                              'linear-swap-api/v1/swap_cross_matchresults_exact': 1,
                              # Swap Strategy Order Interface
                              'linear-swap-api/v1/swap_trigger_order': 1,
                              'linear-swap-api/v1/swap_cross_trigger_order': 1,
                              'linear-swap-api/v1/swap_trigger_cancel': 1,
                              'linear-swap-api/v1/swap_cross_trigger_cancel': 1,
                              'linear-swap-api/v1/swap_trigger_cancelall': 1,
                              'linear-swap-api/v1/swap_cross_trigger_cancelall': 1,
                              'linear-swap-api/v1/swap_trigger_openorders': 1,
                              'linear-swap-api/v1/swap_cross_trigger_openorders': 1,
                              'linear-swap-api/v1/swap_trigger_hisorders': 1,
                              'linear-swap-api/v1/swap_cross_trigger_hisorders': 1,
                              'linear-swap-api/v1/swap_tpsl_order': 1,
                              'linear-swap-api/v1/swap_cross_tpsl_order': 1,
                              'linear-swap-api/v1/swap_tpsl_cancel': 1,
                              'linear-swap-api/v1/swap_cross_tpsl_cancel': 1,
                              'linear-swap-api/v1/swap_tpsl_cancelall': 1,
                              'linear-swap-api/v1/swap_cross_tpsl_cancelall': 1,
                              'linear-swap-api/v1/swap_tpsl_openorders': 1,
                              'linear-swap-api/v1/swap_cross_tpsl_openorders': 1,
                              'linear-swap-api/v1/swap_tpsl_hisorders': 1,
                              'linear-swap-api/v1/swap_cross_tpsl_hisorders': 1,
                              'linear-swap-api/v1/swap_relation_tpsl_order': 1,
                              'linear-swap-api/v1/swap_cross_relation_tpsl_order': 1,
                              'linear-swap-api/v1/swap_track_order': 1,
                              'linear-swap-api/v1/swap_cross_track_order': 1,
                              'linear-swap-api/v1/swap_track_cancel': 1,
                              'linear-swap-api/v1/swap_cross_track_cancel': 1,
                              'linear-swap-api/v1/swap_track_cancelall': 1,
                              'linear-swap-api/v1/swap_cross_track_cancelall': 1,
                              'linear-swap-api/v1/swap_track_openorders': 1,
                              'linear-swap-api/v1/swap_cross_track_openorders': 1,
                              'linear-swap-api/v1/swap_track_hisorders': 1,
                              'linear-swap-api/v1/swap_cross_track_hisorders': 1,
                          },
                      },
                  },
              },
              'fees': {
                  'trading': {
                      'feeSide': 'get',
                      'tierBased': False,
                      'percentage': True,
                      'maker': self.parse_number('0.002'),
                      'taker': self.parse_number('0.002'),
                  },
              },
              'exceptions': {
                  'broad': {
                      'contract is restricted of closing positions on API.  Please contact customer service': OnMaintenance,
                      'maintain': OnMaintenance,
                  },
                  'exact': {
                      # err-code
                      '1017': OrderNotFound,  # {"status":"error","err_code":1017,"err_msg":"Order doesnt exist.","ts":1640550859242}
                      '1034': InvalidOrder,  # {"status":"error","err_code":1034,"err_msg":"Incorrect field of order price type.","ts":1643802870182}
                      '1036': InvalidOrder,  # {"status":"error","err_code":1036,"err_msg":"Incorrect field of open long form.","ts":1643802518986}
                      '1039': InvalidOrder,  # {"status":"error","err_code":1039,"err_msg":"Buy price must be lower than 39270.9USDT. Sell price must exceed 37731USDT.","ts":1643802374403}
                      '1041': InvalidOrder,  # {"status":"error","err_code":1041,"err_msg":"The order amount exceeds the limit(170000Cont), please modify and order again.","ts":1643802784940}
                      '1047': InsufficientFunds,  # {"status":"error","err_code":1047,"err_msg":"Insufficient margin available.","ts":1643802672652}
                      '1066': BadSymbol,  # {"status":"error","err_code":1066,"err_msg":"The symbol field cannot be empty. Please re-enter.","ts":1640550819147}
                      '1067': InvalidOrder,  # {"status":"error","err_code":1067,"err_msg":"The client_order_id field is invalid. Please re-enter.","ts":1643802119413}
                      '1013': BadSymbol,  # {"status":"error","err_code":1013,"err_msg":"This contract symbol doesnt exist.","ts":1640550459583}
                      '1094': InvalidOrder,  # {"status":"error","err_code":1094,"err_msg":"The leverage cannot be empty, please switch the leverage or contact customer service","ts":1640496946243}
                      '1220': AccountNotEnabled,  # {"status":"error","err_code":1220,"err_msg":"You don’t have access permission as you have not opened contracts trading.","ts":1645096660718}
                      'bad-request': BadRequest,
                      'validation-format-error': BadRequest,  # {"status":"error","err-code":"validation-format-error","err-msg":"Format Error: order-id.","data":null}
                      'validation-constraints-required': BadRequest,  # {"status":"error","err-code":"validation-constraints-required","err-msg":"Field is missing: client-order-id.","data":null}
                      'base-date-limit-error': BadRequest,  # {"status":"error","err-code":"base-date-limit-error","err-msg":"date less than system limit","data":null}
                      'api-not-support-temp-addr': PermissionDenied,  # {"status":"error","err-code":"api-not-support-temp-addr","err-msg":"API withdrawal does not support temporary addresses","data":null}
                      'timeout': RequestTimeout,  # {"ts":1571653730865,"status":"error","err-code":"timeout","err-msg":"Request Timeout"}
                      'gateway-internal-error': ExchangeNotAvailable,  # {"status":"error","err-code":"gateway-internal-error","err-msg":"Failed to load data. Try again later.","data":null}
                      'account-frozen-balance-insufficient-error': InsufficientFunds,  # {"status":"error","err-code":"account-frozen-balance-insufficient-error","err-msg":"trade account balance is not enough, left: `0.0027`","data":null}
                      'invalid-amount': InvalidOrder,  # eg "Paramemter `amount` is invalid."
                      'order-limitorder-amount-min-error': InvalidOrder,  # limit order amount error, min: `0.001`
                      'order-limitorder-amount-max-error': InvalidOrder,  # market order amount error, max: `1000000`
                      'order-marketorder-amount-min-error': InvalidOrder,  # market order amount error, min: `0.01`
                      'order-limitorder-price-min-error': InvalidOrder,  # limit order price error
                      'order-limitorder-price-max-error': InvalidOrder,  # limit order price error
                      'order-holding-limit-failed': InvalidOrder,  # {"status":"error","err-code":"order-holding-limit-failed","err-msg":"Order failed, exceeded the holding limit of self currency","data":null}
                      'order-orderprice-precision-error': InvalidOrder,  # {"status":"error","err-code":"order-orderprice-precision-error","err-msg":"order price precision error, scale: `4`","data":null}
                      'order-etp-nav-price-max-error': InvalidOrder,  # {"status":"error","err-code":"order-etp-nav-price-max-error","err-msg":"Order price cannot be higher than 5% of NAV","data":null}
                      'order-orderstate-error': OrderNotFound,  # canceling an already canceled order
                      'order-queryorder-invalid': OrderNotFound,  # querying a non-existent order
                      'order-update-error': ExchangeNotAvailable,  # undocumented error
                      'api-signature-check-failed': AuthenticationError,
                      'api-signature-not-valid': AuthenticationError,  # {"status":"error","err-code":"api-signature-not-valid","err-msg":"Signature not valid: Incorrect Access key [Access key错误]","data":null}
                      'base-record-invalid': OrderNotFound,  # https://github.com/ccxt/ccxt/issues/5750
                      'base-symbol-trade-disabled': BadSymbol,  # {"status":"error","err-code":"base-symbol-trade-disabled","err-msg":"Trading is disabled for self symbol","data":null}
                      'base-symbol-error': BadSymbol,  # {"status":"error","err-code":"base-symbol-error","err-msg":"The symbol is invalid","data":null}
                      'system-maintenance': OnMaintenance,  # {"status": "error", "err-code": "system-maintenance", "err-msg": "System is in maintenance!", "data": null}
                      'base-request-exceed-frequency-limit': RateLimitExceeded,  # {"status":"error","err-code":"base-request-exceed-frequency-limit","err-msg":"Frequency of requests has exceeded the limit, please try again later","data":null}
                      # err-msg
                      'invalid symbol': BadSymbol,  # {"ts":1568813334794,"status":"error","err-code":"invalid-parameter","err-msg":"invalid symbol"}
                      'symbol trade not open now': BadSymbol,  # {"ts":1576210479343,"status":"error","err-code":"invalid-parameter","err-msg":"symbol trade not open now"}
                      'require-symbol': BadSymbol,  # {"status":"error","err-code":"require-symbol","err-msg":"Parameter `symbol` is required.","data":null}
                  },
              },
              'precisionMode': TICK_SIZE,
              'options': {
                  'fetchMarkets': {
                      'types': {
                          'spot': True,
                          'future': {
                              'linear': True,
                              'inverse': True,
                          },
                          'swap': {
                              'linear': True,
                              'inverse': True,
                          },
                      },
                  },
                  'defaultType': 'spot',  # spot, future, swap
                  'defaultSubType': 'inverse',  # inverse, linear
                  'defaultNetwork': 'ERC20',
                  'networks': {
                      'ETH': 'erc20',
                      'TRX': 'trc20',
                      'HRC20': 'hrc20',
                      'HECO': 'hrc20',
                      'HT': 'hrc20',
                      'ALGO': 'algo',
                      'OMNI': '',
                  },
                  # https://github.com/ccxt/ccxt/issues/5376
                  'fetchOrdersByStatesMethod': 'spot_private_get_v1_order_orders',  # 'spot_private_get_v1_order_history'  # https://github.com/ccxt/ccxt/pull/5392
                  'createMarketBuyOrderRequiresPrice': True,
                  'language': 'en-US',
                  'broker': {
                      'id': 'AA03022abc',
                  },
                  'accountsByType': {
                      'spot': 'pro',
                      'future': 'futures',
                  },
                  'typesByAccount': {
                      'pro': 'spot',
                      'futures': 'future',
                  },
                  'spot': {
                      'stopOrderTypes': {
                          'stop-limit': True,
                          'buy-stop-limit': True,
                          'sell-stop-limit': True,
                          'stop-limit-fok': True,
                          'buy-stop-limit-fok': True,
                          'sell-stop-limit-fok': True,
                      },
                      'limitOrderTypes': {
                          'limit': True,
                          'buy-limit': True,
                          'sell-limit': True,
                          'ioc': True,
                          'buy-ioc': True,
                          'sell-ioc': True,
                          'limit-maker': True,
                          'buy-limit-maker': True,
                          'sell-limit-maker': True,
                          'stop-limit': True,
                          'buy-stop-limit': True,
                          'sell-stop-limit': True,
                          'limit-fok': True,
                          'buy-limit-fok': True,
                          'sell-limit-fok': True,
                          'stop-limit-fok': True,
                          'buy-stop-limit-fok': True,
                          'sell-stop-limit-fok': True,
                      },
                  },
              },
              'commonCurrencies': {
                  # https://github.com/ccxt/ccxt/issues/6081
                  # https://github.com/ccxt/ccxt/issues/3365
                  # https://github.com/ccxt/ccxt/issues/2873
                  'GET': 'Themis',  # conflict with GET(Guaranteed Entrance Token, GET Protocol)
                  'GTC': 'Game.com',  # conflict with Gitcoin and Gastrocoin
                  'HIT': 'HitChain',
                  'HOT': 'Hydro Protocol',  # conflict with HOT(Holo) https://github.com/ccxt/ccxt/issues/4929
                  # https://github.com/ccxt/ccxt/issues/7399
                  # https://coinmarketcap.com/currencies/pnetwork/
                  # https://coinmarketcap.com/currencies/penta/markets/
                  # https://en.cryptonomist.ch/blog/eidoo/the-edo-to-pnt-upgrade-what-you-need-to-know-updated/
                  'PNT': 'Penta',
                  'SBTC': 'Super Bitcoin',
                  'BIFI': 'Bitcoin File',  # conflict with Beefy.Finance https://github.com/ccxt/ccxt/issues/8706
              },
          })
  
      async def fetch_time(self, params={}):
          options = self.safe_value(self.options, 'fetchTime', {})
          defaultType = self.safe_string(self.options, 'defaultType', 'spot')
          type = self.safe_string(options, 'type', defaultType)
          type = self.safe_string(params, 'type', type)
          method = 'spotPublicGetV1CommonTimestamp'
          if (type == 'future') or (type == 'swap'):
              method = 'contractPublicGetApiV1Timestamp'
          response = await getattr(self, method)(params)
          #
          # spot
          #
          #     {"status":"ok","data":1637504261099}
          #
          # future, swap
          #
          #     {"status":"ok","ts":1637504164707}
          #
          return self.safe_integer_2(response, 'data', 'ts')
  
      def parse_trading_fee(self, fee, market=None):
          #
          #     {
          #         "symbol":"btcusdt",
          #         "actualMakerRate":"0.002",
          #         "actualTakerRate":"0.002",
          #         "takerFeeRate":"0.002",
          #         "makerFeeRate":"0.002"
          #     }
          #
          marketId = self.safe_string(fee, 'symbol')
          return {
              'info': fee,
              'symbol': self.safe_symbol(marketId, market),
              'maker': self.safe_number(fee, 'actualMakerRate'),
              'taker': self.safe_number(fee, 'actualTakerRate'),
          }
  
      async def fetch_trading_fee(self, symbol, params={}):
          await self.load_markets()
          market = self.market(symbol)
          request = {
              'symbols': market['id'],  # trading symbols comma-separated
          }
          response = await self.spotPrivateGetV2ReferenceTransactFeeRate(self.extend(request, params))
          #
          #     {
          #         "code":200,
          #         "data":[
          #             {
          #                 "symbol":"btcusdt",
          #                 "actualMakerRate":"0.002",
          #                 "actualTakerRate":"0.002",
          #                 "takerFeeRate":"0.002",
          #                 "makerFeeRate":"0.002"
          #             }
          #         ],
          #         "success":true
          #     }
          #
          data = self.safe_value(response, 'data', [])
          first = self.safe_value(data, 0, {})
          return self.parse_trading_fee(first, market)
  
      async def fetch_trading_limits(self, symbols=None, params={}):
          # self method should not be called directly, use loadTradingLimits() instead
          #  by default it will try load withdrawal fees of all currencies(with separate requests)
          #  however if you define symbols = ['ETH/BTC', 'LTC/BTC'] in args it will only load those
          await self.load_markets()
          if symbols is None:
              symbols = self.symbols
          result = {}
          for i in range(0, len(symbols)):
              symbol = symbols[i]
              result[symbol] = await self.fetch_trading_limits_by_id(self.market_id(symbol), params)
          return result
  
      async def fetch_trading_limits_by_id(self, id, params={}):
          request = {
              'symbol': id,
          }
          response = await self.spotPublicGetV1CommonExchange(self.extend(request, params))
          #
          #     {status:   "ok",
          #         data: {                                 symbol: "aidocbtc",
          #                              'buy-limit-must-less-than':  1.1,
          #                          'sell-limit-must-greater-than':  0.9,
          #                         'limit-order-must-greater-than':  1,
          #                            'limit-order-must-less-than':  5000000,
          #                    'market-buy-order-must-greater-than':  0.0001,
          #                       'market-buy-order-must-less-than':  100,
          #                   'market-sell-order-must-greater-than':  1,
          #                      'market-sell-order-must-less-than':  500000,
          #                       'circuit-break-when-greater-than':  10000,
          #                          'circuit-break-when-less-than':  10,
          #                 'market-sell-order-rate-must-less-than':  0.1,
          #                  'market-buy-order-rate-must-less-than':  0.1        }}
          #
          return self.parse_trading_limits(self.safe_value(response, 'data', {}))
  
      def parse_trading_limits(self, limits, symbol=None, params={}):
          #
          #   {                                 symbol: "aidocbtc",
          #                  'buy-limit-must-less-than':  1.1,
          #              'sell-limit-must-greater-than':  0.9,
          #             'limit-order-must-greater-than':  1,
          #                'limit-order-must-less-than':  5000000,
          #        'market-buy-order-must-greater-than':  0.0001,
          #           'market-buy-order-must-less-than':  100,
          #       'market-sell-order-must-greater-than':  1,
          #          'market-sell-order-must-less-than':  500000,
          #           'circuit-break-when-greater-than':  10000,
          #              'circuit-break-when-less-than':  10,
          #     'market-sell-order-rate-must-less-than':  0.1,
          #      'market-buy-order-rate-must-less-than':  0.1        }
          #
          return {
              'info': limits,
              'limits': {
                  'amount': {
                      'min': self.safe_number(limits, 'limit-order-must-greater-than'),
                      'max': self.safe_number(limits, 'limit-order-must-less-than'),
                  },
              },
          }
  
      def cost_to_precision(self, symbol, cost):
          return self.decimal_to_precision(cost, TRUNCATE, self.markets[symbol]['precision']['cost'], self.precisionMode)
  
      async def fetch_markets(self, params={}):
          options = self.safe_value(self.options, 'fetchMarkets', {})
          types = self.safe_value(options, 'types', {})
          allMarkets = []
          keys = list(types.keys())
          for i in range(0, len(keys)):
              type = keys[i]
              value = self.safe_value(types, type)
              if value is True:
                  markets = await self.fetch_markets_by_type_and_sub_type(type, None, params)
                  allMarkets = self.array_concat(allMarkets, markets)
              else:
                  subKeys = list(value.keys())
                  for j in range(0, len(subKeys)):
                      subType = subKeys[j]
                      subValue = self.safe_value(value, subType)
                      if subValue:
                          markets = await self.fetch_markets_by_type_and_sub_type(type, subType, params)
                          allMarkets = self.array_concat(allMarkets, markets)
          return allMarkets
  
      async def fetch_markets_by_type_and_sub_type(self, type, subType, params={}):
          method = 'spotPublicGetV1CommonSymbols'
          query = self.omit(params, ['type', 'subType'])
          spot = (type == 'spot')
          contract = (type != 'spot')
          future = (type == 'future')
          swap = (type == 'swap')
          linear = None
          inverse = None
          request = {}
          if contract:
              linear = (subType == 'linear')
              inverse = (subType == 'inverse')
              if linear:
                  method = 'contractPublicGetLinearSwapApiV1SwapContractInfo'
                  if future:
                      request['business_type'] = 'futures'
              elif inverse:
                  if future:
                      method = 'contractPublicGetApiV1ContractContractInfo'
                  elif swap:
                      method = 'contractPublicGetSwapApiV1SwapContractInfo'
          response = await getattr(self, method)(self.extend(request, query))
          #
          # spot
          #
          #     {
          #         "status":"ok",
          #         "data":[
          #             {
          #                 "base-currency":"xrp3s",
          #                 "quote-currency":"usdt",
          #                 "price-precision":4,
          #                 "amount-precision":4,
          #                 "symbol-partition":"innovation",
          #                 "symbol":"xrp3susdt",
          #                 "state":"online",
          #                 "value-precision":8,
          #                 "min-order-amt":0.01,
          #                 "max-order-amt":1616.4353,
          #                 "min-order-value":5,
          #                 "limit-order-min-order-amt":0.01,
          #                 "limit-order-max-order-amt":1616.4353,
          #                 "limit-order-max-buy-amt":1616.4353,
          #                 "limit-order-max-sell-amt":1616.4353,
          #                 "sell-market-min-order-amt":0.01,
          #                 "sell-market-max-order-amt":1616.4353,
          #                 "buy-market-max-order-value":2500,
          #                 "max-order-value":2500,
          #                 "underlying":"xrpusdt",
          #                 "mgmt-fee-rate":0.035000000000000000,
          #                 "charge-time":"23:55:00",
          #                 "rebal-time":"00:00:00",
          #                 "rebal-threshold":-5,
          #                 "init-nav":10.000000000000000000,
          #                 "api-trading":"enabled",
          #                 "tags":"etp,nav,holdinglimit"
          #             },
          #         ]
          #     }
          #
          # inverse future
          #
          #     {
          #         "status":"ok",
          #         "data":[
          #             {
          #                 "symbol":"BTC",
          #                 "contract_code":"BTC211126",
          #                 "contract_type":"self_week",
          #                 "contract_size":100.000000000000000000,
          #                 "price_tick":0.010000000000000000,
          #                 "delivery_date":"20211126",
          #                 "delivery_time":"1637913600000",
          #                 "create_date":"20211112",
          #                 "contract_status":1,
          #                 "settlement_time":"1637481600000"
          #             },
          #         ],
          #         "ts":1637474595140
          #     }
          #
          # linear futures
          #
          #     {
          #         "status":"ok",
          #         "data":[
          #             {
          #                 "symbol":"BTC",
          #                 "contract_code":"BTC-USDT-211231",
          #                 "contract_size":0.001000000000000000,
          #                 "price_tick":0.100000000000000000,
          #                 "delivery_date":"20211231",
          #                 "delivery_time":"1640937600000",
          #                 "create_date":"20211228",
          #                 "contract_status":1,
          #                 "settlement_date":"1640764800000",
          #                 "support_margin_mode":"cross",
          #                 "business_type":"futures",
          #                 "pair":"BTC-USDT",
          #                 "contract_type":"self_week"  # next_week, quarter
          #             },
          #         ],
          #         "ts":1640736207263
          #     }
          #
          # swaps
          #
          #     {
          #         "status":"ok",
          #         "data":[
          #             {
          #                 "symbol":"BTC",
          #                 "contract_code":"BTC-USDT",
          #                 "contract_size":0.001000000000000000,
          #                 "price_tick":0.100000000000000000,
          #                 "delivery_time":"",
          #                 "create_date":"20201021",
          #                 "contract_status":1,
          #                 "settlement_date":"1637481600000",
          #                 "support_margin_mode":"all",  # isolated
          #             },
          #         ],
          #         "ts":1637474774467
          #     }
          #
          markets = self.safe_value(response, 'data')
          numMarkets = len(markets)
          if numMarkets < 1:
              raise NetworkError(self.id + ' fetchMarkets() returned an empty response: ' + self.json(markets))
          result = []
          for i in range(0, len(markets)):
              market = markets[i]
              baseId = None
              quoteId = None
              settleId = None
              id = None
              if contract:
                  id = self.safe_string(market, 'contract_code')
                  if swap:
                      parts = id.split('-')
                      baseId = self.safe_string(market, 'symbol')
                      quoteId = self.safe_string(parts, 1)
                      settleId = baseId if inverse else quoteId
                  elif future:
                      baseId = self.safe_string(market, 'symbol')
                      if inverse:
                          quoteId = 'USD'
                          settleId = baseId
                      else:
                          pair = self.safe_string(market, 'pair')
                          parts = pair.split('-')
                          quoteId = self.safe_string(parts, 1)
                          settleId = quoteId
              else:
                  baseId = self.safe_string(market, 'base-currency')
                  quoteId = self.safe_string(market, 'quote-currency')
                  id = baseId + quoteId
              base = self.safe_currency_code(baseId)
              quote = self.safe_currency_code(quoteId)
              settle = self.safe_currency_code(settleId)
              symbol = base + '/' + quote
              expiry = None
              if contract:
                  if inverse:
                      symbol += ':' + base
                  elif linear:
                      symbol += ':' + quote
                  if future:
                      expiry = self.safe_integer(market, 'delivery_time')
                      symbol += '-' + self.yymmdd(expiry)
              contractSize = self.safe_number(market, 'contract_size')
              pricePrecision = None
              amountPrecision = None
              costPrecision = None
              if spot:
                  pricePrecision = self.safe_string(market, 'price-precision')
                  pricePrecision = self.parse_number('1e-' + pricePrecision)
                  amountPrecision = self.safe_string(market, 'amount-precision')
                  amountPrecision = self.parse_number('1e-' + amountPrecision)
                  costPrecision = self.safe_string(market, 'value-precision')
                  costPrecision = self.parse_number('1e-' + costPrecision)
              else:
                  pricePrecision = self.safe_number(market, 'price_tick')
                  amountPrecision = 1
              maker = None
              taker = None
              if spot:
                  maker = 0 if (base == 'OMG') else 0.2 / 100
                  taker = 0 if (base == 'OMG') else 0.2 / 100
              minAmount = self.safe_number(market, 'min-order-amt')
              maxAmount = self.safe_number(market, 'max-order-amt')
              minCost = self.safe_number(market, 'min-order-value', 0)
              active = None
              if spot:
                  state = self.safe_string(market, 'state')
                  active = (state == 'online')
              elif contract:
                  contractStatus = self.safe_integer(market, 'contract_status')
                  active = (contractStatus == 1)
              leverageRatio = self.safe_string(market, 'leverage-ratio', '1')
              superLeverageRatio = self.safe_string(market, 'super-margin-leverage-ratio', '1')
              hasLeverage = Precise.string_gt(leverageRatio, '1') or Precise.string_gt(superLeverageRatio, '1')
              # 0 Delisting
              # 1 Listing
              # 2 Pending Listing
              # 3 Suspension
              # 4 Suspending of Listing
              # 5 In Settlement
              # 6 Delivering
              # 7 Settlement Completed
              # 8 Delivered
              # 9 Suspending of Trade
              result.append({
                  'id': id,
                  'symbol': symbol,
                  'base': base,
                  'quote': quote,
                  'settle': settle,
                  'baseId': baseId,
                  'quoteId': quoteId,
                  'settleId': settleId,
                  'type': type,
                  'spot': spot,
                  'margin': (spot and hasLeverage),
                  'swap': swap,
                  'future': future,
                  'option': False,
                  'active': active,
                  'contract': contract,
                  'linear': linear,
                  'inverse': inverse,
                  'taker': taker,
                  'maker': maker,
                  'contractSize': contractSize,
                  'expiry': expiry,
                  'expiryDatetime': self.iso8601(expiry),
                  'strike': None,
                  'optionType': None,
                  'precision': {
                      'amount': amountPrecision,
                      'price': pricePrecision,
                      'cost': costPrecision,
                  },
                  'limits': {
                      'leverage': {
                          'min': self.parse_number('1'),
                          'max': self.parse_number(leverageRatio),
                          'superMax': self.parse_number(superLeverageRatio),
                      },
                      'amount': {
                          'min': minAmount,
                          'max': maxAmount,
                      },
                      'price': {
                          'min': None,
                          'max': None,
                      },
                      'cost': {
                          'min': minCost,
                          'max': None,
                      },
                  },
                  'info': market,
              })
          return result
  
      def parse_ticker(self, ticker, market=None):
          #
          # fetchTicker
          #
          #     {
          #         "amount": 26228.672978342216,
          #         "open": 9078.95,
          #         "close": 9146.86,
          #         "high": 9155.41,
          #         "id": 209988544334,
          #         "count": 265846,
          #         "low": 8988.0,
          #         "version": 209988544334,
          #         "ask": [9146.87, 0.156134],
          #         "vol": 2.3822168242201668E8,
          #         "bid": [9146.86, 0.080758],
          #     }
          #
          # fetchTickers
          #
          #     {
          #         symbol: "bhdht",
          #         open:  2.3938,
          #         high:  2.4151,
          #         low:  2.3323,
          #         close:  2.3909,
          #         amount:  628.992,
          #         vol:  1493.71841095,
          #         count:  2088,
          #         bid:  2.3643,
          #         bidSize:  0.7136,
          #         ask:  2.4061,
          #         askSize:  0.4156
          #     }
          #
          marketId = self.safe_string_2(ticker, 'symbol', 'contract_code')
          symbol = self.safe_symbol(marketId, market)
          timestamp = self.safe_integer(ticker, 'ts')
          bid = None
          bidVolume = None
          ask = None
          askVolume = None
          if 'bid' in ticker:
              if isinstance(ticker['bid'], list):
                  bid = self.safe_string(ticker['bid'], 0)
                  bidVolume = self.safe_string(ticker['bid'], 1)
              else:
                  bid = self.safe_string(ticker, 'bid')
                  bidVolume = self.safe_string(ticker, 'bidSize')
          if 'ask' in ticker:
              if isinstance(ticker['ask'], list):
                  ask = self.safe_string(ticker['ask'], 0)
                  askVolume = self.safe_string(ticker['ask'], 1)
              else:
                  ask = self.safe_string(ticker, 'ask')
                  askVolume = self.safe_string(ticker, 'askSize')
          open = self.safe_string(ticker, 'open')
          close = self.safe_string(ticker, 'close')
          baseVolume = self.safe_string(ticker, 'amount')
          quoteVolume = self.safe_string(ticker, 'vol')
          return self.safe_ticker({
              'symbol': symbol,
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
              'high': self.safe_string(ticker, 'high'),
              'low': self.safe_string(ticker, 'low'),
              'bid': bid,
              'bidVolume': bidVolume,
              'ask': ask,
              'askVolume': askVolume,
              'vwap': None,
              'open': open,
              'close': close,
              'last': close,
              'previousClose': None,
              'change': None,
              'percentage': None,
              'average': None,
              'baseVolume': baseVolume,
              'quoteVolume': quoteVolume,
              'info': ticker,
          }, market, False)
  
      async def fetch_ticker(self, symbol, params={}):
          await self.load_markets()
          market = self.market(symbol)
          request = {}
          fieldName = 'symbol'
          method = 'spotPublicGetMarketDetailMerged'
          if market['linear']:
              method = 'contractPublicGetLinearSwapExMarketDetailMerged'
              fieldName = 'contract_code'
          elif market['inverse']:
              if market['future']:
                  method = 'contractPublicGetMarketDetailMerged'
              elif market['swap']:
                  method = 'contractPublicGetSwapExMarketDetailMerged'
                  fieldName = 'contract_code'
          request[fieldName] = market['id']
          response = await getattr(self, method)(self.extend(request, params))
          #
          # spot
          #
          #     {
          #         "status": "ok",
          #         "ch": "market.btcusdt.detail.merged",
          #         "ts": 1583494336669,
          #         "tick": {
          #             "amount": 26228.672978342216,
          #             "open": 9078.95,
          #             "close": 9146.86,
          #             "high": 9155.41,
          #             "id": 209988544334,
          #             "count": 265846,
          #             "low": 8988.0,
          #             "version": 209988544334,
          #             "ask": [9146.87, 0.156134],
          #             "vol": 2.3822168242201668E8,
          #             "bid": [9146.86, 0.080758],
          #         }
          #     }
          #
          # future, swap
          #
          #     {
          #         "ch":"market.BTC211126.detail.merged",
          #         "status":"ok",
          #         "tick":{
          #             "amount":"669.3385682049668320322569544150680718474",
          #             "ask":[59117.44,48],
          #             "bid":[59082,48],
          #             "close":"59087.97",
          #             "count":5947,
          #             "high":"59892.62",
          #             "id":1637502670,
          #             "low":"57402.87",
          #             "open":"57638",
          #             "ts":1637502670059,
          #             "vol":"394598"
          #         },
          #         "ts":1637502670059
          #     }
          #
          tick = self.safe_value(response, 'tick', {})
          ticker = self.parse_ticker(tick, market)
          timestamp = self.safe_integer(response, 'ts')
          ticker['timestamp'] = timestamp
          ticker['datetime'] = self.iso8601(timestamp)
          return ticker
  
      async def fetch_tickers(self, symbols=None, params={}):
          await self.load_markets()
          options = self.safe_value(self.options, 'fetchTickers', {})
          defaultType = self.safe_string(self.options, 'defaultType', 'spot')
          type = self.safe_string(options, 'type', defaultType)
          type = self.safe_string(params, 'type', type)
          method = 'spotPublicGetMarketTickers'
          defaultSubType = self.safe_string(self.options, 'defaultSubType', 'inverse')
          subType = self.safe_string(options, 'subType', defaultSubType)
          subType = self.safe_string(params, 'subType', subType)
          request = {}
          future = (type == 'future')
          swap = (type == 'swap')
          linear = (subType == 'linear')
          inverse = (subType == 'inverse')
          if linear:
              method = 'contractPublicGetLinearSwapExMarketDetailBatchMerged'
              if future:
                  request['business_type'] = 'futures'
          elif inverse:
              if future:
                  method = 'contractPublicGetMarketDetailBatchMerged'
              elif swap:
                  method = 'contractPublicGetSwapExMarketDetailBatchMerged'
          params = self.omit(params, ['type', 'subType'])
          response = await getattr(self, method)(self.extend(request, params))
          #
          # spot
          #
          #     {
          #         "data":[
          #             {
          #                 "symbol":"hbcbtc",
          #                 "open":5.313E-5,
          #                 "high":5.34E-5,
          #                 "low":5.112E-5,
          #                 "close":5.175E-5,
          #                 "amount":1183.87,
          #                 "vol":0.0618599229,
          #                 "count":205,
          #                 "bid":5.126E-5,
          #                 "bidSize":5.25,
          #                 "ask":5.214E-5,
          #                 "askSize":150.0
          #             },
          #         ],
          #         "status":"ok",
          #         "ts":1639547261293
          #     }
          #
          # inverse swaps, linear swaps, inverse futures
          #
          #     {
          #         "status":"ok",
          #         "ticks":[
          #             {
          #                 "id":1637504679,
          #                 "ts":1637504679372,
          #                 "ask":[0.10644,100],
          #                 "bid":[0.10624,26],
          #                 "symbol":"TRX_CW",
          #                 "open":"0.10233",
          #                 "close":"0.10644",
          #                 "low":"0.1017",
          #                 "high":"0.10725",
          #                 "amount":"2340267.415144052378486261756692535687481566",
          #                 "count":882,
          #                 "vol":"24706"
          #             }
          #         ],
          #         "ts":1637504679376
          #     }
          #
          # linear futures
          #
          #     {
          #         "status":"ok",
          #         "ticks":[
          #             {
          #                 "id":1640745627,
          #                 "ts":1640745627957,
          #                 "ask":[48079.1,20],
          #                 "bid":[47713.8,125],
          #                 "business_type":"futures",
          #                 "contract_code":"BTC-USDT-CW",
          #                 "open":"49011.8",
          #                 "close":"47934",
          #                 "low":"47292.3",
          #                 "high":"49011.8",
          #                 "amount":"17.398",
          #                 "count":1515,
          #                 "vol":"17398",
          #                 "trade_turnover":"840726.5048"
          #             }
          #         ],
          #         "ts":1640745627988
          #     }
          #
          tickers = self.safe_value_2(response, 'data', 'ticks', [])
          timestamp = self.safe_integer(response, 'ts')
          result = {}
          for i in range(0, len(tickers)):
              ticker = self.parse_ticker(tickers[i])
              # the market ids for linear futures are non-standard and differ from all the other endpoints
              # we are doing a linear-matching here
              if future and linear:
                  for j in range(0, len(self.symbols)):
                      symbol = self.symbols[j]
                      market = self.market(symbol)
                      contractType = self.safe_string(market['info'], 'contract_type')
                      if (contractType == 'this_week') and (ticker['symbol'] == (market['baseId'] + '-' + market['quoteId'] + '-CW')):
                          ticker['symbol'] = market['symbol']
                          break
                      elif (contractType == 'next_week') and (ticker['symbol'] == (market['baseId'] + '-' + market['quoteId'] + '-NW')):
                          ticker['symbol'] = market['symbol']
                          break
                      elif (contractType == 'this_quarter') and (ticker['symbol'] == (market['baseId'] + '-' + market['quoteId'] + '-CQ')):
                          ticker['symbol'] = market['symbol']
                          break
                      elif (contractType == 'next_quarter') and (ticker['symbol'] == (market['baseId'] + '-' + market['quoteId'] + '-NQ')):
                          ticker['symbol'] = market['symbol']
                          break
              symbol = ticker['symbol']
              ticker['timestamp'] = timestamp
              ticker['datetime'] = self.iso8601(timestamp)
              result[symbol] = ticker
          return self.filter_by_array(result, 'symbol', symbols)
  
      async def fetch_order_book(self, symbol, limit=None, params={}):
          await self.load_markets()
          market = self.market(symbol)
          request = {
              #
              # from the API docs
              #
              #     to get depth data within step 150, use step0, step1, step2, step3, step4, step5, step14, step15（merged depth data 0-5,14-15, when step is 0，depth data will not be merged
              #     to get depth data within step 20, use step6, step7, step8, step9, step10, step11, step12, step13(merged depth data 7-13), when step is 6, depth data will not be merged
              #
              'type': 'step0',
              # 'symbol': market['id'],  # spot, future
              # 'contract_code': market['id'],  # swap
          }
          fieldName = 'symbol'
          method = 'spotPublicGetMarketDepth'
          if market['linear']:
              method = 'contractPublicGetLinearSwapExMarketDepth'
              fieldName = 'contract_code'
          elif market['inverse']:
              if market['future']:
                  method = 'contractPublicGetMarketDepth'
              elif market['swap']:
                  method = 'contractPublicGetSwapExMarketDepth'
                  fieldName = 'contract_code'
          request[fieldName] = market['id']
          response = await getattr(self, method)(self.extend(request, params))
          #
          # spot, future, swap
          #
          #     {
          #         "status": "ok",
          #         "ch": "market.btcusdt.depth.step0",
          #         "ts": 1583474832790,
          #         "tick": {
          #             "bids": [
          #                 [9100.290000000000000000, 0.200000000000000000],
          #                 [9099.820000000000000000, 0.200000000000000000],
          #                 [9099.610000000000000000, 0.205000000000000000],
          #             ],
          #             "asks": [
          #                 [9100.640000000000000000, 0.005904000000000000],
          #                 [9101.010000000000000000, 0.287311000000000000],
          #                 [9101.030000000000000000, 0.012121000000000000],
          #             ],
          #             "ch":"market.BTC-USD.depth.step0",
          #             "ts":1583474832008,
          #             "id":1637554816,
          #             "mrid":121654491624,
          #             "version":104999698780
          #         }
          #     }
          #
          if 'tick' in response:
              if not response['tick']:
                  raise BadSymbol(self.id + ' fetchOrderBook() returned empty response: ' + self.json(response))
              tick = self.safe_value(response, 'tick')
              timestamp = self.safe_integer(tick, 'ts', self.safe_integer(response, 'ts'))
              result = self.parse_order_book(tick, symbol, timestamp)
              result['nonce'] = self.safe_integer(tick, 'version')
              return result
          raise ExchangeError(self.id + ' fetchOrderBook() returned unrecognized response: ' + self.json(response))
  
      def parse_trade(self, trade, market=None):
          #
          # spot fetchTrades(public)
          #
          #     {
          #         "amount": 0.010411000000000000,
          #         "trade-id": 102090736910,
          #         "ts": 1583497692182,
          #         "id": 10500517034273194594947,
          #         "price": 9096.050000000000000000,
          #         "direction": "sell"
          #     }
          #
          # spot fetchMyTrades(private)
          #
          #     {
          #          'symbol': 'swftcbtc',
          #          'fee-currency': 'swftc',
          #          'filled-fees': '0',
          #          'source': 'spot-api',
          #          'id': 83789509854000,
          #          'type': 'buy-limit',
          #          'order-id': 83711103204909,
          #          'filled-points': '0.005826843283532154',
          #          'fee-deduct-currency': 'ht',
          #          'filled-amount': '45941.53',
          #          'price': '0.0000001401',
          #          'created-at': 1597933260729,
          #          'match-id': 100087455560,
          #          'role': 'maker',
          #          'trade-id': 100050305348
          #     }
          #
          # linear swap isolated margin fetchOrder details
          #
          #     {
          #         "trade_id": 131560927,
          #         "trade_price": 13059.800000000000000000,
          #         "trade_volume": 1.000000000000000000,
          #         "trade_turnover": 13.059800000000000000,
          #         "trade_fee": -0.005223920000000000,
          #         "created_at": 1603703614715,
          #         "role": "taker",
          #         "fee_asset": "USDT",
          #         "profit": 0,
          #         "real_profit": 0,
          #         "id": "131560927-770334322963152896-1"
          #     }
          #
          # inverse swap cross margin fetchMyTrades
          #
          #     {
          #         "contract_type":"swap",
          #         "pair":"O3-USDT",
          #         "business_type":"swap",
          #         "query_id":652123190,
          #         "match_id":28306009409,
          #         "order_id":941137865226903553,
          #         "symbol":"O3",
          #         "contract_code":"O3-USDT",
          #         "direction":"sell",
          #         "offset":"open",
          #         "trade_volume":100.000000000000000000,
          #         "trade_price":0.398500000000000000,
          #         "trade_turnover":39.850000000000000000,
          #         "trade_fee":-0.007970000000000000,
          #         "offset_profitloss":0E-18,
          #         "create_date":1644426352999,
          #         "role":"Maker",
          #         "order_source":"api",
          #         "order_id_str":"941137865226903553",
          #         "id":"28306009409-941137865226903553-1",
          #         "fee_asset":"USDT",
          #         "margin_mode":"cross",
          #         "margin_account":"USDT",
          #         "real_profit":0E-18,
          #         "trade_partition":"USDT"
          #     }
          #
          marketId = self.safe_string_2(trade, 'contract_code', 'symbol')
          market = self.safe_market(marketId, market)
          symbol = market['symbol']
          timestamp = self.safe_integer_2(trade, 'ts', 'created-at')
          timestamp = self.safe_integer_2(trade, 'created_at', 'create_date', timestamp)
          order = self.safe_string_2(trade, 'order-id', 'order_id')
          side = self.safe_string(trade, 'direction')
          type = self.safe_string(trade, 'type')
          if type is not None:
              typeParts = type.split('-')
              side = typeParts[0]
              type = typeParts[1]
          takerOrMaker = self.safe_string_lower(trade, 'role')
          priceString = self.safe_string_2(trade, 'price', 'trade_price')
          amountString = self.safe_string_2(trade, 'filled-amount', 'amount')
          amountString = self.safe_string(trade, 'trade_volume', amountString)
          costString = self.safe_string(trade, 'trade_turnover')
          fee = None
          feeCost = self.safe_string_2(trade, 'filled-fees', 'trade_fee')
          feeCurrencyId = self.safe_string_2(trade, 'fee-currency', 'fee_asset')
          feeCurrency = self.safe_currency_code(feeCurrencyId)
          filledPoints = self.safe_string(trade, 'filled-points')
          if filledPoints is not None:
              if (feeCost is None) or Precise.string_equals(feeCost, '0'):
                  feeDeductCurrency = self.safe_string(trade, 'fee-deduct-currency')
                  if feeDeductCurrency != '':
                      feeCost = filledPoints
                      feeCurrency = self.safe_currency_code(feeDeductCurrency)
          if feeCost is not None:
              fee = {
                  'cost': feeCost,
                  'currency': feeCurrency,
              }
          tradeId = self.safe_string_2(trade, 'trade-id', 'tradeId')
          id = self.safe_string_2(trade, 'trade_id', 'id', tradeId)
          return self.safe_trade({
              'id': id,
              'info': trade,
              'order': order,
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
              'symbol': symbol,
              'type': type,
              'side': side,
              'takerOrMaker': takerOrMaker,
              'price': priceString,
              'amount': amountString,
              'cost': costString,
              'fee': fee,
          }, market)
  
      async def fetch_order_trades(self, id, symbol=None, since=None, limit=None, params={}):
          marketType = None
          marketType, params = self.handle_market_type_and_params('fetchOrderTrades', None, params)
          method = self.get_supported_mapping(marketType, {
              'spot': 'fetchSpotOrderTrades',
              # 'swap': 'fetchContractOrderTrades',
              # 'future': 'fetchContractOrderTrades',
          })
          return await getattr(self, method)(id, symbol, since, limit, params)
  
      async def fetch_spot_order_trades(self, id, symbol=None, since=None, limit=None, params={}):
          await self.load_markets()
          request = {
              'order-id': id,
          }
          response = await self.spotPrivateGetV1OrderOrdersOrderIdMatchresults(self.extend(request, params))
          return self.parse_trades(response['data'], None, since, limit)
  
      async def fetch_my_trades(self, symbol=None, since=None, limit=None, params={}):
          await self.load_markets()
          marketType = None
          marketType, params = self.handle_market_type_and_params('fetchMyTrades', None, params)
          request = {
              # spot -----------------------------------------------------------
              # 'symbol': market['id'],
              # 'types': 'buy-market,sell-market,buy-limit,sell-limit,buy-ioc,sell-ioc,buy-limit-maker,sell-limit-maker,buy-stop-limit,sell-stop-limit',
              # 'start-time': since,  # max 48 hours within 120 days
              # 'end-time': self.milliseconds(),  # max 48 hours within 120 days
              # 'from': 'id',  # tring False N/A Search internal id to begin with if search next page, then self should be the last id(not trade-id) of last page; if search previous page, then self should be the first id(not trade-id) of last page
              # 'direct': 'next',  # next, prev
              # 'size': limit,  # default 100, max 500 The number of orders to return [1-500]
              # contracts ------------------------------------------------------
              # 'symbol': market['settleId'],  # required
              # 'trade_type': 0,  # required, 0 all, 1 open long, 2 open short, 3 close short, 4 close long, 5 liquidate long positions, 6 liquidate short positions
              # 'contract_code': market['id'],
              # 'start_time': since,  # max 48 hours within 120 days
              # 'end_time': self.milliseconds(),  # max 48 hours within 120 days
              # 'from_id': 'id',  # tring False N/A Search internal id to begin with if search next page, then self should be the last id(not trade-id) of last page; if search previous page, then self should be the first id(not trade-id) of last page
              # 'direct': 'prev',  # next, prev
              # 'size': limit,  # default 20, max 50
          }
          method = None
          market = None
          if marketType == 'spot':
              if symbol is not None:
                  market = self.market(symbol)
                  request['symbol'] = market['id']
              if limit is not None:
                  request['size'] = limit  # default 100, max 500
              if since is not None:
                  request['start-time'] = since  # a date within 120 days from today
                  # request['end-time'] = self.sum(since, 172800000)  # 48 hours window
              method = 'spotPrivateGetV1OrderMatchresults'
          else:
              if symbol is None:
                  raise ArgumentsRequired(self.id + ' fetchMyTrades() requires a symbol for ' + marketType + ' orders')
              market = self.market(symbol)
              request['contract_code'] = market['id']
              request['trade_type'] = 0  # 0 all, 1 open long, 2 open short, 3 close short, 4 close long, 5 liquidate long positions, 6 liquidate short positions
              if market['linear']:
                  defaultMargin = 'cross' if market['future'] else 'isolated'
                  marginType = self.safe_string_2(self.options, 'defaultMarginType', 'marginType', defaultMargin)
                  if marginType == 'isolated':
                      method = 'contractPrivatePostLinearSwapApiV1SwapMatchresultsExact'
                  elif marginType == 'cross':
                      method = 'contractPrivatePostLinearSwapApiV1SwapCrossMatchresultsExact'
              elif market['inverse']:
                  if marketType == 'future':
                      method = 'contractPrivatePostApiV1ContractMatchresultsExact'
                      request['symbol'] = market['settleId']
                  elif marketType == 'swap':
                      method = 'contractPrivatePostSwapApiV1SwapMatchresultsExact'
                  else:
                      raise NotSupported(self.id + ' fetchMyTrades() does not support ' + marketType + ' markets')
          response = await getattr(self, method)(self.extend(request, params))
          #
          # spot
          #
          #     {
          #         "status": "ok",
          #         "data": [
          #             {
          #                 "symbol": "polyusdt",
          #                 "fee-currency": "poly",
          #                 "source": "spot-web",
          #                 "price": "0.338",
          #                 "created-at": 1629443051839,
          #                 "role": "taker",
          #                 "order-id": 345487249132375,
          #                 "match-id": 5014,
          #                 "trade-id": 1085,
          #                 "filled-amount": "147.928994082840236",
          #                 "filled-fees": "0",
          #                 "filled-points": "0.1",
          #                 "fee-deduct-currency": "hbpoint",
          #                 "fee-deduct-state": "done",
          #                 "id": 313288753120940,
          #                 "type": "buy-market"
          #             }
          #         ]
          #     }
          #
          # contracts
          #
          #     {
          #         "status": "ok",
          #         "data": {
          #             "trades": [
          #                 {
          #                     "query_id": 2424420723,
          #                     "match_id": 113891764710,
          #                     "order_id": 773135295142658048,
          #                     "symbol": "ADA",
          #                     "contract_type": "quarter",  # swap
          #                     "business_type": "futures",  # swap
          #                     "contract_code": "ADA201225",
          #                     "direction": "buy",
          #                     "offset": "open",
          #                     "trade_volume": 1,
          #                     "trade_price": 0.092,
          #                     "trade_turnover": 10,
          #                     "trade_fee": -0.021739130434782608,
          #                     "offset_profitloss": 0,
          #                     "create_date": 1604371703183,
          #                     "role": "Maker",
          #                     "order_source": "web",
          #                     "order_id_str": "773135295142658048",
          #                     "fee_asset": "ADA",
          #                     "margin_mode": "isolated",  # cross
          #                     "margin_account": "BTC-USDT",
          #                     "real_profit": 0,
          #                     "id": "113891764710-773135295142658048-1",
          #                     "trade_partition":"USDT",
          #                 }
          #             ],
          #             "remain_size": 15,
          #             "next_id": 2424413094
          #         },
          #         "ts": 1604372202243
          #     }
          #
          trades = self.safe_value(response, 'data')
          if not isinstance(trades, list):
              trades = self.safe_value(trades, 'trades')
          return self.parse_trades(trades, market, since, limit)
  
      async def fetch_trades(self, symbol, since=None, limit=1000, params={}):
          await self.load_markets()
          market = self.market(symbol)
          request = {
              # 'symbol': market['id'],  # spot, future
              # 'contract_code': market['id'],  # swap
          }
          fieldName = 'symbol'
          method = 'spotPublicGetMarketHistoryTrade'
          if market['future']:
              if market['inverse']:
                  method = 'contractPublicGetMarketHistoryTrade'
              elif market['linear']:
                  method = 'contractPublicGetLinearSwapExMarketHistoryTrade'
                  fieldName = 'contract_code'
          elif market['swap']:
              if market['inverse']:
                  method = 'contractPublicGetSwapExMarketHistoryTrade'
              elif market['linear']:
                  method = 'contractPublicGetLinearSwapExMarketHistoryTrade'
              fieldName = 'contract_code'
          request[fieldName] = market['id']
          if limit is not None:
              request['size'] = limit  # max 2000
          response = await getattr(self, method)(self.extend(request, params))
          #
          #     {
          #         "status": "ok",
          #         "ch": "market.btcusdt.trade.detail",
          #         "ts": 1583497692365,
          #         "data": [
          #             {
          #                 "id": 105005170342,
          #                 "ts": 1583497692182,
          #                 "data": [
          #                     {
          #                         "amount": 0.010411000000000000,
          #                         "trade-id": 102090736910,
          #                         "ts": 1583497692182,
          #                         "id": 10500517034273194594947,
          #                         "price": 9096.050000000000000000,
          #                         "direction": "sell"
          #                     }
          #                 ]
          #             },
          #             # ...
          #         ]
          #     }
          #
          data = self.safe_value(response, 'data')
          result = []
          for i in range(0, len(data)):
              trades = self.safe_value(data[i], 'data', [])
              for j in range(0, len(trades)):
                  trade = self.parse_trade(trades[j], market)
                  result.append(trade)
          result = self.sort_by(result, 'timestamp')
          return self.filter_by_symbol_since_limit(result, symbol, since, limit)
  
      def parse_ohlcv(self, ohlcv, market=None):
          #
          #     {
          #         "amount":1.2082,
          #         "open":0.025096,
          #         "close":0.025095,
          #         "high":0.025096,
          #         "id":1591515300,
          #         "count":6,
          #         "low":0.025095,
          #         "vol":0.0303205097
          #     }
          #
          return [
              self.safe_timestamp(ohlcv, 'id'),
              self.safe_number(ohlcv, 'open'),
              self.safe_number(ohlcv, 'high'),
              self.safe_number(ohlcv, 'low'),
              self.safe_number(ohlcv, 'close'),
              self.safe_number(ohlcv, 'amount'),
          ]
  
      async def fetch_ohlcv(self, symbol, timeframe='1m', since=None, limit=1000, params={}):
          await self.load_markets()
          market = self.market(symbol)
          request = {
              'period': self.timeframes[timeframe],
              # 'symbol': market['id'],  # spot, future
              # 'contract_code': market['id'],  # swap
              # 'side': limit,  # max 2000
          }
          fieldName = 'symbol'
          price = self.safe_string(params, 'price')
          params = self.omit(params, 'price')
          method = 'spotPublicGetMarketHistoryKline'
          if market['future']:
              if market['inverse']:
                  if price == 'mark':
                      method = 'contractPublicGetIndexMarketHistoryMarkPriceKline'
                  elif price == 'index':
                      method = 'contractPublicGetIndexMarketHistoryIndex'
                  elif price == 'premiumIndex':
                      raise BadRequest(self.id + ' ' + market['type'] + ' has no api endpoint for ' + price + ' kline data')
                  else:
                      method = 'contractPublicGetMarketHistoryKline'
              elif market['linear']:
                  if price == 'mark':
                      method = 'contractPublicGetIndexMarketHistoryLinearSwapMarkPriceKline'
                  elif price == 'index':
                      raise BadRequest(self.id + ' ' + market['type'] + ' has no api endpoint for ' + price + ' kline data')
                  elif price == 'premiumIndex':
                      method = 'contractPublicGetIndexMarketHistoryLinearSwapPremiumIndexKline'
                  else:
                      method = 'contractPublicGetLinearSwapExMarketHistoryKline'
                  fieldName = 'contract_code'
          elif market['swap']:
              if market['inverse']:
                  if price == 'mark':
                      method = 'contractPublicGetIndexMarketHistorySwapMarkPriceKline'
                  elif price == 'index':
                      raise BadRequest(self.id + ' ' + market['type'] + ' has no api endpoint for ' + price + ' kline data')
                  elif price == 'premiumIndex':
                      method = 'contractPublicGetIndexMarketHistorySwapPremiumIndexKline'
                  else:
                      method = 'contractPublicGetSwapExMarketHistoryKline'
              elif market['linear']:
                  if price == 'mark':
                      method = 'contractPublicGetIndexMarketHistoryLinearSwapMarkPriceKline'
                  elif price == 'index':
                      raise BadRequest(self.id + ' ' + market['type'] + ' has no api endpoint for ' + price + ' kline data')
                  elif price == 'premiumIndex':
                      method = 'contractPublicGetIndexMarketHistoryLinearSwapPremiumIndexKline'
                  else:
                      method = 'contractPublicGetLinearSwapExMarketHistoryKline'
              fieldName = 'contract_code'
          request[fieldName] = market['id']
          if limit is not None:
              request['size'] = limit  # max 2000
          response = await getattr(self, method)(self.extend(request, params))
          #
          #     {
          #         "status":"ok",
          #         "ch":"market.ethbtc.kline.1min",
          #         "ts":1591515374371,
          #         "data":[
          #             {"amount":0.0,"open":0.025095,"close":0.025095,"high":0.025095,"id":1591515360,"count":0,"low":0.025095,"vol":0.0},
          #             {"amount":1.2082,"open":0.025096,"close":0.025095,"high":0.025096,"id":1591515300,"count":6,"low":0.025095,"vol":0.0303205097},
          #             {"amount":0.0648,"open":0.025096,"close":0.025096,"high":0.025096,"id":1591515240,"count":2,"low":0.025096,"vol":0.0016262208},
          #         ]
          #     }
          #
          data = self.safe_value(response, 'data', [])
          return self.parse_ohlcvs(data, market, timeframe, since, limit)
  
      async def fetch_index_ohlcv(self, symbol, timeframe='1m', since=None, limit=None, params={}):
          request = {
              'price': 'index',
          }
          return await self.fetch_ohlcv(symbol, timeframe, since, limit, self.extend(request, params))
  
      async def fetch_mark_ohlcv(self, symbol, timeframe='1m', since=None, limit=None, params={}):
          request = {
              'price': 'mark',
          }
          return await self.fetch_ohlcv(symbol, timeframe, since, limit, self.extend(request, params))
  
      async def fetch_premium_index_ohlcv(self, symbol, timeframe='1m', since=None, limit=None, params={}):
          request = {
              'price': 'premiumIndex',
          }
          return await self.fetch_ohlcv(symbol, timeframe, since, limit, self.extend(request, params))
  
      async def fetch_accounts(self, params={}):
          await self.load_markets()
          response = await self.spotPrivateGetV1AccountAccounts(params)
          #
          #     {
          #         "status":"ok",
          #         "data":[
          #             {"id":5202591,"type":"point","subtype":"","state":"working"},
          #             {"id":1528640,"type":"spot","subtype":"","state":"working"},
          #         ]
          #     }
          #
          return response['data']
  
      async def fetch_account_id_by_type(self, type, params={}):
          accounts = await self.load_accounts()
          accountId = self.safe_value(params, 'account-id')
          if accountId is not None:
              return accountId
          indexedAccounts = self.index_by(accounts, 'type')
          defaultAccount = self.safe_value(accounts, 0, {})
          account = self.safe_value(indexedAccounts, type, defaultAccount)
          return self.safe_string(account, 'id')
  
      async def fetch_currencies(self, params={}):
          response = await self.spotPublicGetV2ReferenceCurrencies()
          #     {
          #       "code": 200,
          #       "data": [
          #         {
          #           "currency": "sxp",
          #           "assetType": "1",
          #           "chains": [
          #             {
          #               "chain": "sxp",
          #               "displayName": "ERC20",
          #               "baseChain": "ETH",
          #               "baseChainProtocol": "ERC20",
          #               "isDynamic": True,
          #               "numOfConfirmations": "12",
          #               "numOfFastConfirmations": "12",
          #               "depositStatus": "allowed",
          #               "minDepositAmt": "0.23",
          #               "withdrawStatus": "allowed",
          #               "minWithdrawAmt": "0.23",
          #               "withdrawPrecision": "8",
          #               "maxWithdrawAmt": "227000.000000000000000000",
          #               "withdrawQuotaPerDay": "227000.000000000000000000",
          #               "withdrawQuotaPerYear": null,
          #               "withdrawQuotaTotal": null,
          #               "withdrawFeeType": "fixed",
          #               "transactFeeWithdraw": "11.1653",
          #               "addrWithTag": False,
          #               "addrDepositTag": False
          #             }
          #           ],
          #           "instStatus": "normal"
          #         }
          #       ]
          #     }
          #
          data = self.safe_value(response, 'data', [])
          result = {}
          for i in range(0, len(data)):
              entry = data[i]
              currencyId = self.safe_string(entry, 'currency')
              code = self.safe_currency_code(currencyId)
              chains = self.safe_value(entry, 'chains', [])
              networks = {}
              instStatus = self.safe_string(entry, 'instStatus')
              currencyActive = instStatus == 'normal'
              fee = None
              minPrecision = None
              minWithdraw = None
              maxWithdraw = None
              deposit = None
              withdraw = None
              for j in range(0, len(chains)):
                  chain = chains[j]
                  networkId = self.safe_string(chain, 'chain')
                  baseChainProtocol = self.safe_string(chain, 'baseChainProtocol')
                  huobiToken = 'h' + currencyId
                  if baseChainProtocol is None:
                      if huobiToken == networkId:
                          baseChainProtocol = 'ERC20'
                      else:
                          baseChainProtocol = self.safe_string(chain, 'displayName')
                  network = self.safe_network(baseChainProtocol)
                  minWithdraw = self.safe_number(chain, 'minWithdrawAmt')
                  maxWithdraw = self.safe_number(chain, 'maxWithdrawAmt')
                  withdrawStatus = self.safe_string(chain, 'withdrawStatus')
                  depositStatus = self.safe_string(chain, 'depositStatus')
                  withdrawEnabled = (withdrawStatus == 'allowed')
                  depositEnabled = (depositStatus == 'allowed')
                  active = withdrawEnabled and depositEnabled
                  precision = self.safe_string(chain, 'withdrawPrecision')
                  if precision is not None:
                      precision = self.parse_number('1e-' + precision)
                      minPrecision = precision if (minPrecision is None) else max(precision, minPrecision)
                  if withdrawEnabled and not withdraw:
                      withdraw = True
                  elif not withdrawEnabled:
                      withdraw = False
                  if depositEnabled and not deposit:
                      deposit = True
                  elif not depositEnabled:
                      deposit = False
                  fee = self.safe_number(chain, 'transactFeeWithdraw')
                  networks[network] = {
                      'info': chain,
                      'id': networkId,
                      'network': network,
                      'limits': {
                          'withdraw': {
                              'min': minWithdraw,
                              'max': maxWithdraw,
                          },
                      },
                      'active': active,
                      'deposit': depositEnabled,
                      'withdraw': withdrawEnabled,
                      'fee': fee,
                      'precision': precision,
                  }
              networksKeys = list(networks.keys())
              networkLength = len(networksKeys)
              result[code] = {
                  'info': entry,
                  'code': code,
                  'id': currencyId,
                  'active': currencyActive,
                  'deposit': deposit,
                  'withdraw': withdraw,
                  'fee': fee if (networkLength <= 1) else None,
                  'name': None,
                  'limits': {
                      'amount': {
                          'min': None,
                          'max': None,
                      },
                      'withdraw': {
                          'min': minWithdraw if (networkLength <= 1) else None,
                          'max': maxWithdraw if (networkLength <= 1) else None,
                      },
                  },
                  'precision': minPrecision,
                  'networks': networks,
              }
          return result
  
      async def fetch_balance(self, params={}):
          await self.load_markets()
          options = self.safe_value(self.options, 'fetchTickers', {})
          defaultType = self.safe_string(self.options, 'defaultType', 'spot')
          type = self.safe_string(options, 'type', defaultType)
          type = self.safe_string(params, 'type', type)
          params = self.omit(params, 'type')
          request = {}
          method = None
          spot = (type == 'spot')
          future = (type == 'future')
          swap = (type == 'swap')
          defaultSubType = self.safe_string(self.options, 'defaultSubType', 'inverse')
          subType = self.safe_string(options, 'subType', defaultSubType)
          subType = self.safe_string(params, 'subType', subType)
          inverse = (subType == 'inverse')
          linear = (subType == 'linear')
          marginType = self.safe_string_2(self.options, 'defaultMarginType', 'marginType', 'isolated')
          isolated = (marginType == 'isolated')
          cross = (marginType == 'cross')
          if spot:
              await self.load_accounts()
              accountId = await self.fetch_account_id_by_type(type, params)
              request['account-id'] = accountId
              method = 'spotPrivateGetV1AccountAccountsAccountIdBalance'
          elif linear:
              method = 'contractPrivatePostLinearSwapApiV1SwapCrossAccountInfo'
          elif inverse:
              if future:
                  method = 'contractPrivatePostApiV1ContractAccountInfo'
              elif swap:
                  method = 'contractPrivatePostSwapApiV1SwapAccountInfo'
          response = await getattr(self, method)(self.extend(request, params))
          #
          # spot
          #
          #     {
          #         "status":"ok",
          #         "data":{
          #             "id":1528640,
          #             "type":"spot",
          #             "state":"working",
          #             "list":[
          #                 {"currency":"lun","type":"trade","balance":"0","seq-num":"0"},
          #                 {"currency":"lun","type":"frozen","balance":"0","seq-num":"0"},
          #                 {"currency":"ht","type":"frozen","balance":"0","seq-num":"145"},
          #             ]
          #         },
          #         "ts":1637644827566
          #     }
          #
          # future, swap isolated
          #
          #     {
          #         "status":"ok",
          #         "data":[
          #             {
          #                 "symbol":"BTC",
          #                 "margin_balance":0,
          #                 "margin_position":0E-18,
          #                 "margin_frozen":0,
          #                 "margin_available":0E-18,
          #                 "profit_real":0,
          #                 "profit_unreal":0,
          #                 "risk_rate":null,
          #                 "withdraw_available":0,
          #                 "liquidation_price":null,
          #                 "lever_rate":5,
          #                 "adjust_factor":0.025000000000000000,
          #                 "margin_static":0,
          #                 "is_debit":0,  # future only
          #                 "contract_code":"BTC-USD",  # swap only
          #                 "margin_asset":"USDT",  # linear only
          #                 "margin_mode":"isolated",  # linear only
          #                 "margin_account":"BTC-USDT"  # linear only
          #                 "transfer_profit_ratio":null  # inverse only
          #             },
          #         ],
          #         "ts":1637644827566
          #     }
          #
          # linear cross futures and linear cross swap
          #
          #     {
          #         "status":"ok",
          #         "data":[
          #             {
          #                 "futures_contract_detail":[
          #                     {
          #                         "symbol":"ETH",
          #                         "contract_code":"ETH-USDT-220325",
          #                         "margin_position":0,
          #                         "margin_frozen":0,
          #                         "margin_available":200.000000000000000000,
          #                         "profit_unreal":0E-18,
          #                         "liquidation_price":null,
          #                         "lever_rate":5,
          #                         "adjust_factor":0.060000000000000000,
          #                         "contract_type":"quarter",
          #                         "pair":"ETH-USDT",
          #                         "business_type":"futures"
          #                     },
          #                 ],
          #                 "margin_mode":"cross",
          #                 "margin_account":"USDT",
          #                 "margin_asset":"USDT",
          #                 "margin_balance":200.000000000000000000,
          #                 "margin_static":200.000000000000000000,
          #                 "margin_position":0,
          #                 "margin_frozen":0,
          #                 "profit_real":0E-18,
          #                 "profit_unreal":0,
          #                 "withdraw_available":2E+2,
          #                 "risk_rate":null,
          #                 "contract_detail":[
          #                     {
          #                         "symbol":"MANA",
          #                         "contract_code":"MANA-USDT",
          #                         "margin_position":0,
          #                         "margin_frozen":0,
          #                         "margin_available":200.000000000000000000,
          #                         "profit_unreal":0E-18,
          #                         "liquidation_price":null,
          #                         "lever_rate":5,
          #                         "adjust_factor":0.100000000000000000,
          #                         "contract_type":"swap",
          #                         "pair":"MANA-USDT",
          #                         "business_type":"swap"
          #                     },
          #                 ]
          #             }
          #         ],
          #         "ts":1640915104870
          #     }
          #
          result = {'info': response}
          data = self.safe_value(response, 'data')
          if spot:
              balances = self.safe_value(data, 'list', [])
              for i in range(0, len(balances)):
                  balance = balances[i]
                  currencyId = self.safe_string(balance, 'currency')
                  code = self.safe_currency_code(currencyId)
                  account = None
                  if code in result:
                      account = result[code]
                  else:
                      account = self.account()
                  if balance['type'] == 'trade':
                      account['free'] = self.safe_string(balance, 'balance')
                  if balance['type'] == 'frozen':
                      account['used'] = self.safe_string(balance, 'balance')
                  result[code] = account
          elif linear:
              first = self.safe_value(data, 0, {})
              if cross:
                  account = self.account()
                  account['free'] = self.safe_string(first, 'margin_balance', 'margin_available')
                  account['used'] = self.safe_string(first, 'margin_frozen')
                  currencyId = self.safe_string_2(first, 'margin_asset', 'symbol')
                  code = self.safe_currency_code(currencyId)
                  result[code] = account
              elif isolated:
                  fieldName = 'futures_contract_detail' if future else 'contract_detail'
                  balances = self.safe_value(first, fieldName, [])
                  for i in range(0, len(balances)):
                      balance = balances[i]
                      marketId = self.safe_string_2(balance, 'contract_code', 'margin_account')
                      market = self.safe_market(marketId)
                      account = self.account()
                      account['free'] = self.safe_string(balance, 'margin_balance')
                      account['used'] = self.safe_string(balance, 'margin_frozen')
                      code = market['settle']
                      accountsByCode = {}
                      accountsByCode[code] = account
                      symbol = market['symbol']
                      result[symbol] = self.safe_balance(accountsByCode)
                  return result
          elif inverse:
              for i in range(0, len(data)):
                  balance = data[i]
                  currencyId = self.safe_string(balance, 'symbol')
                  code = self.safe_currency_code(currencyId)
                  account = self.account()
                  account['free'] = self.safe_string(balance, 'margin_available')
                  account['used'] = self.safe_string(balance, 'margin_frozen')
                  result[code] = account
          return self.safe_balance(result)
  
      async def fetch_order(self, id, symbol=None, params={}):
          await self.load_markets()
          marketType = None
          marketType, params = self.handle_market_type_and_params('fetchOrder', None, params)
          request = {
              # spot -----------------------------------------------------------
              # 'order-id': 'id',
              # 'symbol': market['id'],
              # 'client-order-id': clientOrderId,
              # 'clientOrderId': clientOrderId,
              # contracts ------------------------------------------------------
              # 'order_id': id,
              # 'client_order_id': clientOrderId,
              # 'contract_code': market['id'],
              # 'pair': 'BTC-USDT',
              # 'contract_type': 'this_week',  # swap, self_week, next_week, quarter, next_ quarter
          }
          method = None
          market = None
          if marketType == 'spot':
              clientOrderId = self.safe_string(params, 'clientOrderId')
              method = 'spotPrivateGetV1OrderOrdersOrderId'
              if clientOrderId is not None:
                  method = 'spotPrivateGetV1OrderOrdersGetClientOrder'
                  # will be filled below in self.extend()
                  # they expect clientOrderId instead of client-order-id
                  # request['clientOrderId'] = clientOrderId
              else:
                  request['order-id'] = id
          else:
              if symbol is None:
                  raise ArgumentsRequired(self.id + ' fetchOrder() requires a symbol for ' + marketType + ' orders')
              market = self.market(symbol)
              request['contract_code'] = market['id']
              if market['linear']:
                  defaultMargin = 'cross' if market['future'] else 'isolated'
                  marginType = self.safe_string_2(self.options, 'defaultMarginType', 'marginType', defaultMargin)
                  if marginType == 'isolated':
                      method = 'contractPrivatePostLinearSwapApiV1SwapOrderInfo'
                  elif marginType == 'cross':
                      method = 'contractPrivatePostLinearSwapApiV1SwapCrossOrderInfo'
              elif market['inverse']:
                  if marketType == 'future':
                      method = 'contractPrivatePostApiV1ContractOrderInfo'
                      request['symbol'] = market['settleId']
                  elif marketType == 'swap':
                      method = 'contractPrivatePostSwapApiV1SwapOrderInfo'
                  else:
                      raise NotSupported(self.id + ' fetchOrder() does not support ' + marketType + ' markets')
              clientOrderId = self.safe_string_2(params, 'client_order_id', 'clientOrderId')
              if clientOrderId is None:
                  request['order_id'] = id
              else:
                  request['client_order_id'] = clientOrderId
                  params = self.omit(params, ['client_order_id', 'clientOrderId'])
          response = await getattr(self, method)(self.extend(request, params))
          #
          # spot
          #
          #     {
          #         "status":"ok",
          #         "data":{
          #             "id":438398393065481,
          #             "symbol":"ethusdt",
          #             "account-id":1528640,
          #             "client-order-id":"AA03022abc2163433e-006b-480e-9ad1-d4781478c5e7",
          #             "amount":"0.100000000000000000",
          #             "price":"3000.000000000000000000",
          #             "created-at":1640549994642,
          #             "type":"buy-limit",
          #             "field-amount":"0.0",
          #             "field-cash-amount":"0.0",
          #             "field-fees":"0.0",
          #             "finished-at":0,
          #             "source":"spot-api",
          #             "state":"submitted",
          #             "canceled-at":0
          #         }
          #     }
          #
          # linear swap cross margin
          #
          #     {
          #         "status":"ok",
          #         "data":[
          #             {
          #                 "business_type":"swap",
          #                 "contract_type":"swap",
          #                 "pair":"BTC-USDT",
          #                 "symbol":"BTC",
          #                 "contract_code":"BTC-USDT",
          #                 "volume":1,
          #                 "price":3000,
          #                 "order_price_type":"limit",
          #                 "order_type":1,
          #                 "direction":"buy",
          #                 "offset":"open",
          #                 "lever_rate":1,
          #                 "order_id":924912513206878210,
          #                 "client_order_id":null,
          #                 "created_at":1640557927189,
          #                 "trade_volume":0,
          #                 "trade_turnover":0,
          #                 "fee":0,
          #                 "trade_avg_price":null,
          #                 "margin_frozen":3.000000000000000000,
          #                 "profit":0,
          #                 "status":3,
          #                 "order_source":"api",
          #                 "order_id_str":"924912513206878210",
          #                 "fee_asset":"USDT",
          #                 "liquidation_type":"0",
          #                 "canceled_at":0,
          #                 "margin_asset":"USDT",
          #                 "margin_account":"USDT",
          #                 "margin_mode":"cross",
          #                 "is_tpsl":0,
          #                 "real_profit":0
          #             }
          #         ],
          #         "ts":1640557982556
          #     }
          #
          # linear swap isolated margin detail
          #
          #     {
          #         "status": "ok",
          #         "data": {
          #             "symbol": "BTC",
          #             "contract_code": "BTC-USDT",
          #             "instrument_price": 0,
          #             "final_interest": 0,
          #             "adjust_value": 0,
          #             "lever_rate": 10,
          #             "direction": "sell",
          #             "offset": "open",
          #             "volume": 1.000000000000000000,
          #             "price": 13059.800000000000000000,
          #             "created_at": 1603703614712,
          #             "canceled_at": 0,
          #             "order_source": "api",
          #             "order_price_type": "opponent",
          #             "margin_frozen": 0,
          #             "profit": 0,
          #             "trades": [
          #                 {
          #                     "trade_id": 131560927,
          #                     "trade_price": 13059.800000000000000000,
          #                     "trade_volume": 1.000000000000000000,
          #                     "trade_turnover": 13.059800000000000000,
          #                     "trade_fee": -0.005223920000000000,
          #                     "created_at": 1603703614715,
          #                     "role": "taker",
          #                     "fee_asset": "USDT",
          #                     "profit": 0,
          #                     "real_profit": 0,
          #                     "id": "131560927-770334322963152896-1"
          #                 }
          #             ],
          #             "total_page": 1,
          #             "current_page": 1,
          #             "total_size": 1,
          #             "liquidation_type": "0",
          #             "fee_asset": "USDT",
          #             "fee": -0.005223920000000000,
          #             "order_id": 770334322963152896,
          #             "order_id_str": "770334322963152896",
          #             "client_order_id": 57012021045,
          #             "order_type": "1",
          #             "status": 6,
          #             "trade_avg_price": 13059.800000000000000000,
          #             "trade_turnover": 13.059800000000000000,
          #             "trade_volume": 1.000000000000000000,
          #             "margin_asset": "USDT",
          #             "margin_mode": "isolated",
          #             "margin_account": "BTC-USDT",
          #             "real_profit": 0,
          #             "is_tpsl": 0
          #         },
          #         "ts": 1603703678477
          #     }
          order = self.safe_value(response, 'data')
          if isinstance(order, list):
              order = self.safe_value(order, 0)
          return self.parse_order(order)
  
      async def fetch_spot_orders_by_states(self, states, symbol=None, since=None, limit=None, params={}):
          method = self.safe_string(self.options, 'fetchOrdersByStatesMethod', 'spot_private_get_v1_order_orders')  # spot_private_get_v1_order_history
          if method == 'spot_private_get_v1_order_orders':
              if symbol is None:
                  raise ArgumentsRequired(self.id + ' fetchOrders() requires a symbol argument')
          await self.load_markets()
          market = None
          request = {
              # spot_private_get_v1_order_orders GET /v1/order/orders ----------
              # 'symbol': market['id'],  # required
              # 'types': 'buy-market,sell-market,buy-limit,sell-limit,buy-ioc,sell-ioc,buy-stop-limit,sell-stop-limit,buy-limit-fok,sell-limit-fok,buy-stop-limit-fok,sell-stop-limit-fok',
              # 'start-time': since,  # max window of 48h within a range of 180 days, within past 2 hours for cancelled orders
              # 'end-time': self.milliseconds(),
              'states': states,  # filled, partial-canceled, canceled
              # 'from': order['id'],
              # 'direct': 'next',  # next, prev, used with from
              # 'size': 100,  # max 100
              # spot_private_get_v1_order_history GET /v1/order/history --------
              # 'symbol': market['id'],  # optional
              # 'start-time': since,  # max window of 48h within a range of 180 days, within past 2 hours for cancelled orders
              # 'end-time': self.milliseconds(),
              # 'direct': 'next',  # next, prev, used with from
              # 'size': 100,  # max 100
          }
          if symbol is not None:
              market = self.market(symbol)
              request['symbol'] = market['id']
          if since is not None:
              request['start-time'] = since  # a window of 48 hours within 180 days
              request['end-time'] = self.sum(since, 48 * 60 * 60 * 1000)
          if limit is not None:
              request['size'] = limit
          response = await getattr(self, method)(self.extend(request, params))
          #
          # spot_private_get_v1_order_orders GET /v1/order/orders
          #
          #     {
          #         status: "ok",
          #         data: [
          #             {
          #                 id: 13997833014,
          #                 symbol: "ethbtc",
          #                 'account-id': 3398321,
          #                 'client-order-id': "23456",
          #                 amount: "0.045000000000000000",
          #                 price: "0.034014000000000000",
          #                 'created-at': 1545836976871,
          #                 type: "sell-limit",
          #                 'field-amount': "0.045000000000000000",
          #                 'field-cash-amount': "0.001530630000000000",
          #                 'field-fees': "0.000003061260000000",
          #                 'finished-at': 1545837948214,
          #                 source: "spot-api",
          #                 state: "filled",
          #                 'canceled-at': 0
          #             }
          #         ]
          #     }
          #
          data = self.safe_value(response, 'data', [])
          return self.parse_orders(data, market, since, limit)
  
      async def fetch_spot_orders(self, symbol=None, since=None, limit=None, params={}):
          return await self.fetch_spot_orders_by_states('pre-submitted,submitted,partial-filled,filled,partial-canceled,canceled', symbol, since, limit, params)
  
      async def fetch_closed_spot_orders(self, symbol=None, since=None, limit=None, params={}):
          return await self.fetch_spot_orders_by_states('filled,partial-canceled,canceled', symbol, since, limit, params)
  
      async def fetch_contract_orders(self, symbol=None, since=None, limit=None, params={}):
          if symbol is None:
              raise ArgumentsRequired(self.id + ' fetchContractOrders() requires a symbol argument')
          await self.load_markets()
          market = self.market(symbol)
          marketType = None
          marketType, params = self.handle_market_type_and_params('fetchOrders', market, params)
          request = {
              # POST /api/v1/contract_hisorders inverse futures ----------------
              # 'symbol': market['settleId'],  # BTC, ETH, ...
              # 'order_type': '1',  # 1 limit，3 opponent，4 lightning, 5 trigger order, 6 pst_only, 7 optimal_5, 8 optimal_10, 9 optimal_20, 10 fok, 11 ioc
              # POST /swap-api/v1/swap_hisorders inverse swap ------------------
              # POST /linear-swap-api/v1/swap_hisorders linear isolated --------
              # POST /linear-swap-api/v1/swap_cross_hisorders linear cross -----
              'contract_code': market['id'],
              'trade_type': 0,  # 0 all, 1 buy long, 2 sell short, 3 buy short, 4 sell long, 5 sell liquidation, 6 buy liquidation, 7 Delivery long, 8 Delivery short 11 reduce positions to close long, 12 reduce positions to close short
              'type': 1,  # 1 all orders, 2 finished orders
              'status': '0',  # comma separated, 0 all, 3 submitted orders, 4 partially matched, 5 partially cancelled, 6 fully matched and closed, 7 canceled
              'create_date': 90,  # in days?
              # 'page_index': 1,
              # 'page_size': limit,  # default 20, max 50
              # 'sort_by': 'create_date',  # create_date descending, update_time descending
          }
          method = None
          request['contract_code'] = market['id']
          if market['linear']:
              defaultMargin = 'cross' if market['future'] else 'isolated'
              marginType = self.safe_string_2(self.options, 'defaultMarginType', 'marginType', defaultMargin)
              method = self.get_supported_mapping(marginType, {
                  'isolated': 'contractPrivatePostLinearSwapApiV1SwapHisorders',
                  'cross': 'contractPrivatePostLinearSwapApiV1SwapCrossHisorders',
              })
          elif market['inverse']:
              method = self.get_supported_mapping(marketType, {
                  'future': 'contractPrivatePostApiV1ContractHisorders',
                  'swap': 'contractPrivatePostSwapApiV1SwapHisorders',
              })
              if marketType == 'future':
                  request['symbol'] = market['settleId']
          if limit is not None:
              request['page_size'] = limit
          response = await getattr(self, method)(self.extend(request, params))
          #
          #     {
          #         "status": "ok",
          #         "data": {
          #             "orders": [
          #                 {
          #                     "order_id": 773131315209248768,
          #                     "contract_code": "ADA201225",
          #                     "symbol": "ADA",
          #                     "lever_rate": 20,
          #                     "direction": "buy",
          #                     "offset": "close",
          #                     "volume": 1,
          #                     "price": 0.0925,
          #                     "create_date": 1604370469629,
          #                     "update_time": 1603704221118,
          #                     "order_source": "web",
          #                     "order_price_type": 6,
          #                     "order_type": 1,
          #                     "margin_frozen": 0,
          #                     "profit": 0,
          #                     "contract_type": "quarter",
          #                     "trade_volume": 0,
          #                     "trade_turnover": 0,
          #                     "fee": 0,
          #                     "trade_avg_price": 0,
          #                     "status": 3,
          #                     "order_id_str": "773131315209248768",
          #                     "fee_asset": "ADA",
          #                     "liquidation_type": "0",
          #                     "is_tpsl": 0,
          #                     "real_profit": 0
          #                     "pair": "BTC-USDT",
          #                     "business_type": "futures",
          #                     "margin_asset": "USDT",
          #                     "margin_mode": "cross",
          #                     "margin_account": "USDT",
          #                 }
          #             ],
          #             "total_page": 19,
          #             "current_page": 1,
          #             "total_size": 19
          #         },
          #         "ts": 1604370617322
          #     }
          #
          data = self.safe_value(response, 'data', {})
          orders = self.safe_value(data, 'orders', [])
          return self.parse_orders(orders, market, since, limit)
  
      async def fetch_closed_contract_orders(self, symbol=None, since=None, limit=None, params={}):
          request = {
              'status': '5,6,7',  # comma separated, 0 all, 3 submitted orders, 4 partially matched, 5 partially cancelled, 6 fully matched and closed, 7 canceled
          }
          return await self.fetch_contract_orders(symbol, since, limit, self.extend(request, params))
  
      async def fetch_orders(self, symbol=None, since=None, limit=None, params={}):
          await self.load_markets()
          marketType = None
          marketType, params = self.handle_market_type_and_params('fetchOrders', None, params)
          method = self.get_supported_mapping(marketType, {
              'spot': 'fetchSpotOrders',
              'swap': 'fetchContractOrders',
              'future': 'fetchContractOrders',
          })
          if method is None:
              raise NotSupported(self.id + ' fetchOrders does not support ' + marketType + ' markets yet')
          contract = (marketType == 'swap') or (marketType == 'future')
          if contract and (symbol is None):
              raise ArgumentsRequired(self.id + ' fetchOrders() requires a symbol argument for ' + marketType + ' orders')
          return await getattr(self, method)(symbol, since, limit, params)
  
      async def fetch_closed_orders(self, symbol=None, since=None, limit=None, params={}):
          await self.load_markets()
          marketType = None
          marketType, params = self.handle_market_type_and_params('fetchClosedOrders', None, params)
          method = self.get_supported_mapping(marketType, {
              'spot': 'fetchClosedSpotOrders',
              'swap': 'fetchClosedContractOrders',
              'future': 'fetchClosedContractOrders',
          })
          if method is None:
              raise NotSupported(self.id + ' fetchClosedOrders does not support ' + marketType + ' markets yet')
          return await getattr(self, method)(symbol, since, limit, params)
  
      async def fetch_open_orders(self, symbol=None, since=None, limit=None, params={}):
          await self.load_markets()
          marketType = None
          marketType, params = self.handle_market_type_and_params('fetchOpenOrders', None, params)
          request = {
              # spot -----------------------------------------------------------
              # 'account-id': account['id'],
              # 'symbol': market['id'],
              # 'side': 'buy',  # buy, sell
              # 'from': 'id',  # order id to begin with
              # 'direct': 'prev',  # prev, next, mandatory if from is defined
              # 'size': 100,  # default 100, max 500
              # futures --------------------------------------------------------
              # 'symbol': market['settleId'],
              # 'page_index': 1,  # default 1
              # 'page_size': limit,  # default 20, max 50
              # 'sort_by': 'created_at',  # created_at, update_time, descending sorting field
              # 'trade_type': 0,  # 0 all, 1 buy long, 2 sell short, 3 buy short, 4 sell long
          }
          method = None
          market = None
          if marketType == 'spot':
              method = 'spotPrivateGetV1OrderOpenOrders'
              if symbol is not None:
                  market = self.market(symbol)
                  request['symbol'] = market['id']
              # todo replace with fetchAccountIdByType
              accountId = self.safe_string(params, 'account-id')
              if accountId is None:
                  # pick the first account
                  await self.load_accounts()
                  for i in range(0, len(self.accounts)):
                      account = self.accounts[i]
                      if account['type'] == 'spot':
                          accountId = self.safe_string(account, 'id')
                          if accountId is not None:
                              break
              request['account-id'] = accountId
              if limit is not None:
                  request['size'] = limit
              params = self.omit(params, 'account-id')
          else:
              if symbol is None:
                  raise ArgumentsRequired(self.id + ' fetchOpenOrders() requires a symbol for ' + marketType + ' orders')
              market = self.market(symbol)
              request['contract_code'] = market['id']
              if market['linear']:
                  defaultMargin = 'cross' if market['future'] else 'isolated'
                  marginType = self.safe_string_2(self.options, 'defaultMarginType', 'marginType', defaultMargin)
                  if marginType == 'isolated':
                      method = 'contractPrivatePostLinearSwapApiV1SwapOpenorders'
                  elif marginType == 'cross':
                      method = 'contractPrivatePostLinearSwapApiV1SwapCrossOpenorders'
              elif market['inverse']:
                  if market['future']:
                      method = 'contractPrivatePostApiV1ContractOpenorders'
                      request['symbol'] = market['settleId']
                  elif market['swap']:
                      method = 'contractPrivatePostSwapApiV1SwapOpenorders'
              if limit is not None:
                  request['page_size'] = limit
          response = await getattr(self, method)(self.extend(request, params))
          #
          # spot
          #
          #     {
          #         "status":"ok",
          #         "data":[
          #             {
          #                 "symbol":"ethusdt",
          #                 "source":"api",
          #                 "amount":"0.010000000000000000",
          #                 "account-id":1528640,
          #                 "created-at":1561597491963,
          #                 "price":"400.000000000000000000",
          #                 "filled-amount":"0.0",
          #                 "filled-cash-amount":"0.0",
          #                 "filled-fees":"0.0",
          #                 "id":38477101630,
          #                 "state":"submitted",
          #                 "type":"sell-limit"
          #             }
          #         ]
          #     }
          #
          # futures
          #
          #     {
          #         "status": "ok",
          #         "data": {
          #             "orders": [
          #                 {
          #                     "symbol": "ADA",
          #                     "contract_code": "ADA201225",
          #                     "contract_type": "quarter",
          #                     "volume": 1,
          #                     "price": 0.0925,
          #                     "order_price_type": "post_only",
          #                     "order_type": 1,
          #                     "direction": "buy",
          #                     "offset": "close",
          #                     "lever_rate": 20,
          #                     "order_id": 773131315209248768,
          #                     "client_order_id": null,
          #                     "created_at": 1604370469629,
          #                     "trade_volume": 0,
          #                     "trade_turnover": 0,
          #                     "fee": 0,
          #                     "trade_avg_price": null,
          #                     "margin_frozen": 0,
          #                     "profit": 0,
          #                     "status": 3,
          #                     "order_source": "web",
          #                     "order_id_str": "773131315209248768",
          #                     "fee_asset": "ADA",
          #                     "liquidation_type": null,
          #                     "canceled_at": null,
          #                     "is_tpsl": 0,
          #                     "update_time": 1606975980467,
          #                     "real_profit": 0
          #                 }
          #             ],
          #             "total_page": 1,
          #             "current_page": 1,
          #             "total_size": 1
          #         },
          #         "ts": 1604370488518
          #     }
          #
          orders = self.safe_value(response, 'data')
          if not isinstance(orders, list):
              orders = self.safe_value(orders, 'orders', [])
          return self.parse_orders(orders, market, since, limit)
  
      def parse_order_status(self, status):
          statuses = {
              # spot
              'partial-filled': 'open',
              'partial-canceled': 'canceled',
              'filled': 'closed',
              'canceled': 'canceled',
              'submitted': 'open',
              'created': 'open',  # For stop orders
              # contract
              '1': 'open',
              '2': 'open',
              '3': 'open',
              '4': 'open',
              '5': 'canceled',  # partially matched
              '6': 'closed',
              '7': 'canceled',
              '11': 'canceling',
          }
          return self.safe_string(statuses, status, status)
  
      def parse_order(self, order, market=None):
          #
          # spot
          #
          #     {
          #         id:  13997833014,
          #         symbol: "ethbtc",
          #         'account-id':  3398321,
          #         amount: "0.045000000000000000",
          #         price: "0.034014000000000000",
          #         'created-at':  1545836976871,
          #         type: "sell-limit",
          #         'field-amount': "0.045000000000000000",  # they have fixed it for filled-amount
          #         'field-cash-amount': "0.001530630000000000",  # they have fixed it for filled-cash-amount
          #         'field-fees': "0.000003061260000000",  # they have fixed it for filled-fees
          #         'finished-at':  1545837948214,
          #         source: "spot-api",
          #         state: "filled",
          #         'canceled-at':  0
          #     }
          #
          #     {
          #         id:  20395337822,
          #         symbol: "ethbtc",
          #         'account-id':  5685075,
          #         amount: "0.001000000000000000",
          #         price: "0.0",
          #         'created-at':  1545831584023,
          #         type: "buy-market",
          #         'field-amount': "0.029100000000000000",  # they have fixed it for filled-amount
          #         'field-cash-amount': "0.000999788700000000",  # they have fixed it for filled-cash-amount
          #         'field-fees': "0.000058200000000000",  # they have fixed it for filled-fees
          #         'finished-at':  1545831584181,
          #         source: "spot-api",
          #         state: "filled",
          #         'canceled-at':  0
          #     }
          #
          # linear swap cross margin createOrder
          #
          #     {
          #         "order_id":924660854912552960,
          #         "order_id_str":"924660854912552960"
          #     }
          #
          # contracts fetchOrder
          #
          #     {
          #         "business_type":"swap",
          #         "contract_type":"swap",
          #         "pair":"BTC-USDT",
          #         "symbol":"BTC",
          #         "contract_code":"BTC-USDT",
          #         "volume":1,
          #         "price":3000,
          #         "order_price_type":"limit",
          #         "order_type":1,
          #         "direction":"buy",
          #         "offset":"open",
          #         "lever_rate":1,
          #         "order_id":924912513206878210,
          #         "client_order_id":null,
          #         "created_at":1640557927189,
          #         "trade_volume":0,
          #         "trade_turnover":0,
          #         "fee":0,
          #         "trade_avg_price":null,
          #         "margin_frozen":3.000000000000000000,
          #         "profit":0,
          #         "status":3,
          #         "order_source":"api",
          #         "order_id_str":"924912513206878210",
          #         "fee_asset":"USDT",
          #         "liquidation_type":"0",
          #         "canceled_at":0,
          #         "margin_asset":"USDT",
          #         "margin_account":"USDT",
          #         "margin_mode":"cross",
          #         "is_tpsl":0,
          #         "real_profit":0
          #     }
          #
          # contracts fetchOrder detailed
          #
          #     {
          #         "status": "ok",
          #         "data": {
          #             "symbol": "BTC",
          #             "contract_code": "BTC-USDT",
          #             "instrument_price": 0,
          #             "final_interest": 0,
          #             "adjust_value": 0,
          #             "lever_rate": 10,
          #             "direction": "sell",
          #             "offset": "open",
          #             "volume": 1.000000000000000000,
          #             "price": 13059.800000000000000000,
          #             "created_at": 1603703614712,
          #             "canceled_at": 0,
          #             "order_source": "api",
          #             "order_price_type": "opponent",
          #             "margin_frozen": 0,
          #             "profit": 0,
          #             "trades": [
          #                 {
          #                     "trade_id": 131560927,
          #                     "trade_price": 13059.800000000000000000,
          #                     "trade_volume": 1.000000000000000000,
          #                     "trade_turnover": 13.059800000000000000,
          #                     "trade_fee": -0.005223920000000000,
          #                     "created_at": 1603703614715,
          #                     "role": "taker",
          #                     "fee_asset": "USDT",
          #                     "profit": 0,
          #                     "real_profit": 0,
          #                     "id": "131560927-770334322963152896-1"
          #                 }
          #             ],
          #             "total_page": 1,
          #             "current_page": 1,
          #             "total_size": 1,
          #             "liquidation_type": "0",
          #             "fee_asset": "USDT",
          #             "fee": -0.005223920000000000,
          #             "order_id": 770334322963152896,
          #             "order_id_str": "770334322963152896",
          #             "client_order_id": 57012021045,
          #             "order_type": "1",
          #             "status": 6,
          #             "trade_avg_price": 13059.800000000000000000,
          #             "trade_turnover": 13.059800000000000000,
          #             "trade_volume": 1.000000000000000000,
          #             "margin_asset": "USDT",
          #             "margin_mode": "isolated",
          #             "margin_account": "BTC-USDT",
          #             "real_profit": 0,
          #             "is_tpsl": 0
          #         },
          #         "ts": 1603703678477
          #     }
          #
          id = self.safe_string_2(order, 'id', 'order_id_str')
          side = self.safe_string(order, 'direction')
          type = self.safe_string(order, 'order_price_type')
          if 'type' in order:
              orderType = order['type'].split('-')
              side = orderType[0]
              type = orderType[1]
          status = self.parse_order_status(self.safe_string_2(order, 'state', 'status'))
          marketId = self.safe_string_2(order, 'contract_code', 'symbol')
          market = self.safe_market(marketId, market)
          symbol = self.safe_symbol(marketId, market)
          timestamp = self.safe_integer_2(order, 'created_at', 'created-at')
          clientOrderId = self.safe_string_2(order, 'client_order_id', 'client-order-id')
          amount = self.safe_string_2(order, 'volume', 'amount')
          filled = self.safe_string_2(order, 'filled-amount', 'field-amount')  # typo in their API, filled amount
          filled = self.safe_string(order, 'trade_volume', filled)
          price = self.safe_string(order, 'price')
          cost = self.safe_string_2(order, 'filled-cash-amount', 'field-cash-amount')  # same typo
          cost = self.safe_string(order, 'trade_turnover', cost)
          feeCost = self.safe_string_2(order, 'filled-fees', 'field-fees')  # typo in their API, filled feeSide
          feeCost = self.safe_string(order, 'fee', feeCost)
          fee = None
          if feeCost is not None:
              feeCurrency = None
              feeCurrencyId = self.safe_string(order, 'fee_asset')
              if feeCurrencyId is not None:
                  feeCurrency = self.safe_currency_code(feeCurrencyId)
              else:
                  if market is not None:
                      feeCurrency = market['quote'] if (side == 'sell') else market['base']
              fee = {
                  'cost': feeCost,
                  'currency': feeCurrency,
              }
          stopPrice = self.safe_string(order, 'stop-price')
          average = self.safe_string(order, 'trade_avg_price')
          trades = self.safe_value(order, 'trades')
          return self.safe_order({
              'info': order,
              'id': id,
              'clientOrderId': clientOrderId,
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
              'lastTradeTimestamp': None,
              'symbol': symbol,
              'type': type,
              'timeInForce': None,
              'postOnly': None,
              'side': side,
              'price': price,
              'stopPrice': stopPrice,
              'average': average,
              'cost': cost,
              'amount': amount,
              'filled': filled,
              'remaining': None,
              'status': status,
              'fee': fee,
              'trades': trades,
          }, market)
  
      async def create_order(self, symbol, type, side, amount, price=None, params={}):
          await self.load_markets()
          market = self.market(symbol)
          marketType, query = self.handle_market_type_and_params('createOrder', market, params)
          method = self.get_supported_mapping(marketType, {
              'spot': 'createSpotOrder',
              'swap': 'createContractOrder',
              'future': 'createContractOrder',
          })
          if method is None:
              raise NotSupported(self.id + ' createOrder does not support ' + marketType + ' markets yet')
          return await getattr(self, method)(symbol, type, side, amount, price, query)
  
      async def create_spot_order(self, symbol, type, side, amount, price=None, params={}):
          await self.load_markets()
          await self.load_accounts()
          market = self.market(symbol)
          accountId = await self.fetch_account_id_by_type(market['type'])
          request = {
              # spot -----------------------------------------------------------
              'account-id': accountId,
              'symbol': market['id'],
              # 'type': side + '-' + type,  # buy-market, sell-market, buy-limit, sell-limit, buy-ioc, sell-ioc, buy-limit-maker, sell-limit-maker, buy-stop-limit, sell-stop-limit, buy-limit-fok, sell-limit-fok, buy-stop-limit-fok, sell-stop-limit-fok
              # 'amount': self.amount_to_precision(symbol, amount),  # for buy market orders it's the order cost
              # 'price': self.price_to_precision(symbol, price),
              # 'source': 'spot-api',  # optional, spot-api, margin-api = isolated margin, super-margin-api = cross margin, c2c-margin-api
              # 'client-order-id': clientOrderId,  # optional, max 64 chars, must be unique within 8 hours
              # 'stop-price': self.price_to_precision(symbol, stopPrice),  # trigger price for stop limit orders
              # 'operator': 'gte',  # gte, lte, trigger price condition
          }
          orderType = type.replace('buy-', '')
          orderType = orderType.replace('sell-', '')
          options = self.safe_value(self.options, market['type'], {})
          stopPrice = self.safe_string_2(params, 'stopPrice', 'stop-price')
          if stopPrice is None:
              stopOrderTypes = self.safe_value(options, 'stopOrderTypes', {})
              if orderType in stopOrderTypes:
                  raise ArgumentsRequired(self.id + 'createOrder() requires a stopPrice or a stop-price parameter for a stop order')
          else:
              stopOperator = self.safe_string(params, 'operator')
              if stopOperator is None:
                  raise ArgumentsRequired(self.id + ' createOrder() requires an operator parameter "gte" or "lte" for a stop order')
              params = self.omit(params, ['stopPrice', 'stop-price'])
              request['stop-price'] = self.price_to_precision(symbol, stopPrice)
              request['operator'] = stopOperator
              if (orderType == 'limit') or (orderType == 'limit-fok'):
                  orderType = 'stop-' + orderType
              elif (orderType != 'stop-limit') and (orderType != 'stop-limit-fok'):
                  raise NotSupported(self.id + 'createOrder() does not support ' + type + ' orders')
          postOnly = self.safe_value(params, 'postOnly', False)
          if postOnly:
              orderType = 'limit-maker'
          request['type'] = side + '-' + orderType
          clientOrderId = self.safe_string_2(params, 'clientOrderId', 'client-order-id')  # must be 64 chars max and unique within 24 hours
          if clientOrderId is None:
              broker = self.safe_value(self.options, 'broker', {})
              brokerId = self.safe_string(broker, 'id')
              request['client-order-id'] = brokerId + self.uuid()
          else:
              request['client-order-id'] = clientOrderId
          params = self.omit(params, ['clientOrderId', 'client-order-id', 'postOnly'])
          if (orderType == 'market') and (side == 'buy'):
              if self.options['createMarketBuyOrderRequiresPrice']:
                  if price is None:
                      raise InvalidOrder(self.id + " market buy order requires price argument to calculate cost(total amount of quote currency to spend for buying, amount * price). To switch off self warning exception and specify cost in the amount argument, set .options['createMarketBuyOrderRequiresPrice'] = False. Make sure you know what you're doing.")
                  else:
                      # despite that cost = amount * price is in quote currency and should have quote precision
                      # the exchange API requires the cost supplied in 'amount' to be of base precision
                      # more about it here:
                      # https://github.com/ccxt/ccxt/pull/4395
                      # https://github.com/ccxt/ccxt/issues/7611
                      # we use amountToPrecision here because the exchange requires cost in base precision
                      request['amount'] = self.cost_to_precision(symbol, float(amount) * float(price))
              else:
                  request['amount'] = self.cost_to_precision(symbol, amount)
          else:
              request['amount'] = self.amount_to_precision(symbol, amount)
          limitOrderTypes = self.safe_value(options, 'limitOrderTypes', {})
          if orderType in limitOrderTypes:
              request['price'] = self.price_to_precision(symbol, price)
          response = await self.spotPrivatePostV1OrderOrdersPlace(self.extend(request, params))
          #
          # spot
          #
          #     {"status":"ok","data":"438398393065481"}
          #
          id = self.safe_string(response, 'data')
          return {
              'info': response,
              'id': id,
              'timestamp': None,
              'datetime': None,
              'lastTradeTimestamp': None,
              'status': None,
              'symbol': None,
              'type': None,
              'side': None,
              'price': None,
              'amount': None,
              'filled': None,
              'remaining': None,
              'cost': None,
              'trades': None,
              'fee': None,
              'clientOrderId': None,
              'average': None,
          }
  
      async def create_contract_order(self, symbol, type, side, amount, price=None, params={}):
          offset = self.safe_string(params, 'offset')
          if offset is None:
              raise ArgumentsRequired(self.id + ' createOrder() requires a string offset parameter for contract orders, open or close')
          stopPrice = self.safe_string(params, 'stopPrice')
          if stopPrice is not None:
              raise NotSupported(self.id + ' createOrder() supports tp_trigger_price + tp_order_price for take profit orders and/or sl_trigger_price + sl_order price for stop loss orders, stop orders are supported only with open long orders and open short orders')
          market = self.market(symbol)
          request = {
              # 'symbol': 'BTC',  # optional, case-insenstive, both uppercase and lowercase are supported, "BTC", "ETH", ...
              # 'contract_type': 'this_week',  # optional, self_week, next_week, quarter, next_quarter
              'contract_code': market['id'],  # optional BTC180914
              # 'client_order_id': clientOrderId,  # optional, must be less than 9223372036854775807
              # 'price': self.price_to_precision(symbol, price),  # optional
              'volume': self.amount_to_precision(symbol, amount),
              'direction': side,  # buy, sell
              'offset': offset,  # open, close
              #
              #     direction buy, offset open = open long
              #     direction sell, offset close = close long
              #     direction sell, offset open = open short
              #     direction buy, offset close = close short
              #
              'lever_rate': 1,  # required, using leverage greater than 20x requires prior approval of high-leverage agreement
              # 'order_price_type': 'limit',  # required
              #
              #     order_price_type can be:
              #
              #     limit
              #     opponent  # BBO
              #     post_only
              #     optimal_5
              #     optimal_10
              #     optimal_20
              #     ioc
              #     fok
              #     opponent_ioc  # IOC order using the BBO price
              #     optimal_5_ioc
              #     optimal_10_ioc
              #     optimal_20_ioc
              #     opponent_fok  # FOR order using the BBO price
              #     optimal_5_fok
              #     optimal_10_fok
              #     optimal_20_fok
              #
              # 'tp_trigger_price': self.price_to_precision(symbol, triggerPrice),
              # 'tp_order_price': self.price_to_precision(symbol, price),
              # 'tp_order_price_type': 'limit',  # limit，optimal_5，optimal_10，optimal_20
              # 'sl_trigger_price': self.price_to_precision(symbol, stopLossPrice),
              # 'sl_order_price': self.price_to_precision(symbol, price),
              # 'sl_order_price_type': 'limit',  # limit，optimal_5，optimal_10，optimal_20
          }
          stopLossOrderPrice = self.safe_string(params, 'sl_order_price')
          stopLossTriggerPrice = self.safe_string(params, 'sl_trigger_price')
          takeProfitOrderPrice = self.safe_string(params, 'tp_order_price')
          takeProfitTriggerPrice = self.safe_string(params, 'tp_trigger_price')
          isOpenOrder = (offset == 'open')
          isStopOrder = False
          if stopLossTriggerPrice is not None:
              request['sl_trigger_price'] = self.price_to_precision(symbol, stopLossTriggerPrice)
              isStopOrder = True
              if price is not None:
                  request['sl_order_price'] = self.price_to_precision(symbol, price)
          if stopLossOrderPrice is not None:
              request['sl_order_price'] = self.price_to_precision(symbol, stopLossOrderPrice)
              isStopOrder = True
          if takeProfitTriggerPrice is not None:
              request['tp_trigger_price'] = self.price_to_precision(symbol, takeProfitTriggerPrice)
              isStopOrder = True
              if price is not None:
                  request['tp_order_price'] = self.price_to_precision(symbol, price)
          if takeProfitOrderPrice is not None:
              request['tp_order_price'] = self.price_to_precision(symbol, takeProfitOrderPrice)
              isStopOrder = True
          if isStopOrder and not isOpenOrder:
              raise NotSupported(self.id + ' createOrder() supports tp_trigger_price + tp_order_price for take profit orders and/or sl_trigger_price + sl_order price for stop loss orders, stop orders are supported only with open long orders and open short orders')
          params = self.omit(params, ['sl_order_price', 'sl_trigger_price', 'tp_order_price', 'tp_trigger_price'])
          postOnly = self.safe_value(params, 'postOnly', False)
          if postOnly:
              type = 'post_only'
          if type == 'limit' or type == 'ioc' or type == 'fok' or type == 'post_only':
              request['price'] = self.price_to_precision(symbol, price)
          request['order_price_type'] = type
          clientOrderId = self.safe_string_2(params, 'clientOrderId', 'client_order_id')  # must be 64 chars max and unique within 24 hours
          if clientOrderId is None:
              broker = self.safe_value(self.options, 'broker', {})
              brokerId = self.safe_string(broker, 'id')
              request['client_order_id'] = brokerId + self.uuid()
          else:
              request['client_order_id'] = clientOrderId
          if clientOrderId is not None:
              request['client_order_id'] = clientOrderId
              params = self.omit(params, ['clientOrderId', 'client_order_id'])
          method = None
          if market['linear']:
              defaultMargin = 'cross' if market['future'] else 'isolated'
              marginType = self.safe_string_2(self.options, 'defaultMarginType', 'marginType', defaultMargin)
              if marginType == 'isolated':
                  method = 'contractPrivatePostLinearSwapApiV1SwapOrder'
              elif marginType == 'cross':
                  method = 'contractPrivatePostLinearSwapApiV1SwapCrossOrder'
          elif market['inverse']:
              if market['swap']:
                  method = 'contractPrivatePostSwapApiV1SwapOrder'
              elif market['future']:
                  method = 'contractPrivatePostApiV1ContractOrder'
          response = await getattr(self, method)(self.extend(request, params))
          #
          # linear swap cross margin
          #
          #     {
          #         "status":"ok",
          #         "data":{
          #             "order_id":924660854912552960,
          #             "order_id_str":"924660854912552960"
          #         },
          #         "ts":1640497927185
          #     }
          #
          data = self.safe_value(response, 'data', {})
          return self.parse_order(data, market)
  
      async def cancel_order(self, id, symbol=None, params={}):
          await self.load_markets()
          marketType = None
          marketType, params = self.handle_market_type_and_params('cancelOrder', None, params)
          request = {
              # spot -----------------------------------------------------------
              # 'order-id': 'id',
              # 'symbol': market['id'],
              # 'client-order-id': clientOrderId,
              # contracts ------------------------------------------------------
              # 'order_id': id,
              # 'client_order_id': clientOrderId,
              # 'contract_code': market['id'],
              # 'pair': 'BTC-USDT',
              # 'contract_type': 'this_week',  # swap, self_week, next_week, quarter, next_ quarter
          }
          method = None
          market = None
          if marketType == 'spot':
              clientOrderId = self.safe_string_2(params, 'client-order-id', 'clientOrderId')
              method = 'spotPrivatePostV1OrderOrdersOrderIdSubmitcancel'
              if clientOrderId is None:
                  request['order-id'] = id
              else:
                  request['client-order-id'] = clientOrderId
                  method = 'spotPrivatePostV1OrderOrdersSubmitCancelClientOrder'
                  params = self.omit(params, ['client-order-id', 'clientOrderId'])
          else:
              if symbol is None:
                  raise ArgumentsRequired(self.id + ' cancelOrder() requires a symbol for ' + marketType + ' orders')
              market = self.market(symbol)
              request['contract_code'] = market['id']
              if market['linear']:
                  defaultMargin = 'cross' if market['future'] else 'isolated'
                  marginType = self.safe_string_2(self.options, 'defaultMarginType', 'marginType', defaultMargin)
                  if marginType == 'isolated':
                      method = 'contractPrivatePostLinearSwapApiV1SwapCancel'
                  elif marginType == 'cross':
                      method = 'contractPrivatePostLinearSwapApiV1SwapCrossCancel'
              elif market['inverse']:
                  if market['future']:
                      method = 'contractPrivatePostApiV1ContractCancel'
                      request['symbol'] = market['settleId']
                  elif market['swap']:
                      method = 'contractPrivatePostSwapApiV1SwapCancel'
              else:
                  raise NotSupported(self.id + ' cancelOrder() does not support ' + marketType + ' markets')
              clientOrderId = self.safe_string_2(params, 'client_order_id', 'clientOrderId')
              if clientOrderId is None:
                  request['order_id'] = id
              else:
                  request['client_order_id'] = clientOrderId
                  params = self.omit(params, ['client_order_id', 'clientOrderId'])
          response = await getattr(self, method)(self.extend(request, params))
          #
          # spot
          #
          #     {
          #         'status': 'ok',
          #         'data': '10138899000',
          #     }
          #
          # linear swap cross margin
          #
          #     {
          #         "status":"ok",
          #         "data":{
          #             "errors":[],
          #             "successes":"924660854912552960"
          #         },
          #         "ts":1640504486089
          #     }
          #
          return self.extend(self.parse_order(response, market), {
              'id': id,
              'status': 'canceled',
          })
  
      async def cancel_orders(self, ids, symbol=None, params={}):
          await self.load_markets()
          marketType = None
          marketType, params = self.handle_market_type_and_params('cancelOrder', None, params)
          request = {
              # spot -----------------------------------------------------------
              # 'order-ids': ids.jsoin(','),  # max 50
              # 'client-order-ids': ','.join(ids),  # max 50
              # contracts ------------------------------------------------------
              # 'order_id': id,  # comma separated, max 10
              # 'client_order_id': clientOrderId,  # comma separated, max 10
              # 'contract_code': market['id'],
              # 'symbol': market['settleId'],
          }
          method = None
          if marketType == 'spot':
              clientOrderIds = self.safe_value_2(params, 'client-order-id', 'clientOrderId')
              clientOrderIds = self.safe_value_2(params, 'client-order-ids', 'clientOrderIds', clientOrderIds)
              if clientOrderIds is None:
                  if isinstance(clientOrderIds, basestring):
                      request['order-ids'] = ids
                  else:
                      request['order-ids'] = ','.join(ids)
              else:
                  if isinstance(clientOrderIds, basestring):
                      request['client-order-ids'] = clientOrderIds
                  else:
                      request['client-order-ids'] = ','.join(clientOrderIds)
                  params = self.omit(params, ['client-order-id', 'client-order-ids', 'clientOrderId', 'clientOrderIds'])
              method = 'spotPrivatePostV1OrderOrdersBatchcancel'
          else:
              if symbol is None:
                  raise ArgumentsRequired(self.id + ' cancelOrders() requires a symbol for ' + marketType + ' orders')
              market = self.market(symbol)
              request['contract_code'] = market['id']
              if market['linear']:
                  defaultMargin = 'cross' if market['future'] else 'isolated'
                  marginType = self.safe_string_2(self.options, 'defaultMarginType', 'marginType', defaultMargin)
                  if marginType == 'isolated':
                      method = 'contractPrivatePostLinearSwapApiV1SwapCancel'
                  elif marginType == 'cross':
                      method = 'contractPrivatePostLinearSwapApiV1SwapCrossCancel'
              elif market['inverse']:
                  if market['future']:
                      method = 'contractPrivatePostApiV1ContractCancel'
                      request['symbol'] = market['settleId']
                  elif market['swap']:
                      method = 'contractPrivatePostSwapApiV1SwapCancel'
                  else:
                      raise NotSupported(self.id + ' cancelOrders() does not support ' + marketType + ' markets')
              clientOrderIds = self.safe_string_2(params, 'client_order_id', 'clientOrderId')
              clientOrderIds = self.safe_string_2(params, 'client_order_ids', 'clientOrderIds', clientOrderIds)
              if clientOrderIds is None:
                  request['order_id'] = ','.join(ids)
              else:
                  request['client_order_id'] = clientOrderIds
                  params = self.omit(params, ['client_order_id', 'client_order_ids', 'clientOrderId', 'clientOrderIds'])
          response = await getattr(self, method)(self.extend(request, params))
          #
          # spot
          #
          #     {
          #         "status": "ok",
          #         "data": {
          #             "success": [
          #                 "5983466"
          #             ],
          #             "failed": [
          #                 {
          #                     "err-msg": "Incorrect order state",
          #                     "order-state": 7,
          #                     "order-id": "",
          #                     "err-code": "order-orderstate-error",
          #                     "client-order-id": "first"
          #                 },
          #                 {
          #                     "err-msg": "Incorrect order state",
          #                     "order-state": 7,
          #                     "order-id": "",
          #                     "err-code": "order-orderstate-error",
          #                     "client-order-id": "second"
          #                 },
          #                 {
          #                     "err-msg": "The record is not found.",
          #                     "order-id": "",
          #                     "err-code": "base-not-found",
          #                     "client-order-id": "third"
          #                 }
          #             ]
          #         }
          #     }
          #
          # contracts
          #
          #     {
          #         "status": "ok",
          #         "data": {
          #             "errors": [
          #                 {
          #                     "order_id": "769206471845261312",
          #                     "err_code": 1061,
          #                     "err_msg": "This order doesnt exist."
          #                 }
          #             ],
          #             "successes": "773120304138219520"
          #         },
          #         "ts": 1604367997451
          #     }
          #
          return response
  
      async def cancel_all_orders(self, symbol=None, params={}):
          await self.load_markets()
          marketType = None
          marketType, params = self.handle_market_type_and_params('cancelOrder', None, params)
          request = {
              # spot -----------------------------------------------------------
              # 'account-id': account['id'],
              # 'symbol': market['id'],  # a list of comma-separated symbols, all symbols by default
              # 'types' 'string', buy-market, sell-market, buy-limit, sell-limit, buy-ioc, sell-ioc, buy-stop-limit, sell-stop-limit, buy-limit-fok, sell-limit-fok, buy-stop-limit-fok, sell-stop-limit-fok
              # 'side': 'buy',  # or 'sell'
              # 'size': 100,  # the number of orders to cancel 1-100
              # contract -------------------------------------------------------
              # 'symbol': market['settleId'],  # required
              # 'contract_code': market['id'],
              # 'contract_type': 'this_week',  # swap, self_week, next_week, quarter, next_ quarter
              # 'direction': 'buy':  # buy, sell
              # 'offset': 'open',  # open, close
          }
          market = None
          method = None
          if marketType == 'spot':
              if symbol is not None:
                  market = self.market(symbol)
                  request['symbol'] = market['id']
              method = 'spotPrivatePostV1OrderOrdersBatchCancelOpenOrders'
          else:
              if symbol is None:
                  raise ArgumentsRequired(self.id + ' cancelOrders() requires a symbol for ' + marketType + ' orders')
              market = self.market(symbol)
              request['contract_code'] = market['id']
              if market['linear']:
                  defaultMargin = 'cross' if market['future'] else 'isolated'
                  marginType = self.safe_string_2(self.options, 'defaultMarginType', 'marginType', defaultMargin)
                  if marginType == 'isolated':
                      method = 'contractPrivatePostLinearSwapApiV1SwapCancelallall'
                  elif marginType == 'cross':
                      method = 'contractPrivatePostLinearSwapApiV1SwapCrossCancelall'
              elif market['inverse']:
                  if marketType == 'future':
                      method = 'contractPrivatePostApiV1ContractCancelall'
                      request['symbol'] = market['settleId']
                  elif marketType == 'swap':
                      method = 'contractPrivatePostSwapApiV1SwapCancelall'
                  else:
                      raise NotSupported(self.id + ' cancelOrders() does not support ' + marketType + ' markets')
          response = await getattr(self, method)(self.extend(request, params))
          #
          #     {
          #         code: 200,
          #         data: {
          #             "success-count": 2,
          #             "failed-count": 0,
          #             "next-id": 5454600
          #         }
          #     }
          #
          return response
  
      def currency_to_precision(self, currency, fee):
          return self.decimal_to_precision(fee, 0, self.currencies[currency]['precision'])
  
      def safe_network(self, networkId):
          lastCharacterIndex = len(networkId) - 1
          lastCharacter = networkId[lastCharacterIndex]
          if lastCharacter == '1':
              networkId = networkId[0:lastCharacterIndex]
          networksById = {}
          return self.safe_string(networksById, networkId, networkId)
  
      def parse_deposit_address(self, depositAddress, currency=None):
          #
          #     {
          #         currency: "usdt",
          #         address: "0xf7292eb9ba7bc50358e27f0e025a4d225a64127b",
          #         addressTag: "",
          #         chain: "usdterc20",  # trc20usdt, hrc20usdt, usdt, algousdt
          #     }
          #
          address = self.safe_string(depositAddress, 'address')
          tag = self.safe_string(depositAddress, 'addressTag')
          if tag == '':
              tag = None
          currencyId = self.safe_string(depositAddress, 'currency')
          currency = self.safe_currency(currencyId, currency)
          code = self.safe_currency_code(currencyId, currency)
          networkId = self.safe_string(depositAddress, 'chain')
          networks = self.safe_value(currency, 'networks', {})
          networksById = self.index_by(networks, 'id')
          networkValue = self.safe_value(networksById, networkId, networkId)
          network = self.safe_string(networkValue, 'network')
          note = self.safe_string(depositAddress, 'note')
          self.check_address(address)
          return {
              'currency': code,
              'address': address,
              'tag': tag,
              'network': network,
              'note': note,
              'info': depositAddress,
          }
  
      async def fetch_deposit_addresses_by_network(self, code, params={}):
          await self.load_markets()
          currency = self.currency(code)
          request = {
              'currency': currency['id'],
          }
          response = await self.spotPrivateGetV2AccountDepositAddress(self.extend(request, params))
          #
          #     {
          #         code: 200,
          #         data: [
          #             {
          #                 currency: "eth",
          #                 address: "0xf7292eb9ba7bc50358e27f0e025a4d225a64127b",
          #                 addressTag: "",
          #                 chain: "eth"
          #             }
          #         ]
          #     }
          #
          data = self.safe_value(response, 'data', [])
          parsed = self.parse_deposit_addresses(data, [code], False)
          return self.index_by(parsed, 'network')
  
      async def fetch_deposit_address(self, code, params={}):
          rawNetwork = self.safe_string_upper(params, 'network')
          networks = self.safe_value(self.options, 'networks', {})
          network = self.safe_string_upper(networks, rawNetwork, rawNetwork)
          params = self.omit(params, 'network')
          response = await self.fetch_deposit_addresses_by_network(code, params)
          result = None
          if network is None:
              result = self.safe_value(response, code)
              if result is None:
                  alias = self.safe_string(networks, code, code)
                  result = self.safe_value(response, alias)
                  if result is None:
                      defaultNetwork = self.safe_string(self.options, 'defaultNetwork', 'ERC20')
                      result = self.safe_value(response, defaultNetwork)
                      if result is None:
                          values = list(response.values())
                          result = self.safe_value(values, 0)
                          if result is None:
                              raise InvalidAddress(self.id + ' fetchDepositAddress() cannot find deposit address for ' + code)
              return result
          result = self.safe_value(response, network)
          if result is None:
              raise InvalidAddress(self.id + ' fetchDepositAddress() cannot find ' + network + ' deposit address for ' + code)
          return result
  
      async def fetch_withdraw_addresses_by_network(self, code, params={}):
          await self.load_markets()
          currency = self.currency(code)
          request = {
              'currency': currency['id'],
          }
          response = await self.spotPrivateGetV2AccountWithdrawAddress(self.extend(request, params))
          #
          #     {
          #         code: 200,
          #         data: [
          #             {
          #                 currency: "eth",
          #                 chain: "eth"
          #                 note: "Binance - TRC20",
          #                 addressTag: "",
          #                 address: "0xf7292eb9ba7bc50358e27f0e025a4d225a64127b",
          #             }
          #         ]
          #     }
          #
          data = self.safe_value(response, 'data', [])
          parsed = self.parse_deposit_addresses(data, [code], False)
          return self.index_by(parsed, 'network')
  
      async def fetch_withdraw_address(self, code, params={}):
          rawNetwork = self.safe_string_upper(params, 'network')
          networks = self.safe_value(self.options, 'networks', {})
          network = self.safe_string_upper(networks, rawNetwork, rawNetwork)
          params = self.omit(params, 'network')
          response = await self.fetch_withdraw_addresses_by_network(code, params)
          result = None
          if network is None:
              result = self.safe_value(response, code)
              if result is None:
                  alias = self.safe_string(networks, code, code)
                  result = self.safe_value(response, alias)
                  if result is None:
                      defaultNetwork = self.safe_string(self.options, 'defaultNetwork', 'ERC20')
                      result = self.safe_value(response, defaultNetwork)
                      if result is None:
                          values = list(response.values())
                          result = self.safe_value(values, 0)
                          if result is None:
                              raise InvalidAddress(self.id + ' fetchWithdrawAddress() cannot find withdraw address for ' + code)
              return result
          result = self.safe_value(response, network)
          if result is None:
              raise InvalidAddress(self.id + ' fetchWithdrawAddress() cannot find ' + network + ' withdraw address for ' + code)
          return result
  
      async def fetch_deposits(self, code=None, since=None, limit=None, params={}):
          if limit is None or limit > 100:
              limit = 100
          await self.load_markets()
          currency = None
          if code is not None:
              currency = self.currency(code)
          request = {
              'type': 'deposit',
              'from': 0,  # From 'id' ... if you want to get results after a particular transaction id, pass the id in params.from
          }
          if currency is not None:
              request['currency'] = currency['id']
          if limit is not None:
              request['size'] = limit  # max 100
          response = await self.spotPrivateGetV1QueryDepositWithdraw(self.extend(request, params))
          # return response
          return self.parse_transactions(response['data'], currency, since, limit)
  
      async def fetch_withdrawals(self, code=None, since=None, limit=None, params={}):
          if limit is None or limit > 100:
              limit = 100
          await self.load_markets()
          currency = None
          if code is not None:
              currency = self.currency(code)
          request = {
              'type': 'withdraw',
              'from': 0,  # From 'id' ... if you want to get results after a particular transaction id, pass the id in params.from
          }
          if currency is not None:
              request['currency'] = currency['id']
          if limit is not None:
              request['size'] = limit  # max 100
          response = await self.spotPrivateGetV1QueryDepositWithdraw(self.extend(request, params))
          # return response
          return self.parse_transactions(response['data'], currency, since, limit)
  
      def parse_transaction(self, transaction, currency=None):
          #
          # fetchDeposits
          #
          #     {
          #         'id': 8211029,
          #         'type': 'deposit',
          #         'currency': 'eth',
          #         'chain': 'eth',
          #         'tx-hash': 'bd315....',
          #         'amount': 0.81162421,
          #         'address': '4b8b....',
          #         'address-tag': '',
          #         'fee': 0,
          #         'state': 'safe',
          #         'created-at': 1542180380965,
          #         'updated-at': 1542180788077
          #     }
          #
          # fetchWithdrawals
          #
          #     {
          #         'id': 6908275,
          #         'type': 'withdraw',
          #         'currency': 'btc',
          #         'chain': 'btc',
          #         'tx-hash': 'c1a1a....',
          #         'amount': 0.80257005,
          #         'address': '1QR....',
          #         'address-tag': '',
          #         'fee': 0.0005,
          #         'state': 'confirmed',
          #         'created-at': 1552107295685,
          #         'updated-at': 1552108032859
          #     }
          #
          timestamp = self.safe_integer(transaction, 'created-at')
          updated = self.safe_integer(transaction, 'updated-at')
          code = self.safe_currency_code(self.safe_string(transaction, 'currency'))
          type = self.safe_string(transaction, 'type')
          if type == 'withdraw':
              type = 'withdrawal'
          status = self.parse_transaction_status(self.safe_string(transaction, 'state'))
          tag = self.safe_string(transaction, 'address-tag')
          feeCost = self.safe_number(transaction, 'fee')
          if feeCost is not None:
              feeCost = abs(feeCost)
          address = self.safe_string(transaction, 'address')
          network = self.safe_string_upper(transaction, 'chain')
          return {
              'info': transaction,
              'id': self.safe_string(transaction, 'id'),
              'txid': self.safe_string(transaction, 'tx-hash'),
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
              'network': network,
              'address': address,
              'addressTo': None,
              'addressFrom': None,
              'tag': tag,
              'tagTo': None,
              'tagFrom': None,
              'type': type,
              'amount': self.safe_number(transaction, 'amount'),
              'currency': code,
              'status': status,
              'updated': updated,
              'fee': {
                  'currency': code,
                  'cost': feeCost,
                  'rate': None,
              },
          }
  
      def parse_transaction_status(self, status):
          statuses = {
              # deposit statuses
              'unknown': 'failed',
              'confirming': 'pending',
              'confirmed': 'ok',
              'safe': 'ok',
              'orphan': 'failed',
              # withdrawal statuses
              'submitted': 'pending',
              'canceled': 'canceled',
              'reexamine': 'pending',
              'reject': 'failed',
              'pass': 'pending',
              'wallet-reject': 'failed',
              # 'confirmed': 'ok',  # present in deposit statuses
              'confirm-error': 'failed',
              'repealed': 'failed',
              'wallet-transfer': 'pending',
              'pre-transfer': 'pending',
          }
          return self.safe_string(statuses, status, status)
  
      async def withdraw(self, code, amount, address, tag=None, params={}):
          tag, params = self.handle_withdraw_tag_and_params(tag, params)
          await self.load_markets()
          self.check_address(address)
          currency = self.currency(code)
          request = {
              'address': address,  # only supports existing addresses in your withdraw address list
              'amount': amount,
              'currency': currency['id'].lower(),
          }
          if tag is not None:
              request['addr-tag'] = tag  # only for XRP?
          networks = self.safe_value(self.options, 'networks', {})
          network = self.safe_string_upper(params, 'network')  # self line allows the user to specify either ERC20 or ETH
          network = self.safe_string_lower(networks, network, network)  # handle ETH>ERC20 alias
          if network is not None:
              # possible chains - usdterc20, trc20usdt, hrc20usdt, usdt, algousdt
              if network == 'erc20':
                  request['chain'] = currency['id'] + network
              else:
                  request['chain'] = network + currency['id']
              params = self.omit(params, 'network')
          response = await self.spotPrivatePostV1DwWithdrawApiCreate(self.extend(request, params))
          id = self.safe_string(response, 'data')
          return {
              'info': response,
              'id': id,
          }
  
      def parse_transfer(self, transfer, currency=None):
          #
          # transfer
          #
          #     {
          #         "data": 12345,
          #         "status": "ok"
          #     }
          #
          id = self.safe_string(transfer, 'data')
          code = self.safe_currency_code(None, currency)
          return {
              'info': transfer,
              'id': id,
              'timestamp': None,
              'datetime': None,
              'currency': code,
              'amount': None,
              'fromAccount': None,
              'toAccount': None,
              'status': None,
          }
  
      async def transfer(self, code, amount, fromAccount, toAccount, params={}):
          await self.load_markets()
          currency = self.currency(code)
          type = self.safe_string(params, 'type')
          if type is None:
              accountsByType = self.safe_value(self.options, 'accountsByType', {})
              fromAccount = fromAccount.lower()  # pro, futures
              toAccount = toAccount.lower()  # pro, futures
              fromId = self.safe_string(accountsByType, fromAccount)
              toId = self.safe_string(accountsByType, toAccount)
              if fromId is None:
                  keys = list(accountsByType.keys())
                  raise ExchangeError(self.id + ' fromAccount must be one of ' + ', '.join(keys))
              if toId is None:
                  keys = list(accountsByType.keys())
                  raise ExchangeError(self.id + ' toAccount must be one of ' + ', '.join(keys))
              type = fromAccount + '-to-' + toAccount
          request = {
              'currency': currency['id'],
              'amount': float(self.currency_to_precision(code, amount)),
              'type': type,
          }
          response = await self.spotPrivatePostFuturesTransfer(self.extend(request, params))
          #
          #     {
          #         "data": 12345,
          #         "status": "ok"
          #     }
          #
          transfer = self.parse_transfer(response, currency)
          return self.extend(transfer, {
              'amount': amount,
              'currency': code,
              'fromAccount': fromAccount,
              'toAccount': toAccount,
          })
  
      async def fetch_borrow_rates_per_symbol(self, params={}):
          await self.load_markets()
          response = await self.spotPrivateGetV1MarginLoanInfo(params)
          # {
          #     "status": "ok",
          #     "data": [
          #         {
          #             "symbol": "1inchusdt",
          #             "currencies": [
          #                 {
          #                     "currency": "1inch",
          #                     "interest-rate": "0.00098",
          #                     "min-loan-amt": "90.000000000000000000",
          #                     "max-loan-amt": "1000.000000000000000000",
          #                     "loanable-amt": "0.0",
          #                     "actual-rate": "0.00098"
          #                 },
          #                 {
          #                     "currency": "usdt",
          #                     "interest-rate": "0.00098",
          #                     "min-loan-amt": "100.000000000000000000",
          #                     "max-loan-amt": "1000.000000000000000000",
          #                     "loanable-amt": "0.0",
          #                     "actual-rate": "0.00098"
          #                 }
          #             ]
          #         },
          #         ...
          #     ]
          # }
          timestamp = self.milliseconds()
          data = self.safe_value(response, 'data')
          rates = {
              'info': response,
          }
          for i in range(0, len(data)):
              rate = data[i]
              currencies = self.safe_value(rate, 'currencies')
              symbolRates = {}
              for j in range(0, len(currencies)):
                  currency = currencies[j]
                  currencyId = self.safe_string(currency, 'currency')
                  code = self.safe_currency_code(currencyId, 'currency')
                  symbolRates[code] = {
                      'currency': code,
                      'rate': self.safe_number(currency, 'actual-rate'),
                      'span': 86400000,
                      'timestamp': timestamp,
                      'datetime': self.iso8601(timestamp),
                  }
              market = self.markets_by_id[self.safe_string(rate, 'symbol')]
              symbol = market['symbol']
              rates[symbol] = symbolRates
          return rates
  
      async def fetch_borrow_rates(self, params={}):
          await self.load_markets()
          response = await self.spotPrivateGetV1MarginLoanInfo(params)
          # {
          #     "status": "ok",
          #     "data": [
          #         {
          #             "symbol": "1inchusdt",
          #             "currencies": [
          #                 {
          #                     "currency": "1inch",
          #                     "interest-rate": "0.00098",
          #                     "min-loan-amt": "90.000000000000000000",
          #                     "max-loan-amt": "1000.000000000000000000",
          #                     "loanable-amt": "0.0",
          #                     "actual-rate": "0.00098"
          #                 },
          #                 {
          #                     "currency": "usdt",
          #                     "interest-rate": "0.00098",
          #                     "min-loan-amt": "100.000000000000000000",
          #                     "max-loan-amt": "1000.000000000000000000",
          #                     "loanable-amt": "0.0",
          #                     "actual-rate": "0.00098"
          #                 }
          #             ]
          #         },
          #         ...
          #     ]
          # }
          timestamp = self.milliseconds()
          data = self.safe_value(response, 'data')
          rates = {}
          for i in range(0, len(data)):
              market = data[i]
              currencies = self.safe_value(market, 'currencies')
              for j in range(0, len(currencies)):
                  currency = currencies[j]
                  currencyId = self.safe_string(currency, 'currency')
                  code = self.safe_currency_code(currencyId, 'currency')
                  rates[code] = {
                      'currency': code,
                      'rate': self.safe_number(currency, 'actual-rate'),
                      'span': 86400000,
                      'timestamp': timestamp,
                      'datetime': self.iso8601(timestamp),
                      'info': None,
                  }
          return rates
  
      async def fetch_funding_rate_history(self, symbol=None, since=None, limit=None, params={}):
          #
          # Gets a history of funding rates with their timestamps
          #  (param) symbol: Future currency pair
          #  (param) limit: not used by huobi
          #  (param) since: not used by huobi
          #  (param) params: Object containing more params for the request
          #  return: [{symbol, fundingRate, timestamp, dateTime}]
          #
          if symbol is None:
              raise ArgumentsRequired(self.id + ' fetchFundingRateHistory() requires a symbol argument')
          await self.load_markets()
          market = self.market(symbol)
          request = {
              'contract_code': market['id'],
          }
          method = None
          if market['inverse']:
              method = 'contractPublicGetSwapApiV1SwapHistoricalFundingRate'
          elif market['linear']:
              method = 'contractPublicGetLinearSwapApiV1SwapHistoricalFundingRate'
          else:
              raise NotSupported(self.id + ' fetchFundingRateHistory() supports inverse and linear swaps only')
          response = await getattr(self, method)(self.extend(request, params))
          #
          # {
          #     "status": "ok",
          #     "data": {
          #         "total_page": 62,
          #         "current_page": 1,
          #         "total_size": 1237,
          #         "data": [
          #             {
          #                 "avg_premium_index": "-0.000208064395065541",
          #                 "funding_rate": "0.000100000000000000",
          #                 "realized_rate": "0.000100000000000000",
          #                 "funding_time": "1638921600000",
          #                 "contract_code": "BTC-USDT",
          #                 "symbol": "BTC",
          #                 "fee_asset": "USDT"
          #             },
          #         ]
          #     },
          #     "ts": 1638939294277
          # }
          #
          data = self.safe_value(response, 'data')
          result = self.safe_value(data, 'data')
          rates = []
          for i in range(0, len(result)):
              entry = result[i]
              marketId = self.safe_string(entry, 'contract_code')
              symbol = self.safe_symbol(marketId)
              timestamp = self.safe_string(entry, 'funding_time')
              rates.append({
                  'info': entry,
                  'symbol': symbol,
                  'fundingRate': self.safe_number(entry, 'funding_rate'),
                  'timestamp': timestamp,
                  'datetime': self.iso8601(timestamp),
              })
          sorted = self.sort_by(rates, 'timestamp')
          return self.filter_by_symbol_since_limit(sorted, symbol, since, limit)
  
      def parse_funding_rate(self, fundingRate, market=None):
          #
          # {
          #      "status": "ok",
          #      "data": {
          #         "estimated_rate": "0.000100000000000000",
          #         "funding_rate": "0.000100000000000000",
          #         "contract_code": "BCH-USD",
          #         "symbol": "BCH",
          #         "fee_asset": "BCH",
          #         "funding_time": "1639094400000",
          #         "next_funding_time": "1639123200000"
          #     },
          #     "ts": 1639085854775
          # }
          #
          nextFundingRate = self.safe_number(fundingRate, 'estimated_rate')
          fundingTimestamp = self.safe_integer(fundingRate, 'funding_time')
          nextFundingTimestamp = self.safe_integer(fundingRate, 'next_funding_time')
          marketId = self.safe_string(fundingRate, 'contract_code')
          symbol = self.safe_symbol(marketId, market)
          return {
              'info': fundingRate,
              'symbol': symbol,
              'markPrice': None,
              'indexPrice': None,
              'interestRate': None,
              'estimatedSettlePrice': None,
              'timestamp': None,
              'datetime': None,
              'fundingRate': self.safe_number(fundingRate, 'funding_rate'),
              'fundingTimestamp': fundingTimestamp,
              'fundingDatetime': self.iso8601(fundingTimestamp),
              'nextFundingRate': nextFundingRate,
              'nextFundingTimestamp': nextFundingTimestamp,
              'nextFundingDatetime': self.iso8601(nextFundingTimestamp),
              'previousFundingRate': None,
              'previousFundingTimestamp': None,
              'previousFundingDatetime': None,
          }
  
      async def fetch_funding_rate(self, symbol, params={}):
          await self.load_markets()
          market = self.market(symbol)
          method = None
          if market['inverse']:
              method = 'contractPublicGetSwapApiV1SwapFundingRate'
          elif market['linear']:
              method = 'contractPublicGetLinearSwapApiV1SwapFundingRate'
          else:
              raise NotSupported(self.id + ' fetchFundingRateHistory() supports inverse and linear swaps only')
          request = {
              'contract_code': market['id'],
          }
          response = await getattr(self, method)(self.extend(request, params))
          #
          # {
          #     "status": "ok",
          #     "data": {
          #         "estimated_rate": "0.000100000000000000",
          #         "funding_rate": "0.000100000000000000",
          #         "contract_code": "BTC-USDT",
          #         "symbol": "BTC",
          #         "fee_asset": "USDT",
          #         "funding_time": "1603699200000",
          #         "next_funding_time": "1603728000000"
          #     },
          #     "ts": 1603696494714
          # }
          #
          result = self.safe_value(response, 'data', {})
          return self.parse_funding_rate(result, market)
  
      async def fetch_funding_rates(self, symbols, params={}):
          await self.load_markets()
          options = self.safe_value(self.options, 'fetchFundingRates', {})
          defaultSubType = self.safe_string(self.options, 'defaultSubType', 'inverse')
          subType = self.safe_string(options, 'subType', defaultSubType)
          subType = self.safe_string(params, 'subType', subType)
          request = {
              # 'contract_code': market['id'],
          }
          method = self.get_supported_mapping(subType, {
              'linear': 'contractPublicGetLinearSwapApiV1SwapBatchFundingRate',
              'inverse': 'contractPublicGetSwapApiV1SwapBatchFundingRate',
          })
          params = self.omit(params, 'subType')
          response = await getattr(self, method)(self.extend(request, params))
          #
          #     {
          #         "status": "ok",
          #         "data": [
          #             {
          #                 "estimated_rate": "0.000100000000000000",
          #                 "funding_rate": "0.000100000000000000",
          #                 "contract_code": "MANA-USDT",
          #                 "symbol": "MANA",
          #                 "fee_asset": "USDT",
          #                 "funding_time": "1643356800000",
          #                 "next_funding_time": "1643385600000",
          #                 "trade_partition":"USDT"
          #             },
          #         ],
          #         "ts": 1643346173103
          #     }
          #
          data = self.safe_value(response, 'data', [])
          result = self.parse_funding_rates(data)
          return self.filter_by_array(result, 'symbol', symbols)
  
      def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
          url = '/'
          query = self.omit(params, self.extract_params(path))
          if isinstance(api, basestring):
              # signing implementation for the old endpoints
              if api == 'market':
                  url += api
              elif (api == 'public') or (api == 'private'):
                  url += self.version
              elif (api == 'v2Public') or (api == 'v2Private'):
                  url += 'v2'
              url += '/' + self.implode_params(path, params)
              if api == 'private' or api == 'v2Private':
                  self.check_required_credentials()
                  timestamp = self.ymdhms(self.milliseconds(), 'T')
                  request = {
                      'SignatureMethod': 'HmacSHA256',
                      'SignatureVersion': '2',
                      'AccessKeyId': self.apiKey,
                      'Timestamp': timestamp,
                  }
                  if method != 'POST':
                      request = self.extend(request, query)
                  request = self.keysort(request)
                  auth = self.urlencode(request)
                  # unfortunately, PHP demands double quotes for the escaped newline symbol
                  payload = "\n".join([method, self.hostname, url, auth])  # eslint-disable-line quotes
                  signature = self.hmac(self.encode(payload), self.encode(self.secret), hashlib.sha256, 'base64')
                  auth += '&' + self.urlencode({'Signature': signature})
                  url += '?' + auth
                  if method == 'POST':
                      body = self.json(query)
                      headers = {
                          'Content-Type': 'application/json',
                      }
                  else:
                      headers = {
                          'Content-Type': 'application/x-www-form-urlencoded',
                      }
              else:
                  if query:
                      url += '?' + self.urlencode(query)
              url = self.implode_params(self.urls['api'][api], {
                  'hostname': self.hostname,
              }) + url
          else:
              # signing implementation for the new endpoints
              # type, access = api
              type = self.safe_string(api, 0)
              access = self.safe_string(api, 1)
              url += self.implode_params(path, params)
              hostname = self.safe_string(self.urls['hostnames'], type)
              if access == 'public':
                  if query:
                      url += '?' + self.urlencode(query)
              elif access == 'private':
                  self.check_required_credentials()
                  timestamp = self.ymdhms(self.milliseconds(), 'T')
                  request = {
                      'SignatureMethod': 'HmacSHA256',
                      'SignatureVersion': '2',
                      'AccessKeyId': self.apiKey,
                      'Timestamp': timestamp,
                  }
                  if method != 'POST':
                      request = self.extend(request, query)
                  request = self.keysort(request)
                  auth = self.urlencode(request)
                  # unfortunately, PHP demands double quotes for the escaped newline symbol
                  payload = "\n".join([method, hostname, url, auth])  # eslint-disable-line quotes
                  signature = self.hmac(self.encode(payload), self.encode(self.secret), hashlib.sha256, 'base64')
                  auth += '&' + self.urlencode({'Signature': signature})
                  url += '?' + auth
                  if method == 'POST':
                      body = self.json(query)
                      headers = {
                          'Content-Type': 'application/json',
                      }
                  else:
                      headers = {
                          'Content-Type': 'application/x-www-form-urlencoded',
                      }
              url = self.implode_params(self.urls['api'][type], {
                  'hostname': hostname,
              }) + url
          return {'url': url, 'method': method, 'body': body, 'headers': headers}
  
      def calculate_rate_limiter_cost(self, api, method, path, params, config={}, context={}):
          return self.safe_integer(config, 'cost', 1)
  
      def handle_errors(self, httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody):
          if response is None:
              return  # fallback to default error handler
          if 'status' in response:
              #
              #     {"status":"error","err-code":"order-limitorder-amount-min-error","err-msg":"limit order amount error, min: `0.001`","data":null}
              #
              status = self.safe_string(response, 'status')
              if status == 'error':
                  code = self.safe_string_2(response, 'err-code', 'err_code')
                  feedback = self.id + ' ' + body
                  self.throw_broadly_matched_exception(self.exceptions['broad'], body, feedback)
                  self.throw_exactly_matched_exception(self.exceptions['exact'], code, feedback)
                  message = self.safe_string_2(response, 'err-msg', 'err_msg')
                  self.throw_exactly_matched_exception(self.exceptions['exact'], message, feedback)
                  raise ExchangeError(feedback)
  
      async def fetch_funding_history(self, symbol=None, since=None, limit=None, params={}):
          await self.load_markets()
          market = self.market(symbol)
          marketType, query = self.handle_market_type_and_params('fetchFundingHistory', market, params)
          method = None
          request = {
              'type': '30,31',
          }
          if market['linear']:
              method = 'contractPrivatePostLinearSwapApiV1SwapFinancialRecordExact'
              #
              # {
              #   status: 'ok',
              #   data: {
              #     financial_record: [
              #       {
              #         id: '1320088022',
              #         type: '30',
              #         amount: '0.004732510000000000',
              #         ts: '1641168019321',
              #         contract_code: 'BTC-USDT',
              #         asset: 'USDT',
              #         margin_account: 'BTC-USDT',
              #         face_margin_account: ''
              #       },
              #     ],
              #     remain_size: '0',
              #     next_id: null
              #   },
              #   ts: '1641189898425'
              # }
              defaultMargin = 'cross' if market['future'] else 'isolated'
              marginType = self.safe_string_2(self.options, 'defaultMarginType', 'marginType', defaultMargin)
              if marginType == 'isolated':
                  request['margin_account'] = market['id']
              else:
                  request['margin_account'] = market['quoteId']
          else:
              if marketType == 'swap':
                  method = 'contractPrivatePostSwapApiV1SwapFinancialRecordExact'
                  request['contract_code'] = market['id']
              else:
                  raise ExchangeError(self.id + ' fetchFundingHistory() only makes sense for swap contracts')
              #
              # swap
              #     {
              #       status: 'ok',
              #       data: {
              #         financial_record: [
              #           {
              #             id: '1667436164',
              #             symbol: 'BTC',
              #             type: '30',
              #             amount: '3.9755491985E-8',
              #             ts: '1641168097323',
              #             contract_code: 'BTC-USD'
              #           },
              #         ],
              #         remain_size: '0',
              #         next_id: null
              #       },
              #       ts: '1641190296379'
              #     }
              #
          response = await getattr(self, method)(self.extend(request, query))
          data = self.safe_value(response, 'data', {})
          financialRecord = self.safe_value(data, 'financial_record', [])
          return self.parse_incomes(financialRecord, market, since, limit)
  
      async def set_leverage(self, leverage, symbol=None, params={}):
          if symbol is None:
              raise ArgumentsRequired(self.id + ' setLeverage() requires a symbol argument')
          await self.load_markets()
          market = self.market(symbol)
          marketType, query = self.handle_market_type_and_params('fetchPosition', market, params)
          method = None
          if market['linear']:
              defaultMargin = 'cross' if market['future'] else 'isolated'
              marginType = self.safe_string_2(self.options, 'defaultMarginType', 'marginType', defaultMargin)
              method = self.get_supported_mapping(marginType, {
                  'isolated': 'contractPrivatePostLinearSwapApiV1SwapSwitchLeverRate',
                  'cross': 'contractPrivatePostLinearSwapApiV1SwapCrossSwitchLeverRate',
              })
              #
              #     {
              #       status: 'ok',
              #       data: {
              #         contract_code: 'BTC-USDT',
              #         lever_rate: '100',
              #         margin_mode: 'isolated'
              #       },
              #       ts: '1641184710649'
              #     }
              #
          else:
              method = self.get_supported_mapping(marketType, {
                  'future': 'contractPrivatePostApiV1ContractSwitchLeverRate',
                  'swap': 'contractPrivatePostSwapApiV1SwapSwitchLeverRate',
              })
              #
              # future
              #     {
              #       status: 'ok',
              #       data: {symbol: 'BTC', lever_rate: 5},
              #       ts: 1641184578678
              #     }
              #
              # swap
              #
              #     {
              #       status: 'ok',
              #       data: {contract_code: 'BTC-USD', lever_rate: '5'},
              #       ts: '1641184652979'
              #     }
              #
          request = {
              'lever_rate': leverage,
          }
          if marketType == 'future' and market['inverse']:
              request['symbol'] = market['settleId']
          else:
              request['contract_code'] = market['id']
          response = await getattr(self, method)(self.extend(request, query))
          return response
  
      def parse_income(self, income, market=None):
          #
          #     {
          #       id: '1667161118',
          #       symbol: 'BTC',
          #       type: '31',
          #       amount: '-2.11306593188E-7',
          #       ts: '1641139308983',
          #       contract_code: 'BTC-USD'
          #     }
          #
          marketId = self.safe_string(income, 'contract_code')
          symbol = self.safe_symbol(marketId, market)
          amount = self.safe_number(income, 'amount')
          timestamp = self.safe_integer(income, 'ts')
          id = self.safe_string(income, 'id')
          currencyId = self.safe_string_2(income, 'symbol', 'asset')
          code = self.safe_currency_code(currencyId)
          return {
              'info': income,
              'symbol': symbol,
              'code': code,
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
              'id': id,
              'amount': amount,
          }
  
      def parse_incomes(self, incomes, market=None, since=None, limit=None):
          result = []
          for i in range(0, len(incomes)):
              entry = incomes[i]
              parsed = self.parse_income(entry, market)
              result.append(parsed)
          sorted = self.sort_by(result, 'timestamp')
          return self.filter_by_since_limit(sorted, since, limit, 'timestamp')
  
      def parse_position(self, position, market=None):
          #
          #     {
          #       symbol: 'BTC',
          #       contract_code: 'BTC-USDT',
          #       volume: '1.000000000000000000',
          #       available: '1.000000000000000000',
          #       frozen: '0E-18',
          #       cost_open: '47162.000000000000000000',
          #       cost_hold: '47151.300000000000000000',
          #       profit_unreal: '0.007300000000000000',
          #       profit_rate: '-0.000144183876850008',
          #       lever_rate: '2',
          #       position_margin: '23.579300000000000000',
          #       direction: 'buy',
          #       profit: '-0.003400000000000000',
          #       last_price: '47158.6',
          #       margin_asset: 'USDT',
          #       margin_mode: 'isolated',
          #       margin_account: 'BTC-USDT',
          #       margin_balance: '24.973020070000000000',
          #       margin_position: '23.579300000000000000',
          #       margin_frozen: '0',
          #       margin_available: '1.393720070000000000',
          #       profit_real: '0E-18',
          #       risk_rate: '1.044107779705080303',
          #       withdraw_available: '1.386420070000000000000000000000000000',
          #       liquidation_price: '22353.229148614609571788',
          #       adjust_factor: '0.015000000000000000',
          #       margin_static: '24.965720070000000000'
          #     }
          #
          market = self.safe_market(self.safe_string(position, 'contract_code'))
          symbol = market['symbol']
          contracts = self.safe_string(position, 'volume')
          contractSize = self.safe_value(market, 'contractSize')
          contractSizeString = self.number_to_string(contractSize)
          entryPrice = self.safe_number(position, 'cost_hold')
          initialMargin = self.safe_string(position, 'position_margin')
          rawSide = self.safe_string(position, 'direction')
          side = 'long' if (rawSide == 'buy') else 'short'
          unrealizedProfit = self.safe_number(position, 'profit_unreal')
          marginType = self.safe_string(position, 'margin_mode')
          leverage = self.safe_string(position, 'lever_rate')
          percentage = Precise.string_mul(self.safe_string(position, 'profit_rate'), '100')
          lastPrice = self.safe_string(position, 'last_price')
          faceValue = Precise.string_mul(contracts, contractSizeString)
          notional = None
          if market['linear']:
              notional = Precise.string_mul(faceValue, lastPrice)
          else:
              notional = Precise.string_div(faceValue, lastPrice)
              marginType = 'cross'
          intialMarginPercentage = Precise.string_div(initialMargin, notional)
          collateral = self.safe_string(position, 'margin_balance')
          liquidationPrice = self.safe_number(position, 'liquidation_price')
          adjustmentFactor = self.safe_string(position, 'adjust_factor')
          maintenanceMarginPercentage = Precise.string_div(adjustmentFactor, leverage)
          maintenanceMargin = Precise.string_mul(maintenanceMarginPercentage, notional)
          marginRatio = Precise.string_div(maintenanceMargin, collateral)
          return {
              'info': position,
              'symbol': symbol,
              'contracts': self.parse_number(contracts),
              'contractSize': contractSize,
              'entryPrice': entryPrice,
              'collateral': self.parse_number(collateral),
              'side': side,
              'unrealizedProfit': unrealizedProfit,
              'leverage': self.parse_number(leverage),
              'percentage': self.parse_number(percentage),
              'marginType': marginType,
              'notional': self.parse_number(notional),
              'markPrice': None,
              'liquidationPrice': liquidationPrice,
              'initialMargin': self.parse_number(initialMargin),
              'initialMarginPercentage': self.parse_number(intialMarginPercentage),
              'maintenanceMargin': self.parse_number(maintenanceMargin),
              'maintenanceMarginPercentage': self.parse_number(maintenanceMarginPercentage),
              'marginRatio': self.parse_number(marginRatio),
              'timestamp': None,
              'datetime': None,
          }
  
      async def fetch_positions(self, symbols=None, params={}):
          await self.load_markets()
          marginType = self.safe_string_2(self.options, 'defaultMarginType', 'marginType', 'isolated')
          defaultSubType = self.safe_string(self.options, 'defaultSubType', 'inverse')
          marketType, query = self.handle_market_type_and_params('fetchPositions', None, params)
          method = None
          if defaultSubType == 'linear':
              method = self.get_supported_mapping(marginType, {
                  'isolated': 'contractPrivatePostLinearSwapApiV1SwapPositionInfo',
                  'cross': 'contractPrivatePostLinearSwapApiV1SwapCrossPositionInfo',
              })
              #
              #     {
              #       status: 'ok',
              #       data: [
              #         {
              #           symbol: 'BTC',
              #           contract_code: 'BTC-USDT',
              #           volume: '1.000000000000000000',
              #           available: '1.000000000000000000',
              #           frozen: '0E-18',
              #           cost_open: '47162.000000000000000000',
              #           cost_hold: '47162.000000000000000000',
              #           profit_unreal: '0.047300000000000000',
              #           profit_rate: '0.002005852169119206',
              #           lever_rate: '2',
              #           position_margin: '23.604650000000000000',
              #           direction: 'buy',
              #           profit: '0.047300000000000000',
              #           last_price: '47209.3',
              #           margin_asset: 'USDT',
              #           margin_mode: 'isolated',
              #           margin_account: 'BTC-USDT'
              #         }
              #       ],
              #       ts: '1641108676768'
              #     }
              #
          else:
              method = self.get_supported_mapping(marketType, {
                  'future': 'contractPrivatePostApiV1ContractPositionInfo',
                  'swap': 'contractPrivatePostSwapApiV1SwapPositionInfo',
              })
              #
              # future
              #     {
              #       status: 'ok',
              #       data: [
              #         {
              #           symbol: 'BTC',
              #           contract_code: 'BTC220624',
              #           contract_type: 'next_quarter',
              #           volume: '1.000000000000000000',
              #           available: '1.000000000000000000',
              #           frozen: '0E-18',
              #           cost_open: '49018.880000000009853343',
              #           cost_hold: '49018.880000000009853343',
              #           profit_unreal: '-8.62360608500000000000000000000000000000000000000E-7',
              #           profit_rate: '-0.000845439023678622',
              #           lever_rate: '2',
              #           position_margin: '0.001019583964880634',
              #           direction: 'sell',
              #           profit: '-8.62360608500000000000000000000000000000000000000E-7',
              #           last_price: '49039.61'
              #         }
              #       ],
              #       ts: '1641109895199'
              #     }
              #
              # swap
              #     {
              #       status: 'ok',
              #       data: [
              #         {
              #           symbol: 'BTC',
              #           contract_code: 'BTC-USD',
              #           volume: '1.000000000000000000',
              #           available: '1.000000000000000000',
              #           frozen: '0E-18',
              #           cost_open: '47150.000000000012353300',
              #           cost_hold: '47150.000000000012353300',
              #           profit_unreal: '0E-54',
              #           profit_rate: '-7.86E-16',
              #           lever_rate: '3',
              #           position_margin: '0.000706963591375044',
              #           direction: 'buy',
              #           profit: '0E-54',
              #           last_price: '47150'
              #         }
              #       ],
              #       ts: '1641109636572'
              #     }
              #
          response = await getattr(self, method)(query)
          data = self.safe_value(response, 'data')
          timestamp = self.safe_integer(response, 'ts')
          result = []
          for i in range(0, len(data)):
              position = data[i]
              parsed = self.parse_position(position)
              result.append(self.extend(parsed, {
                  'timestamp': timestamp,
                  'datetime': self.iso8601(timestamp),
              }))
          return self.filter_by_array(result, 'symbol', symbols, False)
  
      async def fetch_position(self, symbol, params={}):
          await self.load_markets()
          market = self.market(symbol)
          marginType = self.safe_string_2(self.options, 'defaultMarginType', 'marginType', 'isolated')
          marketType, query = self.handle_market_type_and_params('fetchPosition', market, params)
          method = None
          if market['linear']:
              method = self.get_supported_mapping(marginType, {
                  'isolated': 'contractPrivatePostLinearSwapApiV1SwapAccountPositionInfo',
                  'cross': 'contractPrivatePostLinearSwapApiV1SwapCrossAccountPositionInfo',
              })
              #
              #     {
              #       status: 'ok',
              #       data: [
              #         {
              #           positions: [
              #             {
              #               symbol: 'BTC',
              #               contract_code: 'BTC-USDT',
              #               volume: 1,
              #               available: 1,
              #               frozen: 0,
              #               cost_open: 47027.1,
              #               cost_hold: 47324.4,
              #               profit_unreal: 0.1705,
              #               profit_rate: -0.269631765513927,
              #               lever_rate: 100,
              #               position_margin: 0.471539,
              #               direction: 'sell',
              #               profit: -0.1268,
              #               last_price: 47153.9,
              #               margin_asset: 'USDT',
              #               margin_mode: 'isolated',
              #               margin_account: 'BTC-USDT'
              #             }
              #           ],
              #           symbol: 'BTC',
              #           margin_balance: 8.01274699,
              #           margin_position: 0.471539,
              #           margin_frozen: 0,
              #           margin_available: 7.54120799,
              #           profit_real: 0,
              #           profit_unreal: 0.1705,
              #           risk_rate: 16.442755615124092,
              #           withdraw_available: 7.37070799,
              #           liquidation_price: 54864.89009448036,
              #           lever_rate: 100,
              #           adjust_factor: 0.55,
              #           margin_static: 7.84224699,
              #           contract_code: 'BTC-USDT',
              #           margin_asset: 'USDT',
              #           margin_mode: 'isolated',
              #           margin_account: 'BTC-USDT'
              #         }
              #       ],
              #       ts: 1641162539767
              #     }
              #
          else:
              method = self.get_supported_mapping(marketType, {
                  'future': 'contractPrivatePostApiV1ContractAccountPositionInfo',
                  'swap': 'contractPrivatePostSwapApiV1SwapAccountPositionInfo',
              })
              # future
              #     {
              #       status: 'ok',
              #       data: [
              #         {
              #           symbol: 'BTC',
              #           contract_code: 'BTC-USD',
              #           margin_balance: 0.000752347253890835,
              #           margin_position: 0.000705870726835087,
              #           margin_frozen: 0,
              #           margin_available: 0.000046476527055748,
              #           profit_real: 0,
              #           profit_unreal: -0.000004546248622,
              #           risk_rate: 1.0508428311146076,
              #           withdraw_available: 0.000046476527055748,
              #           liquidation_price: 35017.91655851386,
              #           lever_rate: 3,
              #           adjust_factor: 0.015,
              #           margin_static: 0.000756893502512835,
              #           positions: [
              #             {
              #               symbol: 'BTC',
              #               contract_code: 'BTC-USD',
              #               volume: 1,
              #               available: 1,
              #               frozen: 0,
              #               cost_open: 47150.000000000015,
              #               cost_hold: 47324.6,
              #               profit_unreal: -0.000004546248622,
              #               profit_rate: 0.00463757067530574,
              #               lever_rate: 3,
              #               position_margin: 0.000705870726835087,
              #               direction: 'buy',
              #               profit: 0.0000032785936199,
              #               last_price: 47223
              #             }
              #           ]
              #         }
              #       ],
              #       ts: 1641162795228
              #     }
              #
              # swap
              #     {
              #       status: 'ok',
              #       data: [
              #         {
              #           positions: [
              #             {
              #               symbol: 'BTC',
              #               contract_code: 'BTC-USDT',
              #               volume: 1,
              #               available: 1,
              #               frozen: 0,
              #               cost_open: 47027.1,
              #               cost_hold: 47324.4,
              #               profit_unreal: 0.1705,
              #               profit_rate: -0.269631765513927,
              #               lever_rate: 100,
              #               position_margin: 0.471539,
              #               direction: 'sell',
              #               profit: -0.1268,
              #               last_price: 47153.9,
              #               margin_asset: 'USDT',
              #               margin_mode: 'isolated',
              #               margin_account: 'BTC-USDT'
              #             }
              #           ],
              #           symbol: 'BTC',
              #           margin_balance: 8.01274699,
              #           margin_position: 0.471539,
              #           margin_frozen: 0,
              #           margin_available: 7.54120799,
              #           profit_real: 0,
              #           profit_unreal: 0.1705,
              #           risk_rate: 16.442755615124092,
              #           withdraw_available: 7.37070799,
              #           liquidation_price: 54864.89009448036,
              #           lever_rate: 100,
              #           adjust_factor: 0.55,
              #           margin_static: 7.84224699,
              #           contract_code: 'BTC-USDT',
              #           margin_asset: 'USDT',
              #           margin_mode: 'isolated',
              #           margin_account: 'BTC-USDT'
              #         }
              #       ],
              #       ts: 1641162539767
              #     }
              #
          request = {
              'contract_code': market['id'],
          }
          response = await getattr(self, method)(self.extend(request, query))
          data = self.safe_value(response, 'data')
          account = self.safe_value(data, 0)
          omitted = self.omit(account, ['positions'])
          positions = self.safe_value(account, 'positions')
          position = self.safe_value(positions, 0)
          timestamp = self.safe_integer(response, 'ts')
          parsed = self.parse_position(self.extend(position, omitted))
          return self.extend(parsed, {
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
          })
  
      def parse_ledger_entry_type(self, type):
          types = {
              'trade': 'trade',
              'etf': 'trade',
              'transact-fee': 'fee',
              'fee-deduction': 'fee',
              'transfer': 'transfer',
              'credit': 'credit',
              'liquidation': 'trade',
              'interest': 'credit',
              'deposit': 'deposit',
              'withdraw': 'withdrawal',
              'withdraw-fee': 'fee',
              'exchange': 'exchange',
              'other-types': 'transfer',
              'rebate': 'rebate',
          }
          return self.safe_string(types, type, type)
  
      def parse_ledger_entry(self, item, currency=None):
          #
          #     {
          #         "accountId": 10000001,
          #         "currency": "usdt",
          #         "transactAmt": 10.000000000000000000,
          #         "transactType": "transfer",
          #         "transferType": "margin-transfer-out",
          #         "transactId": 0,
          #         "transactTime": 1629882331066,
          #         "transferer": 28483123,
          #         "transferee": 13496526
          #     }
          #
          id = self.safe_string(item, 'transactId')
          currencyId = self.safe_string(item, 'currency')
          code = self.safe_currency_code(currencyId, currency)
          amount = self.safe_number(item, 'transactAmt')
          transferType = self.safe_string(item, 'transferType')
          type = self.parse_ledger_entry_type(transferType)
          direction = self.safe_string(item, 'direction')
          timestamp = self.safe_integer(item, 'transactTime')
          datetime = self.iso8601(timestamp)
          account = self.safe_string(item, 'accountId')
          return {
              'id': id,
              'direction': direction,
              'account': account,
              'referenceId': id,
              'referenceAccount': account,
              'type': type,
              'currency': code,
              'amount': amount,
              'timestamp': timestamp,
              'datetime': datetime,
              'before': None,
              'after': None,
              'status': None,
              'fee': None,
              'info': item,
          }
  
      async def fetch_ledger(self, code=None, since=None, limit=None, params={}):
          await self.load_markets()
          accountId = await self.fetch_account_id_by_type('spot', params)
          request = {
              'accountId': accountId,
              # 'currency': code,
              # 'transactTypes': 'all',  # default all
              # 'startTime': 1546272000000,
              # 'endTime': 1546272000000,
              # 'sort': asc,  # asc, desc
              # 'limit': 100,  # range 1-500
              # 'fromId': 323  # first record ID in self query for pagination
          }
          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  # max 500
          response = await self.spotPrivateGetV2AccountLedger(self.extend(request, params))
          #
          #     {
          #         "code": 200,
          #         "message": "success",
          #         "data": [
          #             {
          #                 "accountId": 10000001,
          #                 "currency": "usdt",
          #                 "transactAmt": 10.000000000000000000,
          #                 "transactType": "transfer",
          #                 "transferType": "margin-transfer-out",
          #                 "transactId": 0,
          #                 "transactTime": 1629882331066,
          #                 "transferer": 28483123,
          #                 "transferee": 13496526
          #             },
          #             {
          #                 "accountId": 10000001,
          #                 "currency": "usdt",
          #                 "transactAmt": -10.000000000000000000,
          #                 "transactType": "transfer",
          #                 "transferType": "margin-transfer-in",
          #                 "transactId": 0,
          #                 "transactTime": 1629882096562,
          #                 "transferer": 13496526,
          #                 "transferee": 28483123
          #             }
          #         ],
          #         "nextId": 1624316679,
          #         "ok": True
          #     }
          #
          data = self.safe_value(response, 'data', [])
          return self.parse_ledger(data, currency, since, limit)
  