text: # -*- coding: utf-8 -*-
  
  # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
  # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
  
  from ccxt.base.exchange import Exchange
  import hashlib
  from ccxt.base.errors import ExchangeError
  from ccxt.base.errors import ArgumentsRequired
  from ccxt.base.errors import BadRequest
  from ccxt.base.errors import InvalidAddress
  from ccxt.base.errors import OrderNotFound
  
  
  class therock(Exchange):
  
      def describe(self):
          return self.deep_extend(super(therock, self).describe(), {
              'id': 'therock',
              'name': 'TheRockTrading',
              'countries': ['MT'],
              'rateLimit': 1000,
              'version': 'v1',
              'has': {
                  'cancelOrder': True,
                  'CORS': False,
                  'createOrder': True,
                  'fetchBalance': True,
                  'fetchClosedOrders': True,
                  'fetchDeposits': True,
                  'fetchLedger': True,
                  'fetchMarkets': True,
                  'fetchMyTrades': True,
                  'fetchOpenOrders': True,
                  'fetchOrder': True,
                  'fetchOrderBook': True,
                  'fetchOrders': True,
                  'fetchTicker': True,
                  'fetchTickers': True,
                  'fetchTrades': True,
                  'fetchTransactions': 'emulated',
                  'fetchWithdrawals': True,
              },
              'urls': {
                  'logo': 'https://user-images.githubusercontent.com/1294454/27766869-75057fa2-5ee9-11e7-9a6f-13e641fa4707.jpg',
                  'api': 'https://api.therocktrading.com',
                  'www': 'https://therocktrading.com',
                  'doc': [
                      'https://api.therocktrading.com/doc/v1/index.html',
                      'https://api.therocktrading.com/doc/',
                  ],
              },
              'api': {
                  'public': {
                      'get': [
                          'funds',
                          'funds/{id}/orderbook',
                          'funds/{id}/ticker',
                          'funds/{id}/trades',
                          'funds/tickers',
                      ],
                  },
                  'private': {
                      'get': [
                          'balances',
                          'balances/{id}',
                          'discounts',
                          'discounts/{id}',
                          'funds',
                          'funds/{id}',
                          'funds/{id}/trades',
                          'funds/{fund_id}/orders',
                          'funds/{fund_id}/orders/{id}',
                          'funds/{fund_id}/position_balances',
                          'funds/{fund_id}/positions',
                          'funds/{fund_id}/positions/{id}',
                          'transactions',
                          'transactions/{id}',
                          'withdraw_limits/{id}',
                          'withdraw_limits',
                      ],
                      'post': [
                          'atms/withdraw',
                          'funds/{fund_id}/orders',
                      ],
                      'delete': [
                          'funds/{fund_id}/orders/{id}',
                          'funds/{fund_id}/orders/remove_all',
                      ],
                  },
              },
              'fees': {
                  'trading': {
                      'maker': 0.2 / 100,
                      'taker': 0.2 / 100,
                  },
                  'funding': {
                      'tierBased': False,
                      'percentage': False,
                      'withdraw': {
                          'BTC': 0.0005,
                          'BCH': 0.0005,
                          'PPC': 0.02,
                          'ETH': 0.001,
                          'ZEC': 0.001,
                          'LTC': 0.002,
                          'EUR': 2.5,  # worst-case scenario: https://therocktrading.com/en/pages/fees
                      },
                      'deposit': {
                          'BTC': 0,
                          'BCH': 0,
                          'PPC': 0,
                          'ETH': 0,
                          'ZEC': 0,
                          'LTC': 0,
                          'EUR': 0,
                      },
                  },
              },
              'exceptions': {
                  'exact': {
                      'Request already running': BadRequest,
                      'cannot specify multiple address types': BadRequest,
                      'Currency is not included in the list': BadRequest,
                      'Record not found': OrderNotFound,
                  },
                  'broad': {
                      'before must be greater than after param': BadRequest,
                      'must be shorter than 60 days': BadRequest,
                      'must be a multiple of(period param) in minutes': BadRequest,
                      'Address allocation limit reached for currency': InvalidAddress,
                      'is not a valid value for param currency': BadRequest,
                      ' is invalid': InvalidAddress,
                  },
              },
          })
  
      def fetch_markets(self, params={}):
          response = self.publicGetFunds(params)
          #
          #     {funds: [{                     id:   "BTCEUR",
          #                              description:   "Trade Bitcoin with Euro",
          #                                     type:   "currency",
          #                            base_currency:   "EUR",
          #                           trade_currency:   "BTC",
          #                                  buy_fee:    0.2,
          #                                 sell_fee:    0.2,
          #                      minimum_price_offer:    0.01,
          #                   minimum_quantity_offer:    0.0005,
          #                   base_currency_decimals:    2,
          #                  trade_currency_decimals:    4,
          #                                leverages: []                           },
          #                {                     id:   "LTCEUR",
          #                              description:   "Trade Litecoin with Euro",
          #                                     type:   "currency",
          #                            base_currency:   "EUR",
          #                           trade_currency:   "LTC",
          #                                  buy_fee:    0.2,
          #                                 sell_fee:    0.2,
          #                      minimum_price_offer:    0.01,
          #                   minimum_quantity_offer:    0.01,
          #                   base_currency_decimals:    2,
          #                  trade_currency_decimals:    2,
          #                                leverages: []                            }]}
          #
          markets = self.safe_value(response, 'funds')
          result = []
          if markets is None:
              raise ExchangeError(self.id + ' fetchMarkets got an unexpected response')
          else:
              for i in range(0, len(markets)):
                  market = markets[i]
                  id = self.safe_string(market, 'id')
                  baseId = self.safe_string(market, 'trade_currency')
                  quoteId = self.safe_string(market, 'base_currency')
                  base = self.safe_currency_code(baseId)
                  quote = self.safe_currency_code(quoteId)
                  symbol = base + '/' + quote
                  buy_fee = self.safe_float(market, 'buy_fee')
                  sell_fee = self.safe_float(market, 'sell_fee')
                  taker = max(buy_fee, sell_fee)
                  taker = taker / 100
                  maker = taker
                  result.append({
                      'id': id,
                      'symbol': symbol,
                      'base': base,
                      'quote': quote,
                      'baseId': baseId,
                      'quoteId': quoteId,
                      'info': market,
                      'active': True,
                      'maker': maker,
                      'taker': taker,
                      'precision': {
                          'amount': self.safe_integer(market, 'trade_currency_decimals'),
                          'price': self.safe_integer(market, 'base_currency_decimals'),
                      },
                      'limits': {
                          'amount': {
                              'min': self.safe_float(market, 'minimum_quantity_offer'),
                              'max': None,
                          },
                          'price': {
                              'min': self.safe_float(market, 'minimum_price_offer'),
                              'max': None,
                          },
                          'cost': {
                              'min': None,
                              'max': None,
                          },
                      },
                  })
          return result
  
      def fetch_balance(self, params={}):
          self.load_markets()
          response = self.privateGetBalances(params)
          balances = self.safe_value(response, 'balances', [])
          result = {'info': response}
          for i in range(0, len(balances)):
              balance = balances[i]
              currencyId = self.safe_string(balance, 'currency')
              code = self.safe_currency_code(currencyId)
              account = self.account()
              account['free'] = self.safe_float(balance, 'trading_balance')
              account['total'] = self.safe_float(balance, 'balance')
              result[code] = account
          return self.parse_balance(result)
  
      def fetch_order_book(self, symbol, limit=None, params={}):
          self.load_markets()
          request = {
              'id': self.market_id(symbol),
          }
          orderbook = self.publicGetFundsIdOrderbook(self.extend(request, params))
          timestamp = self.parse8601(self.safe_string(orderbook, 'date'))
          return self.parse_order_book(orderbook, timestamp, 'bids', 'asks', 'price', 'amount')
  
      def parse_ticker(self, ticker, market=None):
          timestamp = self.parse8601(ticker['date'])
          symbol = None
          if market is not None:
              symbol = market['symbol']
          last = self.safe_float(ticker, 'last')
          return {
              'symbol': symbol,
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
              'high': self.safe_float(ticker, 'high'),
              'low': self.safe_float(ticker, 'low'),
              'bid': self.safe_float(ticker, 'bid'),
              'bidVolume': None,
              'ask': self.safe_float(ticker, 'ask'),
              'askVolume': None,
              'vwap': None,
              'open': self.safe_float(ticker, 'open'),
              'close': last,
              'last': last,
              'previousClose': self.safe_float(ticker, 'close'),  # previous day close, if any
              'change': None,
              'percentage': None,
              'average': None,
              'baseVolume': self.safe_float(ticker, 'volume_traded'),
              'quoteVolume': self.safe_float(ticker, 'volume'),
              'info': ticker,
          }
  
      def fetch_tickers(self, symbols=None, params={}):
          self.load_markets()
          response = self.publicGetFundsTickers(params)
          tickers = self.index_by(response['tickers'], 'fund_id')
          ids = list(tickers.keys())
          result = {}
          for i in range(0, len(ids)):
              id = ids[i]
              market = self.markets_by_id[id]
              symbol = market['symbol']
              ticker = tickers[id]
              result[symbol] = self.parse_ticker(ticker, market)
          return self.filter_by_array(result, 'symbol', symbols)
  
      def fetch_ticker(self, symbol, params={}):
          self.load_markets()
          market = self.market(symbol)
          ticker = self.publicGetFundsIdTicker(self.extend({
              'id': market['id'],
          }, params))
          return self.parse_ticker(ticker, market)
  
      def parse_trade(self, trade, market=None):
          #
          # fetchTrades, fetchOrder trades
          #
          #     {     id:  4493548,
          #       fund_id: "ETHBTC",
          #        amount:  0.203,
          #         price:  0.02783576,
          #          side: "buy",
          #          dark:  False,
          #          date: "2018-11-30T08:19:18.236Z"}
          #
          # fetchMyTrades
          #
          #     {          id:    237338,
          #            fund_id:   "BTCEUR",
          #             amount:    0.348,
          #              price:    348,
          #               side:   "sell",
          #               dark:    False,
          #           order_id:    14920648,
          #               date:   "2015-06-03T00:49:49.000Z",
          #       transactions: [{      id:  2770768,
          #                             date: "2015-06-03T00:49:49.000Z",
          #                             type: "sold_currency_to_fund",
          #                            price:  121.1,
          #                         currency: "EUR"                       },
          #                       {      id:  2770769,
          #                             date: "2015-06-03T00:49:49.000Z",
          #                             type: "released_currency_to_fund",
          #                            price:  0.348,
          #                         currency: "BTC"                        },
          #                       {      id:  2770772,
          #                             date: "2015-06-03T00:49:49.000Z",
          #                             type: "paid_commission",
          #                            price:  0.06,
          #                         currency: "EUR",
          #                         trade_id:  440492                     }   ]}
          #
          marketId = self.safe_string(trade, 'fund_id')
          symbol = self.safe_symbol(marketId, market)
          timestamp = self.parse8601(self.safe_string(trade, 'date'))
          id = self.safe_string(trade, 'id')
          orderId = self.safe_string(trade, 'order_id')
          side = self.safe_string(trade, 'side')
          price = self.safe_float(trade, 'price')
          amount = self.safe_float(trade, 'amount')
          cost = None
          if price is not None:
              if amount is not None:
                  cost = price * amount
          fee = None
          feeCost = None
          transactions = self.safe_value(trade, 'transactions', [])
          transactionsByType = self.group_by(transactions, 'type')
          feeTransactions = self.safe_value(transactionsByType, 'paid_commission', [])
          for i in range(0, len(feeTransactions)):
              if feeCost is None:
                  feeCost = 0
              feeCost = self.sum(feeCost, self.safe_float(feeTransactions[i], 'price'))
          if feeCost is not None:
              fee = {
                  'cost': feeCost,
                  'currency': market['quote'],
              }
          return {
              'info': trade,
              'id': id,
              'order': orderId,
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
              'symbol': symbol,
              'type': None,
              'side': side,
              'takerOrMaker': None,
              'price': price,
              'amount': amount,
              'cost': cost,
              'fee': fee,
          }
  
      def parse_ledger_entry_direction(self, direction):
          directions = {
              'affiliate_earnings': 'in',
              'atm_payment': 'in',
              'bought_currency_from_fund': 'out',
              'bought_shares': 'out',
              'paid_commission': 'out',
              'paypal_payment': 'in',
              'pos_payment': 'in',
              'released_currency_to_fund': 'out',
              'rollover_commission': 'out',
              'sold_currency_to_fund': 'in',
              'sold_shares': 'in',
              'transfer_received': 'in',
              'transfer_sent': 'out',
              'withdraw': 'out',
              # commented types will be shown as-is
              # 'acquired_currency_from_fund': '',
              # 'acquired_insurance': '',
              # 'dividend_distributed_to_holders': '',
              # 'dividend_from_shares': '',
              # 'exposed_position': '',
              # 'insurances_reimbursement': '',
              # 'lent_currency': '',
              # 'linden_lab_assessment': '',
              # 'position_transfer_received': '',
              # 'return_lent_currency': '',
              # 'returned_lent_currency': '',
              # 'the_rock_assessment': '',
          }
          return self.safe_string(directions, direction, direction)
  
      def parse_ledger_entry_type(self, type):
          types = {
              'affiliate_earnings': 'referral',
              'atm_payment': 'transaction',
              'bought_currency_from_fund': 'trade',
              'bought_shares': 'trade',
              'paid_commission': 'fee',
              'paypal_payment': 'transaction',
              'pos_payment': 'transaction',
              'released_currency_to_fund': 'trade',
              'rollover_commission': 'fee',
              'sold_currency_to_fund': 'trade',
              'sold_shares': 'trade',
              'transfer_received': 'transfer',
              'transfer_sent': 'transfer',
              'withdraw': 'transaction',
              # commented types will be shown as-is
              # 'acquired_currency_from_fund': '',
              # 'acquired_insurance': '',
              # 'dividend_distributed_to_holders': '',
              # 'dividend_from_shares': '',
              # 'exposed_position': '',
              # 'insurances_reimbursement': '',
              # 'lent_currency': '',
              # 'linden_lab_assessment': '',
              # 'position_transfer_received': '',
              # 'return_lent_currency': '',
              # 'returned_lent_currency': '',
              # 'the_rock_assessment': '',
          }
          return self.safe_string(types, type, type)
  
      def parse_ledger_entry(self, item, currency=None):
          #
          # withdrawal
          #
          #     {
          #         "id": 21311223,
          #         "date": "2015-06-30T13:55:11.000Z",
          #         "type": "withdraw",
          #         "price": 103.00,
          #         "currency": "EUR",
          #         "fund_id": null,
          #         "order_id": null,
          #         "trade_id": null,
          #         "transfer_detail": {
          #             "method": "wire_transfer",
          #             "id": "F112DD3",
          #             "recipient": "IT123456789012",
          #             "confirmations": 0
          #         }
          #     }
          #
          # deposit
          #
          #     {
          #         "id": 21311222,
          #         "date": "2015-06-30T13:55:11.000Z",
          #         "type": "atm_payment",
          #         "price": 2.01291,
          #         "currency": "BTC",
          #         "fund_id": "null",
          #         "order_id": null,
          #         "trade_id": null,
          #         "transfer_detail": {
          #             "method": "bitcoin",
          #             "id": "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098",
          #             "recipient": "mzb3NgX9Dr6jgGAu31L6jsPGB2zkaFxxyf",
          #             "confirmations": 3
          #         }
          #     }
          #
          # trade fee
          #
          #     {
          #         "id": 21311221,
          #         "date": "2015-06-30T13:55:11.000Z",
          #         "type": "paid_commission",
          #         "price": 0.0001,
          #         "fund_id": "BTCEUR",
          #         "order_id": 12832371,
          #         "trade_id": 12923212,
          #         "currency": "BTC",
          #         "transfer_detail": null
          #     }
          #
          id = self.safe_string(item, 'id')
          referenceId = None
          type = self.safe_string(item, 'type')
          direction = self.parse_ledger_entry_direction(type)
          type = self.parse_ledger_entry_type(type)
          if type == 'trade' or type == 'fee':
              referenceId = self.safe_string(item, 'trade_id')
          currencyId = self.safe_string(item, 'currency')
          code = self.safe_currency_code(currencyId)
          amount = self.safe_float(item, 'price')
          timestamp = self.parse8601(self.safe_string(item, 'date'))
          status = 'ok'
          return {
              'info': item,
              'id': id,
              'direction': direction,
              'account': None,
              'referenceId': referenceId,
              'referenceAccount': None,
              'type': type,
              'currency': code,
              'amount': amount,
              'before': None,
              'after': None,
              'status': status,
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
              'fee': None,
          }
  
      def fetch_ledger(self, code=None, since=None, limit=None, params={}):
          self.load_markets()
          request = {
              # 'page': 1,
              # 'fund_id': 'ETHBTC',  # filter by fund symbol
              # 'currency': 'BTC',  # filter by currency
              # 'after': '2015-02-06T08:47:26Z',  # filter after a certain timestamp
              # 'before': '2015-02-06T08:47:26Z',
              # 'type': 'withdraw',
              # 'order_id': '12832371',  # filter by a specific order ID
              # 'trade_id': '12923212',  # filter by a specific trade ID
              # 'transfer_method': 'bitcoin',  # wire_transfer, ripple, greenaddress, bitcoin, litecoin, namecoin, peercoin, dogecoin
              # 'transfer_recipient': '1MAHLhJoz9W2ydbRf972WSgJYJ3Ui7aotm',  # filter by a specific recipient(e.g. Bitcoin address, IBAN)
              # 'transfer_id': '8261949194985b01985006724dca5d6059989e096fa95608271d00dd902327fa',  # filter by a specific transfer ID(e.g. Bitcoin TX hash)
          }
          currency = None
          if code is not None:
              currency = self.currency(code)
              request['currency'] = currency['id']
          if since is not None:
              request['after'] = self.iso8601(since)
          response = self.privateGetTransactions(self.extend(request, params))
          #
          #     {
          #         "transactions": [
          #             {
          #                 "id": 21311223,
          #                 "date": "2015-06-30T13:55:11.000Z",
          #                 "type": "withdraw",
          #                 "price": 103.00,
          #                 "currency": "EUR",
          #                 "fund_id": null,
          #                 "order_id": null,
          #                 "trade_id": null,
          #                 "transfer_detail": {
          #                     "method": "wire_transfer",
          #                     "id": "F112DD3",
          #                     "recipient": "IT123456789012",
          #                     "confirmations": 0
          #                 }
          #             },
          #             {
          #                 "id": 21311222,
          #                 "date": "2015-06-30T13:55:11.000Z",
          #                 "type": "atm_payment",
          #                 "price": 2.01291,
          #                 "currency": "BTC",
          #                 "fund_id": "null",
          #                 "order_id": null,
          #                 "trade_id": null,
          #                 "transfer_detail": {
          #                     "method": "bitcoin",
          #                     "id": "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098",
          #                     "recipient": "mzb3NgX9Dr6jgGAu31L6jsPGB2zkaFxxyf",
          #                     "confirmations": 3
          #                 }
          #             },
          #             {
          #                 "id": 21311221,
          #                 "date": "2015-06-30T13:55:11.000Z",
          #                 "type": "paid_commission",
          #                 "price": 0.0001,
          #                 "fund_id": "BTCEUR",
          #                 "order_id": 12832371,
          #                 "trade_id": 12923212,
          #                 "currency": "BTC",
          #                 "transfer_detail": null
          #             }
          #         ],
          #         "meta": {
          #             "total_count": 1221,
          #             "first": {"page": 1, "href": "https://api.therocktrading.com/v1/transactions?page=1"},
          #             "previous": null,
          #             "current": {"page": 1, "href": "https://api.therocktrading.com/v1/transactions?page=1"},
          #             "next": {"page": 2, "href": "https://api.therocktrading.com/v1/transactions?page=2"},
          #             "last": {"page": 1221, "href": "https://api.therocktrading.com/v1/transactions?page=1221"}
          #         }
          #     }
          #
          transactions = self.safe_value(response, 'transactions', [])
          return self.parse_ledger(transactions, currency, since, limit)
  
      def parse_transaction_type(self, type):
          types = {
              'withdraw': 'withdrawal',
              'atm_payment': 'deposit',
          }
          return self.safe_string(types, type, type)
  
      def parse_transaction(self, transaction, currency=None):
          #
          # fetchWithdrawals
          #
          #     # fiat
          #
          #     {
          #         "id": 21311223,
          #         "date": "2015-06-30T13:55:11.000Z",
          #         "type": "withdraw",
          #         "price": 103.00,
          #         "currency": "EUR",
          #         "fund_id": null,
          #         "order_id": null,
          #         "trade_id": null,
          #         "transfer_detail": {
          #             "method": "wire_transfer",
          #             "id": "F112DD3",
          #             "recipient": "IT123456789012",
          #             "confirmations": 0
          #         }
          #     }
          #
          #     {
          #         "id": 12564223,
          #         "date": "2017-08-07T08:13:50.023Z",
          #         "note": "GB7IDL401573388",
          #         "type": "withdraw",
          #         "price": 4345.93,
          #         "fund_id": null,
          #         "currency": "EUR",
          #         "order_id": null,
          #         "trade_id": null,
          #         "transfer_detail": {
          #             "id": "EXECUTEDBUTUNCHECKED",
          #             "method": "wire_transfer",
          #             "recipient": "GB7IDL401573388",
          #             "confirmations": 0
          #         }
          #     }
          #
          #     # crypto
          #
          #     {
          #         id: 20914695,
          #         date: '2018-02-24T07:13:23.002Z',
          #         type: 'withdraw',
          #         price: 2.70883607,
          #         currency: 'BCH',
          #         fund_id: null,
          #         order_id: null,
          #         trade_id: null,
          #         note: '1MAHLhJoz9W2ydbRf972WSgJYJ3Ui7aotm',
          #         transfer_detail: {
          #             method: 'bitcoin_cash',
          #             id: '8261949194985b01985006724dca5d6059989e096fa95608271d00dd902327fa',
          #             recipient: '1MAHLhJoz9W2ydbRf972WSgJYJ3Ui7aotm',
          #             confirmations: 0
          #         }
          #     }
          #
          #
          # fetchDeposits
          #
          #     # fiat
          #
          #     {
          #         id: 16176632,
          #         date: '2017-11-20T21:00:13.355Z',
          #         type: 'atm_payment',
          #         price: 5000,
          #         currency: 'EUR',
          #         fund_id: null,
          #         order_id: null,
          #         trade_id: null,
          #         note: 'Mistral deposit',
          #         transfer_detail: {
          #             method: 'wire_transfer',
          #             id: '972JQ49337DX769T',
          #             recipient: null,
          #             confirmations: 0
          #         }
          #     }
          #
          #     # crypto
          #
          #     {
          #         "id": 21311222,
          #         "date": "2015-06-30T13:55:11.000Z",
          #         "type": "atm_payment",
          #         "price": 2.01291,
          #         "currency": "BTC",
          #         "fund_id": "null",
          #         "order_id": null,
          #         "trade_id": null,
          #         "transfer_detail": {
          #             "method": "bitcoin",
          #             "id": "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098",
          #             "recipient": "mzb3NgX9Dr6jgGAu31L6jsPGB2zkaFxxyf",
          #             "confirmations": 3
          #         }
          #     }
          #
          id = self.safe_string(transaction, 'id')
          type = self.parse_transaction_type(self.safe_string(transaction, 'type'))
          detail = self.safe_value(transaction, 'transfer_detail', {})
          method = self.safe_string(detail, 'method')
          txid = None
          address = None
          if method is not None:
              if method != 'wire_transfer':
                  txid = self.safe_string(detail, 'id')
                  address = self.safe_string(detail, 'recipient')
          currencyId = self.safe_string(transaction, 'currency')
          code = self.safe_currency_code(currencyId)
          amount = self.safe_float(transaction, 'price')
          timestamp = self.parse8601(self.safe_string(transaction, 'date'))
          status = 'ok'
          # todo parse tags
          return {
              'info': transaction,
              'id': id,
              'currency': code,
              'amount': amount,
              'addressFrom': None,
              'addressTo': address,
              'address': address,
              'tagFrom': None,
              'tagTo': None,
              'tag': None,
              'status': status,
              'type': type,
              'updated': None,
              'txid': txid,
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
              'fee': None,
          }
  
      def fetch_withdrawals(self, code=None, since=None, limit=None, params={}):
          request = {
              'type': 'withdraw',
          }
          return self.fetch_transactions(code, since, limit, self.extend(request, params))
  
      def fetch_deposits(self, code=None, since=None, limit=None, params={}):
          request = {
              'type': 'atm_payment',
          }
          return self.fetch_transactions(code, since, limit, self.extend(request, params))
  
      def fetch_transactions(self, code=None, since=None, limit=None, params={}):
          self.load_markets()
          request = {
              # 'page': 1,
              # 'fund_id': 'ETHBTC',  # filter by fund symbol
              # 'currency': 'BTC',  # filter by currency
              # 'after': '2015-02-06T08:47:26Z',  # filter after a certain timestamp
              # 'before': '2015-02-06T08:47:26Z',
              # 'type': 'withdraw',
              # 'order_id': '12832371',  # filter by a specific order ID
              # 'trade_id': '12923212',  # filter by a specific trade ID
              # 'transfer_method': 'bitcoin',  # wire_transfer, ripple, greenaddress, bitcoin, litecoin, namecoin, peercoin, dogecoin
              # 'transfer_recipient': '1MAHLhJoz9W2ydbRf972WSgJYJ3Ui7aotm',  # filter by a specific recipient(e.g. Bitcoin address, IBAN)
              # 'transfer_id': '8261949194985b01985006724dca5d6059989e096fa95608271d00dd902327fa',  # filter by a specific transfer ID(e.g. Bitcoin TX hash)
          }
          currency = None
          if code is not None:
              currency = self.currency(code)
              request['currency'] = currency['id']
          if since is not None:
              request['after'] = self.iso8601(since)
          params = self.extend(request, params)
          response = self.privateGetTransactions(params)
          #
          #     {
          #         "transactions": [
          #             {
          #                 "id": 21311223,
          #                 "date": "2015-06-30T13:55:11.000Z",
          #                 "type": "withdraw",
          #                 "price": 103.00,
          #                 "currency": "EUR",
          #                 "fund_id": null,
          #                 "order_id": null,
          #                 "trade_id": null,
          #                 "transfer_detail": {
          #                     "method": "wire_transfer",
          #                     "id": "F112DD3",
          #                     "recipient": "IT123456789012",
          #                     "confirmations": 0
          #                 }
          #             },
          #             {
          #                 "id": 21311222,
          #                 "date": "2015-06-30T13:55:11.000Z",
          #                 "type": "atm_payment",
          #                 "price": 2.01291,
          #                 "currency": "BTC",
          #                 "fund_id": "null",
          #                 "order_id": null,
          #                 "trade_id": null,
          #                 "transfer_detail": {
          #                     "method": "bitcoin",
          #                     "id": "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098",
          #                     "recipient": "mzb3NgX9Dr6jgGAu31L6jsPGB2zkaFxxyf",
          #                     "confirmations": 3
          #                 }
          #             },
          #             {
          #                 "id": 21311221,
          #                 "date": "2015-06-30T13:55:11.000Z",
          #                 "type": "paid_commission",
          #                 "price": 0.0001,
          #                 "fund_id": "BTCEUR",
          #                 "order_id": 12832371,
          #                 "trade_id": 12923212,
          #                 "currency": "BTC",
          #                 "transfer_detail": null
          #             }
          #         ],
          #         "meta": {
          #             "total_count": 1221,
          #             "first": {"page": 1, "href": "https://api.therocktrading.com/v1/transactions?page=1"},
          #             "previous": null,
          #             "current": {"page": 1, "href": "https://api.therocktrading.com/v1/transactions?page=1"},
          #             "next": {"page": 2, "href": "https://api.therocktrading.com/v1/transactions?page=2"},
          #             "last": {"page": 1221, "href": "https://api.therocktrading.com/v1/transactions?page=1221"}
          #         }
          #     }
          #
          transactions = self.safe_value(response, 'transactions', [])
          transactionTypes = ['withdraw', 'atm_payment']
          depositsAndWithdrawals = self.filter_by_array(transactions, 'type', transactionTypes, False)
          return self.parse_transactions(depositsAndWithdrawals, currency, since, limit)
  
      def parse_order_status(self, status):
          statuses = {
              'active': 'open',
              'executed': 'closed',
              'deleted': 'canceled',
              # don't know what self status means
              # 'conditional': '?',
          }
          return self.safe_string(statuses, status, status)
  
      def parse_order(self, order, market=None):
          #
          #     {
          #         "id": 4325578,
          #         "fund_id":"BTCEUR",
          #         "side":"buy",
          #         "type":"limit",
          #         "status":"executed",
          #         "price":0.0102,
          #         "amount": 50.0,
          #         "amount_unfilled": 0.0,
          #         "conditional_type": null,
          #         "conditional_price": null,
          #         "date":"2015-06-03T00:49:48.000Z",
          #         "close_on": nil,
          #         "leverage": 1.0,
          #         "position_id": null,
          #         "trades": [
          #             {
          #                 "id":237338,
          #                 "fund_id":"BTCEUR",
          #                 "amount":50,
          #                 "price":0.0102,
          #                 "side":"buy",
          #                 "dark":false,
          #                 "date":"2015-06-03T00:49:49.000Z"
          #             }
          #         ]
          #     }
          #
          id = self.safe_string(order, 'id')
          marketId = self.safe_string(order, 'fund_id')
          symbol = self.safe_symbol(marketId, market)
          status = self.parse_order_status(self.safe_string(order, 'status'))
          timestamp = self.parse8601(self.safe_string(order, 'date'))
          type = self.safe_string(order, 'type')
          side = self.safe_string(order, 'side')
          amount = self.safe_float(order, 'amount')
          remaining = self.safe_float(order, 'amount_unfilled')
          filled = None
          if amount is not None:
              if remaining is not None:
                  filled = amount - remaining
          price = self.safe_float(order, 'price')
          trades = self.safe_value(order, 'trades')
          cost = None
          average = None
          lastTradeTimestamp = None
          if trades is not None:
              numTrades = len(trades)
              if numTrades > 0:
                  trades = self.parse_trades(trades, market, None, None, {
                      'orderId': id,
                  })
                  # todo: determine the cost and the average price from trades
                  cost = 0
                  filled = 0
                  for i in range(0, numTrades):
                      trade = trades[i]
                      cost = self.sum(cost, trade['cost'])
                      filled = self.sum(filled, trade['amount'])
                  if filled > 0:
                      average = cost / filled
                  lastTradeTimestamp = trades[numTrades - 1]['timestamp']
              else:
                  cost = 0
          return {
              'id': id,
              'clientOrderId': None,
              'info': order,
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
              'lastTradeTimestamp': lastTradeTimestamp,
              'status': status,
              'symbol': symbol,
              'type': type,
              'side': side,
              'price': price,
              'cost': cost,
              'amount': amount,
              'filled': filled,
              'average': average,
              'remaining': remaining,
              'fee': None,
              'trades': trades,
          }
  
      def fetch_open_orders(self, symbol=None, since=None, limit=None, params={}):
          request = {
              'status': 'active',
          }
          return self.fetch_orders(symbol, since, limit, self.extend(request, params))
  
      def fetch_closed_orders(self, symbol=None, since=None, limit=None, params={}):
          request = {
              'status': 'executed',
          }
          return self.fetch_orders(symbol, since, limit, self.extend(request, params))
  
      def fetch_orders(self, symbol=None, since=None, limit=None, params={}):
          if symbol is None:
              raise ArgumentsRequired(self.id + ' fetchOrders requires a symbol argument')
          self.load_markets()
          market = self.market(symbol)
          request = {
              'fund_id': market['id'],
              # 'after': '2015-02-06T08:47:26Z',
              # 'before': '2015-02-06T08:47:26Z'
              # 'status': 'active',  # 'executed', 'conditional'
              # 'side': 'buy',  # 'sell'
              # 'position_id': 123,  # filter orders by margin position id
          }
          if since is not None:
              request['after'] = self.iso8601(since)
          response = self.privateGetFundsFundIdOrders(self.extend(request, params))
          #
          #     {
          #         orders: [
          #             {
          #                 id: 299333648,
          #                 fund_id: 'BTCEUR',
          #                 side: 'sell',
          #                 type: 'limit',
          #                 status: 'executed',
          #                 price: 5821,
          #                 amount: 0.1,
          #                 amount_unfilled: 0,
          #                 conditional_type: null,
          #                 conditional_price: null,
          #                 date: '2018-06-18T17:38:16.129Z',
          #                 close_on: null,
          #                 dark: False,
          #                 leverage: 1,
          #                 position_id: 0
          #             }
          #         ]
          #     }
          #
          orders = self.safe_value(response, 'orders', [])
          return self.parse_orders(orders, market, since, limit)
  
      def fetch_order(self, id, symbol=None, params={}):
          if symbol is None:
              raise ArgumentsRequired(self.id + ' fetchOrder requires a symbol argument')
          self.load_markets()
          market = self.market(symbol)
          request = {
              'id': id,
              'fund_id': market['id'],
          }
          response = self.privatePostFundsFundIdOrdersId(self.extend(request, params))
          return self.parse_order(response)
  
      def create_order(self, symbol, type, side, amount, price=None, params={}):
          self.load_markets()
          if type == 'market':
              price = 0
          request = {
              'fund_id': self.market_id(symbol),
              'side': side,
              'amount': amount,
              'price': price,
          }
          response = self.privatePostFundsFundIdOrders(self.extend(request, params))
          return self.parse_order(response)
  
      def cancel_order(self, id, symbol=None, params={}):
          self.load_markets()
          request = {
              'id': id,
              'fund_id': self.market_id(symbol),
          }
          response = self.privateDeleteFundsFundIdOrdersId(self.extend(request, params))
          return self.parse_order(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 = {
              'id': market['id'],
          }
          if limit is not None:
              request['per_page'] = limit  # default 25 max 200
          if since is not None:
              request['after'] = self.iso8601(since)
          response = self.privateGetFundsIdTrades(self.extend(request, params))
          #
          #     {trades: [{          id:    237338,
          #                        fund_id:   "BTCEUR",
          #                         amount:    0.348,
          #                          price:    348,
          #                           side:   "sell",
          #                           dark:    False,
          #                       order_id:    14920648,
          #                           date:   "2015-06-03T00:49:49.000Z",
          #                   transactions: [{      id:  2770768,
          #                                         date: "2015-06-03T00:49:49.000Z",
          #                                         type: "sold_currency_to_fund",
          #                                        price:  121.1,
          #                                     currency: "EUR"                       },
          #                                   {      id:  2770769,
          #                                         date: "2015-06-03T00:49:49.000Z",
          #                                         type: "released_currency_to_fund",
          #                                        price:  0.348,
          #                                     currency: "BTC"                        },
          #                                   {      id:  2770772,
          #                                         date: "2015-06-03T00:49:49.000Z",
          #                                         type: "paid_commission",
          #                                        price:  0.06,
          #                                     currency: "EUR",
          #                                     trade_id:  440492                     }   ]}],
          #         meta: {total_count:    31,
          #                       first: {href: "https://api.therocktrading.com/v1/funds/BTCXRP/trades?page=1"},
          #                    previous:    null,
          #                     current: {href: "https://api.therocktrading.com/v1/funds/BTCXRP/trades?page=1"},
          #                        next: {href: "https://api.therocktrading.com/v1/funds/BTCXRP/trades?page=2"},
          #                        last: {href: "https://api.therocktrading.com/v1/funds/BTCXRP/trades?page=2"}  }}
          #
          return self.parse_trades(response['trades'], market, since, limit)
  
      def fetch_trades(self, symbol, since=None, limit=None, params={}):
          self.load_markets()
          market = self.market(symbol)
          request = {
              'id': market['id'],
          }
          if limit is not None:
              request['per_page'] = limit  # default 25 max 200
          if since is not None:
              request['after'] = self.iso8601(since)
          response = self.publicGetFundsIdTrades(self.extend(request, params))
          #
          #     {trades: [{     id:  4493548,
          #                   fund_id: "ETHBTC",
          #                    amount:  0.203,
          #                     price:  0.02783576,
          #                      side: "buy",
          #                      dark:  False,
          #                      date: "2018-11-30T08:19:18.236Z"},
          #                 {     id:  4492926,
          #                   fund_id: "ETHBTC",
          #                    amount:  0.04,
          #                     price:  0.02767034,
          #                      side: "buy",
          #                      dark:  False,
          #                      date: "2018-11-30T07:03:03.897Z"}  ],
          #         meta: {total_count:    null,
          #                       first: {page:  1,
          #                                href: "https://api.therocktrading.com/v1/funds/ETHBTC/trades?page=1"},
          #                    previous:    null,
          #                     current: {page:  1,
          #                                href: "https://api.therocktrading.com/v1/funds/ETHBTC/trades?page=1"},
          #                        next: {page:  2,
          #                                href: "https://api.therocktrading.com/v1/funds/ETHBTC/trades?page=2"},
          #                        last:    null                                                                   }}
          #
          return self.parse_trades(response['trades'], market, since, limit)
  
      def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
          url = self.urls['api'] + '/' + self.version + '/' + self.implode_params(path, params)
          query = self.omit(params, self.extract_params(path))
          headers = {} if (headers is None) else headers
          if api == 'private':
              self.check_required_credentials()
              if query:
                  if method == 'POST':
                      body = self.json(query)
                      headers['Content-Type'] = 'application/json'
                  else:
                      queryString = self.rawencode(query)
                      if len(queryString):
                          url += '?' + queryString
              nonce = str(self.nonce())
              auth = nonce + url
              headers['X-TRT-KEY'] = self.apiKey
              headers['X-TRT-NONCE'] = nonce
              headers['X-TRT-SIGN'] = self.hmac(self.encode(auth), self.encode(self.secret), hashlib.sha512)
          elif api == 'public':
              if query:
                  url += '?' + self.rawencode(query)
          return {'url': url, 'method': method, 'body': body, 'headers': headers}
  
      def handle_errors(self, httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody):
          if response is None:
              return  # fallback to default error handler
          #
          #     {
          #         "errors":
          #         [
          #             {"message": ":currency is not a valid value for param currency","code": "11","meta": {"key":"currency","value":":currency"}},
          #             {"message": "Address allocation limit reached for currency :currency.","code": "13"},
          #             {"message": "Request already running", "code": "50"},
          #             {"message": "cannot specify multiple address types", "code": "12"},
          #             {"message": ":address_type is invalid", "code": "12"}
          #         ]
          #     }
          #
          errors = self.safe_value(response, 'errors', [])
          numErrors = len(errors)
          if numErrors > 0:
              feedback = self.id + ' ' + body
              # here we raise the first error we can identify
              for i in range(0, numErrors):
                  error = errors[i]
                  message = self.safe_string(error, 'message')
                  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
  