text: "use strict";
  
  //  ---------------------------------------------------------------------------
  
  const Exchange = require ('./base/Exchange');
  const { ExchangeError } = require ('./base/errors');
  
  //  ---------------------------------------------------------------------------
  
  module.exports = class btcbox extends Exchange {
  
      describe () {
          return this.deepExtend (super.describe (), {
              'id': 'btcbox',
              'name': 'BtcBox',
              'countries': 'JP',
              'rateLimit': 1000,
              'version': 'v1',
              'hasCORS': false,
              'hasFetchOHLCV': false,
              'urls': {
                  'logo': 'https://user-images.githubusercontent.com/1294454/31275803-4df755a8-aaa1-11e7-9abb-11ec2fad9f2d.jpg',
                  'api': 'https://www.btcbox.co.jp/api',
                  'www': 'https://www.btcbox.co.jp/',
                  'doc': 'https://www.btcbox.co.jp/help/asm',
              },
              'api': {
                  'public': {
                      'get': [
                          'depth',
                          'orders',
                          'ticker',
                          'allticker',
                      ],
                  },
                  'private': {
                      'post': [
                          'balance',
                          'trade_add',
                          'trade_cancel',
                          'trade_list',
                          'trade_view',
                          'wallet',
                      ],
                  },
              },
              'markets': {
                  'BTC/JPY': { 'id': 'BTC/JPY', 'symbol': 'BTC/JPY', 'base': 'BTC', 'quote': 'JPY' },
              },
          });
      }
  
      async fetchBalance (params = {}) {
          await this.loadMarkets ();
          let balances = await this.privatePostBalance ();
          let result = { 'info': balances };
          let currencies = Object.keys (this.currencies);
          for (let i = 0; i < currencies.length; i++) {
              let currency = currencies[i];
              let lowercase = currency.toLowerCase ();
              if (lowercase == 'dash')
                  lowercase = 'drk';
              let account = this.account ();
              let free = lowercase + '_balance';
              let used = lowercase + '_lock';
              if (free in balances)
                  account['free'] = parseFloat (balances[free]);
              if (used in balances)
                  account['used'] = parseFloat (balances[used]);
              account['total'] = this.sum (account['free'], account['used']);
              result[currency] = account;
          }
          return this.parseBalance (result);
      }
  
      async fetchOrderBook (symbol, params = {}) {
          await this.loadMarkets ();
          let market = this.market (symbol);
          let request = {};
          let numSymbols = this.symbols.length;
          if (numSymbols > 1)
              request['coin'] = market['id'];
          let orderbook = await this.publicGetDepth (this.extend (request, params));
          let result = this.parseOrderBook (orderbook);
          result['asks'] = this.sortBy (result['asks'], 0);
          return result;
      }
  
      parseTicker (ticker, market = undefined) {
          let timestamp = this.milliseconds ();
          let symbol = undefined;
          if (market)
              symbol = market['symbol'];
          return {
              'symbol': symbol,
              'timestamp': timestamp,
              'datetime': this.iso8601 (timestamp),
              'high': this.safeFloat (ticker, 'high'),
              'low': this.safeFloat (ticker, 'low'),
              'bid': this.safeFloat (ticker, 'buy'),
              'ask': this.safeFloat (ticker, 'sell'),
              'vwap': undefined,
              'open': undefined,
              'close': undefined,
              'first': undefined,
              'last': this.safeFloat (ticker, 'last'),
              'change': undefined,
              'percentage': undefined,
              'average': undefined,
              'baseVolume': this.safeFloat (ticker, 'vol'),
              'quoteVolume': this.safeFloat (ticker, 'volume'),
              'info': ticker,
          };
      }
  
      async fetchTickers (symbols = undefined, params = {}) {
          await this.loadMarkets ();
          let tickers = await this.publicGetAllticker (params);
          let ids = Object.keys (tickers);
          let result = {};
          for (let i = 0; i < ids.length; i++) {
              let id = ids[i];
              let market = this.markets_by_id[id];
              let symbol = market['symbol'];
              let ticker = tickers[id];
              result[symbol] = this.parseTicker (ticker, market);
          }
          return result;
      }
  
      async fetchTicker (symbol, params = {}) {
          await this.loadMarkets ();
          let market = this.market (symbol);
          let request = {};
          let numSymbols = this.symbols.length;
          if (numSymbols > 1)
              request['coin'] = market['id'];
          let ticker = await this.publicGetTicker (this.extend (request, params));
          return this.parseTicker (ticker, market);
      }
  
      parseTrade (trade, market) {
          let timestamp = parseInt (trade['date']) * 1000;
          return {
              'info': trade,
              'id': trade['tid'],
              'order': undefined,
              'timestamp': timestamp,
              'datetime': this.iso8601 (timestamp),
              'symbol': market['symbol'],
              'type': undefined,
              'side': trade['type'],
              'price': trade['price'],
              'amount': trade['amount'],
          };
      }
  
      async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
          await this.loadMarkets ();
          let market = this.market (symbol);
          let request = {};
          let numSymbols = this.symbols.length;
          if (numSymbols > 1)
              request['coin'] = market['id'];
          let response = await this.publicGetOrders (this.extend (request, params));
          return this.parseTrades (response, market, since, limit);
      }
  
      async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
          await this.loadMarkets ();
          let market = this.market (symbol);
          let request = {
              'amount': amount,
              'price': price,
              'type': side,
          };
          let numSymbols = this.symbols.length;
          if (numSymbols > 1)
              request['coin'] = market['id'];
          let response = await this.privatePostTradeAdd (this.extend (request, params));
          return {
              'info': response,
              'id': response['id'],
          };
      }
  
      async cancelOrder (id, symbol = undefined, params = {}) {
          await this.loadMarkets ();
          return await this.privatePostTradeCancel (this.extend ({
              'id': id,
          }, params));
      }
  
      sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
          let url = this.urls['api'] + '/' + this.version + '/' + path;
          if (api == 'public') {
              if (Object.keys (params).length)
                  url += '?' + this.urlencode (params);
          } else {
              this.checkRequiredCredentials ();
              let nonce = this.nonce ().toString ();
              let query = this.extend ({
                  'key': this.apiKey,
                  'nonce': nonce,
              }, params);
              let request = this.urlencode (query);
              let secret = this.hash (this.encode (this.secret));
              query['signature'] = this.hmac (this.encode (request), this.encode (secret));
              body = this.urlencode (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 ('result' in response)
              if (!response['result'])
                  throw new ExchangeError (this.id + ' ' + this.json (response));
          return response;
      }
  }
  