text: # -*- coding: utf-8 -*-
  
  # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
  # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
  
  from ccxt.async_support.base.exchange import Exchange
  import hashlib
  import math
  from ccxt.base.errors import ExchangeError
  from ccxt.base.errors import ArgumentsRequired
  from ccxt.base.errors import BadRequest
  from ccxt.base.errors import BadSymbol
  from ccxt.base.errors import InvalidOrder
  from ccxt.base.decimal_to_precision import TRUNCATE
  from ccxt.base.decimal_to_precision import SIGNIFICANT_DIGITS
  from ccxt.base.precise import Precise
  
  
  class eterbase(Exchange):
  
      def describe(self):
          return self.deep_extend(super(eterbase, self).describe(), {
              'id': 'eterbase',
              'name': 'Eterbase',
              'countries': ['SK'],  # Slovakia
              'rateLimit': 500,
              'version': 'v1',
              'certified': True,
              'has': {
                  'CORS': False,
                  'publicAPI': True,
                  'privateAPI': True,
                  'cancelOrder': True,
                  'createOrder': True,
                  'deposit': False,
                  'fetchBalance': True,
                  'fetchClosedOrders': True,
                  'fetchCurrencies': True,
                  'fetchDepositAddress': False,
                  'fetchMarkets': True,
                  'fetchMyTrades': True,
                  'fetchOHLCV': True,
                  'fetchOpenOrders': True,
                  'fetchOrder': True,
                  'fetchOrderBook': True,
                  'fetchOrders': False,
                  'fetchOrderTrades': True,
                  'fetchTicker': True,
                  'fetchTickers': True,
                  'fetchTime': True,
                  'fetchTrades': True,
                  'withdraw': True,
              },
              'timeframes': {
                  '1m': '1',
                  '5m': '5',
                  '15m': '15',
                  '1h': '60',
                  '4h': '240',
                  '1d': '1440',
                  '1w': '10080',
              },
              'urls': {
                  'logo': 'https://user-images.githubusercontent.com/1294454/82067900-faeb0f80-96d9-11ea-9f22-0071cfcb9871.jpg',
                  'api': 'https://api.eterbase.exchange',
                  'www': 'https://www.eterbase.com',
                  'doc': 'https://developers.eterbase.exchange',
                  'fees': 'https://www.eterbase.com/exchange/fees',
                  'referral': 'https://eterbase.exchange/invite/1wjjh4Pe',
              },
              'api': {
                  'markets': {
                      'get': [
                          '{id}/order-book',
                      ],
                  },
                  'public': {
                      'get': [
                          'ping',
                          'assets',
                          'markets',
                          'tickers',
                          'tickers/{id}/ticker',
                          'markets/{id}/trades',
                          'markets/{id}/ohlcv',
                          'wstoken',
                      ],
                  },
                  'private': {
                      'get': [
                          'accounts/{id}/balances',
                          'accounts/{id}/orders',
                          'accounts/{id}/fills',
                          'orders/{id}/fills',
                          'orders/{id}',
                      ],
                      'post': [
                          'orders',
                          'accounts/{id}/withdrawals',
                      ],
                      'delete': [
                          'orders/{id}',
                      ],
                  },
                  'feed': {
                      'get': [
                          'feed',
                      ],
                  },
              },
              'fees': {
                  'trading': {
                      'tierBased': True,
                      'percentage': True,
                      'taker': 0.35 / 100,
                      'maker': 0.35 / 100,
                  },
              },
              'requiredCredentials': {
                  'apiKey': True,
                  'secret': True,
                  'uid': True,
              },
              'precisionMode': SIGNIFICANT_DIGITS,
              'options': {
                  'createMarketBuyOrderRequiresPrice': True,
              },
              'exceptions': {
                  'exact': {
                      'Invalid cost': InvalidOrder,  # {"message":"Invalid cost","_links":{"self":{"href":"/orders","templated":false}}}
                      'Invalid order ID': InvalidOrder,  # {"message":"Invalid order ID","_links":{"self":{"href":"/orders/4a151805-d594-4a96-9d64-e3984f2441f7","templated":false}}}
                      'Invalid market !': BadSymbol,  # {"message":"Invalid market !","_links":{"self":{"href":"/markets/300/order-book","templated":false}}}
                  },
                  'broad': {
                      'Failed to convert argument': BadRequest,
                  },
              },
          })
  
      async def fetch_time(self, params={}):
          response = await self.publicGetPing(params)
          #
          #     {"pong": 1556354416582}
          #
          return self.safe_integer(response, 'pong')
  
      async def fetch_markets(self, params={}):
          response = await self.publicGetMarkets(params)
          #
          #     [
          #         {
          #             "id":33,
          #             "symbol":"ETHUSDT",
          #             "base":"ETH",
          #             "quote":"USDT",
          #             "priceSigDigs":5,
          #             "qtySigDigs":8,
          #             "costSigDigs":8,
          #             "verificationLevelUser":1,
          #             "verificationLevelCorporate":11,
          #             "group":"USD",
          #             "tradingRules":[
          #                 {"attribute":"Qty","condition":"Min","value":0.006},
          #                 {"attribute":"Qty","condition":"Max","value":1000},
          #                 {"attribute":"Cost","condition":"Min","value":1},
          #                 {"attribute":"Cost","condition":"Max","value":210000}
          #             ],
          #             "allowedOrderTypes":[1,2,3,4],
          #             "state":"Trading"
          #         }
          #     ]
          #
          result = []
          for i in range(0, len(response)):
              market = self.parse_market(response[i])
              result.append(market)
          return result
  
      def parse_market(self, market):
          #
          #     {
          #         "id":33,
          #         "symbol":"ETHUSDT",
          #         "base":"ETH",
          #         "quote":"USDT",
          #         "priceSigDigs":5,
          #         "qtySigDigs":8,
          #         "costSigDigs":8,
          #         "verificationLevelUser":1,
          #         "verificationLevelCorporate":11,
          #         "group":"USD",
          #         "tradingRules":[
          #             {"attribute":"Qty","condition":"Min","value":0.006},
          #             {"attribute":"Qty","condition":"Max","value":1000},
          #             {"attribute":"Cost","condition":"Min","value":1},
          #             {"attribute":"Cost","condition":"Max","value":210000}
          #         ],
          #         "allowedOrderTypes":[1,2,3,4],
          #         "state":"Trading"
          #     }
          #
          id = self.safe_string(market, 'id')
          # numericId = self.safe_string(market, 'id')
          baseId = self.safe_string(market, 'base')
          quoteId = self.safe_string(market, 'quote')
          base = self.safe_currency_code(baseId)
          quote = self.safe_currency_code(quoteId)
          symbol = base + '/' + quote
          state = self.safe_string(market, 'state')
          active = (state == 'Trading')
          precision = {
              'price': self.safe_integer(market, 'priceSigDigs'),
              'amount': self.safe_integer(market, 'qtySigDigs'),
              'cost': self.safe_integer(market, 'costSigDigs'),
          }
          rules = self.safe_value(market, 'tradingRules', [])
          minAmount = None
          maxAmount = None
          minCost = None
          maxCost = None
          for i in range(0, len(rules)):
              rule = rules[i]
              attribute = self.safe_string(rule, 'attribute')
              condition = self.safe_string(rule, 'condition')
              value = self.safe_number(rule, 'value')
              if (attribute == 'Qty') and (condition == 'Min'):
                  minAmount = value
              elif (attribute == 'Qty') and (condition == 'Max'):
                  maxAmount = value
              elif (attribute == 'Cost') and (condition == 'Min'):
                  minCost = value
              elif (attribute == 'Cost') and (condition == 'Max'):
                  maxCost = value
          return {
              'id': id,
              'symbol': symbol,
              'base': base,
              'quote': quote,
              'baseId': baseId,
              'quoteId': quoteId,
              'info': market,
              'active': active,
              'precision': precision,
              'limits': {
                  'amount': {
                      'min': minAmount,
                      'max': maxAmount,
                  },
                  'price': {
                      'min': None,
                      'max': None,
                  },
                  'cost': {
                      'min': minCost,
                      'max': maxCost,
                  },
              },
          }
  
      async def fetch_currencies(self, params={}):
          response = await self.publicGetAssets(params)
          #
          #     [
          #         {
          #             "id":"LINK",
          #             "name":"ChainLink Token",
          #             "precisionDisplay":8,
          #             "precisionMax":18,
          #             "precisionBasis":1000000000000000000,
          #             "precisionStep":1,
          #             "verificationLevelMin":"null",
          #             "cmcId":"LINK",
          #             "txnUrl":"https://etherscan.io/tx/{txnId}",
          #             "state":"Active",
          #             "type":"Crypto",
          #             "isReference":false,
          #             "withdrawalMin":"0",
          #             "withdrawalMax":"50587",
          #             "withdrawalFee":"0.55",
          #             "depositEnabled":true,
          #             "withdrawalEnabled":true,
          #             "description":"",
          #             "coingeckoUrl":"https://www.coingecko.com/en/coins/chainlink",
          #             "coinmarketcapUrl":"https://coinmarketcap.com/currencies/chainlink",
          #             "eterbaseUrl":"https://www.eterbase.com/system-status/LINK",
          #             "explorerUrl":"https://etherscan.io/token/0x514910771af9ca656af840dff83e8264ecf986ca",
          #             "withdrawalMemoAllowed":false,
          #             "countries":[],
          #             "networks":[]
          #         }
          #     ]
          #
          result = {}
          for i in range(0, len(response)):
              currency = response[i]
              id = self.safe_string(currency, 'id')
              precision = self.safe_integer(currency, 'precisionDisplay')
              code = self.safe_currency_code(id)
              depositEnabled = self.safe_value(currency, 'depositEnabled')
              withdrawalEnabled = self.safe_value(currency, 'withdrawalEnabled')
              state = self.safe_string(currency, 'state')
              active = depositEnabled and withdrawalEnabled and (state == 'Active')
              type = self.safe_string_lower(currency, 'type')
              name = self.safe_string(currency, 'name')
              result[code] = {
                  'id': id,
                  'info': currency,
                  'code': code,
                  'type': type,
                  'name': name,
                  'active': active,
                  'fee': self.safe_number(currency, 'withdrawalFee'),
                  'precision': precision,
                  'limits': {
                      'amount': {
                          'min': math.pow(10, -precision),
                          'max': math.pow(10, precision),
                      },
                      'withdraw': {
                          'min': self.safe_number(currency, 'withdrawalMin'),
                          'max': self.safe_number(currency, 'withdrawalMax'),
                      },
                  },
              }
          return result
  
      def parse_ticker(self, ticker, market=None):
          #
          # fetchTicker
          #
          #     {
          #         "time":1588778516608,
          #         "marketId":250,
          #         "symbol": "ETHUSDT",
          #         "price":0.0,
          #         "change":0.0,
          #         "volumeBase":0.0,
          #         "volume":0.0,
          #         "low":0.0,
          #         "high":0.0,
          #     }
          #
          marketId = self.safe_string(ticker, 'marketId')
          symbol = self.safe_symbol(marketId, market)
          timestamp = self.safe_integer(ticker, 'time')
          last = self.safe_number(ticker, 'price')
          baseVolume = self.safe_number(ticker, 'volumeBase')
          quoteVolume = self.safe_number(ticker, 'volume')
          vwap = self.vwap(baseVolume, quoteVolume)
          percentage = self.safe_number(ticker, 'change')
          result = {
              'symbol': symbol,
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
              'high': self.safe_number(ticker, 'high'),
              'low': self.safe_number(ticker, 'low'),
              'bid': None,
              'bidVolume': None,
              'ask': None,
              'askVolume': None,
              'vwap': vwap,
              'open': None,
              'close': last,
              'last': last,
              'previousClose': None,  # previous day close
              'change': None,
              'percentage': percentage,
              'average': None,
              'baseVolume': baseVolume,
              'quoteVolume': quoteVolume,
              'info': ticker,
          }
          return result
  
      async def fetch_ticker(self, symbol, params={}):
          await self.load_markets()
          market = self.market(symbol)
          request = {
              'id': market['id'],
          }
          response = await self.publicGetTickersIdTicker(self.extend(request, params))
          #
          #     {
          #         "time":1588778516608,
          #         "marketId":250,
          #         "price":0.0,
          #         "change":0.0,
          #         "volumeBase":0.0,
          #         "volume":0.0,
          #         "low":0.0,
          #         "high":0.0,
          #     }
          #
          return self.parse_ticker(response, market)
  
      async def fetch_tickers(self, symbols=None, params={}):
          await self.load_markets()
          request = {
              # 'quote': 'USDT',  # identifier of a quote asset to filter the markets
          }
          response = await self.publicGetTickers(self.extend(request, params))
          #
          #     [
          #         {
          #             "time":1588831771698,
          #             "marketId":33,
          #             "price":204.54,
          #             "change":-1.03,
          #             "volumeBase":544.9801776699998,
          #             "volume":111550.433735,
          #             "low":200.33,
          #             "high":209.51
          #         },
          #     ]
          #
          return self.parse_tickers(response, symbols)
  
      def parse_trade(self, trade, market):
          #
          # fetchTrades(public)
          #
          #     {
          #         "id":251199246,
          #         "side":2,
          #         "price":0.022044,
          #         "executedAt":1588830682664,
          #         "qty":0.13545846,
          #         "makerId":"67ed6ef3-33d8-4389-ba70-5c68d9db9f6c",
          #         "takerId":"229ef0d6-fe67-4b5d-9733-824142fab8f3"
          #     }
          #
          # fetchMyTrades, fetchOrderTrades(private)
          #
          #     {
          #         "id": 123,
          #         "marketId": 123,
          #         "side": 1,
          #         "qty": "1.23456",
          #         "price": "1.23456",
          #         "cost": "1.23456",
          #         "fee": "1.23456",
          #         "feeAsset": "XBASE",
          #         "liquidity": 1,
          #         "orderId": "30a2b5d0-be2e-4d0a-93ed-a7c45fed1792",
          #         "tradeId": 123,
          #         "filledAt": 1556355722341
          #     }
          #
          priceString = self.safe_string(trade, 'price')
          amountString = self.safe_string(trade, 'qty')
          price = self.parse_number(priceString)
          amount = self.parse_number(amountString)
          fee = None
          feeCost = self.safe_number(trade, 'fee')
          if feeCost is not None:
              feeCurrencyId = self.safe_string(trade, 'feeAsset')
              feeCurrencyCode = self.safe_currency_code(feeCurrencyId)
              fee = {
                  'cost': feeCost,
                  'currency': feeCurrencyCode,
              }
          cost = self.safe_number(trade, 'qty')
          if cost is None:
              cost = self.parse_number(Precise.string_mul(priceString, amountString))
          timestamp = self.safe_integer_2(trade, 'executedAt', 'filledAt')
          tradeSide = self.safe_string(trade, 'side')
          side = 'buy' if (tradeSide == '1') else 'sell'
          liquidity = self.safe_string(trade, 'liquidity')
          takerOrMaker = None
          if liquidity is not None:
              takerOrMaker = 'maker' if (liquidity == '1') else 'taker'
          orderId = self.safe_string(trade, 'orderId')
          id = self.safe_string(trade, 'id')
          marketId = self.safe_string(trade, 'marketId')
          symbol = self.safe_symbol(marketId, market)
          return {
              'info': trade,
              'id': id,
              'symbol': symbol,
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
              'order': orderId,
              'type': None,
              'side': side,
              'takerOrMaker': takerOrMaker,
              'price': price,
              'amount': amount,
              'cost': cost,
              'fee': fee,
          }
  
      async def fetch_trades(self, symbol, since=None, limit=None, params={}):
          await self.load_markets()
          market = self.market(symbol)
          request = {
              'id': market['id'],
              # 'offset': 0  # the number of records to skip
          }
          if limit is not None:
              request['limit'] = limit
          response = await self.publicGetMarketsIdTrades(self.extend(request, params))
          #
          #     [
          #         {
          #             "id":251199246,
          #             "side":2,
          #             "price":0.022044,
          #             "executedAt":1588830682664,
          #             "qty":0.13545846,
          #             "makerId":"67ed6ef3-33d8-4389-ba70-5c68d9db9f6c",
          #             "takerId":"229ef0d6-fe67-4b5d-9733-824142fab8f3"
          #         }
          #     ]
          #
          return self.parse_trades(response, market, since, limit)
  
      async def fetch_order_book(self, symbol, limit=None, params={}):
          await self.load_markets()
          request = {
              'id': self.market_id(symbol),
          }
          response = await self.marketsGetIdOrderBook(self.extend(request, params))
          #
          #     {
          #         "type":"ob_snapshot",
          #         "marketId":3,
          #         "timestamp":1588836429847,
          #         "bids":[
          #             [0.021694,8.8793688,1],  # price, amount, count
          #             [0.01937,7.1340473,1],
          #             [0.020774,3.314881,1],
          #         ],
          #         "asks":[
          #             [0.02305,8.8793688,1],
          #             [0.028022,3.314881,1],
          #             [0.022598,3.314881,1],
          #         ]
          #     }
          #
          timestamp = self.safe_integer(response, 'timestamp')
          return self.parse_order_book(response, symbol, timestamp)
  
      def parse_ohlcv(self, ohlcv, market=None):
          #
          #     {
          #         "time":1588807500000,
          #         "open":0.022077,
          #         "high":0.022077,
          #         "low":0.022051,
          #         "close":0.022051,
          #         "volume":10.532025119999997
          #     }
          #
          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='1m', since=None, limit=None, params={}):
          request = {
              # 'id': market['id'],
              'interval': self.timeframes[timeframe],
              # 'start': 1588830682664,  # milliseconds
              # 'end': 1588830682664,  # milliseconds
          }
          duration = self.parse_timeframe(timeframe)
          now = self.milliseconds()
          if since is not None:
              request['start'] = since
              if limit is None:
                  request['end'] = now
              else:
                  request['end'] = self.sum(since, duration * limit * 1000)
          elif limit is not None:
              request['start'] = now - duration * limit * 1000
              request['end'] = now
          else:
              raise ArgumentsRequired(self.id + ' fetchOHLCV() requires a since argument, or a limit argument, or both')
          await self.load_markets()
          market = self.market(symbol)
          request['id'] = market['id']
          response = await self.publicGetMarketsIdOhlcv(self.extend(request, params))
          #
          #     [
          #         {"time":1588807500000,"open":0.022077,"high":0.022077,"low":0.022051,"close":0.022051,"volume":10.532025119999997},
          #         {"time":1588807800000,"open":0.022051,"high":0.022051,"low":0.022044,"close":0.022044,"volume":0.655987},
          #         {"time":1588808400000,"open":0.022044,"high":0.022044,"low":0.022044,"close":0.022044,"volume":3.9615545499999993},
          #     ]
          #
          return self.parse_ohlcvs(response, market, timeframe, since, limit)
  
      async def fetch_balance(self, params={}):
          await self.load_markets()
          request = {
              'id': self.uid,
          }
          response = await self.privateGetAccountsIdBalances(self.extend(request, params))
          #
          #     [
          #         {
          #             "assetId":"USDT",
          #             "available":"25",
          #             "balance":"25",
          #             "reserved":"0",
          #             "balanceBtc":"0.0",
          #             "balanceRef":"0.0",
          #         }
          #     ]
          #
          result = {'info': response}
          for i in range(0, len(response)):
              balance = response[i]
              currencyId = self.safe_string(balance, 'assetId')
              code = self.safe_currency_code(currencyId)
              account = self.account()
              account['free'] = self.safe_string(balance, 'available')
              account['used'] = self.safe_string(balance, 'reserved')
              account['total'] = self.safe_string(balance, 'balance')
              result[code] = account
          return self.parse_balance(result, False)
  
      async def fetch_order(self, id, symbol=None, params={}):
          await self.load_markets()
          request = {
              'id': id,
          }
          response = await self.privateGetOrdersId(self.extend(request, params))
          #
          #     {
          #         "id": "30a2b5d0-be2e-4d0a-93ed-a7c45fed1792",
          #         "accountId": "30a2b5d0-be2e-4d0a-93ed-a7c45fed1792",
          #         "marketId": 123,
          #         "type": 1,
          #         "side": 1,
          #         "qty": "1.23456",
          #         "cost": "1.23456",
          #         "remainingQty": "1.23456",
          #         "remainingCost": "1.23456",
          #         "limitPrice": "1.23456",
          #         "stopPrice": "1.23456",
          #         "postOnly": False,
          #         "timeInForce": "GTC",
          #         "state": 1,
          #         "closeReason": "FILLED",
          #         "placedAt": 1556355722341,
          #         "closedAt": 1556355722341
          #     }
          #
          return self.parse_order(response)
  
      def parse_order_status(self, status):
          statuses = {
              '1': None,  # pending
              '2': 'open',  # open
              '3': 'open',  # partially filled
              '4': 'closed',  # closed
              'FILLED': 'closed',
              'USER_REQUESTED_CANCEL': 'canceled',
              'ADMINISTRATIVE_CANCEL': 'canceled',
              'NOT_ENOUGH_LIQUIDITY': 'canceled',
              'EXPIRED': 'expired',
              'ONE_CANCELS_OTHER': 'canceled',
          }
          return self.safe_string(statuses, status)
  
      def parse_order(self, order, market=None):
          #
          # fetchOrder, fetchOpenOrders, fetchClosedOrders
          #
          #     {
          #         "id": "30a2b5d0-be2e-4d0a-93ed-a7c45fed1792",
          #         "accountId": "30a2b5d0-be2e-4d0a-93ed-a7c45fed1792",
          #         "marketId": 123,
          #         "type": 1,
          #         "side": 1,
          #         "qty": "1.23456",
          #         "cost": "1.23456",
          #         "remainingQty": "1.23456",
          #         "remainingCost": "1.23456",
          #         "limitPrice": "1.23456",
          #         "stopPrice": "1.23456",
          #         "postOnly": False,
          #         "timeInForce": "GTC",
          #         "state": 1,
          #         "closeReason": "FILLED",
          #         "placedAt": 1556355722341,
          #         "closedAt": 1556355722341
          #     }
          #
          # createOrder
          #
          #     market buy
          #
          #     {
          #         "id":"ff81127c-8fd5-4846-b683-110639dcd322",
          #         "accountId":"6d445378-d8a3-4932-91cd-545d0a4ad2a2",
          #         "marketId":33,
          #         "type":1,
          #         "side":1,
          #         "cost":"25",
          #         "postOnly":false,
          #         "timeInForce":"GTC",
          #         "state":1,
          #         "placedAt":1589510846735
          #     }
          #
          #     market sell, limit buy, limit sell
          #
          #     {
          #         "id":"042a38b0-e369-4ad2-ae73-a18ff6b1dcf1",
          #         "accountId":"6d445378-d8a3-4932-91cd-545d0a4ad2a2",
          #         "marketId":33,
          #         "type":2,
          #         "side":1,
          #         "qty":"1000",
          #         "limitPrice":"100",
          #         "postOnly":false,
          #         "timeInForce":"GTC",
          #         "state":1,
          #         "placedAt":1589403938682,
          #     }
          #
          id = self.safe_string(order, 'id')
          timestamp = self.safe_integer(order, 'placedAt')
          marketId = self.safe_integer(order, 'marketId')
          symbol = self.safe_symbol(marketId, market)
          status = self.parse_order_status(self.safe_string(order, 'state'))
          if status == 'closed':
              status = self.parse_order_status(self.safe_string(order, 'closeReason'))
          orderSide = self.safe_string(order, 'side')
          side = 'buy' if (orderSide == '1') else 'sell'
          orderType = self.safe_string(order, 'type')
          type = None
          if orderType == '1':
              type = 'market'
          elif orderType == '2':
              type = 'limit'
          elif orderType == '3':
              type = 'stopmarket'
          else:
              type = 'stoplimit'
          price = self.safe_number(order, 'limitPrice')
          amount = self.safe_number(order, 'qty')
          remaining = self.safe_number(order, 'remainingQty')
          filled = None
          remainingCost = self.safe_number(order, 'remainingCost')
          if (remainingCost is not None) and (remainingCost == 0.0):
              remaining = 0
          if (amount is not None) and (remaining is not None):
              filled = max(0, amount - remaining)
          cost = self.safe_number(order, 'cost')
          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
          average = None
          if cost is not None:
              if filled:
                  average = cost / filled
          timeInForce = self.safe_string(order, 'timeInForce')
          stopPrice = self.safe_number(order, 'stopPrice')
          postOnly = self.safe_value(order, 'postOnly')
          return {
              'info': order,
              'id': id,
              'clientOrderId': None,
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
              'lastTradeTimestamp': None,
              'symbol': symbol,
              'type': type,
              'timeInForce': timeInForce,
              'postOnly': postOnly,
              'side': side,
              'price': price,
              'stopPrice': stopPrice,
              'amount': amount,
              'cost': cost,
              'average': average,
              'filled': filled,
              'remaining': remaining,
              'status': status,
              'fee': None,
              'trades': None,
          }
  
      async def fetch_orders_by_state(self, state, symbol=None, since=None, limit=None, params={}):
          now = self.milliseconds()
          ninetyDays = 90 * 24 * 60 * 60 * 1000  # 90 days timerange max
          request = {
              'id': self.uid,
              'state': state,
              # 'side': Integer,  # 1 = buy, 2 = sell
              # 'offset': 0,  # the number of records to skip
          }
          if since is None:
              request['from'] = now - ninetyDays
              request['to'] = now
          else:
              request['from'] = since
              request['to'] = self.sum(since, ninetyDays)
          await self.load_markets()
          market = None
          if symbol is not None:
              market = self.market(symbol)
              request['marketId'] = market['id']
          if limit is not None:
              request['limit'] = limit  # default 50
          response = await self.privateGetAccountsIdOrders(self.extend(request, params))
          #
          #     [
          #         {
          #             "id": "30a2b5d0-be2e-4d0a-93ed-a7c45fed1792",
          #             "accountId": "30a2b5d0-be2e-4d0a-93ed-a7c45fed1792",
          #             "marketId": 123,
          #             "type": 1,
          #             "side": 1,
          #             "qty": "1.23456",
          #             "cost": "1.23456",
          #             "remainingQty": "1.23456",
          #             "remainingCost": "1.23456",
          #             "limitPrice": "1.23456",
          #             "stopPrice": "1.23456",
          #             "postOnly": False,
          #             "timeInForce": "GTC",
          #             "state": 1,
          #             "closeReason": "FILLED",
          #             "placedAt": 1556355722341,
          #             "closedAt": 1556355722341
          #         }
          #     ]
          #
          return self.parse_orders(response, market, since, limit)
  
      async def fetch_closed_orders(self, symbol=None, since=None, limit=None, params={}):
          return await self.fetch_orders_by_state('INACTIVE', symbol, since, limit, params)
  
      async def fetch_open_orders(self, symbol=None, since=None, limit=None, params={}):
          return await self.fetch_orders_by_state('ACTIVE', symbol, since, limit, params)
  
      async def fetch_my_trades(self, symbol=None, since=None, limit=None, params={}):
          now = self.milliseconds()
          ninetyDays = 90 * 24 * 60 * 60 * 1000  # 90 days timerange max
          request = {
              'id': self.uid,
              # 'side': Integer,  # 1 = buy, 2 = sell
              # 'offset': 0,  # the number of records to skip
          }
          if since is None:
              request['from'] = now - ninetyDays
              request['to'] = now
          else:
              request['from'] = since
              request['to'] = self.sum(since, ninetyDays)
          await self.load_markets()
          market = None
          if symbol is not None:
              market = self.market(symbol)
              request['marketId'] = market['id']
          if limit is not None:
              request['limit'] = limit  # default 50, max 200
          response = await self.privateGetAccountsIdFills(self.extend(request, params))
          #
          #     [
          #         {
          #             "id": 123,
          #             "marketId": 123,
          #             "side": 1,
          #             "qty": "1.23456",
          #             "price": "1.23456",
          #             "cost": "1.23456",
          #             "fee": "1.23456",
          #             "feeAsset": "XBASE",
          #             "liquidity": 1,
          #             "orderId": "30a2b5d0-be2e-4d0a-93ed-a7c45fed1792",
          #             "tradeId": 123,
          #             "filledAt": 1556355722341
          #         }
          #     ]
          #
          return self.parse_trades(response, market, since, limit)
  
      async def fetch_order_trades(self, id, symbol=None, since=None, limit=None, params={}):
          await self.load_markets()
          request = {
              'id': id,
          }
          trades = await self.privateGetOrdersIdFills(self.extend(request, params))
          return self.parse_trades(trades)
  
      async def create_order(self, symbol, type, side, amount, price=None, params={}):
          await self.load_markets()
          market = self.market(symbol)
          uppercaseType = type.upper()
          if uppercaseType == 'MARKET':
              type = 1
          elif uppercaseType == 'LIMIT':
              type = 2
          elif uppercaseType == 'STOPMARKET':
              type = 3
          elif uppercaseType == 'STOPLIMIT':
              type = 4
          uppercaseSide = side.upper()
          side = uppercaseSide == 1 if 'BUY' else 2
          request = {
              'accountId': self.uid,
              'marketId': market['id'],
              'type': type,
              'side': side,
              # 'postOnly': False,
              # 'timeInForce': 'GTC',
          }
          clientOrderId = self.safe_value_2(params, 'refId', 'clientOrderId')
          query = params
          if clientOrderId is not None:
              request['refId'] = clientOrderId
              query = self.omit(params, ['refId', 'clientOrderId'])
          if (uppercaseType == 'MARKET') and (uppercaseSide == 'BUY'):
              # for market buy it requires the amount of quote currency to spend
              cost = self.safe_number(params, 'cost')
              if self.options['createMarketBuyOrderRequiresPrice']:
                  if cost is None:
                      if price is not None:
                          cost = amount * price
                      else:
                          raise InvalidOrder(self.id + " createOrder() requires the price argument with market buy orders to calculate total order cost(amount to spend), where cost = amount * price. Supply a price argument to createOrder() call if you want the cost to be calculated for you from price and amount, or, alternatively, add .options['createMarketBuyOrderRequiresPrice'] = False to supply the cost in the amount argument(the exchange-specific behaviour)")
              else:
                  cost = amount if (cost is None) else cost
              precision = market['precision']['price']
              request['cost'] = self.decimal_to_precision(cost, TRUNCATE, precision, self.precisionMode)
          else:
              request['qty'] = self.amount_to_precision(symbol, amount)
          if uppercaseType == 'LIMIT':
              request['limitPrice'] = self.price_to_precision(symbol, price)
          response = await self.privatePostOrders(self.extend(request, query))
          #
          # market buy
          #
          #     {
          #         "id":"ff81127c-8fd5-4846-b683-110639dcd322",
          #         "accountId":"6d445378-d8a3-4932-91cd-545d0a4ad2a2",
          #         "marketId":33,
          #         "type":1,
          #         "side":1,
          #         "cost":"25",
          #         "postOnly":false,
          #         "timeInForce":"GTC",
          #         "state":1,
          #         "placedAt":1589510846735
          #     }
          #
          # market sell, limit buy, limit sell
          #
          #     {
          #         "id":"042a38b0-e369-4ad2-ae73-a18ff6b1dcf1",
          #         "accountId":"6d445378-d8a3-4932-91cd-545d0a4ad2a2",
          #         "marketId":33,
          #         "type":2,
          #         "side":1,
          #         "qty":"1000",
          #         "limitPrice":"100",
          #         "postOnly":false,
          #         "timeInForce":"GTC",
          #         "state":1,
          #         "placedAt":1589403938682,
          #     }
          #
          return self.parse_order(response, market)
  
      async def cancel_order(self, id, symbol=None, params={}):
          request = {
              'id': id,
          }
          return await self.privateDeleteOrdersId(self.extend(request, params))
  
      async def withdraw(self, code, amount, address, tag=None, params={}):
          self.check_address(address)
          await self.load_markets()
          currency = self.currency(code)
          request = {
              'id': self.uid,
              'accountId': self.uid,
              'assetId': currency['id'],
              'amount': amount,
              # 'cryptoAddress': address,
              # 'accountNumber': 'IBAN',  # IBAN account number
              # 'networkId': 'XBASE',  # underlying network
          }
          if address is not None:
              request['cryptoAddress'] = address
              if tag is not None:
                  request['memo'] = tag
          response = await self.privatePostAccountsIdWithdrawals(self.extend(request, params))
          #
          #     {
          #         "id": "98b62dde-a87f-45f0-8db8-80ae2d312fa6"
          #     }
          #
          return {
              'info': response,
              'id': self.safe_string(response, 'id'),
          }
  
      def sign(self, path, api='public', method='GET', params={}, httpHeaders=None, body=None):
          query = self.omit(params, self.extract_params(path))
          request = '/'
          if api == 'public':
              request += 'api/' + self.version
          elif api == 'private':
              request += 'api/' + self.version
          elif api == 'markets':
              request += 'api/' + api
          request += '/' + self.implode_params(path, params)
          if method == 'GET':
              if query:
                  request += '?' + self.urlencode(query)
          url = self.urls['api'] + request
          if api == 'private':
              self.check_required_credentials()
              payload = ''
              if method != 'GET':
                  if query:
                      body = self.json(query)
                      payload = body
              # construct signature
              hasBody = (method == 'POST') or (method == 'PUT') or (method == 'PATCH')
              # date = 'Mon, 30 Sep 2019 13:57:23 GMT'
              date = self.rfc2616(self.milliseconds())
              headersCSV = 'date' + ' ' + 'request-line'
              message = 'date' + ':' + ' ' + date + "\n" + method + ' ' + request + ' HTTP/1.1'  # eslint-disable-line quotes
              digest = ''
              if hasBody:
                  digest = 'SHA-256=' + self.hash(payload, 'sha256', 'base64')
                  message += "\ndigest" + ':' + ' ' + digest  # eslint-disable-line quotes
                  headersCSV += ' ' + 'digest'
              signature = self.hmac(self.encode(message), self.encode(self.secret), hashlib.sha256, 'base64')
              authorizationHeader = 'hmac username="' + self.apiKey + '",algorithm="hmac-sha256",headers="' + headersCSV + '",' + 'signature="' + signature + '"'
              httpHeaders = {
                  'Date': date,
                  'Authorization': authorizationHeader,
                  'Content-Type': 'application/json',
              }
              if hasBody:
                  httpHeaders['Digest'] = digest
          return {'url': url, 'method': method, 'body': body, 'headers': httpHeaders}
  
      def handle_errors(self, httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody):
          if response is None:
              return  # fallback to default error handler
          #
          #     {"message":"Invalid cost","_links":{"self":{"href":"/orders","templated":false}}}
          #
          message = self.safe_string(response, 'message')
          if message is not None:
              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
  