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.base.exchange import Exchange
  import hashlib
  import math
  from ccxt.base.errors import ExchangeError
  from ccxt.base.errors import AuthenticationError
  from ccxt.base.errors import PermissionDenied
  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 RateLimitExceeded
  from ccxt.base.decimal_to_precision import TICK_SIZE
  from ccxt.base.precise import Precise
  
  
  class mexc(Exchange):
  
      def describe(self):
          return self.deep_extend(super(mexc, self).describe(), {
              'id': 'mexc',
              'name': 'MEXC Global',
              'countries': ['SC'],  # Seychelles
              'rateLimit': 50,  # default rate limit is 20 times per second
              'version': 'v2',
              'certified': True,
              'has': {
                  'CORS': None,
                  'spot': True,
                  'margin': None,  # has but unimplemented
                  'swap': True,
                  'future': False,
                  'option': False,
                  'addMargin': True,
                  'cancelAllOrders': True,
                  'cancelOrder': True,
                  'createMarketOrder': False,
                  'createOrder': True,
                  'createReduceOnlyOrder': False,
                  'fetchBalance': True,
                  'fetchCanceledOrders': True,
                  'fetchClosedOrders': True,
                  'fetchCurrencies': True,
                  'fetchDepositAddress': True,
                  'fetchDepositAddressesByNetwork': True,
                  'fetchDeposits': True,
                  'fetchFundingHistory': True,
                  'fetchFundingRate': True,
                  'fetchFundingRateHistory': True,
                  'fetchFundingRates': False,
                  'fetchIndexOHLCV': True,
                  'fetchIsolatedPositions': None,
                  'fetchLeverage': None,
                  'fetchLeverageTiers': True,
                  'fetchMarkets': True,
                  'fetchMarkOHLCV': True,
                  'fetchMyTrades': True,
                  'fetchOHLCV': True,
                  'fetchOpenOrders': True,
                  'fetchOrder': True,
                  'fetchOrderBook': True,
                  'fetchOrderTrades': True,
                  'fetchPosition': True,
                  'fetchPositions': True,
                  'fetchPositionsRisk': False,
                  'fetchPremiumIndexOHLCV': True,
                  'fetchStatus': True,
                  'fetchTicker': True,
                  'fetchTickers': True,
                  'fetchTime': True,
                  'fetchTrades': True,
                  'fetchWithdrawals': True,
                  'reduceMargin': True,
                  'setLeverage': True,
                  'setMarginMode': False,
                  'withdraw': True,
              },
              'timeframes': {
                  '1m': '1m',
                  '5m': '5m',
                  '15m': '15m',
                  '30m': '30m',
                  '1h': '1h',
                  '1d': '1d',
                  '1w': '1w',
                  '1M': '1M',
              },
              'urls': {
                  'logo': 'https://user-images.githubusercontent.com/1294454/137283979-8b2a818d-8633-461b-bfca-de89e8c446b2.jpg',
                  'api': {
                      'spot': {
                          'public': 'https://www.mexc.com/open/api/v2',
                          'private': 'https://www.mexc.com/open/api/v2',
                      },
                      'contract': {
                          'public': 'https://contract.mexc.com/api/v1/contract',
                          'private': 'https://contract.mexc.com/api/v1/private',
                      },
                  },
                  'www': 'https://www.mexc.com/',
                  'doc': [
                      'https://mxcdevelop.github.io/APIDoc/',
                  ],
                  'fees': [
                      'https://www.mexc.com/fee',
                  ],
                  'referral': 'https://m.mexc.com/auth/signup?inviteCode=1FQ1G',
              },
              'api': {
                  'contract': {
                      'public': {
                          'get': {
                              'ping': 2,
                              'detail': 2,
                              'support_currencies': 2,
                              'depth/{symbol}': 2,
                              'depth_commits/{symbol}/{limit}': 2,
                              'index_price/{symbol}': 2,
                              'fair_price/{symbol}': 2,
                              'funding_rate/{symbol}': 2,
                              'kline/{symbol}': 2,
                              'kline/index_price/{symbol}': 2,
                              'kline/fair_price/{symbol}': 2,
                              'deals/{symbol}': 2,
                              'ticker': 2,
                              'risk_reverse': 2,
                              'risk_reverse/history': 2,
                              'funding_rate/history': 2,
                          },
                      },
                      'private': {
                          'get': {
                              'account/assets': 2,
                              'account/asset/{currency}': 2,
                              'account/transfer_record': 2,
                              'position/list/history_positions': 2,
                              'position/open_positions': 2,
                              'position/funding_records': 2,
                              'order/list/open_orders/{symbol}': 2,
                              'order/list/history_orders': 2,
                              'order/external/{symbol}/{external_oid}': 2,
                              'order/get/{order_id}': 2,
                              'order/batch_query': 8,
                              'order/deal_details/{order_id}': 2,
                              'order/list/order_deals': 2,
                              'planorder/list/orders': 2,
                              'stoporder/list/orders': 2,
                              'stoporder/order_details/{stop_order_id}': 2,
                              'account/risk_limit': 2,
                              'account/tiered_fee_rate': 2,
                          },
                          'post': {
                              'position/change_margin': 2,
                              'position/change_leverage': 2,
                              'order/submit': 2,
                              'order/submit_batch': 40,
                              'order/cancel': 2,
                              'order/cancel_with_external': 2,
                              'order/cancel_all': 2,
                              'account/change_risk_level': 2,
                              'planorder/place': 2,
                              'planorder/cancel': 2,
                              'planorder/cancel_all': 2,
                              'stoporder/cancel': 2,
                              'stoporder/cancel_all': 2,
                              'stoporder/change_price': 2,
                              'stoporder/change_plan_price': 2,
                          },
                      },
                  },
                  'spot': {
                      'public': {
                          'get': {
                              'market/symbols': 1,
                              'market/coin/list': 2,
                              'common/timestamp': 1,
                              'common/ping': 1,
                              'market/ticker': 1,
                              'market/depth': 1,
                              'market/deals': 1,
                              'market/kline': 1,
                          },
                      },
                      'private': {
                          'get': {
                              'account/info': 1,
                              'order/open_orders': 1,
                              'order/list': 1,
                              'order/query': 1,
                              'order/deals': 1,
                              'order/deal_detail': 1,
                              'asset/deposit/address/list': 2,
                              'asset/deposit/list': 2,
                              'asset/address/list': 2,
                              'asset/withdraw/list': 2,
                          },
                          'post': {
                              'order/place': 1,
                              'order/place_batch': 1,
                              'asset/withdraw': 1,
                          },
                          'delete': {
                              'order/cancel': 1,
                              'order/cancel_by_symbol': 1,
                          },
                      },
                  },
              },
              'precisionMode': TICK_SIZE,
              'fees': {
                  'trading': {
                      'tierBased': False,
                      'percentage': True,
                      'maker': 0.2 / 100,  # maker / taker
                      'taker': 0.2 / 100,
                  },
              },
              'options': {
                  'timeframes': {
                      'spot': {
                          '1m': '1m',
                          '5m': '5m',
                          '15m': '15m',
                          '30m': '30m',
                          '1h': '1h',
                          '1d': '1d',
                          '1M': '1M',
                      },
                      'contract': {
                          '1m': 'Min1',
                          '5m': 'Min5',
                          '15m': 'Min15',
                          '30m': 'Min30',
                          '1h': 'Min60',
                          '4h': 'Hour4',
                          '8h': 'Hour8',
                          '1d': 'Day1',
                          '1w': 'Week1',
                          '1M': 'Month1',
                      },
                  },
                  'defaultType': 'spot',  # spot, swap
                  'networks': {
                      'TRX': 'TRC-20',
                      'TRC20': 'TRC-20',
                      'ETH': 'ERC-20',
                      'ERC20': 'ERC-20',
                      'BEP20': 'BEP20(BSC)',
                  },
              },
              'commonCurrencies': {
                  'BEYONDPROTOCOL': 'BEYOND',
                  'BIFI': 'BIFIF',
                  'BYN': 'BeyondFi',
                  'COFI': 'COFIX',  # conflict with CoinFi
                  'DFI': 'DfiStarter',
                  'DFT': 'dFuture',
                  'DRK': 'DRK',
                  'EGC': 'Egoras Credit',
                  'FLUX1': 'FLUX',  # switched places
                  'FLUX': 'FLUX1',  # switched places
                  'FREE': 'FreeRossDAO',  # conflict with FREE Coin
                  'HERO': 'Step Hero',  # conflict with Metahero
                  'MIMO': 'Mimosa',
                  'PROS': 'Pros.Finance',  # conflict with Prosper
                  'SIN': 'Sin City Token',
              },
              'exceptions': {
                  'exact': {
                      '400': BadRequest,  # Invalid parameter
                      '401': AuthenticationError,  # Invalid signature, fail to pass the validation
                      '403': PermissionDenied,  # {"msg":"no permission to access the endpoint","code":403}
                      '429': RateLimitExceeded,  # too many requests, rate limit rule is violated
                      '1000': PermissionDenied,  # {"success":false,"code":1000,"message":"Please open contract account first!"}
                      '1002': InvalidOrder,  # {"success":false,"code":1002,"message":"Contract not allow place order!"}
                      '10072': AuthenticationError,  # Invalid access key
                      '10073': AuthenticationError,  # Invalid request time
                      '10075': PermissionDenied,  # {"msg":"IP [xxx.xxx.xxx.xxx] not in the ip white list","code":10075}
                      '10101': InsufficientFunds,  # {"code":10101,"msg":"Insufficient balance"}
                      '10216': InvalidAddress,  # {"code":10216,"msg":"No available deposit address"}
                      '10232': BadSymbol,  # {"code":10232,"msg":"The currency not exist"}
                      '30000': BadSymbol,  # Trading is suspended for the requested symbol
                      '30001': InvalidOrder,  # Current trading type(bid or ask) is not allowed
                      '30002': InvalidOrder,  # Invalid trading amount, smaller than the symbol minimum trading amount
                      '30003': InvalidOrder,  # Invalid trading amount, greater than the symbol maximum trading amount
                      '30004': InsufficientFunds,  # Insufficient balance
                      '30005': InvalidOrder,  # Oversell error
                      '30010': InvalidOrder,  # Price out of allowed range
                      '30016': BadSymbol,  # Market is closed
                      '30019': InvalidOrder,  # Orders count over limit for batch processing
                      '30020': BadSymbol,  # Restricted symbol, API access is not allowed for the time being
                      '30021': BadSymbol,  # Invalid symbol
                      '33333': BadSymbol,  # {"code":33333,"msg":"currency can not be null"}
                  },
                  'broad': {
                      'price and quantity must be positive': InvalidOrder,  # {"msg":"price and quantity must be positive","code":400}
                  },
              },
          })
  
      def fetch_time(self, params={}):
          marketType, query = self.handle_market_type_and_params('fetchTime', None, params)
          method = self.get_supported_mapping(marketType, {
              'spot': 'spotPublicGetCommonTimestamp',
              'swap': 'contractPublicGetPing',
          })
          response = getattr(self, method)(self.extend(query))
          #
          # spot
          #
          #     {
          #         "code":200,
          #         "data":1633375641837
          #     }
          #
          # contract
          #
          #     {
          #         "success":true,
          #         "code":0,
          #         "data":1634095541710
          #     }
          #
          return self.safe_integer(response, 'data')
  
      def fetch_status(self, params={}):
          response = self.spotPublicGetCommonPing(params)
          #
          # {"code":200}
          #
          code = self.safe_integer(response, 'code')
          if code is not None:
              status = 'ok' if (code == 200) else 'maintenance'
              self.status = self.extend(self.status, {
                  'status': status,
                  'updated': self.milliseconds(),
              })
          return self.status
  
      def fetch_currencies(self, params={}):
          response = self.spotPublicGetMarketCoinList(params)
          #
          #     {
          #         "code":200,
          #         "data":[
          #             {
          #                 "currency":"AGLD",
          #                 "coins":[
          #                     {
          #                         "chain":"ERC20",
          #                         "precision":18,
          #                         "fee":8.09,
          #                         "is_withdraw_enabled":true,
          #                         "is_deposit_enabled":true,
          #                         "deposit_min_confirm":16,
          #                         "withdraw_limit_max":500000.0,
          #                         "withdraw_limit_min":14.0
          #                     }
          #                 ],
          #                 "full_name":"Adventure Gold"
          #             },
          #         ]
          #     }
          #
          data = self.safe_value(response, 'data', [])
          result = {}
          for i in range(0, len(data)):
              currency = data[i]
              id = self.safe_string(currency, 'currency')
              code = self.safe_currency_code(id)
              name = self.safe_string(currency, 'full_name')
              currencyActive = False
              currencyPrecision = None
              currencyFee = None
              currencyWithdrawMin = None
              currencyWithdrawMax = None
              networks = {}
              chains = self.safe_value(currency, 'coins', [])
              depositEnabled = False
              withdrawEnabled = False
              for j in range(0, len(chains)):
                  chain = chains[j]
                  networkId = self.safe_string(chain, 'chain')
                  network = self.safe_network(networkId)
                  isDepositEnabled = self.safe_value(chain, 'is_deposit_enabled', False)
                  isWithdrawEnabled = self.safe_value(chain, 'is_withdraw_enabled', False)
                  active = (isDepositEnabled and isWithdrawEnabled)
                  currencyActive = active or currencyActive
                  precisionDigits = self.safe_integer(chain, 'precision')
                  precision = 1 / math.pow(10, precisionDigits)
                  withdrawMin = self.safe_string(chain, 'withdraw_limit_min')
                  withdrawMax = self.safe_string(chain, 'withdraw_limit_max')
                  currencyWithdrawMin = withdrawMin if (currencyWithdrawMin is None) else currencyWithdrawMin
                  currencyWithdrawMax = withdrawMax if (currencyWithdrawMax is None) else currencyWithdrawMax
                  if Precise.string_gt(currencyWithdrawMin, withdrawMin):
                      currencyWithdrawMin = withdrawMin
                  if Precise.string_lt(currencyWithdrawMax, withdrawMax):
                      currencyWithdrawMax = withdrawMax
                  if isDepositEnabled:
                      depositEnabled = True
                  if isWithdrawEnabled:
                      withdrawEnabled = True
                  networks[network] = {
                      'info': chain,
                      'id': networkId,
                      'network': network,
                      'active': active,
                      'deposit': isDepositEnabled,
                      'withdraw': isWithdrawEnabled,
                      'fee': self.safe_number(chain, 'fee'),
                      'precision': precision,
                      'limits': {
                          'withdraw': {
                              'min': withdrawMin,
                              'max': withdrawMax,
                          },
                      },
                  }
              networkKeys = list(networks.keys())
              networkKeysLength = len(networkKeys)
              if (networkKeysLength == 1) or ('NONE' in networks):
                  defaultNetwork = self.safe_value_2(networks, 'NONE', networkKeysLength - 1)
                  if defaultNetwork is not None:
                      currencyFee = defaultNetwork['fee']
                      currencyPrecision = defaultNetwork['precision']
              result[code] = {
                  'id': id,
                  'code': code,
                  'info': currency,
                  'name': name,
                  'active': currencyActive,
                  'deposit': depositEnabled,
                  'withdraw': withdrawEnabled,
                  'fee': currencyFee,
                  'precision': currencyPrecision,
                  'limits': {
                      'amount': {
                          'min': None,
                          'max': None,
                      },
                      'withdraw': {
                          'min': currencyWithdrawMin,
                          'max': currencyWithdrawMax,
                      },
                  },
                  'networks': networks,
              }
          return result
  
      def fetch_markets_by_type(self, type, params={}):
          method = 'fetch_' + type + '_markets'
          return getattr(self, method)(params)
  
      def fetch_markets(self, params={}):
          defaultType = self.safe_string_2(self.options, 'fetchMarkets', 'defaultType', 'spot')
          type = self.safe_string(params, 'type', defaultType)
          query = self.omit(params, 'type')
          spot = (type == 'spot')
          swap = (type == 'swap')
          if not spot and not swap:
              raise ExchangeError(self.id + " does not support '" + type + "' type, set exchange.options['defaultType'] to 'spot', 'margin', 'delivery' or 'future'")  # eslint-disable-line quotes
          if spot:
              return self.fetch_spot_markets(query)
          elif swap:
              return self.fetch_contract_markets(query)
  
      def fetch_contract_markets(self, params={}):
          response = self.contractPublicGetDetail(params)
          #
          #     {
          #         "success":true,
          #         "code":0,
          #         "data":[
          #             {
          #                 "symbol":"BTC_USDT",
          #                 "displayName":"BTC_USDT永续",
          #                 "displayNameEn":"BTC_USDT SWAP",
          #                 "positionOpenType":3,
          #                 "baseCoin":"BTC",
          #                 "quoteCoin":"USDT",
          #                 "settleCoin":"USDT",
          #                 "contractSize":0.0001,
          #                 "minLeverage":1,
          #                 "maxLeverage":125,
          #                 "priceScale":2,
          #                 "volScale":0,
          #                 "amountScale":4,
          #                 "priceUnit":0.5,
          #                 "volUnit":1,
          #                 "minVol":1,
          #                 "maxVol":1000000,
          #                 "bidLimitPriceRate":0.1,
          #                 "askLimitPriceRate":0.1,
          #                 "takerFeeRate":0.0006,
          #                 "makerFeeRate":0.0002,
          #                 "maintenanceMarginRate":0.004,
          #                 "initialMarginRate":0.008,
          #                 "riskBaseVol":10000,
          #                 "riskIncrVol":200000,
          #                 "riskIncrMmr":0.004,
          #                 "riskIncrImr":0.004,
          #                 "riskLevelLimit":5,
          #                 "priceCoefficientVariation":0.1,
          #                 "indexOrigin":["BINANCE","GATEIO","HUOBI","MXC"],
          #                 "state":0,  # 0 enabled, 1 delivery, 2 completed, 3 offline, 4 pause
          #                 "isNew":false,
          #                 "isHot":true,
          #                 "isHidden":false
          #             },
          #         ]
          #     }
          #
          data = self.safe_value(response, 'data', [])
          result = []
          for i in range(0, len(data)):
              market = data[i]
              id = self.safe_string(market, 'symbol')
              baseId = self.safe_string(market, 'baseCoin')
              quoteId = self.safe_string(market, 'quoteCoin')
              settleId = self.safe_string(market, 'settleCoin')
              base = self.safe_currency_code(baseId)
              quote = self.safe_currency_code(quoteId)
              settle = self.safe_currency_code(settleId)
              state = self.safe_string(market, 'state')
              result.append({
                  'id': id,
                  'symbol': base + '/' + quote + ':' + settle,
                  'base': base,
                  'quote': quote,
                  'settle': settle,
                  'baseId': baseId,
                  'quoteId': quoteId,
                  'settleId': settleId,
                  'type': 'swap',
                  'spot': False,
                  'margin': False,
                  'swap': True,
                  'future': False,
                  'option': False,
                  'active': (state == '0'),
                  'contract': True,
                  'linear': True,
                  'inverse': False,
                  'taker': self.safe_number(market, 'takerFeeRate'),
                  'maker': self.safe_number(market, 'makerFeeRate'),
                  'contractSize': self.safe_number(market, 'contractSize'),
                  'expiry': None,
                  'expiryDatetime': None,
                  'strike': None,
                  'optionType': None,
                  'precision': {
                      'amount': self.safe_number(market, 'volUnit'),
                      'price': self.safe_number(market, 'priceUnit'),
                  },
                  'limits': {
                      'leverage': {
                          'min': self.safe_number(market, 'minLeverage'),
                          'max': self.safe_number(market, 'maxLeverage'),
                      },
                      'amount': {
                          'min': self.safe_number(market, 'minVol'),
                          'max': self.safe_number(market, 'maxVol'),
                      },
                      'price': {
                          'min': None,
                          'max': None,
                      },
                      'cost': {
                          'min': None,
                          'max': None,
                      },
                  },
                  'info': market,
              })
          return result
  
      def fetch_spot_markets(self, params={}):
          response = self.spotPublicGetMarketSymbols(params)
          #
          #     {
          #         "code":200,
          #         "data":[
          #             {
          #                 "symbol":"DFD_USDT",
          #                 "state":"ENABLED",
          #                 "countDownMark":1,
          #                 "vcoinName":"DFD",
          #                 "vcoinStatus":1,
          #                 "price_scale":4,
          #                 "quantity_scale":2,
          #                 "min_amount":"5",  # not an amount = cost
          #                 "max_amount":"5000000",
          #                 "maker_fee_rate":"0.002",
          #                 "taker_fee_rate":"0.002",
          #                 "limited":true,
          #                 "etf_mark":0,
          #                 "symbol_partition":"ASSESS"
          #             },
          #         ]
          #     }
          #
          data = self.safe_value(response, 'data', [])
          result = []
          for i in range(0, len(data)):
              market = data[i]
              id = self.safe_string(market, 'symbol')
              baseId, quoteId = id.split('_')
              base = self.safe_currency_code(baseId)
              quote = self.safe_currency_code(quoteId)
              priceScale = self.safe_string(market, 'price_scale')
              quantityScale = self.safe_string(market, 'quantity_scale')
              state = self.safe_string(market, 'state')
              result.append({
                  'id': id,
                  'symbol': base + '/' + quote,
                  'base': base,
                  'quote': quote,
                  'settle': None,
                  'baseId': baseId,
                  'quoteId': quoteId,
                  'settleId': None,
                  'type': 'spot',
                  'spot': True,
                  'margin': False,
                  'swap': False,
                  'future': False,
                  'option': False,
                  'active': (state == 'ENABLED'),
                  'contract': False,
                  'linear': None,
                  'inverse': None,
                  'taker': self.safe_number(market, 'taker_fee_rate'),
                  'maker': self.safe_number(market, 'maker_fee_rate'),
                  'contractSize': None,
                  'expiry': None,
                  'expiryDatetime': None,
                  'strike': None,
                  'optionType': None,
                  'precision': {
                      'amount': self.parse_number(self.parse_precision(quantityScale)),
                      'price': self.parse_number(self.parse_precision(priceScale)),
                  },
                  'limits': {
                      'leverage': {
                          'min': None,
                          'max': None,
                      },
                      'amount': {
                          'min': None,
                          'max': None,
                      },
                      'price': {
                          'min': None,
                          'max': None,
                      },
                      'cost': {
                          'min': self.safe_number(market, 'min_amount'),
                          'max': self.safe_number(market, 'max_amount'),
                      },
                  },
                  'info': market,
              })
          return result
  
      def fetch_tickers(self, symbols=None, params={}):
          self.load_markets()
          marketType, query = self.handle_market_type_and_params('fetchTickers', None, params)
          method = self.get_supported_mapping(marketType, {
              'spot': 'spotPublicGetMarketTicker',
              'swap': 'contractPublicGetTicker',
          })
          response = getattr(self, method)(self.extend(query))
          #
          #     {
          #         "success":true,
          #         "code":0,
          #         "data":[
          #             {
          #                 "symbol":"NKN_USDT",
          #                 "lastPrice":0.36199,
          #                 "bid1":0.35908,
          #                 "ask1":0.36277,
          #                 "volume24":657754,
          #                 "amount24":239024.53998,
          #                 "holdVol":149969,
          #                 "lower24Price":0.34957,
          #                 "high24Price":0.37689,
          #                 "riseFallRate":0.0117,
          #                 "riseFallValue":0.00419,
          #                 "indexPrice":0.36043,
          #                 "fairPrice":0.36108,
          #                 "fundingRate":0.000535,
          #                 "maxBidPrice":0.43251,
          #                 "minAskPrice":0.28834,
          #                 "timestamp":1634163352075
          #             },
          #         ]
          #     }
          #
          data = self.safe_value(response, 'data', [])
          return self.parse_tickers(data, symbols)
  
      def fetch_ticker(self, symbol, params={}):
          self.load_markets()
          market = self.market(symbol)
          request = {
              'symbol': market['id'],
          }
          method = None
          if market['spot']:
              method = 'spotPublicGetMarketTicker'
          elif market['swap']:
              method = 'contractPublicGetTicker'
          response = getattr(self, method)(self.extend(request, params))
          #
          # spot
          #
          #     {
          #         "code":200,
          #         "data":[
          #             {
          #                 "symbol":"BTC_USDT",
          #                 "volume":"880.821523",
          #                 "high":"49496.95",  # highest price over the past 24 hours
          #                 "low":"46918.4",  # lowest
          #                 "bid":"49297.64",  # current buying price == the best price you can sell for
          #                 "ask":"49297.75",  # current selling price == the best price you can buy for
          #                 "open":"48764.9",  # open price 24h ago
          #                 "last":"49297.73",  # last = close
          #                 "time":1633378200000,  # timestamp
          #                 "change_rate":"0.0109265"  #(last / open) - 1
          #             }
          #         ]
          #     }
          #
          # swap / contract
          #
          #     {
          #         "success":true,
          #         "code":0,
          #         "data":{
          #             "symbol":"ETH_USDT",
          #             "lastPrice":3581.3,
          #             "bid1":3581.25,
          #             "ask1":3581.5,
          #             "volume24":4045530,
          #             "amount24":141331823.5755,
          #             "holdVol":5832946,
          #             "lower24Price":3413.4,
          #             "high24Price":3588.7,
          #             "riseFallRate":0.0275,
          #             "riseFallValue":95.95,
          #             "indexPrice":3580.7852,
          #             "fairPrice":3581.08,
          #             "fundingRate":0.000063,
          #             "maxBidPrice":3938.85,
          #             "minAskPrice":3222.7,
          #             "timestamp":1634162885016
          #         }
          #     }
          #
          if market['spot']:
              data = self.safe_value(response, 'data', [])
              ticker = self.safe_value(data, 0)
              return self.parse_ticker(ticker, market)
          elif market['swap']:
              data = self.safe_value(response, 'data', {})
              return self.parse_ticker(data, market)
  
      def parse_ticker(self, ticker, market=None):
          #
          # spot
          #
          #     {
          #         "symbol":"BTC_USDT",
          #         "volume":"880.821523",
          #         "high":"49496.95",
          #         "low":"46918.4",
          #         "bid":"49297.64",
          #         "ask":"49297.75",
          #         "open":"48764.9",
          #         "last":"49297.73",
          #         "time":1633378200000,
          #         "change_rate":"0.0109265"
          #     }
          #
          # contract
          #
          #     {
          #         "symbol":"ETH_USDT",
          #         "lastPrice":3581.3,
          #         "bid1":3581.25,
          #         "ask1":3581.5,
          #         "volume24":4045530,
          #         "amount24":141331823.5755,
          #         "holdVol":5832946,
          #         "lower24Price":3413.4,
          #         "high24Price":3588.7,
          #         "riseFallRate":0.0275,
          #         "riseFallValue":95.95,
          #         "indexPrice":3580.7852,
          #         "fairPrice":3581.08,
          #         "fundingRate":0.000063,
          #         "maxBidPrice":3938.85,
          #         "minAskPrice":3222.7,
          #         "timestamp":1634162885016
          #     }
          #
          timestamp = self.safe_integer_2(ticker, 'time', 'timestamp')
          marketId = self.safe_string(ticker, 'symbol')
          symbol = self.safe_symbol(marketId, market, '_')
          baseVolume = self.safe_string_2(ticker, 'volume', 'volume24')
          quoteVolume = self.safe_string(ticker, 'amount24')
          open = self.safe_string(ticker, 'open')
          last = self.safe_string_2(ticker, 'last', 'lastPrice')
          change = self.safe_string(ticker, 'riseFallValue')
          riseFallRate = self.safe_string(ticker, 'riseFallRate')
          percentage = Precise.string_add(riseFallRate, '1')
          return self.safe_ticker({
              'symbol': symbol,
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
              'high': self.safe_string_2(ticker, 'high', 'high24Price'),
              'low': self.safe_string_2(ticker, 'low', 'lower24Price'),
              'bid': self.safe_string_2(ticker, 'bid', 'bid1'),
              'bidVolume': None,
              'ask': self.safe_string_2(ticker, 'ask', 'ask1'),
              'askVolume': None,
              'vwap': None,
              'open': open,
              'close': last,
              'last': last,
              'previousClose': None,
              'change': change,
              'percentage': percentage,
              'average': None,
              'baseVolume': baseVolume,
              'quoteVolume': quoteVolume,
              'info': ticker,
          }, market, False)
  
      def fetch_order_book(self, symbol, limit=None, params={}):
          self.load_markets()
          market = self.market(symbol)
          request = {
              'symbol': market['id'],
          }
          method = None
          if market['spot']:
              method = 'spotPublicGetMarketDepth'
              if limit is None:
                  limit = 100  # the spot api requires a limit
              request['depth'] = limit
          elif market['swap']:
              method = 'contractPublicGetDepthSymbol'
              if limit is not None:
                  request['limit'] = limit
          response = getattr(self, method)(self.extend(request, params))
          #
          # spot
          #
          #     {
          #         "code":200,
          #         "data":{
          #             "asks":[
          #                 {"price":"49060.56","quantity":"0.099842"},
          #                 {"price":"49060.58","quantity":"0.016003"},
          #                 {"price":"49060.6","quantity":"0.023677"}
          #             ],
          #             "bids":[
          #                 {"price":"49060.45","quantity":"1.693009"},
          #                 {"price":"49060.44","quantity":"0.000843"},
          #                 {"price":"49059.98","quantity":"0.735"},
          #             ],
          #             "version":"202454074",
          #         }
          #     }
          #
          # swap / contract
          #
          #     {
          #         "success":true,
          #         "code":0,
          #         "data":{
          #             "asks":[
          #                 [3445.7,48379,1],
          #                 [3445.75,34994,1],
          #                 [3445.8,68634,2],
          #             ],
          #             "bids":[
          #                 [3445.55,44081,1],
          #                 [3445.5,24857,1],
          #                 [3445.45,50272,1],
          #             ],
          #             "version":2827730444,
          #             "timestamp":1634117846232
          #         }
          #     }
          #
          data = self.safe_value(response, 'data', {})
          priceKey = 'price' if market['spot'] else 0
          amountKey = 'quantity' if market['spot'] else 1
          timestamp = self.safe_integer(data, 'timestamp')
          orderbook = self.parse_order_book(data, symbol, timestamp, 'bids', 'asks', priceKey, amountKey)
          orderbook['nonce'] = self.safe_integer(data, 'version')
          return orderbook
  
      def fetch_trades(self, symbol, since=None, limit=None, params={}):
          self.load_markets()
          market = self.market(symbol)
          request = {
              'symbol': market['id'],
          }
          if limit is not None:
              request['limit'] = limit  # default 100, max 100
          method = None
          if market['spot']:
              method = 'spotPublicGetMarketDeals'
          elif market['swap']:
              method = 'contractPublicGetDealsSymbol'
          response = getattr(self, method)(self.extend(request, params))
          #
          # spot
          #
          #     {
          #         "code":200,
          #         "data":[
          #             {"trade_time":1633381766725,"trade_price":"0.068981","trade_quantity":"0.005","trade_type":"BID"},
          #             {"trade_time":1633381732705,"trade_price":"0.068979","trade_quantity":"0.006","trade_type":"BID"},
          #             {"trade_time":1633381694604,"trade_price":"0.068975","trade_quantity":"0.011","trade_type":"ASK"},
          #         ]
          #     }
          #
          # swap / contract
          #
          #     {
          #         "success":true,
          #         "code":0,
          #         "data":[
          #             {"p":3598.85,"v":52,"T":1,"O":2,"M":2,"t":1634169038038},
          #             {"p":3599.2,"v":15,"T":2,"O":3,"M":1,"t":1634169035603},
          #             {"p":3600.15,"v":229,"T":2,"O":1,"M":2,"t":1634169026354},
          #         ]
          #     }
          #
          data = self.safe_value(response, 'data', [])
          return self.parse_trades(data, market, since, limit)
  
      def parse_trade(self, trade, market=None):
          #
          # public fetchTrades
          #
          #     spot
          #
          #     {
          #         "trade_time":1633381766725,
          #         "trade_price":"0.068981",
          #         "trade_quantity":"0.005",
          #         "trade_type":"BID"
          #     }
          #
          #     swap / contract
          #
          #     {
          #         "p":3598.85,
          #         "v":52,
          #         "T":1,  # 1 buy, 2 sell
          #         "O":2,  # 1 opens a position, 2 does not open a position
          #         "M":2,  # self-trading, 1 yes, 2 no
          #         "t":1634169038038
          #     }
          #
          # private fetchMyTrades, fetchOrderTrades
          #
          #     {
          #         "id":"b160b8f072d9403e96289139d5544809",
          #         "symbol":"USDC_USDT",
          #         "quantity":"150",
          #         "price":"0.9997",
          #         "amount":"149.955",
          #         "fee":"0.29991",
          #         "trade_type":"ASK",
          #         "order_id":"d798765285374222990bbd14decb86cd",
          #         "is_taker":true,
          #         "fee_currency":"USDT",
          #         "create_time":1633984904000
          #     }
          #
          timestamp = self.safe_integer_2(trade, 'create_time', 'trade_time')
          timestamp = self.safe_integer(trade, 't', timestamp)
          marketId = self.safe_string(trade, 'symbol')
          market = self.safe_market(marketId, market, '_')
          symbol = market['symbol']
          priceString = self.safe_string_2(trade, 'price', 'trade_price')
          priceString = self.safe_string(trade, 'p', priceString)
          amountString = self.safe_string_2(trade, 'quantity', 'trade_quantity')
          amountString = self.safe_string(trade, 'v', amountString)
          costString = self.safe_string(trade, 'amount')
          side = self.safe_string_2(trade, 'trade_type', 'T')
          if (side == 'BID') or (side == '1'):
              side = 'buy'
          elif (side == 'ASK') or (side == '2'):
              side = 'sell'
          id = self.safe_string_2(trade, 'id', 'trade_time')
          if id is None:
              id = self.safe_string(trade, 't', id)
              if id is not None:
                  id += '-' + market['id'] + '-' + amountString
          feeCostString = self.safe_string(trade, 'fee')
          fee = None
          if feeCostString is not None:
              feeCurrencyId = self.safe_string(trade, 'fee_currency')
              feeCurrencyCode = self.safe_currency_code(feeCurrencyId)
              fee = {
                  'cost': feeCostString,
                  'currency': feeCurrencyCode,
              }
          orderId = self.safe_string(trade, 'order_id')
          isTaker = self.safe_value(trade, 'is_taker', True)
          takerOrMaker = 'taker' if isTaker else 'maker'
          return self.safe_trade({
              'info': trade,
              'id': id,
              'order': orderId,
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
              'symbol': symbol,
              'type': None,
              'side': side,
              'takerOrMaker': takerOrMaker,
              'price': priceString,
              'amount': amountString,
              'cost': costString,
              'fee': fee,
          }, market)
  
      def fetch_ohlcv(self, symbol, timeframe='1m', since=None, limit=None, params={}):
          self.load_markets()
          market = self.market(symbol)
          options = self.safe_value(self.options, 'timeframes', {})
          timeframes = self.safe_value(options, market['type'], {})
          timeframeValue = self.safe_string(timeframes, timeframe)
          if timeframeValue is None:
              raise NotSupported(self.id + ' fetchOHLCV() does not support ' + timeframe + ' timeframe for ' + market['type'] + ' markets')
          request = {
              'symbol': market['id'],
              'interval': timeframeValue,
          }
          method = None
          if market['spot']:
              method = 'spotPublicGetMarketKline'
              if since is not None:
                  request['start_time'] = int(since / 1000)
              if limit is not None:
                  request['limit'] = limit  # default 100
          elif market['swap']:
              method = 'contractPublicGetKlineSymbol'
              if since is not None:
                  request['start'] = int(since / 1000)
              # request['end'] = self.seconds()
          response = getattr(self, method)(self.extend(request, params))
          #
          # spot
          #
          #     {
          #         "code":200,
          #         "data":[
          #             [1633377000,"49227.47","49186.21","49227.47","49169.48","0.5984809999999999","29434.259665989997"],
          #             [1633377060,"49186.21","49187.03","49206.64","49169.18","0.3658478","17990.651234393"],
          #             [1633377120,"49187.03","49227.2","49227.2","49174.4","0.0687651","3382.353190352"],
          #         ],
          #     }
          #
          # swap / contract
          #
          #     {
          #         "success":true,
          #         "code":0,
          #         "data":{
          #             "time":[1634052300,1634052360,1634052420],
          #             "open":[3492.2,3491.3,3495.65],
          #             "close":[3491.3,3495.65,3495.2],
          #             "high":[3495.85,3496.55,3499.4],
          #             "low":[3491.15,3490.9,3494.2],
          #             "vol":[1740.0,351.0,314.0],
          #             "amount":[60793.623,12260.4885,10983.1375],
          #         }
          #     }
          #
          if market['spot']:
              data = self.safe_value(response, 'data', [])
              return self.parse_ohlcvs(data, market, timeframe, since, limit)
          elif market['swap']:
              data = self.safe_value(response, 'data', {})
              result = self.convert_trading_view_to_ohlcv(data, 'time', 'open', 'high', 'low', 'close', 'vol')
              return self.parse_ohlcvs(result, market, timeframe, since, limit)
  
      def parse_ohlcv(self, ohlcv, market=None):
          #
          # the ordering in spot candles is OCHLV
          #
          #     [
          #         1633377000,  # 0 timestamp(unix seconds)
          #         "49227.47",  # 1 open price
          #         "49186.21",  # 2 closing price
          #         "49227.47",  # 3 high
          #         "49169.48",  # 4 low
          #         "0.5984809999999999",  # 5 base volume
          #         "29434.259665989997",  # 6 quote volume
          #     ]
          #
          # the ordering in swap / contract candles is OHLCV
          #
          return [
              self.safe_timestamp(ohlcv, 0),
              self.safe_number(ohlcv, 1),
              self.safe_number(ohlcv, 3 if market['spot'] else 2),
              self.safe_number(ohlcv, 4 if market['spot'] else 3),
              self.safe_number(ohlcv, 2 if market['spot'] else 4),
              self.safe_number(ohlcv, 5),
          ]
  
      def fetch_premium_index_ohlcv(self, symbol, timeframe='1m', since=None, limit=None, params={}):
          request = {
              'price': 'premiumIndex',
          }
          return self.fetch_ohlcv(symbol, timeframe, since, limit, self.extend(request, params))
  
      def fetch_index_ohlcv(self, symbol, timeframe='1m', since=None, limit=None, params={}):
          request = {
              'price': 'index',
          }
          return self.fetch_ohlcv(symbol, timeframe, since, limit, self.extend(request, params))
  
      def fetch_mark_ohlcv(self, symbol, timeframe='1m', since=None, limit=None, params={}):
          request = {
              'price': 'mark',
          }
          return self.fetch_ohlcv(symbol, timeframe, since, limit, self.extend(request, params))
  
      def fetch_balance(self, params={}):
          self.load_markets()
          marketType, query = self.handle_market_type_and_params('fetchBalance', None, params)
          method = self.get_supported_mapping(marketType, {
              'spot': 'spotPrivateGetAccountInfo',
              'margin': 'spotPrivateGetAccountInfo',
              'swap': 'contractPrivateGetAccountAssets',
          })
          spot = (marketType == 'spot')
          response = getattr(self, method)(query)
          #
          # spot
          #
          #     {
          #         code: "200",
          #         data: {
          #             USDC: {frozen: "0", available: "150"}
          #         }
          #     }
          #
          # swap / contract
          #
          #     {
          #         "success":true,
          #         "code":0,
          #         "data":[
          #             {"currency":"BSV","positionMargin":0,"availableBalance":0,"cashBalance":0,"frozenBalance":0,"equity":0,"unrealized":0,"bonus":0},
          #             {"currency":"BCH","positionMargin":0,"availableBalance":0,"cashBalance":0,"frozenBalance":0,"equity":0,"unrealized":0,"bonus":0},
          #             {"currency":"CRV","positionMargin":0,"availableBalance":0,"cashBalance":0,"frozenBalance":0,"equity":0,"unrealized":0,"bonus":0},
          #         ]
          #     }
          #
          data = self.safe_value(response, 'data', {})
          currentTime = self.milliseconds()
          result = {
              'info': response,
              'timestamp': currentTime,
              'datetime': self.iso8601(currentTime),
          }
          if spot:
              currencyIds = list(data.keys())
              for i in range(0, len(currencyIds)):
                  currencyId = currencyIds[i]
                  code = self.safe_currency_code(currencyId)
                  balance = self.safe_value(data, currencyId, {})
                  account = self.account()
                  account['free'] = self.safe_string(balance, 'available')
                  account['used'] = self.safe_string(balance, 'frozen')
                  result[code] = account
          else:
              for i in range(0, len(data)):
                  balance = data[i]
                  currencyId = self.safe_string(balance, 'currency')
                  code = self.safe_currency_code(currencyId)
                  account = self.account()
                  account['free'] = self.safe_string(balance, 'availableBalance')
                  account['used'] = self.safe_string(balance, 'frozenBalance')
                  result[code] = account
          return self.safe_balance(result)
  
      def safe_network(self, networkId):
          if networkId.find('BSC') >= 0:
              return 'BEP20'
          parts = networkId.split(' ')
          networkId = ''.join(parts)
          networkId = networkId.replace('-20', '20')
          networksById = {
              'ETH': 'ETH',
              'ERC20': 'ERC20',
              'BEP20(BSC)': 'BEP20',
              'TRX': 'TRC20',
          }
          return self.safe_string(networksById, networkId, networkId)
  
      def parse_deposit_address(self, depositAddress, currency=None):
          #
          #     {"chain":"ERC-20","address":"0x55cbd73db24eafcca97369e3f2db74b2490586e6"},
          #     {"chain":"MATIC","address":"0x05aa3236f1970eae0f8feb17ec19435b39574d74"},
          #     {"chain":"TRC20","address":"TGaPfhW41EXD3sAfs1grLF6DKfugfqANNw"},
          #     {"chain":"SOL","address":"5FSpUKuh2gjw4mF89T2e7sEjzUA1SkRKjBChFqP43KhV"},
          #     {"chain":"ALGO","address":"B3XTZND2JJTSYR7R2TQVCUDT4QSSYVAIZYDPWVBX34DGAYATBU3AUV43VU"}
          #
          #
          address = self.safe_string(depositAddress, 'address')
          code = self.safe_currency_code(None, currency)
          networkId = self.safe_string(depositAddress, 'chain')
          network = self.safe_network(networkId)
          self.check_address(address)
          return {
              'currency': code,
              'address': address,
              'tag': None,
              'network': network,
              'info': depositAddress,
          }
  
      def fetch_deposit_addresses_by_network(self, code, params={}):
          self.load_markets()
          currency = self.currency(code)
          request = {
              'currency': currency['id'],
          }
          response = self.spotPrivateGetAssetDepositAddressList(self.extend(request, params))
          #
          #     {
          #         "code":200,
          #         "data":{
          #             "currency":"USDC",
          #             "chains":[
          #                 {"chain":"ERC-20","address":"0x55cbd73db24eafcca97369e3f2db74b2490586e6"},
          #                 {"chain":"MATIC","address":"0x05aa3236f1970eae0f8feb17ec19435b39574d74"},
          #                 {"chain":"TRC20","address":"TGaPfhW41EXD3sAfs1grLF6DKfugfqANNw"},
          #                 {"chain":"SOL","address":"5FSpUKuh2gjw4mF89T2e7sEjzUA1SkRKjBChFqP43KhV"},
          #                 {"chain":"ALGO","address":"B3XTZND2JJTSYR7R2TQVCUDT4QSSYVAIZYDPWVBX34DGAYATBU3AUV43VU"}
          #             ]
          #         }
          #     }
          #
          data = self.safe_value(response, 'data', {})
          chains = self.safe_value(data, 'chains', [])
          depositAddresses = []
          for i in range(0, len(chains)):
              depositAddress = self.parse_deposit_address(chains[i], currency)
              depositAddresses.append(depositAddress)
          return self.index_by(depositAddresses, 'network')
  
      def fetch_deposit_address(self, code, params={}):
          rawNetwork = self.safe_string_upper(params, 'network')
          params = self.omit(params, 'network')
          response = self.fetch_deposit_addresses_by_network(code, params)
          networks = self.safe_value(self.options, 'networks', {})
          network = self.safe_string(networks, rawNetwork, rawNetwork)
          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
          # TODO: add support for all aliases here
          result = self.safe_value(response, rawNetwork)
          if result is None:
              raise InvalidAddress(self.id + ' fetchDepositAddress() cannot find ' + network + ' deposit address for ' + code)
          return result
  
      def fetch_deposits(self, code=None, since=None, limit=None, params={}):
          self.load_markets()
          request = {
              # 'currency': currency['id'],
              # 'state': 'state',
              # 'start_time': since,  # default 1 day
              # 'end_time': self.milliseconds(),
              # 'page_num': 1,
              # 'page_size': limit,  # default 20, maximum 50
          }
          currency = None
          if code is not None:
              currency = self.currency(code)
              request['currency'] = currency['id']
          if since is not None:
              request['start_time'] = since
          if limit is not None:
              request['limit'] = limit
          response = self.spotPrivateGetAssetDepositList(self.extend(request, params))
          #
          #     {
          #         "code":200,
          #         "data":{
          #             "page_size":20,
          #             "total_page":1,
          #             "total_size":1,
          #             "page_num":1,
          #             "result_list":[
          #                 {
          #                     "currency":"USDC",
          #                     "amount":150.0,
          #                     "fee":0.0,
          #                     "confirmations":19,
          #                     "address":"0x55cbd73db24eafcca97369e3f2db74b2490586e6",
          #                     "state":"SUCCESS",
          #                     "tx_id":"0xc65a9b09e1b71def81bf8bb3ec724c0c1b2b4c82200c8c142e4ea4c1469fd789:0",
          #                     "require_confirmations":12,
          #                     "create_time":"2021-10-11T18:58:25.000+00:00",
          #                     "update_time":"2021-10-11T19:01:06.000+00:00"
          #                 }
          #             ]
          #         }
          #     }
          #
          data = self.safe_value(response, 'data', {})
          resultList = self.safe_value(data, 'result_list', [])
          return self.parse_transactions(resultList, code, since, limit)
  
      def fetch_withdrawals(self, code=None, since=None, limit=None, params={}):
          self.load_markets()
          request = {
              # 'withdrawal_id': '4b450616042a48c99dd45cacb4b092a7',  # string
              # 'currency': currency['id'],
              # 'state': 'state',
              # 'start_time': since,  # default 1 day
              # 'end_time': self.milliseconds(),
              # 'page_num': 1,
              # 'page_size': limit,  # default 20, maximum 50
          }
          currency = None
          if code is not None:
              currency = self.currency(code)
              request['currency'] = currency['id']
          if since is not None:
              request['start_time'] = since
          if limit is not None:
              request['limit'] = limit
          response = self.spotPrivateGetAssetWithdrawList(self.extend(request, params))
          #
          #     {
          #         "code":200,
          #         "data":{
          #             "page_size":20,
          #             "total_page":1,
          #             "total_size":1,
          #             "page_num":1,
          #             "result_list":[
          #                 {
          #                     "id":"4b450616042a48c99dd45cacb4b092a7",
          #                     "currency":"USDT-TRX",
          #                     "address":"TRHKnx74Gb8UVcpDCMwzZVe4NqXfkdtPak",
          #                     "amount":30.0,
          #                     "fee":1.0,
          #                     "remark":"self is my first withdrawal remark",
          #                     "state":"WAIT",
          #                     "create_time":"2021-10-11T20:45:08.000+00:00"
          #                 }
          #             ]
          #         }
          #     }
          #
          data = self.safe_value(response, 'data', {})
          resultList = self.safe_value(data, 'result_list', [])
          return self.parse_transactions(resultList, code, since, limit)
  
      def parse_transaction(self, transaction, currency=None):
          #
          # fetchDeposits
          #
          #     {
          #         "currency":"USDC",
          #         "amount":150.0,
          #         "fee":0.0,
          #         "confirmations":19,
          #         "address":"0x55cbd73db24eafcca97369e3f2db74b2490586e6",
          #         "state":"SUCCESS",
          #         "tx_id":"0xc65a9b09e1b71def81bf8bb3ec724c0c1b2b4c82200c8c142e4ea4c1469fd789:0",
          #         "require_confirmations":12,
          #         "create_time":"2021-10-11T18:58:25.000+00:00",
          #         "update_time":"2021-10-11T19:01:06.000+00:00"
          #     }
          #
          # fetchWithdrawals
          #
          #     {
          #         "id":"4b450616042a48c99dd45cacb4b092a7",
          #         "currency":"USDT-TRX",
          #         "address":"TRHKnx74Gb8UVcpDCMwzZVe4NqXfkdtPak",
          #         "amount":30.0,
          #         "fee":1.0,
          #         "remark":"self is my first withdrawal remark",
          #         "state":"WAIT",
          #         "create_time":"2021-10-11T20:45:08.000+00:00"
          #     }
          #
          id = self.safe_string(transaction, 'id')
          type = 'deposit' if (id is None) else 'withdrawal'
          timestamp = self.parse8601(self.safe_string(transaction, 'create_time'))
          updated = self.parse8601(self.safe_string(transaction, 'update_time'))
          currencyId = self.safe_string(transaction, 'currency')
          network = None
          if (currencyId is not None) and (currencyId.find('-') >= 0):
              parts = currencyId.split('-')
              currencyId = self.safe_string(parts, 0)
              networkId = self.safe_string(parts, 1)
              network = self.safe_network(networkId)
          code = self.safe_currency_code(currencyId, currency)
          status = self.parse_transaction_status(self.safe_string(transaction, 'state'))
          amountString = self.safe_string(transaction, 'amount')
          address = self.safe_string(transaction, 'address')
          txid = self.safe_string(transaction, 'tx_id')
          fee = None
          feeCostString = self.safe_string(transaction, 'fee')
          if feeCostString is not None:
              fee = {
                  'cost': self.parse_number(feeCostString),
                  'currency': code,
              }
          if type == 'withdrawal':
              # mexc withdrawal amount includes the fee
              amountString = Precise.string_sub(amountString, feeCostString)
          return {
              'info': transaction,
              'id': id,
              'txid': txid,
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
              'network': network,
              'address': address,
              'addressTo': None,
              'addressFrom': None,
              'tag': None,
              'tagTo': None,
              'tagFrom': None,
              'type': type,
              'amount': self.parse_number(amountString),
              'currency': code,
              'status': status,
              'updated': updated,
              'fee': fee,
          }
  
      def parse_transaction_status(self, status):
          statuses = {
              'WAIT': 'pending',
              'WAIT_PACKAGING': 'pending',
              'SUCCESS': 'ok',
          }
          return self.safe_string(statuses, status, status)
  
      def fetch_position(self, symbol, params={}):
          self.load_markets()
          market = self.market(symbol)
          request = {
              'symbol': market['id'],
          }
          response = self.fetch_positions(self.extend(request, params))
          firstPosition = self.safe_value(response, 0)
          return self.parse_position(firstPosition, market)
  
      def fetch_positions(self, symbols=None, params={}):
          self.load_markets()
          response = self.contractPrivateGetPositionOpenPositions(params)
          #
          #     {
          #         "success": True,
          #         "code": 0,
          #         "data": [
          #             {
          #                 "positionId": 1394650,
          #                 "symbol": "ETH_USDT",
          #                 "positionType": 1,
          #                 "openType": 1,
          #                 "state": 1,
          #                 "holdVol": 1,
          #                 "frozenVol": 0,
          #                 "closeVol": 0,
          #                 "holdAvgPrice": 1217.3,
          #                 "openAvgPrice": 1217.3,
          #                 "closeAvgPrice": 0,
          #                 "liquidatePrice": 1211.2,
          #                 "oim": 0.1290338,
          #                 "im": 0.1290338,
          #                 "holdFee": 0,
          #                 "realised": -0.0073,
          #                 "leverage": 100,
          #                 "createTime": 1609991676000,
          #                 "updateTime": 1609991676000,
          #                 "autoAddIm": False
          #             }
          #         ]
          #     }
          #
          data = self.safe_value(response, 'data', [])
          return self.parse_positions(data)
  
      def parse_position(self, position, market=None):
          #
          #     {
          #         "positionId": 1394650,
          #         "symbol": "ETH_USDT",
          #         "positionType": 1,
          #         "openType": 1,
          #         "state": 1,
          #         "holdVol": 1,
          #         "frozenVol": 0,
          #         "closeVol": 0,
          #         "holdAvgPrice": 1217.3,
          #         "openAvgPrice": 1217.3,
          #         "closeAvgPrice": 0,
          #         "liquidatePrice": 1211.2,
          #         "oim": 0.1290338,
          #         "im": 0.1290338,
          #         "holdFee": 0,
          #         "realised": -0.0073,
          #         "leverage": 100,
          #         "createTime": 1609991676000,
          #         "updateTime": 1609991676000,
          #         "autoAddIm": False
          #     }
          #
          market = self.safe_market(self.safe_string(position, 'symbol'), market)
          symbol = market['symbol']
          contracts = self.safe_string(position, 'holdVol')
          entryPrice = self.safe_number(position, 'openAvgPrice')
          initialMargin = self.safe_string(position, 'im')
          rawSide = self.safe_string(position, 'positionType')
          side = 'long' if (rawSide == '1') else 'short'
          openType = self.safe_string(position, 'margin_mode')
          marginType = 'isolated' if (openType == '1') else 'cross'
          leverage = self.safe_string(position, 'leverage')
          liquidationPrice = self.safe_number(position, 'liquidatePrice')
          timestamp = self.safe_number(position, 'updateTime')
          return {
              'info': position,
              'symbol': symbol,
              'contracts': self.parse_number(contracts),
              'contractSize': None,
              'entryPrice': entryPrice,
              'collateral': None,
              'side': side,
              'unrealizedProfit': None,
              'leverage': self.parse_number(leverage),
              'percentage': None,
              'marginType': marginType,
              'notional': None,
              'markPrice': None,
              'liquidationPrice': liquidationPrice,
              'initialMargin': self.parse_number(initialMargin),
              'initialMarginPercentage': None,
              'maintenanceMargin': None,
              'maintenanceMarginPercentage': None,
              'marginRatio': None,
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
          }
  
      def parse_positions(self, positions):
          result = []
          for i in range(0, len(positions)):
              result.append(self.parse_position(positions[i]))
          return result
  
      def create_order(self, symbol, type, side, amount, price=None, params={}):
          self.load_markets()
          market = self.market(symbol)
          if market['spot']:
              return self.create_spot_order(symbol, type, side, amount, price, params)
          elif market['swap']:
              return self.create_swap_order(symbol, type, side, amount, price, params)
  
      def create_spot_order(self, symbol, type, side, amount, price=None, params={}):
          self.load_markets()
          market = self.market(symbol)
          orderSide = None
          if side == 'buy':
              orderSide = 'BID'
          elif side == 'sell':
              orderSide = 'ASK'
          orderType = type.upper()
          postOnly = self.safe_value(params, 'postOnly', False)
          if postOnly:
              orderType = 'POST_ONLY'
          elif orderType == 'LIMIT':
              orderType = 'LIMIT_ORDER'
          elif (orderType != 'POST_ONLY') and (orderType != 'IMMEDIATE_OR_CANCEL'):
              raise InvalidOrder(self.id + ' createOrder() does not support ' + type + ' order type, specify one of LIMIT, LIMIT_ORDER, POST_ONLY or IMMEDIATE_OR_CANCEL')
          request = {
              'symbol': market['id'],
              'price': self.price_to_precision(symbol, price),
              'quantity': self.amount_to_precision(symbol, amount),
              'trade_type': orderSide,
              'order_type': orderType,  # LIMIT_ORDER，POST_ONLY，IMMEDIATE_OR_CANCEL
          }
          clientOrderId = self.safe_string_2(params, 'clientOrderId', 'client_order_id')
          if clientOrderId is not None:
              request['client_order_id'] = clientOrderId
          params = self.omit(params, ['type', 'clientOrderId', 'client_order_id', 'postOnly'])
          response = self.spotPrivatePostOrderPlace(self.extend(request, params))
          #
          #     {"code":200,"data":"2ff3163e8617443cb9c6fc19d42b1ca4"}
          #
          return self.parse_order(response, market)
  
      def create_swap_order(self, symbol, type, side, amount, price=None, params={}):
          self.load_markets()
          market = self.market(symbol)
          openType = self.safe_integer(params, 'openType')
          if openType is None:
              raise ArgumentsRequired(self.id + ' createSwapOrder() requires an integer openType parameter, 1 for isolated margin, 2 for cross margin')
          if (type != 'limit') and (type != 'market') and (type != 1) and (type != 2) and (type != 3) and (type != 4) and (type != 5) and (type != 6):
              raise InvalidOrder(self.id + ' createSwapOrder() order type must either limit, market, or 1 for limit orders, 2 for post-only orders, 3 for IOC orders, 4 for FOK orders, 5 for market orders or 6 to convert market price to current price')
          postOnly = self.safe_value(params, 'postOnly', False)
          if postOnly:
              type = 2
          elif type == 'limit':
              type = 1
          elif type == 'market':
              type = 6
          if (side != 1) and (side != 2) and (side != 3) and (side != 4):
              raise InvalidOrder(self.id + ' createSwapOrder() order side must be 1 open long, 2 close short, 3 open short or 4 close long')
          request = {
              'symbol': market['id'],
              'price': float(self.price_to_precision(symbol, price)),
              'vol': float(self.amount_to_precision(symbol, amount)),
              # 'leverage': int,  # required for isolated margin
              'side': side,  # 1 open long, 2 close short, 3 open short, 4 close long
              #
              # supported order types
              #
              #     1 limit
              #     2 post only maker(PO)
              #     3 transact or cancel instantly(IOC)
              #     4 transact completely or cancel completely(FOK)
              #     5 market orders
              #     6 convert market price to current price
              #
              'type': type,
              'openType': openType,  # 1 isolated, 2 cross
              # 'positionId': 1394650,  # long, filling in self parameter when closing a position is recommended
              # 'externalOid': clientOrderId,
              # 'stopLossPrice': self.price_to_precision(symbol, stopLossPrice),
              # 'takeProfitPrice': self.price_to_precision(symbol, takeProfitPrice),
          }
          if openType == 1:
              leverage = self.safe_integer(params, 'leverage')
              if leverage is None:
                  raise ArgumentsRequired(self.id + ' createSwapOrder() requires a leverage parameter for isolated margin orders')
          clientOrderId = self.safe_string_2(params, 'clientOrderId', 'externalOid')
          if clientOrderId is not None:
              request['externalOid'] = clientOrderId
          params = self.omit(params, ['clientOrderId', 'externalOid', 'postOnly'])
          response = self.contractPrivatePostOrderSubmit(self.extend(request, params))
          #
          #     {"code":200,"data":"2ff3163e8617443cb9c6fc19d42b1ca4"}
          #
          return self.parse_order(response, market)
  
      def cancel_order(self, id, symbol=None, params={}):
          self.load_markets()
          request = {}
          clientOrderId = self.safe_string_2(params, 'clientOrderId', 'client_order_ids')
          if clientOrderId is not None:
              params = self.omit(params, ['clientOrderId', 'client_order_ids'])
              request['client_order_ids'] = clientOrderId
          else:
              request['order_ids'] = id
          response = self.spotPrivateDeleteOrderCancel(self.extend(request, params))
          #
          #    {"code":200,"data":{"965245851c444078a11a7d771323613b":"success"}}
          #
          data = self.safe_value(response, 'data')
          return self.parse_order(data)
  
      def parse_order_status(self, status):
          statuses = {
              'NEW': 'open',
              'FILLED': 'closed',
              'PARTIALLY_FILLED': 'open',
              'CANCELED': 'canceled',
              'PARTIALLY_CANCELED': 'canceled',
          }
          return self.safe_string(statuses, status, status)
  
      def parse_order(self, order, market=None):
          #
          # createOrder
          #
          # spot
          #
          #     {"code":200,"data":"2ff3163e8617443cb9c6fc19d42b1ca4"}
          #
          # swap / contract
          #
          #     {"success": True, "code": 0, "data": 102057569836905984}
          #
          # fetchOpenOrders
          #
          #     {
          #         "id":"965245851c444078a11a7d771323613b",
          #         "symbol":"ETH_USDT",
          #         "price":"3430",
          #         "quantity":"0.01",
          #         "state":"NEW",
          #         "type":"BID",
          #         "remain_quantity":"0.01",
          #         "remain_amount":"34.3",
          #         "create_time":1633989029039,
          #         "client_order_id":"",
          #         "order_type":"LIMIT_ORDER"
          #     }
          #
          # fetchClosedOrders, fetchCanceledOrders, fetchOrder
          #
          #     {
          #         "id":"d798765285374222990bbd14decb86cd",
          #         "symbol":"USDC_USDT",
          #         "price":"0.9988",
          #         "quantity":"150",
          #         "state":"FILLED",  # CANCELED
          #         "type":"ASK",  # BID
          #         "deal_quantity":"150",
          #         "deal_amount":"149.955",
          #         "create_time":1633984904000,
          #         "order_type":"MARKET_ORDER"  # LIMIT_ORDER
          #     }
          #
          # cancelOrder
          #
          #     {"965245851c444078a11a7d771323613b":"success"}
          #
          id = self.safe_string_2(order, 'data', 'id')
          status = None
          if id is None:
              keys = list(order.keys())
              id = self.safe_string(keys, 0)
              state = self.safe_string(order, id)
              if state == 'success':
                  status = 'canceled'
          state = self.safe_string(order, 'state')
          timestamp = self.safe_integer(order, 'create_time')
          price = self.safe_string(order, 'price')
          amount = self.safe_string(order, 'quantity')
          remaining = self.safe_string(order, 'remain_quantity')
          filled = self.safe_string(order, 'deal_quantity')
          marketId = self.safe_string(order, 'symbol')
          symbol = self.safe_symbol(marketId, market, '_')
          side = None
          bidOrAsk = self.safe_string(order, 'type')
          if bidOrAsk == 'BID':
              side = 'buy'
          elif bidOrAsk == 'ASK':
              side = 'sell'
          status = self.parse_order_status(state)
          clientOrderId = self.safe_string(order, 'client_order_id')
          if clientOrderId == '':
              clientOrderId = None
          orderType = self.safe_string_lower(order, 'order_type')
          if orderType is not None:
              orderType = orderType.replace('_order', '')
          return self.safe_order({
              'id': id,
              'clientOrderId': clientOrderId,
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
              'lastTradeTimestamp': None,
              'status': status,
              'symbol': symbol,
              'type': orderType,
              'timeInForce': None,
              'side': side,
              'price': price,
              'stopPrice': None,
              'average': None,
              'amount': amount,
              'cost': None,
              'filled': filled,
              'remaining': remaining,
              'fee': None,
              'trades': None,
              'info': order,
          }, market)
  
      def fetch_open_orders(self, symbol=None, since=None, limit=None, params={}):
          if symbol is None:
              raise ArgumentsRequired(self.id + ' fetchOpenOrders() requires a symbol argument')
          self.load_markets()
          market = self.market(symbol)
          request = {
              'symbol': market['id'],
              # 'start_time': since,
              # 'limit': limit,  # default 50, max 1000
              # 'trade_type': 'BID',  # BID / ASK
          }
          response = self.spotPrivateGetOrderOpenOrders(self.extend(request, params))
          #
          #     {
          #         "code":200,
          #         "data":[
          #             {
          #                 "id":"965245851c444078a11a7d771323613b",
          #                 "symbol":"ETH_USDT",
          #                 "price":"3430",
          #                 "quantity":"0.01",
          #                 "state":"NEW",
          #                 "type":"BID",
          #                 "remain_quantity":"0.01",
          #                 "remain_amount":"34.3",
          #                 "create_time":1633989029039,
          #                 "client_order_id":"",
          #                 "order_type":"LIMIT_ORDER"
          #             },
          #             {
          #                 "id":"2ff3163e8617443cb9c6fc19d42b1ca4",
          #                 "symbol":"ETH_USDT",
          #                 "price":"3420",
          #                 "quantity":"0.01",
          #                 "state":"NEW",
          #                 "type":"BID",
          #                 "remain_quantity":"0.01",
          #                 "remain_amount":"34.2",
          #                 "create_time":1633988662382,
          #                 "client_order_id":"",
          #                 "order_type":"LIMIT_ORDER"
          #             }
          #         ]
          #     }
          #
          data = self.safe_value(response, 'data', [])
          return self.parse_orders(data, market, since, limit)
  
      def fetch_order(self, id, symbol=None, params={}):
          self.load_markets()
          request = {
              'order_ids': id,
          }
          response = self.spotPrivateGetOrderQuery(self.extend(request, params))
          #
          #     {
          #         "code":200,
          #         "data":[
          #             {
          #                 "id":"2ff3163e8617443cb9c6fc19d42b1ca4",
          #                 "symbol":"ETH_USDT",
          #                 "price":"3420",
          #                 "quantity":"0.01",
          #                 "state":"CANCELED",
          #                 "type":"BID",
          #                 "deal_quantity":"0",
          #                 "deal_amount":"0",
          #                 "create_time":1633988662000,
          #                 "order_type":"LIMIT_ORDER"
          #             }
          #         ]
          #     }
          #
          data = self.safe_value(response, 'data', [])
          firstOrder = self.safe_value(data, 0)
          if firstOrder is None:
              raise OrderNotFound(self.id + ' fetchOrder() could not find the order id ' + id)
          return self.parse_order(firstOrder)
  
      def fetch_orders_by_state(self, state, symbol=None, since=None, limit=None, params={}):
          if symbol is None:
              raise ArgumentsRequired(self.id + ' fetchOrdersByState requires a symbol argument')
          self.load_markets()
          market = self.market(symbol)
          request = {
              'symbol': market['id'],
              # 'start_time': since,  # default 7 days, max 30 days
              # 'limit': limit,  # default 50, max 1000
              # 'trade_type': 'BID',  # BID / ASK
              'states': state,  # NEW, FILLED, PARTIALLY_FILLED, CANCELED, PARTIALLY_CANCELED
          }
          if limit is not None:
              request['limit'] = limit
          if since is not None:
              request['start_time'] = since
          response = self.spotPrivateGetOrderList(self.extend(request, params))
          data = self.safe_value(response, 'data', [])
          return self.parse_orders(data, market, since, limit)
  
      def fetch_canceled_orders(self, symbol=None, since=None, limit=None, params={}):
          return self.fetch_orders_by_state('CANCELED', symbol, since, limit, params)
  
      def fetch_closed_orders(self, symbol=None, since=None, limit=None, params={}):
          return self.fetch_orders_by_state('FILLED', symbol, since, limit, params)
  
      def cancel_all_orders(self, symbol=None, params={}):
          self.load_markets()
          market = self.market(symbol)
          request = {
              'symbol': market['id'],
          }
          response = self.spotPrivateDeleteOrderCancelBySymbol(self.extend(request, params))
          #
          #     {
          #         "code": 200,
          #         "data": [
          #             {
          #                 "msg": "success",
          #                 "order_id": "75ecf99feef04538b78e4622beaba6eb",
          #                 "client_order_id": "a9329e86f2094b0d8b58e92c25029554"
          #             },
          #             {
          #                 "msg": "success",
          #                 "order_id": "139413c48f8b4c018f452ce796586bcf"
          #             },
          #             {
          #                 "msg": "success",
          #                 "order_id": "b58ef34c570e4917981f276d44091484"
          #             }
          #         ]
          #     }
          #
          return response
  
      def fetch_my_trades(self, symbol=None, since=None, limit=None, params={}):
          if symbol is None:
              raise ArgumentsRequired(self.id + ' fetchMyTrades requires a symbol argument')
          self.load_markets()
          market = self.market(symbol)
          request = {
              'symbol': market['id'],
              # 'start_time': since,  # default 7 days, max 30 days
              # 'limit': limit,  # default 50, max 1000
          }
          if since is not None:
              request['start_time'] = since
          if limit is not None:
              request['limit'] = limit
          response = self.spotPrivateGetOrderDeals(self.extend(request, params))
          #
          #     {
          #         "code":200,
          #         "data":[
          #             {
          #                 "id":"b160b8f072d9403e96289139d5544809",
          #                 "symbol":"USDC_USDT",
          #                 "quantity":"150",
          #                 "price":"0.9997",
          #                 "amount":"149.955",
          #                 "fee":"0.29991",
          #                 "trade_type":"ASK",
          #                 "order_id":"d798765285374222990bbd14decb86cd",
          #                 "is_taker":true,
          #                 "fee_currency":"USDT",
          #                 "create_time":1633984904000
          #             }
          #         ]
          #     }
          #
          data = self.safe_value(response, 'data', [])
          return self.parse_trades(data, market, since, limit)
  
      def fetch_order_trades(self, id, symbol=None, since=None, limit=None, params={}):
          self.load_markets()
          market = None
          if symbol is not None:
              market = self.market(symbol)
          request = {
              'order_id': id,
          }
          response = self.spotPrivateGetOrderDealDetail(self.extend(request, params))
          #
          #     {
          #         "code":200,
          #         "data":[
          #             {
          #                 "id":"b160b8f072d9403e96289139d5544809",
          #                 "symbol":"USDC_USDT",
          #                 "quantity":"150",
          #                 "price":"0.9997",
          #                 "amount":"149.955",
          #                 "fee":"0.29991",
          #                 "trade_type":"ASK",
          #                 "order_id":"d798765285374222990bbd14decb86cd",
          #                 "is_taker":true,
          #                 "fee_currency":"USDT",
          #                 "create_time":1633984904000
          #             }
          #         ]
          #     }
          #
          data = self.safe_value(response, 'data', [])
          return self.parse_trades(data, market, since, limit)
  
      def modify_margin_helper(self, symbol, amount, addOrReduce, params={}):
          positionId = self.safe_integer(params, 'positionId')
          if positionId is None:
              raise ArgumentsRequired(self.id + ' modifyMarginHelper() requires a positionId parameter')
          self.load_markets()
          request = {
              'positionId': positionId,
              'amount': amount,
              'type': addOrReduce,
          }
          response = self.contractPrivatePostPositionChangeMargin(self.extend(request, params))
          #
          #     {
          #         "success": True,
          #         "code": 0
          #     }
          return response
  
      def reduce_margin(self, symbol, amount, params={}):
          return self.modify_margin_helper(symbol, amount, 'SUB', params)
  
      def add_margin(self, symbol, amount, params={}):
          return self.modify_margin_helper(symbol, amount, 'ADD', params)
  
      def set_leverage(self, leverage, symbol=None, params={}):
          positionId = self.safe_integer(params, 'positionId')
          if positionId is None:
              raise ArgumentsRequired(self.id + ' setLeverage() requires a positionId parameter')
          self.load_markets()
          request = {
              'positionId': positionId,
              'leverage': leverage,
          }
          return self.contractPrivatePostPositionChangeLeverage(self.extend(request, params))
  
      def withdraw(self, code, amount, address, tag=None, params={}):
          tag, params = self.handle_withdraw_tag_and_params(tag, params)
          networks = self.safe_value(self.options, 'networks', {})
          network = self.safe_string_2(params, 'network', 'chain')  # self line allows the user to specify either ERC20 or ETH
          network = self.safe_string(networks, network, network)  # handle ETH > ERC-20 alias
          self.check_address(address)
          self.load_markets()
          currency = self.currency(code)
          if tag is not None:
              address += ':' + tag
          request = {
              'currency': currency['id'],
              'address': address,
              'amount': amount,
          }
          if network is not None:
              request['chain'] = network
              params = self.omit(params, ['network', 'chain'])
          response = self.spotPrivatePostAssetWithdraw(self.extend(request, params))
          #
          #     {
          #         "code":200,
          #         "data": {
          #             "withdrawId":"25fb2831fb6d4fc7aa4094612a26c81d"
          #         }
          #     }
          #
          data = self.safe_value(response, 'data', {})
          return {
              'info': data,
              'id': self.safe_string(data, 'withdrawId'),
          }
  
      def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
          section, access = api
          url = self.urls['api'][section][access] + '/' + self.implode_params(path, params)
          params = self.omit(params, self.extract_params(path))
          if access == 'public':
              if params:
                  url += '?' + self.urlencode(params)
          else:
              self.check_required_credentials()
              timestamp = str(self.milliseconds())
              auth = ''
              headers = {
                  'ApiKey': self.apiKey,
                  'Request-Time': timestamp,
                  'Content-Type': 'application/json',
              }
              if method == 'POST':
                  auth = self.json(params)
                  body = auth
              else:
                  params = self.keysort(params)
                  if params:
                      auth += self.urlencode(params)
                      url += '?' + auth
              auth = self.apiKey + timestamp + auth
              signature = self.hmac(self.encode(auth), self.encode(self.secret), hashlib.sha256)
              headers['Signature'] = signature
          return {'url': url, 'method': method, 'body': body, 'headers': headers}
  
      def handle_errors(self, code, reason, url, method, headers, body, response, requestHeaders, requestBody):
          if response is None:
              return
          #     {"code":10232,"msg":"The currency not exist"}
          #     {"code":10216,"msg":"No available deposit address"}
          #
          #     {
          #         "success":true,
          #         "code":0,
          #         "data":1634095541710
          #     }
          #
          success = self.safe_value(response, 'success', False)
          if success is True:
              return
          responseCode = self.safe_string(response, 'code')
          if (responseCode != '200') and (responseCode != '0'):
              feedback = self.id + ' ' + body
              self.throw_broadly_matched_exception(self.exceptions['broad'], body, feedback)
              self.throw_exactly_matched_exception(self.exceptions['exact'], responseCode, feedback)
              raise ExchangeError(feedback)
  
      def fetch_funding_history(self, symbol=None, since=None, limit=None, params={}):
          self.load_markets()
          market = None
          request = {
              # 'symbol': market['id'],
              # 'position_id': positionId,
              # 'page_num': 1,
              # 'page_size': limit,  # default 20, max 100
          }
          if symbol is not None:
              market = self.market(symbol)
              request['symbol'] = market['id']
          if limit is not None:
              request['page_size'] = limit
          response = self.contractPrivateGetPositionFundingRecords(self.extend(request, params))
          #
          #     {
          #         "success": True,
          #         "code": 0,
          #         "data": {
          #             "pageSize": 20,
          #             "totalCount": 2,
          #             "totalPage": 1,
          #             "currentPage": 1,
          #             "resultList": [
          #                 {
          #                     "id": 7423910,
          #                     "symbol": "BTC_USDT",
          #                     "positionType": 1,
          #                     "positionValue": 29.30024,
          #                     "funding": 0.00076180624,
          #                     "rate": -0.000026,
          #                     "settleTime": 1643299200000
          #                 },
          #                 {
          #                     "id": 7416473,
          #                     "symbol": "BTC_USDT",
          #                     "positionType": 1,
          #                     "positionValue": 28.9188,
          #                     "funding": 0.0014748588,
          #                     "rate": -0.000051,
          #                     "settleTime": 1643270400000
          #                 }
          #             ]
          #         }
          #     }
          #
          data = self.safe_value(response, 'data', {})
          resultList = self.safe_value(data, 'resultList', [])
          result = []
          for i in range(0, len(resultList)):
              entry = resultList[i]
              timestamp = self.safe_string(entry, 'settleTime')
              result.append({
                  'info': entry,
                  'symbol': symbol,
                  'code': None,
                  'timestamp': timestamp,
                  'datetime': self.iso8601(timestamp),
                  'id': self.safe_number(entry, 'id'),
                  'amount': self.safe_number(entry, 'funding'),
              })
          return result
  
      def parse_funding_rate(self, fundingRate, market=None):
          #
          #     {
          #         "symbol": "BTC_USDT",
          #         "fundingRate": 0.000014,
          #         "maxFundingRate": 0.003,
          #         "minFundingRate": -0.003,
          #         "collectCycle": 8,
          #         "nextSettleTime": 1643241600000,
          #         "timestamp": 1643240373359
          #     }
          #
          nextFundingRate = self.safe_number(fundingRate, 'fundingRate')
          nextFundingTimestamp = self.safe_integer(fundingRate, 'nextSettleTime')
          marketId = self.safe_string(fundingRate, 'symbol')
          symbol = self.safe_symbol(marketId, market)
          timestamp = self.safe_integer(fundingRate, 'timestamp')
          datetime = self.iso8601(timestamp)
          return {
              'info': fundingRate,
              'symbol': symbol,
              'markPrice': None,
              'indexPrice': None,
              'interestRate': None,
              'estimatedSettlePrice': None,
              'timestamp': timestamp,
              'datetime': datetime,
              'fundingRate': None,
              'fundingTimestamp': None,
              'fundingDatetime': None,
              'nextFundingRate': nextFundingRate,
              'nextFundingTimestamp': nextFundingTimestamp,
              'nextFundingDatetime': self.iso8601(nextFundingTimestamp),
              'previousFundingRate': None,
              'previousFundingTimestamp': None,
              'previousFundingDatetime': None,
          }
  
      def fetch_funding_rate(self, symbol, params={}):
          self.load_markets()
          market = self.market(symbol)
          request = {
              'symbol': market['id'],
          }
          response = self.contractPublicGetFundingRateSymbol(self.extend(request, params))
          #
          #     {
          #         "success": True,
          #         "code": 0,
          #         "data": {
          #             "symbol": "BTC_USDT",
          #             "fundingRate": 0.000014,
          #             "maxFundingRate": 0.003,
          #             "minFundingRate": -0.003,
          #             "collectCycle": 8,
          #             "nextSettleTime": 1643241600000,
          #             "timestamp": 1643240373359
          #         }
          #     }
          #
          result = self.safe_value(response, 'data', {})
          return self.parse_funding_rate(result, market)
  
      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: mexc limit is page_size default 20, maximum is 100
          #  (param) since: not used by mexc
          #  (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')
          self.load_markets()
          market = self.market(symbol)
          request = {
              'symbol': market['id'],
              # 'page_size': limit,  # optional
              # 'page_num': 1,  # optional, current page number, default is 1
          }
          if limit is not None:
              request['page_size'] = limit
          response = self.contractPublicGetFundingRateHistory(self.extend(request, params))
          #
          # {
          #     "success": True,
          #     "code": 0,
          #     "data": {
          #         "pageSize": 2,
          #         "totalCount": 21,
          #         "totalPage": 11,
          #         "currentPage": 1,
          #         "resultList": [
          #             {
          #                 "symbol": "BTC_USDT",
          #                 "fundingRate": 0.000266,
          #                 "settleTime": 1609804800000
          #             },
          #             {
          #                 "symbol": "BTC_USDT",
          #                 "fundingRate": 0.00029,
          #                 "settleTime": 1609776000000
          #             }
          #         ]
          #     }
          # }
          #
          data = self.safe_value(response, 'data')
          result = self.safe_value(data, 'resultList')
          rates = []
          for i in range(0, len(result)):
              entry = result[i]
              marketId = self.safe_string(entry, 'symbol')
              symbol = self.safe_symbol(marketId)
              timestamp = self.safe_string(entry, 'settleTime')
              rates.append({
                  'info': entry,
                  'symbol': symbol,
                  'fundingRate': self.safe_number(entry, 'fundingRate'),
                  'timestamp': timestamp,
                  'datetime': self.iso8601(timestamp),
              })
          sorted = self.sort_by(rates, 'timestamp')
          return self.filter_by_symbol_since_limit(sorted, symbol, since, limit)
  
      def fetch_leverage_tiers(self, symbol=None, params={}):
          self.load_markets()
          symbolDefined = (symbol is not None)
          market = None
          if symbolDefined:
              market = self.market(symbol)
              if not market['contract']:
                  raise BadRequest(self.id + ' fetchLeverageTiers() supports contract markets only')
          response = self.contractPublicGetDetail(params)
          #
          #     {
          #         "success":true,
          #         "code":0,
          #         "data":[
          #             {
          #                 "symbol":"BTC_USDT",
          #                 "displayName":"BTC_USDT永续",
          #                 "displayNameEn":"BTC_USDT SWAP",
          #                 "positionOpenType":3,
          #                 "baseCoin":"BTC",
          #                 "quoteCoin":"USDT",
          #                 "settleCoin":"USDT",
          #                 "contractSize":0.0001,
          #                 "minLeverage":1,
          #                 "maxLeverage":125,
          #                 "priceScale":2,
          #                 "volScale":0,
          #                 "amountScale":4,
          #                 "priceUnit":0.5,
          #                 "volUnit":1,
          #                 "minVol":1,
          #                 "maxVol":1000000,
          #                 "bidLimitPriceRate":0.1,
          #                 "askLimitPriceRate":0.1,
          #                 "takerFeeRate":0.0006,
          #                 "makerFeeRate":0.0002,
          #                 "maintenanceMarginRate":0.004,
          #                 "initialMarginRate":0.008,
          #                 "riskBaseVol":10000,
          #                 "riskIncrVol":200000,
          #                 "riskIncrMmr":0.004,
          #                 "riskIncrImr":0.004,
          #                 "riskLevelLimit":5,
          #                 "priceCoefficientVariation":0.1,
          #                 "indexOrigin":["BINANCE","GATEIO","HUOBI","MXC"],
          #                 "state":0,  # 0 enabled, 1 delivery, 2 completed, 3 offline, 4 pause
          #                 "isNew":false,
          #                 "isHot":true,
          #                 "isHidden":false
          #             },
          #             ...
          #         ]
          #     }
          #
          result = {}
          data = self.safe_value(response, 'data')
          for i in range(0, len(data)):
              item = data[i]
              maintenanceMarginRate = self.safe_string(item, 'maintenanceMarginRate')
              initialMarginRate = self.safe_string(item, 'initialMarginRate')
              maxVol = self.safe_string(item, 'maxVol')
              riskIncrVol = self.safe_string(item, 'riskIncrVol')
              riskIncrMmr = self.safe_string(item, 'riskIncrMmr')
              riskIncrImr = self.safe_string(item, 'riskIncrImr')
              floor = '0'
              tiers = []
              quoteId = self.safe_string(item, 'quoteCoin')
              while(Precise.string_lt(floor, maxVol)):
                  cap = Precise.string_add(floor, riskIncrVol)
                  tiers.append({
                      'tier': self.parse_number(Precise.string_div(cap, riskIncrVol)),
                      'notionalCurrency': self.safe_currency_code(quoteId),
                      'notionalFloor': self.parse_number(floor),
                      'notionalCap': self.parse_number(cap),
                      'maintenanceMarginRate': self.parse_number(maintenanceMarginRate),
                      'maxLeverage': self.parse_number(Precise.string_div('1', initialMarginRate)),
                      'info': item,
                  })
                  initialMarginRate = Precise.string_add(initialMarginRate, riskIncrImr)
                  maintenanceMarginRate = Precise.string_add(maintenanceMarginRate, riskIncrMmr)
                  floor = cap
              id = self.safe_string(item, 'symbol')
              ccxtSymbol = self.safe_symbol(id)
              result[ccxtSymbol] = tiers
          return self.safe_value(result, symbol) if symbolDefined else result
  