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 ArgumentsRequired
  from ccxt.base.errors import BadSymbol
  from ccxt.base.errors import InsufficientFunds
  from ccxt.base.errors import InvalidOrder
  from ccxt.base.decimal_to_precision import ROUND
  
  
  class bitmax(Exchange):
  
      def describe(self):
          return self.deep_extend(super(bitmax, self).describe(), {
              'id': 'bitmax',
              'name': 'BitMax',
              'countries': ['CN'],  # China
              'rateLimit': 500,
              'certified': False,
              # new metainfo interface
              'has': {
                  'CORS': False,
                  'fetchAccounts': True,
                  'fetchTickers': True,
                  'fetchOHLCV': True,
                  'fetchMyTrades': False,
                  'fetchOrder': True,
                  'fetchOrders': False,
                  'fetchOpenOrders': True,
                  'fetchOrderTrades': True,
                  'fetchClosedOrders': True,
                  'fetchTransactions': False,
                  'fetchCurrencies': True,
                  'cancelAllOrders': True,
                  'fetchDepositAddress': True,
              },
              'timeframes': {
                  '1m': '1',
                  '3m': '3',
                  '5m': '5',
                  '15m': '15',
                  '30m': '30',
                  '1h': '60',
                  '2h': '120',
                  '4h': '240',
                  '6h': '360',
                  '12h': '720',
                  '1d': '1d',
                  '1w': '1w',
                  '1M': '1m',
              },
              'version': 'v1',
              'urls': {
                  'logo': 'https://user-images.githubusercontent.com/1294454/66820319-19710880-ef49-11e9-8fbe-16be62a11992.jpg',
                  'api': 'https://bitmax.io',
                  'test': 'https://bitmax-test.io/api',
                  'www': 'https://bitmax.io',
                  'doc': [
                      'https://github.com/bitmax-exchange/api-doc/blob/master/bitmax-api-doc-v1.2.md',
                  ],
                  'fees': 'https://bitmax.io/#/feeRate/tradeRate',
                  'referral': 'https://bitmax.io/#/register?inviteCode=EL6BXBQM',
              },
              'api': {
                  'public': {
                      'get': [
                          'assets',
                          'depth',
                          'fees',
                          'quote',
                          'depth',
                          'trades',
                          'products',
                          'ticker/24hr',
                          'barhist',
                          'barhist/info',
                          'margin/ref-price',
                      ],
                  },
                  'private': {
                      'get': [
                          'deposit',
                          'user/info',
                          'balance',
                          'order/batch',
                          'order/open',
                          'order',
                          'order/history',
                          'order/{coid}',
                          'order/fills/{coid}',
                          'transaction',
                          'margin/balance',
                          'margin/order/open',
                          'margin/order',
                      ],
                      'post': [
                          'margin/order',
                          'order',
                          'order/batch',
                      ],
                      'delete': [
                          'margin/order',
                          'order',
                          'order/all',
                          'order/batch',
                      ],
                  },
              },
              'fees': {
                  'trading': {
                      'tierBased': False,
                      'percentage': True,
                      'taker': 0.001,
                      'maker': 0.001,
                  },
              },
              'options': {
                  'accountGroup': None,
                  'parseOrderToPrecision': False,
              },
              'exceptions': {
                  'exact': {
                      '2100': AuthenticationError,  # {"code":2100,"message":"ApiKeyFailure"}
                      '5002': BadSymbol,  # {"code":5002,"message":"Invalid Symbol"}
                      '6010': InsufficientFunds,  # {'code': 6010, 'message': 'Not enough balance.'}
                      '60060': InvalidOrder,  # {'code': 60060, 'message': 'The order is already filled or canceled.'}
                      '600503': InvalidOrder,  # {"code":600503,"message":"Notional is too small."}
                  },
                  'broad': {},
              },
          })
  
      def fetch_currencies(self, params={}):
          response = self.publicGetAssets(params)
          #
          #     [
          #         {
          #           "assetCode" : "LTO",
          #           "assetName" : "LTO",
          #           "precisionScale" : 9,
          #           "nativeScale" : 3,
          #           "withdrawalFee" : 5.0,
          #           "minWithdrawalAmt" : 10.0,
          #           "status" : "Normal"
          #         },
          #     ]
          #
          result = {}
          for i in range(0, len(response)):
              currency = response[i]
              id = self.safe_string(currency, 'assetCode')
              # todo: will need to rethink the fees
              # to add support for multiple withdrawal/deposit methods and
              # differentiated fees for each particular method
              code = self.safe_currency_code(id)
              precision = self.safe_integer(currency, 'precisionScale')
              fee = self.safe_float(currency, 'withdrawalFee')  # todo: redesign
              status = self.safe_string(currency, 'status')
              active = (status == 'Normal')
              result[code] = {
                  'id': id,
                  'code': code,
                  'info': currency,
                  'type': None,
                  'name': self.safe_string(currency, 'assetName'),
                  'active': active,
                  'fee': fee,
                  'precision': precision,
                  'limits': {
                      'amount': {
                          'min': math.pow(10, -precision),
                          'max': None,
                      },
                      'price': {
                          'min': math.pow(10, -precision),
                          'max': None,
                      },
                      'cost': {
                          'min': None,
                          'max': None,
                      },
                      'withdraw': {
                          'min': self.safe_float(currency, 'minWithdrawalAmt'),
                          'max': None,
                      },
                  },
              }
          return result
  
      def fetch_markets(self, params={}):
          response = self.publicGetProducts(params)
          #
          #     [
          #         {
          #             "symbol" : "BCH/USDT",
          #             "domain" : "USDS",
          #             "baseAsset" : "BCH",
          #             "quoteAsset" : "USDT",
          #             "priceScale" : 2,
          #             "qtyScale" : 3,
          #             "notionalScale" : 9,
          #             "minQty" : "0.000000001",
          #             "maxQty" : "1000000000",
          #             "minNotional" : "5",
          #             "maxNotional" : "200000",
          #             "status" : "Normal",
          #             "miningStatus" : "",
          #             "marginTradable" : True,
          #             "commissionType" : "Quote",
          #             "commissionReserveRate" : 0.0010000000
          #         },
          #     ]
          #
          result = []
          for i in range(0, len(response)):
              market = response[i]
              id = self.safe_string(market, 'symbol')
              baseId = self.safe_string(market, 'baseAsset')
              quoteId = self.safe_string(market, 'quoteAsset')
              base = self.safe_currency_code(baseId)
              quote = self.safe_currency_code(quoteId)
              symbol = base + '/' + quote
              precision = {
                  'amount': self.safe_integer(market, 'qtyScale'),
                  'price': self.safe_integer(market, 'notionalScale'),
              }
              status = self.safe_string(market, 'status')
              active = (status == 'Normal')
              result.append({
                  'id': id,
                  'symbol': symbol,
                  'base': base,
                  'quote': quote,
                  'baseId': baseId,
                  'quoteId': quoteId,
                  'info': market,
                  'active': active,
                  'precision': precision,
                  'limits': {
                      'amount': {
                          'min': self.safe_float(market, 'minQty'),
                          'max': self.safe_float(market, 'maxQty'),
                      },
                      'price': {'min': None, 'max': None},
                      'cost': {
                          'min': self.safe_float(market, 'minNotional'),
                          'max': self.safe_float(market, 'maxNotional'),
                      },
                  },
              })
          return result
  
      def calculate_fee(self, symbol, type, side, amount, price, takerOrMaker='taker', params={}):
          market = self.markets[symbol]
          key = 'quote'
          rate = market[takerOrMaker]
          cost = amount * rate
          precision = market['precision']['price']
          if side == 'sell':
              cost *= price
          else:
              key = 'base'
              precision = market['precision']['amount']
          cost = self.decimal_to_precision(cost, ROUND, precision, self.precisionMode)
          return {
              'type': takerOrMaker,
              'currency': market[key],
              'rate': rate,
              'cost': float(cost),
          }
  
      def fetch_accounts(self, params={}):
          accountGroup = self.safe_string(self.options, 'accountGroup')
          response = None
          if accountGroup is None:
              response = self.privateGetUserInfo(params)
              #
              #     {
              #         "accountGroup": 5
              #     }
              #
              accountGroup = self.safe_string(response, 'accountGroup')
          return [
              {
                  'id': accountGroup,
                  'type': None,
                  'currency': None,
                  'info': response,
              },
          ]
  
      def fetch_balance(self, params={}):
          self.load_markets()
          self.load_accounts()
          response = self.privateGetBalance(params)
          #
          #     {
          #         "code": 0,
          #         "status": "success",  # self field will be deprecated soon
          #         "email": "foo@bar.com",  # self field will be deprecated soon
          #         "data": [
          #             {
          #                 "assetCode": "TSC",
          #                 "assetName": "Ethereum",
          #                 "totalAmount": "20.03",  # total balance amount
          #                 "availableAmount": "20.03",  # balance amount available to trade
          #                 "inOrderAmount": "0.000",  # in order amount
          #                 "btcValue": "70.81"     # the current BTC value of the balance, may be missing
          #             },
          #         ]
          #     }
          #
          result = {'info': response}
          balances = self.safe_value(response, 'data', [])
          for i in range(0, len(balances)):
              balance = balances[i]
              code = self.safe_currency_code(self.safe_string(balance, 'assetCode'))
              account = self.account()
              account['free'] = self.safe_float(balance, 'availableAmount')
              account['used'] = self.safe_float(balance, 'inOrderAmount')
              account['total'] = self.safe_float(balance, 'totalAmount')
              result[code] = account
          return self.parse_balance(result)
  
      def fetch_order_book(self, symbol, limit=None, params={}):
          self.load_markets()
          market = self.market(symbol)
          request = {
              'symbol': market['id'],
          }
          if limit is not None:
              request['n'] = limit  # default = maximum = 100
          response = self.publicGetDepth(self.extend(request, params))
          #
          #     {
          #         "m":"depth",
          #         "ts":1570866464777,
          #         "seqnum":5124140078,
          #         "s":"ETH/USDT",
          #         "asks":[
          #             ["183.57","5.92"],
          #             ["183.6","10.185"]
          #         ],
          #         "bids":[
          #             ["183.54","0.16"],
          #             ["183.53","10.8"],
          #         ]
          #     }
          #
          timestamp = self.safe_integer(response, 'ts')
          result = self.parse_order_book(response, timestamp)
          result['nonce'] = self.safe_integer(response, 'seqnum')
          return result
  
      def parse_ticker(self, ticker, market=None):
          #
          #     {
          #         "symbol":"BCH/USDT",
          #         "interval":"1d",
          #         "barStartTime":1570866600000,
          #         "openPrice":"225.16",
          #         "closePrice":"224.05",
          #         "highPrice":"226.08",
          #         "lowPrice":"218.92",
          #         "volume":"8607.036"
          #     }
          #
          timestamp = self.safe_integer(ticker, 'barStartTime')
          symbol = None
          marketId = self.safe_string(ticker, 'symbol')
          if marketId in self.markets_by_id:
              market = self.markets_by_id[marketId]
          elif marketId is not None:
              baseId, quoteId = marketId.split('/')
              base = self.safe_currency_code(baseId)
              quote = self.safe_currency_code(quoteId)
              symbol = base + '/' + quote
          if (symbol is None) and (market is not None):
              symbol = market['symbol']
          last = self.safe_float(ticker, 'closePrice')
          return {
              'symbol': symbol,
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
              'high': self.safe_float(ticker, 'highPrice'),
              'low': self.safe_float(ticker, 'lowPrice'),
              'bid': None,
              'bidVolume': None,
              'ask': None,
              'askVolume': None,
              'vwap': None,
              'open': self.safe_float(ticker, 'openPrice'),
              'close': last,
              'last': last,
              'previousClose': None,  # previous day close
              'change': None,
              'percentage': None,
              'average': None,
              'baseVolume': self.safe_float(ticker, 'volume'),
              'quoteVolume': None,
              'info': ticker,
          }
  
      def parse_tickers(self, rawTickers, symbols=None):
          tickers = []
          for i in range(0, len(rawTickers)):
              tickers.append(self.parse_ticker(rawTickers[i]))
          return self.filter_by_array(tickers, 'symbol', symbols)
  
      def fetch_ticker(self, symbol, params={}):
          self.load_markets()
          market = self.market(symbol)
          request = {
              'symbol': market['id'],
          }
          response = self.publicGetTicker24hr(self.extend(request, params))
          return self.parse_ticker(response, market)
  
      def fetch_tickers(self, symbols=None, params={}):
          self.load_markets()
          response = self.publicGetTicker24hr(params)
          return self.parse_tickers(response, symbols)
  
      def parse_ohlcv(self, ohlcv, market=None, timeframe='1m', since=None, limit=None):
          #
          #     {
          #         "m":"bar",
          #         "s":"ETH/BTC",
          #         "ba":"ETH",
          #         "qa":"BTC",
          #         "i":"1",
          #         "t":1570867020000,
          #         "o":"0.022023",
          #         "c":"0.022018",
          #         "h":"0.022023",
          #         "l":"0.022018",
          #         "v":"2.510",
          #     }
          #
          return [
              self.safe_integer(ohlcv, 't'),
              self.safe_float(ohlcv, 'o'),
              self.safe_float(ohlcv, 'h'),
              self.safe_float(ohlcv, 'l'),
              self.safe_float(ohlcv, 'c'),
              self.safe_float(ohlcv, 'v'),
          ]
  
      def fetch_ohlcv(self, symbol, timeframe='1m', since=None, limit=None, params={}):
          self.load_markets()
          market = self.market(symbol)
          request = {
              'symbol': market['id'],
              'interval': self.timeframes[timeframe],
          }
          # if since and limit are not specified
          # the exchange will return just 1 last candle by default
          duration = self.parse_timeframe(timeframe)
          if since is not None:
              request['from'] = since
              if limit is not None:
                  request['to'] = self.sum(since, limit * duration * 1000, 1)
          elif limit is not None:
              request['to'] = self.milliseconds()
              request['from'] = request['to'] - limit * duration * 1000 - 1
          response = self.publicGetBarhist(self.extend(request, params))
          return self.parse_ohlcvs(response, market, timeframe, since, limit)
  
      def parse_trade(self, trade, market=None):
          #
          # public fetchTrades
          #
          #     {
          #         "p": "13.75",  # price
          #         "q": "6.68",  # quantity
          #         "t": 1528988084944,  # timestamp
          #         "bm": False,  # if True, the buyer is the market maker, we only use self field to "define the side" of a public trade
          #     }
          #
          # private fetchOrderTrades
          #
          #     {
          #         "ap": "0.029062965",  # average filled price
          #         "bb": "36851.981",  # base asset total balance
          #         "bc": "0",  # if possitive, self is the BTMX commission charged by reverse mining, if negative, self is the mining output of the current fill.
          #         "bpb": "36851.981",  # base asset pending balance
          #         "btmxBal": "0.0",  # optional, the BTMX balance of the current account. This field is only available when bc is non-zero.
          #         "cat": "CASH",  # account category: CASH/MARGIN
          #         "coid": "41g6wtPRFrJXgg6YxjqI6Qoog139Dmoi",  # client order id,(needed to cancel order)
          #         "ei": "NULL_VAL",  # execution instruction
          #         "errorCode": "NULL_VAL",  # if the order is rejected, self field explains why
          #         "execId": "12562285",  # for each user, self is a strictly increasing long integer(represented as string)
          #         "f": "78.074",  # filled quantity, self is the aggregated quantity executed by all past fills
          #         "fa": "BTC",  # fee asset
          #         "fee": "0.000693608",  # fee
          #         'lp': "0.029064",  # last price, the price executed by the last fill
          #         "l": "11.932",  # last quantity, the quantity executed by the last fill
          #         "m": "order",  # message type
          #         "orderType": "Limit",  # Limit, Market, StopLimit, StopMarket
          #         "p": "0.029066",  # limit price, only available for limit and stop limit orders
          #         "q": "100.000",  # order quantity
          #         "qb": "98878.642957097",  # quote asset total balance
          #         "qpb": "98877.967247508",  # quote asset pending balance
          #         "s": "ETH/BTC",  # symbol
          #         "side": "Buy",  # side
          #         "status": "PartiallyFilled",  # order status
          #         "t": 1561131458389,  # timestamp
          #     }
          #
          timestamp = self.safe_integer(trade, 't')
          price = self.safe_float(trade, 'p')
          amount = self.safe_float(trade, 'q')
          cost = None
          if (price is not None) and (amount is not None):
              cost = price * amount
          buyerIsMaker = self.safe_value(trade, 'bm')
          symbol = None
          marketId = self.safe_string(trade, 's')
          if marketId is not None:
              if marketId in self.markets_by_id:
                  market = self.markets_by_id[marketId]
                  symbol = market['symbol']
              else:
                  baseId, quoteId = market.split('/')
                  base = self.safe_currency_code(baseId)
                  quote = self.safe_currency_code(quoteId)
                  symbol = base + '/' + quote
          if (symbol is None) and (market is not None):
              symbol = market['symbol']
          fee = None
          feeCost = self.safe_float(trade, 'fee')
          if feeCost is not None:
              feeCurrencyId = self.safe_string(trade, 'fa')
              feeCurrencyCode = self.safe_currency_code(feeCurrencyId)
              fee = {
                  'cost': feeCost,
                  'currency': feeCurrencyCode,
              }
          orderId = self.safe_string(trade, 'coid')
          side = self.safe_string_lower(trade, 'side')
          if (side is None) and (buyerIsMaker is not None):
              side = 'buy' if buyerIsMaker else 'sell'
          type = self.safe_string_lower(trade, 'orderType')
          return {
              'info': trade,
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
              'symbol': symbol,
              'id': None,
              'order': orderId,
              'type': type,
              'takerOrMaker': None,
              'side': side,
              'price': price,
              'amount': amount,
              'cost': cost,
              'fee': fee,
          }
  
      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['n'] = limit  # currently limited to 100 or fewer
          response = self.publicGetTrades(self.extend(request, params))
          #
          #     {
          #         "m": "marketTrades",  # message type
          #         "s": "ETH/BTC",  # symbol
          #         "trades": [
          #             {
          #                 "p": "13.75",  # price
          #                 "q": "6.68",  # quantity
          #                 "t": 1528988084944,  # timestamp
          #                 "bm": False,  # if True, the buyer is the market maker
          #             },
          #         ]
          #     }
          #
          trades = self.safe_value(response, 'trades', [])
          return self.parse_trades(trades, market, since, limit)
  
      def parse_order_status(self, status):
          statuses = {
              'PendingNew': 'open',
              'New': 'open',
              'PartiallyFilled': 'open',
              'Filled': 'closed',
              'Canceled': 'canceled',
              'Rejected': 'rejected',
          }
          return self.safe_string(statuses, status, status)
  
      def parse_order(self, order, market=None):
          #
          # createOrder
          #
          #     {
          #         "coid": "xxx...xxx",
          #         "action": "new",
          #         "success": True  # success = True means the order has been submitted to the matching engine.
          #     }
          #
          # fetchOrder, fetchOpenOrders, fetchClosedOrders
          #
          #     {
          #         "accountCategory": "CASH",
          #         "accountId": "cshKAhmTHQNUKhR1pQyrDOdotE3Tsnz4",
          #         "avgPrice": "0.000000000",
          #         "baseAsset": "ETH",
          #         "btmxCommission": "0.000000000",
          #         "coid": "41g6wtPRFrJXgg6Y7vpIkcCyWhgcK0cF",  # the unique identifier, you will need, self value to cancel self order
          #         "errorCode": "NULL_VAL",
          #         "execId": "12452288",
          #         "execInst": "NULL_VAL",
          #         "fee": "0.000000000",  # cumulative fee paid for self order
          #         "feeAsset": "",  # the asset
          #         "filledQty": "0.000000000",  # filled quantity
          #         "notional": "0.000000000",
          #         "orderPrice": "0.310000000",  # only available for limit and stop limit orders
          #         "orderQty": "1.000000000",
          #         "orderType": "StopLimit",
          #         "quoteAsset": "BTC",
          #         "side": "Buy",
          #         "status": "PendingNew",
          #         "stopPrice": "0.300000000",  # only available for stop market and stop limit orders
          #         "symbol": "ETH/BTC",
          #         "time": 1566091628227,  # The last execution time of the order
          #         "sendingTime": 1566091503547,  # The sending time of the order
          #         "userId": "supEQeSJQllKkxYSgLOoVk7hJAX59WSz"
          #     }
          #
          status = self.parse_order_status(self.safe_string(order, 'status'))
          marketId = self.safe_string(order, 'symbol')
          symbol = None
          if marketId is not None:
              if marketId in self.markets_by_id:
                  market = self.markets_by_id[marketId]
              else:
                  baseId, quoteId = marketId.split('/')
                  base = self.safe_currency_code(baseId)
                  quote = self.safe_currency_code(quoteId)
                  symbol = base + '/' + quote
          if (symbol is None) and (market is not None):
              symbol = market['symbol']
          timestamp = self.safe_integer(order, 'sendingTime')
          price = self.safe_float(order, 'orderPrice')
          amount = self.safe_float(order, 'orderQty')
          filled = self.safe_float(order, 'filledQty')
          remaining = None
          cost = self.safe_float(order, 'cummulativeQuoteQty')
          if filled is not None:
              if amount is not None:
                  remaining = amount - filled
                  if self.options['parseOrderToPrecision']:
                      remaining = float(self.amount_to_precision(symbol, remaining))
                  remaining = max(remaining, 0.0)
              if price is not None:
                  if cost is None:
                      cost = price * filled
          id = self.safe_string(order, 'coid')
          type = self.safe_string(order, 'orderType')
          if type is not None:
              type = type.lower()
              if type == 'market':
                  if price == 0.0:
                      if (cost is not None) and (filled is not None):
                          if (cost > 0) and (filled > 0):
                              price = cost / filled
          side = self.safe_string_lower(order, 'side')
          fee = {
              'cost': self.safe_float(order, 'fee'),
              'currency': self.safe_string(order, 'feeAsset'),
          }
          average = self.safe_float(order, 'avgPrice')
          return {
              'info': order,
              'id': id,
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
              'lastTradeTimestamp': None,
              'symbol': symbol,
              'type': type,
              'side': side,
              'price': price,
              'amount': amount,
              'cost': cost,
              'average': average,
              'filled': filled,
              'remaining': remaining,
              'status': status,
              'fee': fee,
              'trades': None,
          }
  
      def create_order(self, symbol, type, side, amount, price=None, params={}):
          self.load_markets()
          self.load_accounts()
          market = self.market(symbol)
          request = {
              'coid': self.coid(),  # a unique identifier of length 32
              # 'time': self.milliseconds(),  # milliseconds since UNIX epoch in UTC, self is filled in the private section of the sign() method below
              'symbol': market['id'],
              # 'orderPrice': self.price_to_precision(symbol, price),  # optional, limit price of the order. This field is required for limit orders and stop limit orders
              # 'stopPrice': '15.7',  # optional, stopPrice of the order. This field is required for stop_market orders and stop limit orders
              'orderQty': self.amount_to_precision(symbol, amount),
              'orderType': type,  # order type, you shall specify one of the following: "limit", "market", "stop_market", "stop_limit"
              'side': side,  # "buy" or "sell"
              # 'postOnly': True,  # optional, if True, the order will either be posted to the limit order book or be cancelled, i.e. the order cannot take liquidity, default is False
              # 'timeInForce': 'GTC',  # optional, supports "GTC" good-till-canceled and "IOC" immediate-or-cancel
          }
          if (type == 'limit') or (type == 'stop_limit'):
              request['orderPrice'] = self.price_to_precision(symbol, price)
          response = self.privatePostOrder(self.extend(request, params))
          #
          #     {
          #         "code": 0,
          #         "email": "foo@bar.com",  # self field will be deprecated soon
          #         "status": "success",  # self field will be deprecated soon
          #         "data": {
          #             "coid": "xxx...xxx",
          #             "action": "new",
          #             "success": True,  # success = True means the order has been submitted to the matching engine
          #         }
          #     }
          #
          data = self.safe_value(response, 'data', {})
          return self.parse_order(data, market)
  
      def fetch_order(self, id, symbol=None, params={}):
          self.load_markets()
          self.load_accounts()
          market = None
          if symbol is not None:
              market = self.market(symbol)
          request = {
              'coid': id,
          }
          response = self.privateGetOrderCoid(self.extend(request, params))
          #
          #     {
          #         'code': 0,
          #         'status': 'success',  # self field will be deprecated soon
          #         'email': 'foo@bar.com',  # self field will be deprecated soon
          #         "data": {
          #             "accountCategory": "CASH",
          #             "accountId": "cshKAhmTHQNUKhR1pQyrDOdotE3Tsnz4",
          #             "avgPrice": "0.000000000",
          #             "baseAsset": "ETH",
          #             "btmxCommission": "0.000000000",
          #             "coid": "41g6wtPRFrJXgg6Y7vpIkcCyWhgcK0cF",  # the unique identifier, you will need, self value to cancel self order
          #             "errorCode": "NULL_VAL",
          #             "execId": "12452288",
          #             "execInst": "NULL_VAL",
          #             "fee": "0.000000000",  # cumulative fee paid for self order
          #             "feeAsset": "",  # the asset
          #             "filledQty": "0.000000000",  # filled quantity
          #             "notional": "0.000000000",
          #             "orderPrice": "0.310000000",  # only available for limit and stop limit orders
          #             "orderQty": "1.000000000",
          #             "orderType": "StopLimit",
          #             "quoteAsset": "BTC",
          #             "side": "Buy",
          #             "status": "PendingNew",
          #             "stopPrice": "0.300000000",  # only available for stop market and stop limit orders
          #             "symbol": "ETH/BTC",
          #             "time": 1566091628227,  # The last execution time of the order
          #             "sendingTime": 1566091503547,  # The sending time of the order
          #             "userId": "supEQeSJQllKkxYSgLOoVk7hJAX59WSz"
          #         }
          #     }
          #
          data = self.safe_value(response, 'data', {})
          return self.parse_order(data, market)
  
      def fetch_order_trades(self, id, symbol=None, since=None, limit=None, params={}):
          self.load_markets()
          self.load_accounts()
          market = None
          if symbol is not None:
              market = self.market(symbol)
          request = {
              'coid': id,
          }
          response = self.privateGetOrderFillsCoid(self.extend(request, params))
          #
          #     {
          #         'code': 0,
          #         'status': 'success',  # self field will be deprecated soon
          #         'email': 'foo@bar.com',  # self field will be deprecated soon
          #         "data": [
          #             {
          #                 "ap": "0.029062965",  # average filled price
          #                 "bb": "36851.981",  # base asset total balance
          #                 "bc": "0",  # if possitive, self is the BTMX commission charged by reverse mining, if negative, self is the mining output of the current fill.
          #                 "bpb": "36851.981",  # base asset pending balance
          #                 "btmxBal": "0.0",  # optional, the BTMX balance of the current account. This field is only available when bc is non-zero.
          #                 "cat": "CASH",  # account category: CASH/MARGIN
          #                 "coid": "41g6wtPRFrJXgg6YxjqI6Qoog139Dmoi",  # client order id,(needed to cancel order)
          #                 "ei": "NULL_VAL",  # execution instruction
          #                 "errorCode": "NULL_VAL",  # if the order is rejected, self field explains why
          #                 "execId": "12562285",  # for each user, self is a strictly increasing long integer(represented as string)
          #                 "f": "78.074",  # filled quantity, self is the aggregated quantity executed by all past fills
          #                 "fa": "BTC",  # fee asset
          #                 "fee": "0.000693608",  # fee
          #                 'lp': "0.029064",  # last price, the price executed by the last fill
          #                 "l": "11.932",  # last quantity, the quantity executed by the last fill
          #                 "m": "order",  # message type
          #                 "orderType": "Limit",  # Limit, Market, StopLimit, StopMarket
          #                 "p": "0.029066",  # limit price, only available for limit and stop limit orders
          #                 "q": "100.000",  # order quantity
          #                 "qb": "98878.642957097",  # quote asset total balance
          #                 "qpb": "98877.967247508",  # quote asset pending balance
          #                 "s": "ETH/BTC",  # symbol
          #                 "side": "Buy",  # side
          #                 "status": "PartiallyFilled",  # order status
          #                 "t": 1561131458389,  # timestamp
          #             },
          #         ]
          #     }
          #
          data = self.safe_value(response, 'data', {})
          return self.parse_trades(data, market, since, limit)
  
      def fetch_open_orders(self, symbol=None, since=None, limit=None, params={}):
          self.load_markets()
          self.load_accounts()
          market = None
          request = {
              # 'side': 'buy',  # or 'sell', optional
          }
          if symbol is not None:
              market = self.market(symbol)
              request['symbol'] = market['id']
          response = self.privateGetOrderOpen(self.extend(request, params))
          #
          #     {
          #         'code': 0,
          #         'status': 'success',  # self field will be deprecated soon
          #         'email': 'foo@bar.com',  # self field will be deprecated soon
          #         "data": [
          #             {
          #                 "accountCategory": "CASH",
          #                 "accountId": "cshKAhmTHQNUKhR1pQyrDOdotE3Tsnz4",
          #                 "avgPrice": "0.000000000",
          #                 "baseAsset": "ETH",
          #                 "btmxCommission": "0.000000000",
          #                 "coid": "41g6wtPRFrJXgg6Y7vpIkcCyWhgcK0cF",  # the unique identifier, you will need, self value to cancel self order
          #                 "errorCode": "NULL_VAL",
          #                 "execId": "12452288",
          #                 "execInst": "NULL_VAL",
          #                 "fee": "0.000000000",  # cumulative fee paid for self order
          #                 "feeAsset": "",  # the asset
          #                 "filledQty": "0.000000000",  # filled quantity
          #                 "notional": "0.000000000",
          #                 "orderPrice": "0.310000000",  # only available for limit and stop limit orders
          #                 "orderQty": "1.000000000",
          #                 "orderType": "StopLimit",
          #                 "quoteAsset": "BTC",
          #                 "side": "Buy",
          #                 "status": "PendingNew",
          #                 "stopPrice": "0.300000000",  # only available for stop market and stop limit orders
          #                 "symbol": "ETH/BTC",
          #                 "time": 1566091628227,  # The last execution time of the order
          #                 "sendingTime": 1566091503547,  # The sending time of the order
          #                 "userId": "supEQeSJQllKkxYSgLOoVk7hJAX59WSz"
          #             },
          #         ]
          #     }
          #
          data = self.safe_value(response, 'data', [])
          return self.parse_orders(data, market, since, limit)
  
      def fetch_closed_orders(self, symbol=None, since=None, limit=None, params={}):
          self.load_markets()
          self.load_accounts()
          market = None
          request = {
              # 'symbol': 'ETH/BTC',  # optional
              # 'category': 'CASH',  # optional, string
              # 'orderType': 'Market',  # optional, string
              # 'page': 1,  # optional, integer type, starts at 1
              # 'pageSize': 100,  # optional, integer type
              # 'side': 'buy',  # or 'sell', optional, case insensitive.
              # 'startTime': 1566091628227,  # optional, integer milliseconds since UNIX epoch representing the start of the range
              # 'endTime': 1566091628227,  # optional, integer milliseconds since UNIX epoch representing the end of the range
              # 'status': 'Filled',  # optional, can only be one of "Filled", "Canceled", "Rejected"
          }
          if symbol is not None:
              market = self.market(symbol)
              request['symbol'] = market['id']
          if since is not None:
              request['startTime'] = since
          if limit is not None:
              request['n'] = limit  # default 15, max 50
          response = self.privateGetOrderHistory(self.extend(request, params))
          #
          #     {
          #         'code': 0,
          #         'status': 'success',  # self field will be deprecated soon
          #         'email': 'foo@bar.com',  # self field will be deprecated soon
          #         'data': {
          #             'page': 1,
          #             'pageSize': 20,
          #             'limit': 500,
          #             'hasNext': False,
          #             'data': [
          #                 {
          #                     'time': 1566091429000,  # The last execution time of the order(This timestamp is in second level resolution)
          #                     'coid': 'QgQIMJhPFrYfUf60ZTihmseTqhzzwOCx',
          #                     'execId': '331',
          #                     'symbol': 'BTMX/USDT',
          #                     'orderType': 'Market',
          #                     'baseAsset': 'BTMX',
          #                     'quoteAsset': 'USDT',
          #                     'side': 'Buy',
          #                     'stopPrice': '0.000000000',  # only meaningful for stop market and stop limit orders
          #                     'orderPrice': '0.123000000',  # only meaningful for limit and stop limit orders
          #                     'orderQty': '9229.409000000',
          #                     'filledQty': '9229.409000000',
          #                     'avgPrice': '0.095500000',
          #                     'fee': '0.352563424',
          #                     'feeAsset': 'USDT',
          #                     'btmxCommission': '0.000000000',
          #                     'status': 'Filled',
          #                     'notional': '881.408559500',
          #                     'userId': '5DNEppWy33SayHjFQpgQUTjwNMSjEhD3',
          #                     'accountId': 'ACPHERRWRIA3VQADMEAB2ZTLYAXNM3PJ',
          #                     'accountCategory': 'CASH',
          #                     'errorCode': 'NULL_VAL',
          #                     'execInst': 'NULL_VAL',
          #                     "sendingTime": 1566091382736,  # The sending time of the order
          #                },
          #             ]
          #         }
          #     }
          #
          data = self.safe_value(response, 'data', {})
          orders = self.safe_value(data, 'data', [])
          return self.parse_orders(orders, market, since, limit)
  
      def cancel_order(self, id, symbol=None, params={}):
          if symbol is None:
              raise ArgumentsRequired(self.id + ' cancelOrder requires a symbol argument')
          self.load_markets()
          self.load_accounts()
          market = self.market(symbol)
          request = {
              'symbol': market['id'],
              'coid': self.coid(),
              'origCoid': id,
              # 'time': self.milliseconds(),  # self is filled in the private section of the sign() method below
          }
          response = self.privateDeleteOrder(self.extend(request, params))
          #
          #     {
          #         'code': 0,
          #         'status': 'success',  # self field will be deprecated soon
          #         'email': 'foo@bar.com',  # self field will be deprecated soon
          #         'data': {
          #             'action': 'cancel',
          #             'coid': 'gaSRTi3o3Yo4PaXpVK0NSLP47vmJuLea',
          #             'success': True,
          #         }
          #     }
          #
          order = self.safe_value(response, 'data', {})
          return self.parse_order(order)
  
      def cancel_all_orders(self, symbol=None, params={}):
          self.load_markets()
          self.load_accounts()
          request = {
              # 'side': 'buy',  # optional string field(case-insensitive), either "buy" or "sell"
          }
          market = None
          if symbol is not None:
              market = self.market(symbol)
              request['symbol'] = market['id']  # optional
          response = self.privateDeleteOrderAll(self.extend(request, params))
          #
          #     ?
          #
          return response
  
      def coid(self):
          uuid = self.uuid()
          parts = uuid.split('-')
          clientOrderId = ''.join(parts)
          coid = clientOrderId[0:32]
          return coid
  
      def fetch_deposit_address(self, code, params={}):
          self.load_markets()
          self.load_accounts()
          currency = self.currency(code)
          request = {
              'requestId': self.coid(),
              # 'time': self.milliseconds(),  # self is filled in the private section of the sign() method below
              'assetCode': currency['id'],
          }
          # note: it is highly recommended to use V2 version of self route,
          # especially for assets with multiple block chains such as USDT.
          response = self.privateGetDeposit(self.extend(request, params))
          #
          # v1
          #
          #     {
          #         "data": {
          #             "address": "0x26a3CB49578F07000575405a57888681249c35Fd"
          #         },
          #         "email": "igor.kroitor@gmial.com",
          #         "status": "success",
          #     }
          #
          # v2
          #
          #     {
          #         "code": 0,
          #         "data": [
          #             {
          #                 "asset": "XRP",
          #                 "blockChain": "Ripple",
          #                 "addressData": {
          #                     "address": "rpinhtY4p35bPmVXPbfWRUtZ1w1K1gYShB",
          #                     "destTag": "54301"
          #                 }
          #             }
          #         ],
          #         "email": "xxx@xxx.com",
          #         "status": "success"  # the request has been submitted to the server
          #     }
          #
          addressData = self.safe_value(response, 'data')
          if isinstance(addressData, list):
              firstElement = self.safe_value(addressData, 0, {})
              addressData = self.safe_value(firstElement, 'addressData', {})
          address = self.safe_string(addressData, 'address')
          tag = self.safe_string(addressData, 'destTag')
          self.check_address(address)
          return {
              'currency': code,
              'address': address,
              'tag': tag,
              'info': response,
          }
  
      def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
          url = '/api/' + self.version + '/' + self.implode_params(path, params)
          query = self.omit(params, self.extract_params(path))
          if api == 'public':
              if query:
                  url += '?' + self.urlencode(query)
          else:
              self.check_required_credentials()
              accountGroup = self.safe_string(self.options, 'accountGroup')
              if accountGroup is None:
                  if self.accounts is not None:
                      accountGroup = self.accounts[0]['id']
              if accountGroup is not None:
                  url = '/' + accountGroup + url
              coid = self.safe_string(query, 'coid')
              query['time'] = str(self.milliseconds())
              auth = query['time'] + '+' + path.replace('/{coid}', '')  # fix sign error
              headers = {
                  'x-auth-key': self.apiKey,
                  'x-auth-timestamp': query['time'],
                  'Content-Type': 'application/json',
              }
              if coid is not None:
                  auth += '+' + coid
                  headers['x-auth-coid'] = coid
              signature = self.hmac(self.encode(auth), self.encode(self.secret), hashlib.sha256, 'base64')
              headers['x-auth-signature'] = signature
              if method == 'GET':
                  if query:
                      url += '?' + self.urlencode(query)
              else:
                  body = self.json(query)
          url = self.urls['api'] + url
          return {'url': url, 'method': method, 'body': body, 'headers': headers}
  
      def handle_errors(self, httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody):
          if response is None:
              return  # fallback to default error handler
          #
          #     {"code":2100,"message":"ApiKeyFailure"}
          #     {'code': 6010, 'message': 'Not enough balance.'}
          #     {'code': 60060, 'message': 'The order is already filled or canceled.'}
          #
          code = self.safe_string(response, 'code')
          message = self.safe_string(response, 'message')
          error = (code is not None) and (code != '0')
          if error or (message is not None):
              feedback = self.id + ' ' + body
              self.throw_exactly_matched_exception(self.exceptions['exact'], code, feedback)
              self.throw_exactly_matched_exception(self.exceptions['exact'], message, feedback)
              self.throw_broadly_matched_exception(self.exceptions['broad'], message, feedback)
              raise ExchangeError(feedback)  # unknown message
  