text: # -*- coding: utf-8 -*-
  
  # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
  # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
  
  from ccxt.async_support.base.exchange import Exchange
  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': {
                  'cancelAllOrders': True,
                  'cancelOrder': True,
                  'createMarketOrder': False,
                  'createOrder': True,
                  'fetchBalance': True,
                  'fetchCanceledOrders': True,
                  'fetchClosedOrders': True,
                  'fetchCurrencies': True,
                  'fetchDepositAddress': True,
                  'fetchDepositAddressByNetwork': True,
                  'fetchDeposits': True,
                  'fetchMarkets': True,
                  'fetchMyTrades': True,
                  'fetchOHLCV': True,
                  'fetchOpenOrders': True,
                  'fetchOrder': True,
                  'fetchOrderBook': True,
                  'fetchOrderTrades': True,
                  'fetchPosition': True,
                  'fetchPositions': True,
                  'fetchStatus': True,
                  'fetchTicker': True,
                  'fetchTime': True,
                  'fetchTrades': True,
                  'fetchWIthdrawals': True,
                  'withdraw': True,
              },
              'timeframes': {
                  '1m': '1m',
                  '5m': '5m',
                  '15m': '15m',
                  '30m': '30m',
                  '1h': '1h',
                  '1d': '1d',
                  '1M': '1M',
              },
              'urls': {
                  'logo': 'https://user-images.githubusercontent.com/1294454/137283979-8b2a818d-8633-461b-bfca-de89e8c446b2.jpg',
                  'api': {
                      'spot': {
                          'public': 'https://www.mxc.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': {
                  'SIN': 'Sin City Token',
              },
              'exceptions': {
                  'exact': {
                      '400': BadRequest,  # Invalid parameter
                      '401': AuthenticationError,  # Invalid signature, fail to pass the validation
                      '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
                      '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': {
                  },
              },
          })
  
      async def fetch_time(self, params={}):
          defaultType = self.safe_string_2(self.options, 'fetchMarkets', 'defaultType', 'spot')
          type = self.safe_string(params, 'type', defaultType)
          query = self.omit(params, 'type')
          method = 'spotPublicGetCommonTimestamp'
          if type == 'contract':
              method = 'contractPublicGetPing'
          response = await getattr(self, method)(query)
          #
          # spot
          #
          #     {
          #         "code":200,
          #         "data":1633375641837
          #     }
          #
          # contract
          #
          #     {
          #         "success":true,
          #         "code":0,
          #         "data":1634095541710
          #     }
          #
          return self.safe_integer(response, 'data')
  
      async def fetch_status(self, params={}):
          response = await 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
  
      async def fetch_currencies(self, params={}):
          response = await 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 = None
              currencyPrecision = None
              currencyFee = None
              currencyWithdrawMin = None
              currencyWithdrawMax = None
              networks = {}
              chains = self.safe_value(currency, 'coins', [])
              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 if (currencyActive is None) else 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
                  networks[network] = {
                      'info': chain,
                      'id': networkId,
                      'network': network,
                      'active': active,
                      '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,
                  'fee': currencyFee,
                  'precision': currencyPrecision,
                  'limits': {
                      'amount': {
                          'min': None,
                          'max': None,
                      },
                      'withdraw': {
                          'min': currencyWithdrawMin,
                          'max': currencyWithdrawMax,
                      },
                  },
                  'networks': networks,
              }
          return result
  
      async def fetch_markets_by_type(self, type, params={}):
          method = 'fetch_' + type + '_markets'
          return await getattr(self, method)(params)
  
      async 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 await self.fetch_spot_markets(query)
          elif swap:
              return await self.fetch_contract_markets(query)
  
      async def fetch_contract_markets(self, params={}):
          response = await 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')
              base = self.safe_currency_code(baseId)
              quote = self.safe_currency_code(quoteId)
              symbol = id
              precision = {
                  'price': self.safe_number(market, 'priceUnit'),
                  'amount': self.safe_number(market, 'volUnit'),
              }
              taker = self.safe_number(market, 'takerFeeRate')
              maker = self.safe_number(market, 'makerFeeRate')
              state = self.safe_string(market, 'state')
              active = (state == '0')
              type = 'swap'
              swap = True
              spot = False
              contractSize = self.safe_string(market, 'contractSize')
              linear = True
              inverse = False
              result.append(self.extend(self.fees['trading'], {
                  'info': market,
                  'id': id,
                  'symbol': symbol,
                  'base': base,
                  'quote': quote,
                  'baseId': baseId,
                  'quoteId': quoteId,
                  'type': type,
                  'swap': swap,
                  'spot': spot,
                  'contractSize': contractSize,
                  'linear': linear,
                  'inverse': inverse,
                  'active': active,
                  'taker': taker,
                  'maker': maker,
                  'precision': precision,
                  'limits': {
                      'amount': {
                          'min': self.safe_number(market, 'minVol'),
                          'max': self.safe_number(market, 'maxVol'),
                      },
                      'price': {
                          'min': None,
                          'max': None,
                      },
                      'cost': {
                          'min': None,
                          'max': None,
                      },
                  },
              }))
          return result
  
      async def fetch_spot_markets(self, params={}):
          response = await 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)
              symbol = base + '/' + quote
              priceScale = self.safe_integer(market, 'price_scale')
              quantityScale = self.safe_integer(market, 'quantity_scale')
              pricePrecision = 1 / math.pow(10, priceScale)
              quantityPrecision = 1 / math.pow(10, quantityScale)
              precision = {
                  'price': pricePrecision,
                  'amount': quantityPrecision,
              }
              taker = self.safe_number(market, 'taker_fee_rate')
              maker = self.safe_number(market, 'maker_fee_rate')
              state = self.safe_string(market, 'state')
              active = (state == 'ENABLED')
              type = 'spot'
              swap = False
              spot = True
              result.append(self.extend(self.fees['trading'], {
                  'info': market,
                  'id': id,
                  'symbol': symbol,
                  'base': base,
                  'quote': quote,
                  'baseId': baseId,
                  'quoteId': quoteId,
                  'type': type,
                  'swap': swap,
                  'spot': spot,
                  'active': active,
                  'taker': taker,
                  'maker': maker,
                  'precision': precision,
                  'limits': {
                      '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'),
                      },
                  },
              }))
          return result
  
      async def fetch_tickers(self, symbols=None, params={}):
          await self.load_markets()
          defaultType = self.safe_string_2(self.options, 'fetchTickers', 'defaultType', 'spot')
          type = self.safe_string(params, 'type', defaultType)
          query = self.omit(params, 'type')
          if type != 'swap':
              raise NotSupported(self.id + ' fetchTickers() is supported for swap markets only')
          response = await self.contractPublicGetTicker(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)
  
      async def fetch_ticker(self, symbol, params={}):
          await self.load_markets()
          market = self.market(symbol)
          request = {
              'symbol': market['id'],
          }
          method = None
          if market['spot']:
              method = 'spotPublicGetMarketTicker'
          elif market['swap']:
              method = 'contractPublicGetTicker'
          response = await 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_number_2(ticker, 'volume', 'volume24')
          quoteVolume = self.safe_number(ticker, 'amount24')
          open = self.safe_number(ticker, 'open')
          lastString = self.safe_string_2(ticker, 'last', 'lastPrice')
          last = self.parse_number(lastString)
          change = self.safe_number(ticker, 'riseFallValue')
          riseFallRate = self.safe_string(ticker, 'riseFallRate')
          percentageString = Precise.string_add(riseFallRate, '1')
          percentage = self.parse_number(percentageString)
          return self.safe_ticker({
              'symbol': symbol,
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
              'high': self.safe_number_2(ticker, 'high', 'high24Price'),
              'low': self.safe_number_2(ticker, 'low', 'lower24Price'),
              'bid': self.safe_number_2(ticker, 'bid', 'bid1'),
              'bidVolume': None,
              'ask': self.safe_number_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)
  
      async def fetch_order_book(self, symbol, limit=None, params={}):
          await 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 = await 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
  
      async def fetch_trades(self, symbol, since=None, limit=None, params={}):
          await 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 = await 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')
          if costString is None:
              costString = Precise.string_mul(priceString, amountString)
          price = self.parse_number(priceString)
          amount = self.parse_number(amountString)
          cost = self.parse_number(costString)
          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
          feeCost = self.safe_number(trade, 'fee')
          fee = None
          if feeCost is not None:
              feeCurrencyId = self.safe_string(trade, 'fee_currency')
              feeCurrencyCode = self.safe_currency_code(feeCurrencyId)
              fee = {
                  'cost': feeCost,
                  'currency': feeCurrencyCode,
              }
          orderId = self.safe_string(trade, 'order_id')
          isTaker = self.safe_value(trade, 'is_taker', True)
          takerOrMaker = 'taker' if isTaker else 'maker'
          return {
              'info': trade,
              'id': id,
              'order': orderId,
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
              'symbol': symbol,
              'type': None,
              'side': side,
              'takerOrMaker': takerOrMaker,
              'price': price,
              'amount': amount,
              'cost': cost,
              'fee': fee,
          }
  
      async def fetch_ohlcv(self, symbol, timeframe='1m', since=None, limit=None, params={}):
          await self.load_markets()
          market = self.market(symbol)
          options = self.safe_value(self.options, 'timeframes', {})
          timeframes = self.safe_value(options, market['type'], {})
          request = {
              'symbol': market['id'],
              'interval': timeframes[timeframe],
          }
          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 = await 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),
          ]
  
      async def fetch_balance(self, params={}):
          await self.load_markets()
          defaultType = self.safe_string_2(self.options, 'fetchBalance', 'defaultType', 'spot')
          type = self.safe_string(params, 'type', defaultType)
          spot = (type == 'spot')
          swap = (type == 'swap')
          method = None
          if spot:
              method = 'spotPrivateGetAccountInfo'
          elif swap:
              method = 'contractPrivateGetAccountAssets'
          query = self.omit(params, 'type')
          response = await 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', {})
          result = {
              'info': response,
              'timestamp': None,
              'datetime': None,
          }
          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.parse_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': '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,
          }
  
      async def fetch_deposit_addresses_by_network(self, code, params={}):
          await self.load_markets()
          currency = self.currency(code)
          request = {
              'currency': currency['id'],
          }
          response = await self.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')
  
      async def fetch_deposit_address(self, code, params={}):
          rawNetwork = self.safe_string(params, 'network')
          params = self.omit('network')
          response = await 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
          result = self.safe_value(response, network)
          if result is None:
              raise InvalidAddress(self.id + ' fetchDepositAddress() cannot find ' + network + ' deposit address for ' + code)
          return result
  
      async def fetch_deposits(self, code=None, since=None, limit=None, params={}):
          await 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 = await 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)
  
      async def fetch_withdrawals(self, code=None, since=None, limit=None, params={}):
          await 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 = await 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.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'))
          amount = self.safe_number(transaction, 'amount')
          address = self.safe_string(transaction, 'address')
          txid = self.safe_string(transaction, 'tx_id')
          fee = None
          feeCost = self.safe_number(transaction, 'fee')
          if feeCost is not None:
              fee = {
                  'cost': feeCost,
                  'currency': code,
              }
          return {
              'info': transaction,
              'id': id,
              'txid': txid,
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
              'address': address,
              'tag': None,
              'type': type,
              'amount': amount,
              'currency': code,
              'network': network,
              'status': status,
              'updated': updated,
              'fee': fee,
          }
  
      def parse_transaction_status(self, status):
          statuses = {
              'WAIT': 'pending',
              'SUCCESS': 'ok',
          }
          return self.safe_string(statuses, status, status)
  
      async def fetch_position(self, symbol, params={}):
          await self.load_markets()
          market = self.market(symbol)
          request = {
              'symbol': market['id'],
          }
          response = await self.fetch_positions(self.extend(request, params))
          firstPosition = self.safe_value(response, 0)
          return firstPosition
  
      async def fetch_positions(self, symbols=None, params={}):
          await self.load_markets()
          response = await 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
          #             }
          #         ]
          #     }
          #
          # todo add parsePositions, parsePosition
          data = self.safe_value(response, 'data', [])
          return data
  
      async def create_order(self, symbol, type, side, amount, price=None, params={}):
          await self.load_markets()
          market = self.market(symbol)
          if market['spot']:
              return await self.create_spot_order(symbol, type, side, amount, price, params)
          elif market['swap']:
              return await self.create_swap_order(symbol, type, side, amount, price, params)
  
      async def create_spot_order(self, symbol, type, side, amount, price=None, params={}):
          await self.load_markets()
          market = self.market(symbol)
          orderSide = None
          if side == 'buy':
              orderSide = 'BID'
          elif side == 'sell':
              orderSide = 'ASK'
          orderType = None
          uppercaseOrderType = type.upper()
          if uppercaseOrderType == 'LIMIT':
              orderType = 'LIMIT_ORDER'
          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'])
          response = await self.spotPrivatePostOrderPlace(self.extend(request, params))
          #
          #     {"code":200,"data":"2ff3163e8617443cb9c6fc19d42b1ca4"}
          #
          return self.parse_order(response, market)
  
      async def create_swap_order(self, symbol, type, side, amount, price=None, params={}):
          await 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')
          if 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'])
          response = await self.contractPrivatePostOrderSubmit(self.extend(request, params))
          #
          #     {"code":200,"data":"2ff3163e8617443cb9c6fc19d42b1ca4"}
          #
          return self.parse_order(response, market)
  
      async def cancel_order(self, id, symbol=None, params={}):
          await 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 = await 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_order2({
              '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,
          })
  
      async 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')
          await 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 = await 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)
  
      async def fetch_order(self, id, symbol=None, params={}):
          await self.load_markets()
          request = {
              'order_ids': id,
          }
          response = await 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)
  
      async 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')
          await 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 = await self.spotPrivateGetOrderList(self.extend(request, params))
          data = self.safe_value(response, 'data', [])
          return self.parse_orders(data, market, since, limit)
  
      async def fetch_canceled_orders(self, symbol=None, since=None, limit=None, params={}):
          return await self.fetch_orders_by_state('CANCELED', symbol, since, limit, params)
  
      async def fetch_closed_orders(self, symbol=None, since=None, limit=None, params={}):
          return await self.fetch_orders_by_state('FILLED', symbol, since, limit, params)
  
      async def cancel_all_orders(self, symbol=None, params={}):
          await self.load_markets()
          market = self.market(symbol)
          request = {
              'symbol': market['id'],
          }
          response = await 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
  
      async 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')
          await 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 = await 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)
  
      async def fetch_order_trades(self, id, symbol=None, since=None, limit=None, params={}):
          await self.load_markets()
          market = None
          if symbol is not None:
              market = self.market(symbol)
          request = {
              'order_id': id,
          }
          response = await 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)
  
      async 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')
          await self.load_markets()
          request = {
              'positionId': positionId,
              'amount': amount,
              'type': addOrReduce,
          }
          response = await self.contractPrivatePostPositionChangeMargin(self.extend(request, params))
          #
          #     {
          #         "success": True,
          #         "code": 0
          #     }
          return response
  
      async def reduce_margin(self, symbol, amount, params={}):
          return await self.modify_margin_helper(symbol, amount, 'SUB', params)
  
      async def add_margin(self, symbol, amount, params={}):
          return await self.modify_margin_helper(symbol, amount, 'ADD', params)
  
      async 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')
          await self.load_markets()
          request = {
              'positionId': positionId,
              'leverage': leverage,
          }
          return await self.contractPrivatePostPositionChangeLeverage(self.extend(request, params))
  
      async 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)
          await 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 = await self.spotPrivatePostAssetWithdraw(self.extend(request, params))
          data = self.safe_value(response, 'data', {})
          return self.parse_transaction(data, currency)
  
      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_exactly_matched_exception(self.exceptions['exact'], responseCode, feedback)
              raise ExchangeError(feedback)
  