text: # -*- coding: utf-8 -*-
  
  # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
  # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
  
  from ccxt.base.exchange import Exchange
  from ccxt.base.errors import ExchangeError
  from ccxt.base.errors import AuthenticationError
  from ccxt.base.errors import PermissionDenied
  from ccxt.base.errors import AccountSuspended
  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': {
                  'CORS': None,
                  'spot': True,
                  'margin': False,
                  'swap': False,
                  'future': False,
                  'option': False,
                  'addMargin': False,
                  'cancelAllOrders': True,
                  'cancelOrder': True,
                  'createDepositAddress': True,
                  'createMarketOrder': False,
                  'createOrder': True,
                  'createReduceOnlyOrder': False,
                  'fetchBalance': True,
                  'fetchBorrowRate': False,
                  'fetchBorrowRateHistories': False,
                  'fetchBorrowRateHistory': False,
                  'fetchBorrowRates': False,
                  'fetchBorrowRatesPerSymbol': False,
                  'fetchClosedOrder': True,
                  'fetchCurrencies': True,
                  'fetchDeposit': True,
                  'fetchDepositAddress': True,
                  'fetchDeposits': True,
                  'fetchFundingHistory': False,
                  'fetchFundingRate': False,
                  'fetchFundingRateHistory': False,
                  'fetchFundingRates': False,
                  'fetchIndexOHLCV': False,
                  'fetchLeverage': False,
                  'fetchLeverageTiers': False,
                  'fetchMarkets': True,
                  'fetchMarkOHLCV': False,
                  'fetchMyTrades': True,
                  'fetchOHLCV': True,
                  'fetchOpenInterestHistory': False,
                  'fetchOpenOrders': True,
                  'fetchOrder': True,
                  'fetchOrderBook': True,
                  'fetchOrderTrades': True,
                  'fetchPosition': False,
                  'fetchPositions': False,
                  'fetchPositionsRisk': False,
                  'fetchPremiumIndexOHLCV': False,
                  'fetchTicker': True,
                  'fetchTickers': True,
                  'fetchTime': True,
                  'fetchTrades': True,
                  'fetchTradingFee': True,
                  'fetchTradingFees': False,
                  'fetchTransactionFees': True,
                  'fetchWithdrawal': True,
                  'fetchWithdrawals': True,
                  'reduceMargin': False,
                  'setLeverage': False,
                  'setMarginMode': False,
                  'setPositionMode': False,
                  'transfer': 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://apidocs.stex.com/',
                      '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,
                  },
                  'accountsByType': {
                      'spot': 'spot',
                      'hold': 'hold',
                      'funding': 'funding',
                      'referal': 'referal',
                  },
                  'transfer': {
                      'fillResponseFromRequest': True,
                  },
              },
              '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"}
                      'Your account not verified!': AccountSuspended,  # {"success":false,"message":"Your account not verified!","unified_message":{"message_id":"verification_required_to_continue","substitutions":null},"notice":"Please be informed that parameter `message` is deprecated and will be removed. Use unified_message instead."}
                  },
                  'broad': {
                      'Not enough': InsufficientFunds,  # {"success":false,"message":"Not enough  ETH"}
                  },
              },
          })
  
      def fetch_currencies(self, params={}):
          """
          fetches all available currencies on an exchange
          :param dict params: extra parameters specific to the stex api endpoint
          :returns dict: an associative dictionary of currencies
          """
          response = 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,
                  'deposit': None,
                  'withdraw': None,
                  '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
  
      def fetch_markets(self, params={}):
          """
          retrieves data on all markets for stex
          :param dict params: extra parameters specific to the exchange api endpoint
          :returns [dict]: an array of objects representing market data
          """
          request = {
              'code': 'ALL',
          }
          response = 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'))
              minBuyPrice = self.safe_string(market, 'min_buy_price')
              minSellPrice = self.safe_string(market, 'min_sell_price')
              minPrice = Precise.string_max(minBuyPrice, minSellPrice)
              buyFee = Precise.string_div(self.safe_string(market, 'buy_fee_percent'), '100')
              sellFee = Precise.string_div(self.safe_string(market, 'sell_fee_percent'), '100')
              fee = Precise.string_max(buyFee, sellFee)
              result.append({
                  'id': id,
                  'numericId': numericId,
                  'symbol': base + '/' + quote,
                  'base': base,
                  'quote': quote,
                  'settle': None,
                  'baseId': baseId,
                  'quoteId': quoteId,
                  'settleId': None,
                  'baseNumericId': baseNumericId,
                  'quoteNumericId': quoteNumericId,
                  'type': 'spot',
                  'spot': True,
                  'margin': False,
                  'swap': False,
                  'future': False,
                  'option': False,
                  'active': self.safe_value(market, 'active'),
                  'contract': False,
                  'linear': None,
                  'inverse': None,
                  'taker': fee,
                  'maker': fee,
                  'contractSize': None,
                  'expiry': None,
                  'expiryDatetime': None,
                  'strike': None,
                  'optionType': None,
                  'precision': {
                      'amount': self.safe_integer(market, 'currency_precision'),
                      'price': self.safe_integer(market, 'market_precision'),
                  },
                  'limits': {
                      'leverage': {
                          'min': None,
                          'max': None,
                      },
                      'amount': {
                          'min': self.safe_number(market, 'min_order_amount'),
                          'max': None,
                      },
                      'price': {
                          'min': minPrice,
                          'max': None,
                      },
                      'cost': {
                          'min': None,
                          'max': None,
                      },
                  },
                  'info': market,
              })
          return result
  
      def fetch_ticker(self, symbol, params={}):
          """
          fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
          :param str symbol: unified symbol of the market to fetch the ticker for
          :param dict params: extra parameters specific to the stex api endpoint
          :returns dict: a `ticker structure <https://docs.ccxt.com/en/latest/manual.html#ticker-structure>`
          """
          self.load_markets()
          market = self.market(symbol)
          request = {
              'currencyPairId': market['id'],
          }
          response = 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)
  
      def fetch_time(self, params={}):
          """
          fetches the current integer timestamp in milliseconds from the exchange server
          :param dict params: extra parameters specific to the stex api endpoint
          :returns int: the current integer timestamp in milliseconds from the exchange server
          """
          response = 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'))
  
      def fetch_order_book(self, symbol, limit=None, params={}):
          """
          fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
          :param str symbol: unified symbol of the market to fetch the order book for
          :param int|None limit: the maximum amount of order book entries to return
          :param dict params: extra parameters specific to the stex api endpoint
          :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/en/latest/manual.html#order-book-structure>` indexed by market symbols
          """
          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 = 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_string(ticker, 'last')
          open = self.safe_string(ticker, 'open')
          return self.safe_ticker({
              'symbol': symbol,
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
              'high': self.safe_string(ticker, 'high'),
              'low': self.safe_string(ticker, 'low'),
              'bid': self.safe_string(ticker, 'bid'),
              'bidVolume': None,
              'ask': self.safe_string(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_string(ticker, 'volumeQuote'),
              'quoteVolume': self.safe_string(ticker, 'volume'),
              'info': ticker,
          }, market)
  
      def fetch_tickers(self, symbols=None, params={}):
          """
          fetches price tickers for multiple markets, statistical calculations with the information calculated over the past 24 hours each market
          :param [str]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
          :param dict params: extra parameters specific to the stex api endpoint
          :returns dict: an array of `ticker structures <https://docs.ccxt.com/en/latest/manual.html#ticker-structure>`
          """
          self.load_markets()
          response = 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'),
          ]
  
      def fetch_ohlcv(self, symbol, timeframe='1d', since=None, limit=None, params={}):
          """
          fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
          :param str symbol: unified symbol of the market to fetch OHLCV data for
          :param str timeframe: the length of time each candle represents
          :param int|None since: timestamp in ms of the earliest candle to fetch
          :param int|None limit: the maximum amount of candles to fetch
          :param dict params: extra parameters specific to the stex api endpoint
          :returns [[int]]: A list of candles ordered as timestamp, open, high, low, close, volume
          """
          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 = 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')
          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 self.safe_trade({
              'info': trade,
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
              'symbol': symbol,
              'id': id,
              'order': None,
              'type': None,
              'takerOrMaker': None,
              'side': side,
              'price': priceString,
              'amount': amountString,
              'cost': None,
              'fee': None,
          }, market)
  
      def fetch_trades(self, symbol, since=None, limit=None, params={}):
          """
          get the list of most recent trades for a particular symbol
          :param str symbol: unified symbol of the market to fetch trades for
          :param int|None since: timestamp in ms of the earliest trade to fetch
          :param int|None limit: the maximum amount of trades to fetch
          :param dict params: extra parameters specific to the stex api endpoint
          :returns [dict]: a list of `trade structures <https://docs.ccxt.com/en/latest/manual.html?#public-trades>`
          """
          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 = 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)
  
      def fetch_trading_fee(self, symbol, params={}):
          """
          fetch the trading fees for a market
          :param str symbol: unified market symbol
          :param dict params: extra parameters specific to the stex api endpoint
          :returns dict: a `fee structure <https://docs.ccxt.com/en/latest/manual.html#fee-structure>`
          """
          self.load_markets()
          market = self.market(symbol)
          request = {
              'currencyPairId': market['id'],
          }
          response = self.tradingGetFeesCurrencyPairId(self.extend(request, params))
          #
          #     {
          #         success: True,
          #         data: {buy_fee: '0.00200000', sell_fee: '0.00200000'},
          #         unified_message: {message_id: 'operation_successful', substitutions: []}
          #      }
          #
          data = self.safe_value(response, 'data')
          return {
              'info': response,
              'symbol': market['symbol'],
              'maker': self.safe_number(data, 'sell_fee'),
              'taker': self.safe_number(data, 'buy_fee'),
              'percentage': True,
              'tierBased': True,
          }
  
      def parse_balance(self, response):
          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 fetch_balance(self, params={}):
          """
          query for balance and get the amount of funds available for trading or funds locked in orders
          :param dict params: extra parameters specific to the stex api endpoint
          :returns dict: a `balance structure <https://docs.ccxt.com/en/latest/manual.html?#balance-structure>`
          """
          self.load_markets()
          # self.load_accounts()
          response = 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"},
          #             },
          #         ]
          #     }
          #
          return self.parse_balance(response)
  
      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
  
      def create_order(self, symbol, type, side, amount, price=None, params={}):
          """
          create a trade order
          :param str symbol: unified symbol of the market to create an order in
          :param str type: 'market' or 'limit'
          :param str side: 'buy' or 'sell'
          :param float amount: how much of currency you want to trade in units of base currency
          :param float price: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
          :param dict params: extra parameters specific to the stex api endpoint
          :returns dict: an `order structure <https://docs.ccxt.com/en/latest/manual.html#order-structure>`
          """
          if type == 'market':
              raise ExchangeError(self.id + ' createOrder() allows limit orders only')
          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 = 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)
  
      def fetch_order(self, id, symbol=None, params={}):
          """
          fetches information on an order made by the user
          :param str|None symbol: unified symbol of the market the order was made in
          :param dict params: extra parameters specific to the stex api endpoint
          :returns dict: An `order structure <https://docs.ccxt.com/en/latest/manual.html#order-structure>`
          """
          self.load_markets()
          request = {
              'orderId': id,
          }
          response = 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)
  
      def fetch_closed_order(self, id, symbol=None, params={}):
          self.load_markets()
          request = {
              'orderId': id,
          }
          response = 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)
  
      def fetch_order_trades(self, id, symbol=None, since=None, limit=None, params={}):
          order = self.fetch_closed_order(id, symbol, params)
          return order['trades']
  
      def fetch_open_orders(self, symbol=None, since=None, limit=None, params={}):
          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 = 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)
  
      def cancel_order(self, id, symbol=None, params={}):
          """
          cancels an open order
          :param str id: order id
          :param str|None symbol: not used by stex cancelOrder()
          :param dict params: extra parameters specific to the stex api endpoint
          :returns dict: An `order structure <https://docs.ccxt.com/en/latest/manual.html#order-structure>`
          """
          self.load_markets()
          request = {
              'orderId': id,
          }
          response = 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))
  
      def cancel_all_orders(self, symbol=None, params={}):
          self.load_markets()
          request = {}
          method = 'tradingDeleteOrders'
          if symbol is not None:
              market = self.market(symbol)
              request['currencyPairId'] = market['id']
              method = 'tradingDeleteOrdersCurrencyPairId'
          response = 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
  
      def fetch_my_trades(self, symbol=None, since=None, limit=None, params={}):
          if symbol is None:
              raise ArgumentsRequired(self.id + ' fetchMyTrades() requires a symbol argument')
          self.load_markets()
          market = self.market(symbol)
          request = {
              '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 = 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)
  
      def create_deposit_address(self, code, params={}):
          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 = 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,
          }
  
      def fetch_deposit_address(self, code, params={}):
          self.load_markets()
          balance = 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 = 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):
          #
          # fetchDeposit & 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"
          #     }
          #
          # fetchWithdrawal and 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_2(transaction, 'fee_currency_id', 'deposit_fee_currency_id')
              feeCurrencyCode = self.safe_currency_code(feeCurrencyId)
              fee = {
                  'cost': feeCost,
                  'currency': feeCurrencyCode,
              }
          network = self.safe_string(withdrawalAddress, 'protocol_name')
          return {
              'info': transaction,
              'id': id,
              'txid': txid,
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
              'network': network,
              'addressFrom': None,
              'address': address,
              'addressTo': address,
              'tagFrom': None,
              'tag': tag,
              'tagTo': tag,
              'type': type,
              'amount': amount,
              'currency': code,
              'status': status,
              'updated': updated,
              'fee': fee,
          }
  
      def fetch_deposit(self, id, code=None, params={}):
          self.load_markets()
          request = {
              'id': id,
          }
          response = self.profileGetDepositsId(self.extend(request, params))
          #
          #     {
          #         success: True,
          #         data: {
          #             id: '21974074',
          #             currency_id: '272',
          #             block_explorer_url: 'https://omniexplorer.info/search/',
          #             currency_code: 'USDT',
          #             deposit_fee_currency_id: '272',
          #             deposit_fee_currency_code: 'USDT',
          #             amount: '11.00000000',
          #             fee: '0.00000000',
          #             deposit_status_id: '3',
          #             status: 'FINISHED',
          #             status_color: '#00BE75',
          #             txid: '15b50da4600a5021dbddaed8f4a71de093bf206ea66eb4ab2f151e3e9e2fed71',
          #             protocol_id: '24',
          #             confirmations: '129 of 20',
          #             created_at: '2022-05-16 16:38:40',
          #             timestamp: '1652719120',
          #             protocol_specific_settings: [{
          #                 protocol_name: 'TRON',
          #                 protocol_id: '24',
          #                 block_explorer_url: 'https://tronscan.org/#/transaction/'
          #             }]
          #         },
          #         unified_message: {
          #             message_id: 'operation_successful',
          #             substitutions: []
          #         }
          #     }
          #
          data = self.safe_value(response, 'data', {})
          return self.parse_transaction(data)
  
      def fetch_deposits(self, code=None, since=None, limit=None, params={}):
          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 = 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)
  
      def fetch_withdrawal(self, id, code=None, params={}):
          self.load_markets()
          request = {
              'id': id,
          }
          response = self.profileGetWithdrawalsId(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",
          #             "reason": "string",
          #             "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/"
          #             }
          #         }
          #     }
          #
          data = self.safe_value(response, 'data', {})
          return self.parse_transaction(data)
  
      def fetch_withdrawals(self, code=None, since=None, limit=None, params={}):
          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 = 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)
  
      def transfer(self, code, amount, fromAccount, toAccount, params={}):
          """
          transfer currency internally between wallets on the same account
          :param str code: unified currency code
          :param float amount: amount to transfer
          :param str fromAccount: account to transfer from
          :param str toAccount: account to transfer to
          :param dict params: extra parameters specific to the stex api endpoint
          :returns dict: a `transfer structure <https://docs.ccxt.com/en/latest/manual.html#transfer-structure>`
          """
          self.load_markets()
          currency = self.currency(code)
          method = None
          request = {}
          if fromAccount == 'referal' and toAccount == 'spot':
              request['currencyId'] = currency['id']
              method = 'profilePostReferralBonusTransferCurrencyId'
          elif toAccount == 'hold':
              request['walletId'] = fromAccount
              amount = self.currency_to_precision(code, amount)
              amount = Precise.string_neg(amount)
              request['amount'] = amount
              method = 'profilePostWalletsWalletIdHoldAmount'
          elif fromAccount == 'hold':
              request['walletId'] = toAccount
              request['amount'] = amount
              method = 'profilePostWalletsWalletIdHoldAmount'
          else:
              raise ExchangeError(self.id + ' transfer() only allows transfers of referal to spot and between a walletId and funding')
          response = getattr(self, method)(self.extend(request, params))
          #
          #  profilePostReferralBonusTransferCurrencyId
          #     {
          #         "success": True,
          #         "data": ""
          #     }
          #
          #  profilePostWalletsWalletIdHoldAmount
          #     {
          #         success: True,
          #         data: {
          #             id: '4055802',
          #             currency_id: '272',
          #             currency_code: 'USDT',
          #             currency_name: 'TetherUSD',
          #             balance: '10.00000000',
          #             frozen_balance: '0.00000000',
          #             bonus_balance: '0.00000000',
          #             hold_balance: '1.00000000',
          #             total_balance: '11.00000000',
          #             disable_deposits: False,
          #             disable_withdrawals: False,
          #             withdrawal_limit: '0.00000000',
          #             delisted: False,
          #             disabled: False,
          #             deposit_address: null,
          #             multi_deposit_addresses: [{
          #                 address: 'TYzhabfHWMLgLnMW46ZyUHkUVJPXaDgdxK',
          #                 address_name: 'Deposit Address',
          #                 additional_address_parameter: null,
          #                 additional_address_parameter_name: null,
          #                 notification: '',
          #                 protocol_id: '24',
          #                 protocol_name: 'TRON',
          #                 supports_new_address_creation: False
          #             }],
          #             contract_or_asset_id: '31',
          #             contract_field_name: null,
          #             withdrawal_additional_field_name: null,
          #             depo_message: '',
          #             wd_message: '',
          #             currency_type_id: '23',
          #             protocol_specific_settings: [{
          #                 {
          #                     protocol_name: 'ERC20',
          #                     protocol_id: '5',
          #                     active: True,
          #                     disable_deposits: False,
          #                     disable_withdrawals: False,
          #                     withdrawal_limit: '0',
          #                     deposit_fee_currency_id: '272',
          #                     deposit_fee_currency_code: 'USDT',
          #                     deposit_fee_percent: '0',
          #                     deposit_fee_const: '0',
          #                     withdrawal_fee_currency_id: '272',
          #                     withdrawal_fee_currency_code: 'USDT',
          #                     withdrawal_fee_const: '10',
          #                     withdrawal_fee_percent: '0',
          #                     block_explorer_url: 'https://etherscan.io/tx/',
          #                     contract_or_asset_id: '0xdac17f958d2ee523a2206206994597c13d831ec7',
          #                     contract_field_name: '',
          #                     withdrawal_additional_field_name: '',
          #                     depo_message: '',
          #                     wd_message: ''
          #                 },
          #                 ...
          #             ],
          #             coin_info: {
          #                 twitter: 'https://twitter.com/Tether_to',
          #                 version: '',
          #                 facebook: 'https://www.facebook.com/tether.to',
          #                 telegram: '',
          #                 icon_large: 'https://app-coin-images.stex.com/large/usdt.png',
          #                 icon_small: 'https://app-coin-images.stex.com/small/usdt.png',
          #                 description: 'Tether(USDT) is a cryptocurrency with a value meant to mirror the value of the U.S. dollar. The idea was to create a stable cryptocurrency that can be used like digital dollars. Coins that serve self purpose of being a stable dollar substitute are called “stable coins.” Tether is the most popular stable coin and even acts as a dollar replacement on many popular exchanges! According to their site, Tether converts cash into digital currency, to anchor or “tether” the value of the coin to the price of national currencies like the US dollar, the Euro, and the Yen. Like other cryptos it uses blockchain. Unlike other cryptos, it is [according to the official Tether site] “100% backed by USD”(USD is held in reserve). The primary use of Tether is that it offers some stability to the otherwise volatile crypto space and offers liquidity to exchanges who can’t deal in dollars and with banks(for example to the sometimes controversial but leading exchange Bitfinex).The digital coins are issued by a company called Tether Limited that is governed by the laws of the British Virgin Islands, according to the legal part of its website. It is incorporated in Hong Kong. It has emerged that Jan Ludovicus van der Velde is the CEO of cryptocurrency exchange Bitfinex, which has been accused of being involved in the price manipulation of bitcoin, as well as tether. Many people trading on exchanges, including Bitfinex, will use tether to buy other cryptocurrencies like bitcoin. Tether Limited argues that using self method to buy virtual currencies allows users to move fiat in and out of an exchange more quickly and cheaply. Also, exchanges typically have rocky relationships with banks, and using Tether is a way to circumvent that.USDT is fairly simple to use. Once on exchanges like Poloniex or Bittrex, it can be used to purchase Bitcoin and other cryptocurrencies. It can be easily transferred from an exchange to any Omni Layer enabled wallet. Tether has no transaction fees, although external wallets and exchanges may charge one. In order to convert USDT to USD and vise versa through the Tether.to Platform, users must pay a small fee. Buying and selling Tether for Bitcoin can be done through a variety of exchanges like the ones mentioned previously or through the Tether.to platform, which also allows the conversion between USD to and from your bank account.',
          #                 official_site: 'https://tether.to/',
          #                 official_block_explorer: 'https://etherscan.io/token/0xdac17f958d2ee523a2206206994597c13d831ec7'
          #             },
          #             rates: {
          #                 BTC: '0.00003372',
          #                 USD: '1'
          #             }
          #         },
          #         unified_message: {
          #             message_id: 'operation_successful',
          #             substitutions: []
          #         }
          #     }
          #
          data = self.safe_value(response, 'data', {})
          transfer = self.parse_transfer(data, currency)
          transferOptions = self.safe_value(self.options, 'transfer', {})
          fillResponseFromRequest = self.safe_value(transferOptions, 'fillResponseFromRequest', True)
          if fillResponseFromRequest:
              transfer['fromAccount'] = fromAccount
              transfer['toAccount'] = toAccount
              if isinstance(amount, str) and Precise.string_lt(amount, '0'):
                  amount = self.parse_number(Precise.string_neg(amount))
              transfer['amount'] = amount
              if transfer['currency'] is None:
                  transfer['currency'] = code
          return transfer
  
      def parse_transfer(self, transfer, currency=None):
          #
          #     {
          #         "id": 45875,
          #         "currency_id": 1,
          #         "currency_code": "USDT",
          #         "currency_name": "TetherUSD",
          #         "balance": "0.198752",
          #         "frozen_balance": "1.5784",
          #         "bonus_balance": "0.000",
          #         "hold_balance": "0.000",
          #         "total_balance": "1.777152",
          #         "disable_deposits": False,
          #         "disable_withdrawals": False,
          #         "withdrawal_limit": "string",
          #         "delisted": False,
          #         "disabled": False,
          #         "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)",
          #         "currency_type_id": 23,
          #         "protocol_specific_settings": [{
          #             "protocol_name": "Tether OMNI",
          #             "protocol_id": 10,
          #             "active": True,
          #             "disable_deposits": False,
          #             "disable_withdrawals": False,
          #             "withdrawal_limit": 0,
          #             "deposit_fee_currency_id": 272,
          #             "deposit_fee_currency_code": "USDT",
          #             "deposit_fee_percent": 0,
          #             "deposit_fee_const": 0,
          #             "withdrawal_fee_currency_id": 1,
          #             "withdrawal_fee_currency_code": "USDT",
          #             "withdrawal_fee_const": 0.002,
          #             "withdrawal_fee_percent": 0,
          #             "block_explorer_url": "https://omniexplorer.info/search/",
          #             "withdrawal_additional_field_name": ""
          #         }],
          #         "coin_info": {
          #             "twitter": "https://twitter.com/btc",
          #             "version": "",
          #             "facebook": "https://www.facebook.com/bitcoins",
          #             "telegram": "",
          #             "icon_large": "https://app-coin-images.stex.com/large/btc.png",
          #             "icon_small": "https://app-coin-images.stex.com/small/btc.png",
          #             "description": "Bitcoin is the first successful internet money based on peer-to-peer technology;....",
          #             "official_site": "http://www.bitcoin.org",
          #             "official_block_explorer": "https://blockchair.com/bitcoin/"
          #         },
          #         "rates": {
          #             "BTC": 0.000001
          #         }
          #     }
          #
          currencyId = self.safe_string(transfer, '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(transfer, 'currency_code'))
          if code is None:
              code = self.safe_value(currency, 'code')
          return {
              'info': transfer,
              'id': self.safe_string(transfer, 'id'),
              'timestamp': None,
              'datetime': None,
              'currency': code,
              'amount': None,
              'fromAccount': None,
              'toAccount': None,
              'status': None,
          }
  
      def withdraw(self, code, amount, address, tag=None, params={}):
          """
          make a withdrawal
          :param str code: unified currency code
          :param float amount: the amount to withdraw
          :param str address: the address to withdraw to
          :param str|None tag:
          :param dict params: extra parameters specific to the stex api endpoint
          :returns dict: a `transaction structure <https://docs.ccxt.com/en/latest/manual.html#transaction-structure>`
          """
          tag, params = self.handle_withdraw_tag_and_params(tag, params)
          self.check_address(address)
          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 = 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)
  
      def fetch_transaction_fees(self, codes=None, params={}):
          """
          fetch transaction fees
          :param [str]|None codes: not used by stex fetchTransactionFees()
          :param dict params: extra parameters specific to the stex api endpoint
          :returns dict: a list of `fee structures <https://docs.ccxt.com/en/latest/manual.html#fee-structure>`
          """
          self.load_markets()
          response = 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
  