text: "use strict";
  
  //  ---------------------------------------------------------------------------
  
  const Exchange = require ('./base/Exchange');
  const { ExchangeError } = require ('./base/errors');
  
  //  ---------------------------------------------------------------------------
  
  module.exports = class nova extends Exchange {
  
      describe () {
          return this.deepExtend (super.describe (), {
              'id': 'nova',
              'name': 'Novaexchange',
              'countries': 'TZ', // Tanzania
              'rateLimit': 2000,
              'version': 'v2',
              'has': {
                  'CORS': false,
              },
              'urls': {
                  'logo': 'https://user-images.githubusercontent.com/1294454/30518571-78ca0bca-9b8a-11e7-8840-64b83a4a94b2.jpg',
                  'api': 'https://novaexchange.com/remote',
                  'www': 'https://novaexchange.com',
                  'doc': 'https://novaexchange.com/remote/faq',
              },
              'api': {
                  'public': {
                      'get': [
                          'markets/',
                          'markets/{basecurrency}/',
                          'market/info/{pair}/',
                          'market/orderhistory/{pair}/',
                          'market/openorders/{pair}/buy/',
                          'market/openorders/{pair}/sell/',
                          'market/openorders/{pair}/both/',
                          'market/openorders/{pair}/{ordertype}/',
                      ],
                  },
                  'private': {
                      'post': [
                          'getbalances/',
                          'getbalance/{currency}/',
                          'getdeposits/',
                          'getwithdrawals/',
                          'getnewdepositaddress/{currency}/',
                          'getdepositaddress/{currency}/',
                          'myopenorders/',
                          'myopenorders_market/{pair}/',
                          'cancelorder/{orderid}/',
                          'withdraw/{currency}/',
                          'trade/{pair}/',
                          'tradehistory/',
                          'getdeposithistory/',
                          'getwithdrawalhistory/',
                          'walletstatus/',
                          'walletstatus/{currency}/',
                      ],
                  },
              },
          });
      }
  
      async fetchMarkets () {
          let response = await this.publicGetMarkets ();
          let markets = response['markets'];
          let result = [];
          for (let i = 0; i < markets.length; i++) {
              let market = markets[i];
              if (!market['disabled']) {
                  let id = market['marketname'];
                  let [ quote, base ] = id.split ('_');
                  let symbol = base + '/' + quote;
                  result.push ({
                      'id': id,
                      'symbol': symbol,
                      'base': base,
                      'quote': quote,
                      'info': market,
                  });
              }
          }
          return result;
      }
  
      async fetchOrderBook (symbol, params = {}) {
          await this.loadMarkets ();
          let orderbook = await this.publicGetMarketOpenordersPairBoth (this.extend ({
              'pair': this.marketId (symbol),
          }, params));
          return this.parseOrderBook (orderbook, undefined, 'buyorders', 'sellorders', 'price', 'amount');
      }
  
      async fetchTicker (symbol, params = {}) {
          await this.loadMarkets ();
          let response = await this.publicGetMarketInfoPair (this.extend ({
              'pair': this.marketId (symbol),
          }, params));
          let ticker = response['markets'][0];
          let timestamp = this.milliseconds ();
          return {
              'symbol': symbol,
              'timestamp': timestamp,
              'datetime': this.iso8601 (timestamp),
              'high': parseFloat (ticker['high24h']),
              'low': parseFloat (ticker['low24h']),
              'bid': this.safeFloat (ticker, 'bid'),
              'ask': this.safeFloat (ticker, 'ask'),
              'vwap': undefined,
              'open': undefined,
              'close': undefined,
              'first': undefined,
              'last': parseFloat (ticker['last_price']),
              'change': parseFloat (ticker['change24h']),
              'percentage': undefined,
              'average': undefined,
              'baseVolume': undefined,
              'quoteVolume': parseFloat (ticker['volume24h']),
              'info': ticker,
          };
      }
  
      parseTrade (trade, market) {
          let timestamp = trade['unix_t_datestamp'] * 1000;
          return {
              'info': trade,
              'timestamp': timestamp,
              'datetime': this.iso8601 (timestamp),
              'symbol': market['symbol'],
              'id': undefined,
              'order': undefined,
              'type': undefined,
              'side': trade['tradetype'].toLowerCase (),
              'price': parseFloat (trade['price']),
              'amount': parseFloat (trade['amount']),
          };
      }
  
      async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
          await this.loadMarkets ();
          let market = this.market (symbol);
          let response = await this.publicGetMarketOrderhistoryPair (this.extend ({
              'pair': market['id'],
          }, params));
          return this.parseTrades (response['items'], market, since, limit);
      }
  
      async fetchBalance (params = {}) {
          await this.loadMarkets ();
          let response = await this.privatePostGetbalances ();
          let balances = response['balances'];
          let result = { 'info': response };
          for (let b = 0; b < balances.length; b++) {
              let balance = balances[b];
              let currency = balance['currency'];
              let lockbox = parseFloat (balance['amount_lockbox']);
              let trades = parseFloat (balance['amount_trades']);
              let account = {
                  'free': parseFloat (balance['amount']),
                  'used': this.sum (lockbox, trades),
                  'total': parseFloat (balance['amount_total']),
              };
              result[currency] = account;
          }
          return this.parseBalance (result);
      }
  
      async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
          if (type == 'market')
              throw new ExchangeError (this.id + ' allows limit orders only');
          await this.loadMarkets ();
          amount = amount.toString ();
          price = price.toString ();
          let market = this.market (symbol);
          let order = {
              'tradetype': side.toUpperCase (),
              'tradeamount': amount,
              'tradeprice': price,
              'tradebase': 1,
              'pair': market['id'],
          };
          let response = await this.privatePostTradePair (this.extend (order, params));
          return {
              'info': response,
              'id': undefined,
          };
      }
  
      async cancelOrder (id, symbol = undefined, params = {}) {
          return await this.privatePostCancelorder (this.extend ({
              'orderid': id,
          }, params));
      }
  
      sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
          let url = this.urls['api'] + '/' + this.version + '/';
          if (api == 'private')
              url += api + '/';
          url += this.implodeParams (path, params);
          let query = this.omit (params, this.extractParams (path));
          if (api == 'public') {
              if (Object.keys (query).length)
                  url += '?' + this.urlencode (query);
          } else {
              this.checkRequiredCredentials ();
              let nonce = this.nonce ().toString ();
              url += '?' + this.urlencode ({ 'nonce': nonce });
              let signature = this.hmac (this.encode (url), this.encode (this.secret), 'sha512', 'base64');
              body = this.urlencode (this.extend ({
                  'apikey': this.apiKey,
                  'signature': signature,
              }, query));
              headers = {
                  'Content-Type': 'application/x-www-form-urlencoded',
              };
          }
          return { 'url': url, 'method': method, 'body': body, 'headers': headers };
      }
  
      async request (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
          let response = await this.fetch2 (path, api, method, params, headers, body);
          if ('status' in response)
              if (response['status'] != 'success')
                  throw new ExchangeError (this.id + ' ' + this.json (response));
          return response;
      }
  }
  