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
  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 InvalidOrder
  from ccxt.base.errors import OrderNotFound
  from ccxt.base.errors import DDoSProtection
  from ccxt.base.precise import Precise
  
  
  class stex(Exchange):
  
      def describe(self):
          return self.deep_extend(super(stex, self).describe(), {
              'id': 'stex',
              'name': 'STEX',  # formerly known as stocks.exchange
              'countries': ['EE'],  # Estonia
              'rateLimit': 1000 / 3,  # https://help.stex.com/en/articles/2815043-api-3-rate-limits
              'certified': False,
              # new metainfo interface
              'has': {
                  'cancelAllOrders': True,
                  'cancelOrder': True,
                  'CORS': None,
                  'createDepositAddress': True,
                  'createMarketOrder': None,  # limit orders only
                  'createOrder': True,
                  'fetchBalance': True,
                  'fetchCurrencies': True,
                  'fetchDepositAddress': True,
                  'fetchDeposits': True,
                  'fetchFundingFees': True,
                  'fetchMarkets': True,
                  'fetchMyTrades': True,
                  'fetchOHLCV': True,
                  'fetchOpenOrders': True,
                  'fetchOrder': True,
                  'fetchOrderBook': True,
                  'fetchOrderTrades': True,
                  'fetchTicker': True,
                  'fetchTickers': True,
                  'fetchTime': True,
                  'fetchTrades': True,
                  'fetchWithdrawals': True,
                  'withdraw': True,
              },
              'version': 'v3',
              'urls': {
                  'logo': 'https://user-images.githubusercontent.com/1294454/69680782-03fd0b80-10bd-11ea-909e-7f603500e9cc.jpg',
                  'api': 'https://api3.stex.com',
                  'www': 'https://www.stex.com',
                  'doc': [
                      'https://help.stex.com/en/collections/1593608-api-v3-documentation',
                  ],
                  'fees': 'https://app.stex.com/en/pairs-specification',
                  'referral': 'https://app.stex.com?ref=36416021',
              },
              'requiredCredentials': {
                  'apiKey': False,
                  'secret': False,
                  'token': True,
              },
              'timeframes': {
                  '1m': '1',
                  '5m': '5',
                  '30m': '30',
                  '1h': '60',
                  '4h': '240',
                  '12h': '720',
                  '1d': '1D',  # default
              },
              'api': {
                  'public': {
                      'get': {
                          'currencies': 1,  # Available Currencies
                          'currencies/{currencyId}': 1,  # Get currency info
                          'markets': 1,  # Available markets
                          'pairs-groups': 1,  # Available currency pairs groups(as displayed at stex trading page)
                          'currency_pairs/list/{code}': 1,  # Available currency pairs
                          'currency_pairs/group/{currencyPairGroupId}': 1,  # Available currency pairs for a given group
                          'currency_pairs/{currencyPairId}': 1,  # Get currency pair information
                          'ticker': 1,  # Tickers list for all currency pairs
                          'ticker/{currencyPairId}': 1,  # Ticker for currency pair
                          'trades/{currencyPairId}': 1,  # Trades for given currency pair
                          'orderbook/{currencyPairId}': 1,  # Orderbook for given currency pair
                          'chart/{currencyPairId}/{candlesType}': 1,  # A list of candles for given currency pair
                          'deposit-statuses': 1,  # Available Deposit Statuses
                          'deposit-statuses/{statusId}': 1,  # Get deposit status info
                          'withdrawal-statuses': 1,  # Available Withdrawal Statuses
                          'withdrawal-statuses/{statusId}': 1,  # Get status info
                          'ping': 1,  # Test API is working and get server time
                          'mobile-versions': 1,  # Shows the official mobile applications data
                          'twitter': 1,  # Get the last 20 posts(stex.com) on Twitter
                      },
                  },
                  'trading': {
                      'get': {
                          'fees/{currencyPairId}': 1,  # Returns the user's fees for a given currency pair
                          'orders': 12,  # List your currently open orders
                          'orders/{currencyPairId}': 6,  # List your currently open orders for given currency pair
                          'order/{orderId}': 12,  # Get a single order
                      },
                      'post': {
                          'orders/{currencyPairId}': 1.5,  # Create new order and put it to the orders processing queue
                          'orders/bulk/{currencyPairId}': 12,  # Create new orders in a bulk and put it to the orders processing queue
                      },
                      'delete': {
                          'orders': 30,  # Delete all active orders
                          'orders/{currencyPairId}': 12,  # Delete active orders for given currency pair
                          'order/{orderId}': 1.5,  # Cancel order
                      },
                  },
                  'reports': {
                      'get': {
                          'currencies': 12,  # Get a list of currencies user had any activity in
                          'currency_pairs': 12,  # Gets the list of currency pairs the user had orders in for all the time
                          'orders': 12,  # Get past orders
                          'orders/{orderId}': 12,  # Get specified order details
                          'trades/{currencyPairId}': 12,  # Get a list of user trades according to request parameters
                          'background/{listMode}': 12,  # Get reports list for category
                          'background/{id}': 12,  # Get some report info
                          'background/download/{id}': 12,  # Get file by id
                      },
                      'post': {
                          'background/create': 12,  # Create new report
                      },
                      'delete': {
                          'background/{id}': 12,  # Remove report by id
                      },
                  },
                  'profile': {
                      'get': {
                          'info': 3,  # Account information
                          'wallets': 3,  # Get a list of user wallets
                          'wallets/{walletId}': 3,  # Single wallet information
                          'wallets/address/{walletId}': 3,  # Get deposit address for given wallet
                          'deposits': 3,  # Get a list of deposits made by user
                          'deposits/{id}': 3,  # Get deposit by id
                          'rewards': 3,  # Get a list of rewards obtained by user(e.g. in trading competitions)
                          'rewards/{id}': 3,  # Get reward by id
                          'addressbook': 3,  # Get a list of user address book items
                          'addressbook/{itemId}': 3,  # Single address book item
                          'withdrawals': 3,  # Get a list of withdrawals made by user
                          'withdrawals/{id}': 3,  # Get withdrawal by id
                          'notifications': 3,  # Get notifications
                          'notifications/price': 3,  # Get a list of active price alerts
                          'favorite/currency_pairs': 3,  # Get favorite currency pairs
                          'token-scopes': 3,  # Get current token scopes
                      },
                      'post': {
                          'wallets/burn/{walletId}': 3,  # Burns the given wallet
                          'wallets/{walletId}/hold_amount': 3,  # Move a part of the funds on the wallet to the "hold" to keep it safe from trading
                          'wallets/{currencyId}': 3,  # Create a wallet for given currency
                          'wallets/address/{walletId}': 3,  # Create new deposit address
                          'addressbook/disable_item/{itemId}': 3,  # Disables the address book item
                          'addressbook/enable_item/{itemId}': 3,  # Enable the address book item
                          'addressbook/enable_strict_wd': 3,  # Restrict the withdrawals to only addresses that are active in addressbook
                          'addressbook/disable_strict_wd': 3,  # Remove restriction to withdraw to only addresses that are active in addressbook. E.g. allow to withdraw to any address.
                          'withdraw': 30,  # Create withdrawal request
                          'notifications/price': 3,  # Create new price alert
                          'referral/program': 3,  # Create referral program
                          'referral/insert/{code}': 3,  # Insert referral code
                          'referral/bonus_transfer/{currencyId}': 3,  # Transfer referral bonuses balance to main balance for given currency
                      },
                      'put': {
                          'favorite/currency_pairs/set': 3,  # Set favorite currency pairs
                      },
                      'delete': {
                          'addressbook/{itemId}': 3,  # Deletes address book item
                          'withdraw/{withdrawalId}': 30,  # Cancel unconfirmed withdrawal
                          'notifications/price/{priceAlertId}': 3,  # Delete the price alert by ID
                      },
                  },
                  'verification': {
                      'get': {
                          'countries': 1,  # Countries list, beta
                          'status': 1,  # Get status verify
                          'fractal/url': 1,  # Generate verify url from Fractal
                          'smart-id': 1,  # Check Smart-ID verify
                          'stex': 1,  # Get information about your KYC, beta
                          'cryptonomica/code': 1,  # Get Discount code for Cryptonomica
                      },
                      'post': {
                          'smart-id': 1,  # Initialization Smart-ID verify(Send request to Smart-ID App)
                          'stex': 1,  # Update information regarding of your KYC verification, beta
                          'cryptonomica': 1,  # Add verification from Cryptonomica
                      },
                  },
                  'settings': {
                      'get': {
                          'notifications/{event}': 1,  # User event notification settings
                          'notifications': 1,  # User events notification settings
                      },
                      'put': {
                          'notifications': 1,  # Set notification settings
                          'notifications/set': 1,
                      },
                  },
              },
              'fees': {
                  'trading': {
                      'tierBased': False,
                      'percentage': True,
                      'taker': self.parse_number('0.002'),
                      'maker': self.parse_number('0.002'),
                  },
              },
              'commonCurrencies': {
                  'BC': 'Bitcoin Confidential',
                  'BITS': 'Bitcoinus',
                  'BITSW': 'BITS',
                  'BHD': 'Bithold',
                  'BTH': 'Bithereum',
                  'MPH': 'Chasyr Token',
                  'SBTC': 'SBTCT',  # SiamBitcoin
              },
              'options': {
                  'parseOrderToPrecision': False,
                  'networks': {
                      'ERC20': 5,
                      'ETH': 5,
                      'OMNI': 10,
                      'XLM': 20,
                      'BEP2': 22,
                      'TRC20': 24,
                      'TRX': 24,
                      'SOL': 25,
                      'BEP20': 501,
                  },
              },
              'exceptions': {
                  'exact': {
                      # {"success":false,"message":"Wrong parameters","errors":{"candleType":["Invalid Candle Type!"]}}
                      # {"success":false,"message":"Wrong parameters","errors":{"time":["timeStart or timeEnd is less then 1"]}}
                      'Wrong parameters': BadRequest,
                      'Unauthenticated.': AuthenticationError,  # {"message":"Unauthenticated."}
                      'Server Error': ExchangeError,  # {"message": "Server Error"}
                      'This feature is only enabled for users verifies by Cryptonomica': PermissionDenied,  # {"success":false,"message":"This feature is only enabled for users verifies by Cryptonomica"}
                      'Too Many Attempts.': DDoSProtection,  # {"message": "Too Many Attempts."}
                      'Selected Pair is disabled': BadSymbol,  # {"success":false,"message":"Selected Pair is disabled"}
                      'Invalid scope(s) provided.': PermissionDenied,  # {"message": "Invalid scope(s) provided."}
                      'The maximum amount of open orders with the same price cannot exceed 10': InvalidOrder,  # {"success":false,"message":"The maximum amount of open orders with the same price cannot exceed 10"}
                  },
                  'broad': {
                      'Not enough': InsufficientFunds,  # {"success":false,"message":"Not enough  ETH"}
                  },
              },
          })
  
      async def fetch_currencies(self, params={}):
          response = await self.publicGetCurrencies(params)
          #
          #     {
          #         "success":true,
          #         "data":[
          #             {
          #                 "id":1,
          #                 "code":"BTC",
          #                 "name":"Bitcoin",
          #                 "active":true,
          #                 "delisted":false,
          #                 "precision":8,
          #                 "minimum_tx_confirmations":1,
          #                 "minimum_withdrawal_amount":"0.00200000",
          #                 "minimum_deposit_amount":"0.00000000",
          #                 "deposit_fee_currency_id":1,
          #                 "deposit_fee_currency_code":"BTC",
          #                 "deposit_fee_const":"0.00000000",
          #                 "deposit_fee_percent":"0.00000000",
          #                 "withdrawal_fee_currency_id":1,
          #                 "withdrawal_fee_currency_code":"BTC",
          #                 "withdrawal_fee_const":"0.00100000",
          #                 "withdrawal_fee_percent":"0.00000000",
          #                 "block_explorer_url":"https:\/\/blockchain.info\/tx\/",
          #                 "protocol_specific_settings":null
          #             },
          #         ]
          #     }
          #
          result = {}
          currencies = self.safe_value(response, 'data', [])
          for i in range(0, len(currencies)):
              currency = currencies[i]
              id = self.safe_string(currency, 'id')
              numericId = self.safe_integer(currency, 'id')
              # 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(self.safe_string(currency, 'code'))
              precision = self.safe_string(currency, 'precision')
              amountLimit = self.parse_precision(precision)
              fee = self.safe_number(currency, 'withdrawal_fee_const')  # todo: redesign
              active = self.safe_value(currency, 'active', True)
              result[code] = {
                  'id': id,
                  'numericId': numericId,
                  'code': code,
                  'info': currency,
                  'type': None,
                  'name': self.safe_string(currency, 'name'),
                  'active': active,
                  'fee': fee,
                  'precision': int(precision),
                  'limits': {
                      'amount': {'min': self.parse_number(amountLimit), 'max': None},
                      'deposit': {
                          'min': self.safe_number(currency, 'minimum_deposit_amount'),
                          'max': None,
                      },
                      'withdraw': {
                          'min': self.safe_number(currency, 'minimum_withdrawal_amount'),
                          'max': None,
                      },
                  },
              }
          return result
  
      async def fetch_markets(self, params={}):
          request = {
              'code': 'ALL',
          }
          response = await self.publicGetCurrencyPairsListCode(self.extend(request, params))
          #
          #     {
          #         "success":true,
          #         "data":[
          #             {
          #                 "id":935,
          #                 "currency_id":662,
          #                 "currency_code":"ABET",
          #                 "currency_name":"Altbet",
          #                 "market_currency_id":1,
          #                 "market_code":"BTC",
          #                 "market_name":"Bitcoin",
          #                 "min_order_amount":"0.00000010",
          #                 "min_buy_price":"0.00000001",
          #                 "min_sell_price":"0.00000001",
          #                 "buy_fee_percent":"0.20000000",
          #                 "sell_fee_percent":"0.20000000",
          #                 "active":true,
          #                 "delisted":false,
          #                 "pair_message":"",
          #                 "currency_precision":8,
          #                 "market_precision":8,
          #                 "symbol":"ABET_BTC",
          #                 "group_name":"BTC",
          #                 "group_id":1
          #             }
          #         ]
          #     }
          #
          result = []
          markets = self.safe_value(response, 'data', [])
          for i in range(0, len(markets)):
              market = markets[i]
              id = self.safe_string(market, 'id')
              numericId = self.safe_integer(market, 'id')
              baseId = self.safe_string(market, 'currency_id')
              quoteId = self.safe_string(market, 'market_currency_id')
              baseNumericId = self.safe_integer(market, 'currency_id')
              quoteNumericId = self.safe_integer(market, 'market_currency_id')
              base = self.safe_currency_code(self.safe_string(market, 'currency_code'))
              quote = self.safe_currency_code(self.safe_string(market, 'market_code'))
              symbol = base + '/' + quote
              precision = {
                  'amount': self.safe_integer(market, 'currency_precision'),
                  'price': self.safe_integer(market, 'market_precision'),
              }
              active = self.safe_value(market, 'active')
              minBuyPrice = self.safe_number(market, 'min_buy_price')
              minSellPrice = self.safe_number(market, 'min_sell_price')
              minPrice = max(minBuyPrice, minSellPrice)
              buyFee = self.safe_number(market, 'buy_fee_percent') / 100
              sellFee = self.safe_number(market, 'sell_fee_percent') / 100
              fee = max(buyFee, sellFee)
              result.append({
                  'id': id,
                  'numericId': numericId,
                  'symbol': symbol,
                  'base': base,
                  'quote': quote,
                  'baseId': baseId,
                  'quoteId': quoteId,
                  'baseNumericId': baseNumericId,
                  'quoteNumericId': quoteNumericId,
                  'info': market,
                  'type': 'spot',
                  'spot': True,
                  'active': active,
                  'maker': fee,
                  'taker': fee,
                  'precision': precision,
                  'limits': {
                      'amount': {
                          'min': self.safe_number(market, 'min_order_amount'),
                          'max': None,
                      },
                      'price': {'min': minPrice, 'max': None},
                      'cost': {
                          'min': None,
                          'max': None,
                      },
                  },
              })
          return result
  
      async def fetch_ticker(self, symbol, params={}):
          await self.load_markets()
          market = self.market(symbol)
          request = {
              'currencyPairId': market['id'],
          }
          response = await self.publicGetTickerCurrencyPairId(self.extend(request, params))
          #
          #     {
          #         "success": True,
          #         "data": {
          #             "id": 2,
          #             "amount_multiplier": 1,
          #             "currency_code": "ETH",
          #             "market_code": "BTC",
          #             "currency_name": "Ethereum",
          #             "market_name": "Bitcoin",
          #             "symbol": "ETH_BTC",
          #             "group_name": "BTC",
          #             "group_id": 1,
          #             "ask": "0.02069998",
          #             "bid": "0.02028622",
          #             "last": "0.02049224",
          #             "open": "0.02059605",
          #             "low": "0.01977744",
          #             "high": "0.02097005",
          #             "volume": "480.43248971",
          #             "volumeQuote": "23491.29826130",
          #             "count": "7384",
          #             "fiatsRate": {
          #                 "USD": 7230.86,
          #                 "EUR": 6590.79,
          #                 "UAH": 173402,
          #                 "AUD": 10595.51,
          #                 "IDR": 101568085,
          #                 "CNY": 50752,
          #                 "KRW": 8452295,
          #                 "JPY": 784607,
          #                 "VND": 167315119,
          #                 "INR": 517596,
          #                 "GBP": 5607.25,
          #                 "CAD": 9602.63,
          #                 "BRL": 30472,
          #                 "RUB": 460718
          #             },
          #             "timestamp": 1574698235601
          #         }
          #     }
          #
          ticker = self.safe_value(response, 'data', {})
          return self.parse_ticker(ticker, market)
  
      async def fetch_time(self, params={}):
          response = await self.publicGetPing(params)
          #
          #     {
          #         "success": True,
          #         "data": {
          #             "server_datetime": {
          #                 "date": "2019-01-22 15:13:34.233796",
          #                 "timezone_type": 3,
          #                 "timezone": "UTC"
          #             },
          #             "server_timestamp": 1548170014
          #         }
          #     }
          #
          data = self.safe_value(response, 'data', {})
          serverDatetime = self.safe_value(data, 'server_datetime', {})
          return self.parse8601(self.safe_string(serverDatetime, 'date'))
  
      async def fetch_order_book(self, symbol, limit=None, params={}):
          await self.load_markets()
          market = self.market(symbol)
          request = {
              'currencyPairId': market['id'],
          }
          if limit is not None:
              request['limit_bids'] = limit  # returns all if set to 0, default 100
              request['limit_asks'] = limit  # returns all if set to 0, default 100
          response = await self.publicGetOrderbookCurrencyPairId(self.extend(request, params))
          #
          #     {
          #         "success": True,
          #         "data": {
          #             "ask": [
          #                 {"currency_pair_id": 2, "amount": "2.17865373", "price": "0.02062917", "amount2": "0.04494382", "count": 1, "cumulative_amount": 2.17865373},
          #                 {"currency_pair_id": 2, "amount": "2.27521743", "price": "0.02062918", "amount2": "0.04693587", "count": 1, "cumulative_amount": 4.45387116},
          #                 {"currency_pair_id": 2, "amount": "1.26980049", "price": "0.02063170", "amount2": "0.02619814", "count": 1, "cumulative_amount": 5.72367165},
          #             ],
          #             "bid": [
          #                 {"currency_pair_id": 2, "amount": "0.00978005", "price": "0.02057000", "amount2": "0.00020118", "count": 1, "cumulative_amount": 0.00978005},
          #                 {"currency_pair_id": 2, "amount": "0.00500000", "price": "0.02056000", "amount2": "0.00010280", "count": 1, "cumulative_amount": 0.01478005},
          #                 {"currency_pair_id": 2, "amount": "0.77679882", "price": "0.02054001", "amount2": "0.01595546", "count": 1, "cumulative_amount": 0.79157887},
          #             ],
          #             "ask_total_amount": 2555.749174609999,
          #             "bid_total_amount": 29.180037330000005
          #         }
          #     }
          #
          orderbook = self.safe_value(response, 'data', {})
          return self.parse_order_book(orderbook, symbol, None, 'bid', 'ask', 'price', 'amount')
  
      def parse_ticker(self, ticker, market=None):
          #
          #     {
          #         "id": 2,
          #         "amount_multiplier": 1,
          #         "currency_code": "ETH",
          #         "market_code": "BTC",
          #         "currency_name": "Ethereum",
          #         "market_name": "Bitcoin",
          #         "symbol": "ETH_BTC",
          #         "group_name": "BTC",
          #         "group_id": 1,
          #         "ask": "0.02069998",
          #         "bid": "0.02028622",
          #         "last": "0.02049224",
          #         "open": "0.02059605",
          #         "low": "0.01977744",
          #         "high": "0.02097005",
          #         "volume": "480.43248971",
          #         "volumeQuote": "23491.29826130",
          #         "count": "7384",
          #         "fiatsRate": {
          #             "USD": 7230.86,
          #             "EUR": 6590.79,
          #             "UAH": 173402,
          #             "AUD": 10595.51,
          #             "IDR": 101568085,
          #             "CNY": 50752,
          #             "KRW": 8452295,
          #             "JPY": 784607,
          #             "VND": 167315119,
          #             "INR": 517596,
          #             "GBP": 5607.25,
          #             "CAD": 9602.63,
          #             "BRL": 30472,
          #             "RUB": 460718
          #         },
          #         "timestamp": 1574698235601
          #     }
          #
          timestamp = self.safe_integer(ticker, 'timestamp')
          marketId = self.safe_string_2(ticker, 'id', 'symbol')
          symbol = self.safe_symbol(marketId, market, '_')
          last = self.safe_number(ticker, 'last')
          open = self.safe_number(ticker, 'open')
          return self.safe_ticker({
              'symbol': symbol,
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
              'high': self.safe_number(ticker, 'high'),
              'low': self.safe_number(ticker, 'low'),
              'bid': self.safe_number(ticker, 'bid'),
              'bidVolume': None,
              'ask': self.safe_number(ticker, 'ask'),
              'askVolume': None,
              'vwap': None,
              'open': open,
              'close': last,
              'last': last,
              'previousClose': None,  # previous day close
              'change': None,
              'percentage': None,
              'average': None,
              'baseVolume': self.safe_number(ticker, 'volumeQuote'),
              'quoteVolume': self.safe_number(ticker, 'volume'),
              'info': ticker,
          }, market)
  
      async def fetch_tickers(self, symbols=None, params={}):
          await self.load_markets()
          response = await self.publicGetTicker(params)
          #
          #     {
          #         "success":true,
          #         "data":[
          #             {
          #                 "id":262,
          #                 "amount_multiplier":1,
          #                 "currency_code":"ARDR",
          #                 "market_code":"BTC",
          #                 "currency_name":"ARDOR",
          #                 "market_name":"Bitcoin",
          #                 "symbol":"ARDR_BTC",
          #                 "group_name":"BTC",
          #                 "group_id":1,
          #                 "ask":"0.00000630",
          #                 "bid":"0.00000613",
          #                 "last":"0.00000617",
          #                 "open":"0.00000620",
          #                 "low":"0.00000614",
          #                 "high":"0.00000630",
          #                 "volume":"30.37795305",
          #                 "volumeQuote":"4911487.01996544",
          #                 "count":"710",
          #                 "fiatsRate":{
          #                     "USD":7230.86,
          #                     "EUR":6590.79,
          #                     "UAH":173402,
          #                     "AUD":10744.52,
          #                     "IDR":101568085,
          #                     "CNY":50752,
          #                     "KRW":8452295,
          #                     "JPY":784607,
          #                     "VND":167315119,
          #                     "INR":517596,
          #                     "GBP":5607.25,
          #                     "CAD":9602.63,
          #                     "BRL":30472,
          #                     "RUB":467358
          #                 },
          #                 "timestamp":1574698617304,
          #                 "group_position":1
          #             },
          #         ]
          #     }
          #
          tickers = self.safe_value(response, 'data', [])
          return self.parse_tickers(tickers, symbols)
  
      def parse_ohlcv(self, ohlcv, market=None):
          #
          #     {
          #         "time": 1566086400000,
          #         "close": 0.01895,
          #         "open": 0.01812427,
          #         "high": 0.0191588,
          #         "low": 0.01807001,
          #         "volume": 2588.597813750006
          #     }
          #
          return [
              self.safe_integer(ohlcv, 'time'),
              self.safe_number(ohlcv, 'open'),
              self.safe_number(ohlcv, 'high'),
              self.safe_number(ohlcv, 'low'),
              self.safe_number(ohlcv, 'close'),
              self.safe_number(ohlcv, 'volume'),
          ]
  
      async def fetch_ohlcv(self, symbol, timeframe='1d', since=None, limit=None, params={}):
          await self.load_markets()
          market = self.market(symbol)
          request = {
              'currencyPairId': market['id'],
              'candlesType': self.timeframes[timeframe],  # default 1d
              # 'timeStart': 1574709092,  # unix timestamp in seconds, required
              # 'timeEnd': 1574709092,  # unix timestamp in seconds, required
              # 'limit': 100,  # default 100, optional
              # 'offset' 100,  # optional, pagination within timerange
          }
          if limit is None:
              limit = 100
          else:
              request['limit'] = limit
          duration = self.parse_timeframe(timeframe)
          timerange = limit * duration
          if since is None:
              request['timeEnd'] = self.seconds()
              request['timeStart'] = request['timeEnd'] - timerange
          else:
              request['timeStart'] = int(since / 1000)
              request['timeEnd'] = self.sum(request['timeStart'], timerange)
          response = await self.publicGetChartCurrencyPairIdCandlesType(self.extend(request, params))
          #
          #     {
          #         "success": True,
          #         "data": [
          #             {
          #                 "time": 1566086400000,
          #                 "close": 0.01895,
          #                 "open": 0.01812427,
          #                 "high": 0.0191588,
          #                 "low": 0.01807001,
          #                 "volume": 2588.597813750006
          #             },
          #         ]
          #     }
          #
          data = self.safe_value(response, 'data', [])
          return self.parse_ohlcvs(data, market, timeframe, since, limit)
  
      def parse_trade(self, trade, market=None):
          #
          # public fetchTrades
          #
          #     {
          #         "id": 35989317,
          #         "price": "0.02033813",
          #         "amount": "3.60000000",
          #         "type": "BUY",
          #         "timestamp": "1574713503"
          #     }
          #
          # private fetchMyTrades, fetchClosedOrder, fetchOrderTrades
          #
          #     {
          #         "id": 658745,
          #         "buy_order_id": 6587453,
          #         "sell_order_id": 6587459,
          #         "price": 0.012285,
          #         "amount": 6.35,
          #         "trade_type": "SELL",
          #         "timestamp": "1538737692"
          #     }
          #
          id = self.safe_string(trade, 'id')
          timestamp = self.safe_timestamp(trade, 'timestamp')
          priceString = self.safe_string(trade, 'price')
          amountString = self.safe_string(trade, 'amount')
          price = self.parse_number(priceString)
          amount = self.parse_number(amountString)
          cost = self.parse_number(Precise.string_mul(priceString, amountString))
          symbol = None
          if (symbol is None) and (market is not None):
              symbol = market['symbol']
          side = self.safe_string_lower_2(trade, 'type', 'trade_type')
          return {
              'info': trade,
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
              'symbol': symbol,
              'id': id,
              'order': None,
              'type': None,
              'takerOrMaker': None,
              'side': side,
              'price': price,
              'amount': amount,
              'cost': cost,
              'fee': None,
          }
  
      async def fetch_trades(self, symbol, since=None, limit=None, params={}):
          await self.load_markets()
          market = self.market(symbol)
          request = {
              'currencyPairId': market['id'],
              # 'sort': 'ASC',  # ASC or DESC, default DESC
              # 'from': 1574709092,  # unix timestamp, optional
              # 'till': 1574709092,  # unix timestamp, optional
              # 'limit': 100,  # default 100, optional
              # 'offset': 100,  # optional
          }
          if limit is not None:
              request['limit'] = limit  # currently limited to 100 or fewer
          if since is not None:
              request['sort'] = 'ASC'  # needed to make the from param work
              request['from'] = int(since / 1000)
          response = await self.publicGetTradesCurrencyPairId(self.extend(request, params))
          #
          #     {
          #         "success": True,
          #         "data": [
          #             {
          #                 "id": 35989317,
          #                 "price": "0.02033813",
          #                 "amount": "3.60000000",
          #                 "type": "BUY",
          #                 "timestamp": "1574713503"
          #             },
          #         ]
          #     }
          #
          trades = self.safe_value(response, 'data', [])
          return self.parse_trades(trades, market, since, limit)
  
      async def fetch_balance(self, params={}):
          await self.load_markets()
          # await self.load_accounts()
          response = await self.profileGetWallets(params)
          #
          #     {
          #         "success": True,
          #         "data": [
          #             {
          #                 "id": null,
          #                 "currency_id": 665,
          #                 "delisted": False,
          #                 "disabled": False,
          #                 "disable_deposits": False,
          #                 "currency_code": "ORM",
          #                 "currency_name": "Orium",
          #                 "currency_type_id": 5,
          #                 "balance": "0",
          #                 "frozen_balance": "0",
          #                 "bonus_balance": "0",
          #                 "total_balance": "0",
          #                 "protocol_specific_settings": null,
          #                 "rates": {"BTC": "0.00000000020", "USD": "0.00000147"},
          #             },
          #             {
          #                 "id": null,
          #                 "currency_id": 272,
          #                 "delisted": False,
          #                 "disabled": False,
          #                 "disable_deposits": False,
          #                 "currency_code": "USDT",
          #                 "currency_name": "TetherUSD",
          #                 "currency_type_id": 23,
          #                 "balance": "0",
          #                 "frozen_balance": "0",
          #                 "bonus_balance": "0",
          #                 "total_balance": "0",
          #                 "protocol_specific_settings": [
          #                     {"protocol_name": "OMNI", "protocol_id": 10, "active": True, "withdrawal_fee_currency_id": 272, "withdrawal_fee_const": 10, "withdrawal_fee_percent": 0, "block_explorer_url": "https://omniexplorer.info/search/"},
          #                     {"protocol_name": "ERC20", "protocol_id": 5, "active": True, "withdrawal_fee_const": 1.2, "withdrawal_fee_percent": 0, "block_explorer_url": "https://etherscan.io/tx/"},
          #                     {"protocol_name": "TRON", "protocol_id": 24, "active": True, "withdrawal_fee_currency_id": 272, "withdrawal_fee_const": 0.2, "withdrawal_fee_percent": 0, "block_explorer_url": "https://tronscan.org/#/transaction/"}
          #                 ],
          #                 "rates": {"BTC": "0.00013893", "USD": "1"},
          #             },
          #         ]
          #     }
          #
          result = {
              'info': response,
              'timestamp': None,
              'datetime': None,
          }
          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, 'currency_id'))
              account = self.account()
              account['free'] = self.safe_string(balance, 'balance')
              account['used'] = self.safe_string(balance, 'frozen_balance')
              result[code] = account
          return self.safe_balance(result)
  
      def parse_order_status(self, status):
          statuses = {
              'PROCESSING': 'open',
              'PENDING': 'open',
              'PARTIAL': 'open',
              'FINISHED': 'closed',
              'CANCELLED': 'canceled',
          }
          return self.safe_string(statuses, status, status)
  
      def parse_order(self, order, market=None):
          #
          # createOrder, fetchOpenOrders, fetchClosedOrders, cancelOrder, fetchOrder, fetchClosedOrder
          #
          #     {
          #         "id": 828680665,
          #         "currency_pair_id": 1,
          #         "currency_pair_name": "NXT_BTC",
          #         "price": "0.011384",
          #         "trigger_price": 0.011385,
          #         "initial_amount": "13.942",
          #         "processed_amount": "3.724",  # missing in fetchClosedOrder
          #         "type": "SELL",
          #         "original_type": "STOP_LIMIT_SELL",
          #         "created": "2019-01-17 10:14:48",
          #         "timestamp": "1547720088",
          #         "status": "PARTIAL"
          #         # fetchClosedOrder only
          #         "trades": [
          #             {
          #                 "id": 658745,
          #                 "buy_order_id": 658745,
          #                 "sell_order_id": 828680665,
          #                 "price": 0.012285,
          #                 "amount": 6.35,
          #                 "trade_type": "SELL",
          #                 "timestamp": "1538737692"
          #             }
          #         ],
          #         # fetchClosedOrder only
          #         "fees": [
          #             {
          #                 "id": 1234567,
          #                 "currency_id": 1,
          #                 "amount": 0.00025,
          #                 "timestamp": "1548149238"
          #             }
          #         ]
          #     }
          #
          id = self.safe_string(order, 'id')
          status = self.parse_order_status(self.safe_string(order, 'status'))
          marketId = self.safe_string_2(order, 'currency_pair_id', 'currency_pair_name')
          symbol = self.safe_symbol(marketId, market, '_')
          timestamp = self.safe_timestamp(order, 'timestamp')
          price = self.safe_number(order, 'price')
          amount = self.safe_number(order, 'initial_amount')
          filled = self.safe_number(order, 'processed_amount')
          remaining = None
          cost = None
          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
          type = self.safe_string(order, 'original_type')
          if (type == 'BUY') or (type == 'SELL'):
              type = None
          side = self.safe_string_lower(order, 'type')
          rawTrades = self.safe_value(order, 'trades')
          trades = None
          if rawTrades is not None:
              trades = self.parse_trades(rawTrades, market, None, None, {
                  'symbol': symbol,
                  'order': id,
              })
          stopPrice = self.safe_number(order, 'trigger_price')
          result = {
              'info': order,
              'id': id,
              'clientOrderId': None,
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
              'lastTradeTimestamp': None,
              'symbol': symbol,
              'type': type,
              'timeInForce': None,
              'postOnly': None,
              'side': side,
              'price': price,
              'stopPrice': stopPrice,
              'amount': amount,
              'cost': cost,
              'average': None,
              'filled': filled,
              'remaining': remaining,
              'status': status,
              'trades': trades,
          }
          fees = self.safe_value(order, 'fees')
          if fees is None:
              result['fee'] = None
          else:
              numFees = len(fees)
              if numFees > 0:
                  result['fees'] = []
                  for i in range(0, len(fees)):
                      feeCost = self.safe_number(fees[i], 'amount')
                      if feeCost is not None:
                          feeCurrencyId = self.safe_string(fees[i], 'currency_id')
                          feeCurrencyCode = self.safe_currency_code(feeCurrencyId)
                          result['fees'].append({
                              'cost': feeCost,
                              'currency': feeCurrencyCode,
                          })
              else:
                  result['fee'] = None
          return result
  
      async def create_order(self, symbol, type, side, amount, price=None, params={}):
          if type == 'market':
              raise ExchangeError(self.id + ' createOrder allows limit orders only')
          await self.load_markets()
          market = self.market(symbol)
          if type == 'limit':
              type = side
          request = {
              'currencyPairId': market['id'],
              'type': type.upper(),  # 'BUY', 'SELL', 'STOP_LIMIT_BUY', 'STOP_LIMIT_SELL'
              'amount': float(self.amount_to_precision(symbol, amount)),  # required
              'price': float(self.price_to_precision(symbol, price)),  # required
              # 'trigger_price': 123.45  # required for STOP_LIMIT_BUY or STOP_LIMIT_SELL
          }
          response = await self.tradingPostOrdersCurrencyPairId(self.extend(request, params))
          #
          #     {
          #         "success": True,
          #         "data": {
          #             "id": 828680665,
          #             "currency_pair_id": 1,
          #             "currency_pair_name": "NXT_BTC",
          #             "price": "0.011384",
          #             "trigger_price": 0.011385,
          #             "initial_amount": "13.942",
          #             "processed_amount": "3.724",
          #             "type": "SELL",
          #             "original_type": "STOP_LIMIT_SELL",
          #             "created": "2019-01-17 10:14:48",
          #             "timestamp": "1547720088",
          #             "status": "PARTIAL"
          #         }
          #     }
          #
          data = self.safe_value(response, 'data', {})
          return self.parse_order(data, market)
  
      async def fetch_order(self, id, symbol=None, params={}):
          await self.load_markets()
          request = {
              'orderId': id,
          }
          response = await self.tradingGetOrderOrderId(self.extend(request, params))
          #
          #     {
          #         "success": True,
          #         "data": {
          #             "id": 828680665,
          #             "currency_pair_id": 1,
          #             "currency_pair_name": "NXT_BTC",
          #             "price": "0.011384",
          #             "trigger_price": 0.011385,
          #             "initial_amount": "13.942",
          #             "processed_amount": "3.724",
          #             "type": "SELL",
          #             "original_type": "STOP_LIMIT_SELL",
          #             "created": "2019-01-17 10:14:48",
          #             "timestamp": "1547720088",
          #             "status": "PARTIAL"
          #         }
          #     }
          #
          data = self.safe_value(response, 'data', {})
          market = None
          if symbol is not None:
              market = self.market(symbol)
          return self.parse_order(data, market)
  
      async def fetch_closed_order(self, id, symbol=None, params={}):
          await self.load_markets()
          request = {
              'orderId': id,
          }
          response = await self.reportsGetOrdersOrderId(self.extend(request, params))
          #
          #     {
          #         "success": True,
          #         "data": {
          #             "id": 5478965,
          #             "currency_pair_id": 1,
          #             "currency_pair_name": "NXT_BTC",
          #             "price": "0.00013800",
          #             "initial_amount": "1.00000000",
          #             "type": "BUY",
          #             "created": "2019-01-22 09:27:17",
          #             "timestamp": 1548149237,
          #             "status": "FINISHED",
          #             "trades": [
          #                 {
          #                     "id": 658745,
          #                     "buy_order_id": 6587453,
          #                     "sell_order_id": 6587459,
          #                     "price": 0.012285,
          #                     "amount": 6.35,
          #                     "trade_type": "SELL",
          #                     "timestamp": "1538737692"
          #                 }
          #             ],
          #             "fees": [
          #                 {
          #                     "id": 1234567,
          #                     "currency_id": 1,
          #                     "amount": 0.00025,
          #                     "timestamp": "1548149238"
          #                 }
          #             ]
          #         }
          #     }
          #
          data = self.safe_value(response, 'data', {})
          market = None
          if symbol is not None:
              market = self.market(symbol)
          return self.parse_order(data, market)
  
      async def fetch_order_trades(self, id, symbol=None, since=None, limit=None, params={}):
          order = await self.fetch_closed_order(id, symbol, params)
          return order['trades']
  
      async def fetch_open_orders(self, symbol=None, since=None, limit=None, params={}):
          await self.load_markets()
          market = None
          method = 'tradingGetOrders'
          request = {
              # 'limit': 100,  # default 100
              # 'offset': 100,
          }
          if symbol is not None:
              method = 'tradingGetOrdersCurrencyPairId'
              market = self.market(symbol)
              request['currencyPairId'] = market['id']
          if limit is not None:
              request['limit'] = limit
          response = await getattr(self, method)(self.extend(request, params))
          #
          #     {
          #         "success": True,
          #         "data": [
          #             {
          #                 "id": 828680665,
          #                 "currency_pair_id": 1,
          #                 "currency_pair_name": "NXT_BTC",
          #                 "price": "0.011384",
          #                 "trigger_price": 0.011385,
          #                 "initial_amount": "13.942",
          #                 "processed_amount": "3.724",
          #                 "type": "SELL",
          #                 "original_type": "STOP_LIMIT_SELL",
          #                 "created": "2019-01-17 10:14:48",
          #                 "timestamp": "1547720088",
          #                 "status": "PARTIAL"
          #             }
          #         ]
          #     }
          #
          data = self.safe_value(response, 'data', [])
          return self.parse_orders(data, market, since, limit)
  
      async def cancel_order(self, id, symbol=None, params={}):
          await self.load_markets()
          request = {
              'orderId': id,
          }
          response = await self.tradingDeleteOrderOrderId(self.extend(request, params))
          #
          #     {
          #         "success": True,
          #         "data": {
          #             "put_into_processing_queue": [
          #                 {
          #                     "id": 828680665,
          #                     "currency_pair_id": 1,
          #                     "currency_pair_name": "NXT_BTC",
          #                     "price": "0.011384",
          #                     "trigger_price": 0.011385,
          #                     "initial_amount": "13.942",
          #                     "processed_amount": "3.724",
          #                     "type": "SELL",
          #                     "original_type": "STOP_LIMIT_SELL",
          #                     "created": "2019-01-17 10:14:48",
          #                     "timestamp": "1547720088",
          #                     "status": "PARTIAL"
          #                 }
          #             ],
          #             "not_put_into_processing_queue": [
          #                 {
          #                     "id": 828680665,
          #                     "currency_pair_id": 1,
          #                     "currency_pair_name": "NXT_BTC",
          #                     "price": "0.011384",
          #                     "trigger_price": 0.011385,
          #                     "initial_amount": "13.942",
          #                     "processed_amount": "3.724",
          #                     "type": "SELL",
          #                     "original_type": "STOP_LIMIT_SELL",
          #                     "created": "2019-01-17 10:14:48",
          #                     "timestamp": "1547720088",
          #                     "status": "PARTIAL"
          #                 }
          #             ],
          #             "message": "string"
          #         }
          #     }
          #
          data = self.safe_value(response, 'data', {})
          acceptedOrders = self.safe_value(data, 'put_into_processing_queue', [])
          rejectedOrders = self.safe_value(data, 'not_put_into_processing_queue', [])
          numAcceptedOrders = len(acceptedOrders)
          numRejectedOrders = len(rejectedOrders)
          if numAcceptedOrders < 1:
              if numRejectedOrders < 1:
                  raise OrderNotFound(self.id + ' cancelOrder received an empty response: ' + self.json(response))
              else:
                  return self.parse_order(rejectedOrders[0])
          else:
              if numRejectedOrders < 1:
                  return self.parse_order(acceptedOrders[0])
              else:
                  raise OrderNotFound(self.id + ' cancelOrder received an empty response: ' + self.json(response))
  
      async def cancel_all_orders(self, symbol=None, params={}):
          await self.load_markets()
          request = {}
          method = 'tradingDeleteOrders'
          if symbol is not None:
              market = self.market(symbol)
              request['currencyPairId'] = market['id']
              method = 'tradingDeleteOrdersCurrencyPairId'
          response = await getattr(self, method)(self.extend(request, params))
          #
          #     {
          #         "success":true,
          #         "data":{
          #             "put_into_processing_queue":[],
          #             "not_put_into_processing_queue":[],
          #             "message":"Orders operations are handled in processing queue, therefore cancelling is not immediate."
          #         }
          #     }
          #
          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 = {
              'currencyPairId': market['id'],
              # 'timeStart': '2019-11-26T19:54:55.901Z',  # datetime in iso format
              # 'timeEnd': '2019-11-26T19:54:55.901Z',  # datetime in iso format
              # 'limit': 100,  # default 100
              # 'offset': 100,
          }
          if since is not None:
              request['timeStart'] = self.iso8601(since)
          if limit is not None:
              request['limit'] = limit
          response = await self.reportsGetTradesCurrencyPairId(self.extend(request, params))
          #
          #     {
          #         "success": True,
          #         "data": [
          #             {
          #                 "id": 658745,
          #                 "buy_order_id": 6587453,
          #                 "sell_order_id": 6587459,
          #                 "price": 0.012285,
          #                 "amount": 6.35,
          #                 "trade_type": "SELL",
          #                 "timestamp": "1538737692"
          #             }
          #         ]
          #     }
          #
          trades = self.safe_value(response, 'data', [])
          return self.parse_trades(trades, market, since, limit)
  
      async def create_deposit_address(self, code, params={}):
          await self.load_markets()
          currency = self.currency(code)
          request = {
              'currencyId': currency['id'],
              # Default value is the value that represents legacy protocol.
              # In case of USDT it is 10 as Tether OMNI was the default previously.
              # The list of protocols can be obtained from the /public/currencies/{currencyId}
              # 'protocol_id': 10,
          }
          response = await self.profilePostWalletsCurrencyId(self.extend(request, params))
          #
          #     {
          #         "success": True,
          #         "data": {
          #             "id": 45875,
          #             "currency_id": 1,
          #             "delisted": False,
          #             "disabled": False,
          #             "disable_deposits": False,
          #             "code": "BTC",
          #             "balance": "0.198752",
          #             "frozen_balance": "1.5784",
          #             "bonus_balance": "0.000",
          #             "deposit_address": {
          #                 "address": "0X12WERTYUIIJHGFVBNMJHGDFGHJ765SDFGHJ",
          #                 "address_name": "Address",
          #                 "additional_address_parameter": "qwertyuiopasdfghjkl",
          #                 "additional_address_parameter_name": "Destination Tag",
          #                 "notification": "",
          #                 "protocol_id": 10,
          #                 "protocol_name": "Tether OMNI",
          #                 "supports_new_address_creation": False
          #                 },
          #             "multi_deposit_addresses": [
          #                 {
          #                     "address": "0X12WERTYUIIJHGFVBNMJHGDFGHJ765SDFGHJ",
          #                     "address_name": "Address",
          #                     "additional_address_parameter": "qwertyuiopasdfghjkl",
          #                     "additional_address_parameter_name": "Destination Tag",
          #                     "notification": "",
          #                     "protocol_id": 10,
          #                     "protocol_name": "Tether OMNI",
          #                     "supports_new_address_creation": False
          #                 }
          #             ],
          #             "withdrawal_additional_field_name": "Payment ID(optional)",
          #             "rates": {"BTC": 0.000001},
          #             "protocol_specific_settings": [
          #                 {
          #                     "protocol_name": "Tether OMNI",
          #                     "protocol_id": 10,
          #                     "active": True,
          #                     "withdrawal_fee_currency_id": 1,
          #                     "withdrawal_fee_const": 0.002,
          #                     "withdrawal_fee_percent": 0,
          #                     "block_explorer_url": "https://omniexplorer.info/search/"
          #                 }
          #             ]
          #         }
          #     }
          #
          data = self.safe_value(response, 'data', {})
          depositAddress = self.safe_value(data, 'deposit_address', {})
          address = self.safe_string(depositAddress, 'address')
          tag = self.safe_string(depositAddress, 'additional_address_parameter')
          self.check_address(address)
          return {
              'currency': code,
              'address': address,
              'tag': tag,
              'info': response,
          }
  
      async def fetch_deposit_address(self, code, params={}):
          await self.load_markets()
          balance = await self.fetch_balance()
          wallets = self.safe_value(balance['info'], 'data', [])
          walletsByCurrencyId = self.index_by(wallets, 'currency_id')
          currency = self.currency(code)
          wallet = self.safe_value(walletsByCurrencyId, currency['id'])
          if wallet is None:
              raise ExchangeError(self.id + ' fetchDepositAddress() could not find the wallet id for currency code ' + code + ', try to call createDepositAddress() first')
          walletId = self.safe_integer(wallet, 'id')
          if walletId is None:
              raise ExchangeError(self.id + ' fetchDepositAddress() could not find the wallet id for currency code ' + code + ', try to call createDepositAddress() first')
          request = {
              'walletId': walletId,
          }
          response = await self.profileGetWalletsWalletId(self.extend(request, params))
          #
          #     {
          #         "success": True,
          #         "data": {
          #             "id": 45875,
          #             "currency_id": 1,
          #             "delisted": False,
          #             "disabled": False,
          #             "disable_deposits": False,
          #             "code": "BTC",
          #             "balance": "0.198752",
          #             "frozen_balance": "1.5784",
          #             "bonus_balance": "0.000",
          #             "deposit_address": {
          #                 "address": "0X12WERTYUIIJHGFVBNMJHGDFGHJ765SDFGHJ",
          #                 "address_name": "Address",
          #                 "additional_address_parameter": "qwertyuiopasdfghjkl",
          #                 "additional_address_parameter_name": "Destination Tag",
          #                 "notification": "",
          #                 "protocol_id": 10,
          #                 "protocol_name": "Tether OMNI",
          #                 "supports_new_address_creation": False
          #             },
          #             "multi_deposit_addresses": [
          #                 {
          #                     "address": "0X12WERTYUIIJHGFVBNMJHGDFGHJ765SDFGHJ",
          #                     "address_name": "Address",
          #                     "additional_address_parameter": "qwertyuiopasdfghjkl",
          #                     "additional_address_parameter_name": "Destination Tag",
          #                     "notification": "",
          #                     "protocol_id": 10,
          #                     "protocol_name": "Tether OMNI",
          #                     "supports_new_address_creation": False
          #                 }
          #             ],
          #             "withdrawal_additional_field_name": "Payment ID(optional)",
          #             "rates": {"BTC": 0.000001},
          #             "protocol_specific_settings": [
          #                 {
          #                     "protocol_name": "Tether OMNI",
          #                     "protocol_id": 10,
          #                     "active": True,
          #                     "withdrawal_fee_currency_id": 1,
          #                     "withdrawal_fee_const": 0.002,
          #                     "withdrawal_fee_percent": 0,
          #                     "block_explorer_url": "https://omniexplorer.info/search/"
          #                 }
          #             ]
          #         }
          #     }
          #
          data = self.safe_value(response, 'data', [])
          depositAddress = self.safe_value(data, 'deposit_address', {})
          address = self.safe_string(depositAddress, 'address')
          tag = self.safe_string(depositAddress, 'additional_address_parameter')
          self.check_address(address)
          return {
              'currency': code,
              'address': address,
              'tag': tag,
              'network': None,
              'info': response,
          }
  
      def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
          url = self.urls['api'] + '/' + api + '/' + 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()
              headers = {
                  'Authorization': 'Bearer ' + self.token,
              }
              if method == 'GET' or method == 'DELETE':
                  if query:
                      url += '?' + self.urlencode(query)
              else:
                  body = self.json(query)
                  if query:
                      headers['Content-Type'] = 'application/json'
          return {'url': url, 'method': method, 'body': body, 'headers': headers}
  
      def parse_transaction_status(self, status):
          statuses = {
              'processing': 'pending',
              'checking by system': 'pending',
              'hodl': 'pending',
              'amount too low': 'failed',
              'not confirmed': 'pending',
              'cancelled by user': 'canceled',
              'approved': 'pending',
              'finished': 'ok',
              'withdrawal error': 'failed',
              'deposit error': 'failed',
              'cancelled by admin': 'canceled',
              'awaiting': 'pending',
          }
          return self.safe_string(statuses, status, status)
  
      def parse_transaction(self, transaction, currency=None):
          #
          # fetchDeposits
          #
          #     {
          #         "id": 123654789,
          #         "currency_id": 1,
          #         "currency_code": "BTC",
          #         "deposit_fee_currency_id": 1,
          #         "deposit_fee_currency_code": "BTC",
          #         "amount": 0.25,
          #         "fee": 0.00025,
          #         "txid": "qwertyuhgfdsasdfgh",
          #         "protocol_id": 0,
          #         "deposit_status_id": 1,
          #         "status": "PROCESSING",
          #         "status_color": "#BC3D51",
          #         "created_at": "2018-11-28 12:32:08",
          #         "timestamp": "1543409389",
          #         "confirmations": "1 of 2"
          #     }
          #
          # fetchWithdrawals
          #
          #     {
          #         "id": 65899,
          #         "amount": "0.00600000",
          #         "currency_id": 1,
          #         "currency_code": "BTC",
          #         "fee": "0.00400000",
          #         "fee_currency_id": 1,
          #         "fee_currency_code": "BTC",
          #         "withdrawal_status_id": 1,
          #         "status": "Not Confirmed",
          #         "status_color": "#BC3D51",
          #         "created_at": "2019-01-21 09:36:05",
          #         "created_ts": "1548063365",
          #         "updated_at": "2019-01-21 09:36:05",
          #         "updated_ts": "1548063365",
          #         "txid": null,
          #         "protocol_id": 0,
          #         "withdrawal_address": {
          #             "address": "0X12WERTYUIIJHGFVBNMJHGDFGHJ765SDFGHJ",
          #             "address_name": "Address",
          #             "additional_address_parameter": "qwertyuiopasdfghjkl",
          #             "additional_address_parameter_name": "Destination Tag",
          #             "notification": "",
          #             "protocol_id": 10,
          #             "protocol_name": "Tether OMNI",
          #             "supports_new_address_creation": False
          #         }
          #     }
          #
          id = self.safe_string(transaction, 'id')
          withdrawalAddress = self.safe_value(transaction, 'withdrawal_address', {})
          address = self.safe_string(withdrawalAddress, 'address')
          tag = self.safe_string(withdrawalAddress, 'additional_address_parameter')
          currencyId = self.safe_string(transaction, 'currency_id')
          code = None
          if currencyId in self.currencies_by_id:
              currency = self.currencies_by_id[currencyId]
          else:
              code = self.common_currency_code(self.safe_string(transaction, 'currency_code'))
          if (code is None) and (currency is not None):
              code = currency['code']
          type = 'deposit' if ('deposit_status_id' in transaction) else 'withdrawal'
          amount = self.safe_number(transaction, 'amount')
          status = self.parse_transaction_status(self.safe_string_lower(transaction, 'status'))
          timestamp = self.safe_timestamp_2(transaction, 'timestamp', 'created_ts')
          updated = self.safe_timestamp(transaction, 'updated_ts')
          txid = self.safe_string(transaction, 'txid')
          fee = None
          feeCost = self.safe_number(transaction, 'fee')
          if feeCost is not None:
              feeCurrencyId = self.safe_string(transaction, 'fee_currency_id', 'deposit_fee_currency_id')
              feeCurrencyCode = self.safe_currency_code(feeCurrencyId)
              fee = {
                  'cost': feeCost,
                  'currency': feeCurrencyCode,
              }
          return {
              'info': transaction,
              'id': id,
              'txid': txid,
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
              'addressFrom': None,
              'address': address,
              'addressTo': address,
              'tagFrom': None,
              'tag': tag,
              'tagTo': tag,
              'type': type,
              'amount': amount,
              'currency': code,
              'status': status,
              'updated': updated,
              'fee': fee,
          }
  
      async def fetch_deposits(self, code=None, since=None, limit=None, params={}):
          await self.load_markets()
          currency = None
          request = {}
          if code is not None:
              currency = self.currency(code)
              request['currencyId'] = currency['id']
          if limit is not None:
              request['limit'] = limit
          if since is not None:
              request['timeStart'] = since
          response = await self.profileGetDeposits(self.extend(request, params))
          #
          #     {
          #         "success": True,
          #         "data": [
          #             {
          #                 "id": 123654789,
          #                 "currency_id": 1,
          #                 "currency_code": "BTC",
          #                 "deposit_fee_currency_id": 1,
          #                 "deposit_fee_currency_code": "BTC",
          #                 "amount": 0.25,
          #                 "fee": 0.00025,
          #                 "txid": "qwertyuhgfdsasdfgh",
          #                 "protocol_id": 0,
          #                 "deposit_status_id": 1,
          #                 "status": "PROCESSING",
          #                 "status_color": "#BC3D51",
          #                 "created_at": "2018-11-28 12:32:08",
          #                 "timestamp": "1543409389",
          #                 "confirmations": "1 of 2",
          #                 "protocol_specific_settings": {
          #                     "protocol_name": "Tether OMNI",
          #                     "protocol_id": 10,
          #                     "block_explorer_url": "https://omniexplorer.info/search/"
          #                 }
          #             }
          #         ]
          #     }
          #
          deposits = self.safe_value(response, 'data', [])
          return self.parse_transactions(deposits, code, since, limit)
  
      async def fetch_withdrawals(self, code=None, since=None, limit=None, params={}):
          await self.load_markets()
          currency = None
          request = {}
          if code is not None:
              currency = self.currency(code)
              request['currencyId'] = currency['id']
          if limit is not None:
              request['limit'] = limit
          if since is not None:
              request['timeStart'] = since
          response = await self.profileGetWithdrawals(self.extend(request, params))
          #
          #     {
          #         "success": True,
          #         "data": [
          #             {
          #                 "id": 65899,
          #                 "amount": "0.00600000",
          #                 "currency_id": 1,
          #                 "currency_code": "BTC",
          #                 "fee": "0.00400000",
          #                 "fee_currency_id": 1,
          #                 "fee_currency_code": "BTC",
          #                 "withdrawal_status_id": 1,
          #                 "status": "Not Confirmed",
          #                 "status_color": "#BC3D51",
          #                 "created_at": "2019-01-21 09:36:05",
          #                 "created_ts": "1548063365",
          #                 "updated_at": "2019-01-21 09:36:05",
          #                 "updated_ts": "1548063365",
          #                 "txid": null,
          #                 "protocol_id": 0,
          #                 "withdrawal_address": {
          #                     "address": "0X12WERTYUIIJHGFVBNMJHGDFGHJ765SDFGHJ",
          #                     "address_name": "Address",
          #                     "additional_address_parameter": "qwertyuiopasdfghjkl",
          #                     "additional_address_parameter_name": "Destination Tag",
          #                     "notification": "",
          #                     "protocol_id": 10,
          #                     "protocol_name": "Tether OMNI",
          #                     "supports_new_address_creation": False
          #                 },
          #                 "protocol_specific_settings": {
          #                     "protocol_name": "Tether OMNI",
          #                     "protocol_id": 10,
          #                     "block_explorer_url": "https://omniexplorer.info/search/"
          #                 }
          #             }
          #         ]
          #     }
          #
          withdrawals = self.safe_value(response, 'data', [])
          return self.parse_transactions(withdrawals, code, since, limit)
  
      async def withdraw(self, code, amount, address, tag=None, params={}):
          tag, params = self.handle_withdraw_tag_and_params(tag, params)
          self.check_address(address)
          await self.load_markets()
          currency = self.currency(code)
          request = {
              'currency_id': currency['id'],
              'amount': float(self.currency_to_precision(code, amount)),
              'address': address,
              # 'protocol_id': 10,  # optional, to be used with multicurrency wallets like USDT
              # 'additional_address_parameter': tag,  # optional
          }
          if tag is not None:
              request['additional_address_parameter'] = tag
          networks = self.safe_value(self.options, 'networks', {})
          network = self.safe_string_upper(params, 'network')  # self line allows the user to specify either ERC20 or ETH
          network = self.safe_integer(networks, network, network)  # handle ERC20>ETH alias
          if network is not None:
              request['protocol_id'] = network
              params = self.omit(params, 'network')
          response = await self.profilePostWithdraw(self.extend(request, params))
          #
          #     {
          #         "success": True,
          #         "data": {
          #             "id": 65899,
          #             "amount": "0.00600000",
          #             "currency_id": 1,
          #             "currency_code": "BTC",
          #             "fee": "0.00400000",
          #             "fee_currency_id": 1,
          #             "fee_currency_code": "BTC",
          #             "withdrawal_status_id": 1,
          #             "status": "Not Confirmed",
          #             "status_color": "#BC3D51",
          #             "created_at": "2019-01-21 09:36:05",
          #             "created_ts": "1548063365",
          #             "updated_at": "2019-01-21 09:36:05",
          #             "updated_ts": "1548063365",
          #             "txid": null,
          #             "protocol_id": 0,
          #             "withdrawal_address": {
          #                 "address": "0X12WERTYUIIJHGFVBNMJHGDFGHJ765SDFGHJ",
          #                 "address_name": "Address",
          #                 "additional_address_parameter": "qwertyuiopasdfghjkl",
          #                 "additional_address_parameter_name": "Destination Tag",
          #                 "notification": "",
          #                 "protocol_id": 10,
          #                 "protocol_name": "Tether OMNI",
          #                 "supports_new_address_creation": False
          #             }
          #         }
          #     }
          #
          data = self.safe_value(response, 'data', {})
          return self.parse_transaction(data, currency)
  
      async def fetch_funding_fees(self, codes=None, params={}):
          await self.load_markets()
          response = await self.publicGetCurrencies(params)
          #
          #     {
          #         "success": True,
          #         "data": [
          #             {
          #                 "id": 1,
          #                 "code": "BTC",
          #                 "name": "Bitcoin",
          #                 "active": True,
          #                 "delisted": False,
          #                 "precision": 8,
          #                 "minimum_tx_confirmations": 24,
          #                 "minimum_withdrawal_amount": "0.009",
          #                 "minimum_deposit_amount": "0.000003",
          #                 "deposit_fee_currency_id": 1,
          #                 "deposit_fee_currency_code": "ETH",
          #                 "deposit_fee_const": "0.00001",
          #                 "deposit_fee_percent": "0",
          #                 "withdrawal_fee_currency_id": 1,
          #                 "withdrawal_fee_currency_code": "ETH",
          #                 "withdrawal_fee_const": "0.0015",
          #                 "withdrawal_fee_percent": "0",
          #                 "withdrawal_limit": "string",
          #                 "block_explorer_url": "https://blockchain.info/tx/",
          #                 "protocol_specific_settings": [
          #                     {
          #                         "protocol_name": "Tether OMNI",
          #                         "protocol_id": 10,
          #                         "active": True,
          #                         "withdrawal_fee_currency_id": 1,
          #                         "withdrawal_fee_const": 0.002,
          #                         "withdrawal_fee_percent": 0,
          #                         "block_explorer_url": "https://omniexplorer.info/search/"
          #                     }
          #                 ]
          #             }
          #         ]
          #     }
          #
          data = self.safe_value(response, 'data', [])
          withdrawFees = {}
          depositFees = {}
          for i in range(0, len(data)):
              id = self.safe_string(data[i], 'id')
              code = self.safe_currency_code(id)
              withdrawFees[code] = self.safe_number(data[i], 'withdrawal_fee_const')
              depositFees[code] = self.safe_number(data[i], 'deposit_fee_const')
          return {
              'withdraw': withdrawFees,
              'deposit': depositFees,
              'info': response,
          }
  
      def handle_errors(self, httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody):
          if response is None:
              return  # fallback to default error handler
          #
          #     {"success":false,"message":"Wrong parameters","errors":{"candleType":["Invalid Candle Type!"]}}
          #     {"success":false,"message":"Wrong parameters","errors":{"time":["timeStart or timeEnd is less then 1"]}}
          #     {"success":false,"message":"Not enough  ETH"}
          #
          success = self.safe_value(response, 'success', False)
          if not success:
              message = self.safe_string(response, 'message')
              feedback = self.id + ' ' + body
              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
  