text: # -*- coding: utf-8 -*-
  
  from ccxt.base.exchange import Exchange
  
  # -----------------------------------------------------------------------------
  
  try:
      basestring  # Python 3
  except NameError:
      basestring = str  # Python 2
  
  
  from ccxt.base.errors import ExchangeError
  
  
  class quadrigacx (Exchange):
  
      def describe(self):
          return self.deep_extend(super(quadrigacx, self).describe(), {
              'id': 'quadrigacx',
              'name': 'QuadrigaCX',
              'countries': 'CA',
              'rateLimit': 1000,
              'version': 'v2',
              'hasCORS': True,
              # obsolete metainfo interface
              'hasWithdraw': True,
              # new metainfo interface
              'has': {
                  'withdraw': True,
              },
              'urls': {
                  'logo': 'https://user-images.githubusercontent.com/1294454/27766825-98a6d0de-5ee7-11e7-9fa4-38e11a2c6f52.jpg',
                  'api': 'https://api.quadrigacx.com',
                  'www': 'https://www.quadrigacx.com',
                  'doc': 'https://www.quadrigacx.com/api_info',
              },
              'requiredCredentials': {
                  'apiKey': True,
                  'secret': True,
                  'uid': True,
              },
              'api': {
                  'public': {
                      'get': [
                          'order_book',
                          'ticker',
                          'transactions',
                      ],
                  },
                  'private': {
                      'post': [
                          'balance',
                          'bitcoin_deposit_address',
                          'bitcoin_withdrawal',
                          'buy',
                          'cancel_order',
                          'ether_deposit_address',
                          'ether_withdrawal',
                          'lookup_order',
                          'open_orders',
                          'sell',
                          'user_transactions',
                      ],
                  },
              },
              'markets': {
                  'BTC/CAD': {'id': 'btc_cad', 'symbol': 'BTC/CAD', 'base': 'BTC', 'quote': 'CAD', 'maker': 0.005, 'taker': 0.005},
                  'BTC/USD': {'id': 'btc_usd', 'symbol': 'BTC/USD', 'base': 'BTC', 'quote': 'USD', 'maker': 0.005, 'taker': 0.005},
                  'ETH/BTC': {'id': 'eth_btc', 'symbol': 'ETH/BTC', 'base': 'ETH', 'quote': 'BTC', 'maker': 0.002, 'taker': 0.002},
                  'ETH/CAD': {'id': 'eth_cad', 'symbol': 'ETH/CAD', 'base': 'ETH', 'quote': 'CAD', 'maker': 0.005, 'taker': 0.005},
                  'LTC/CAD': {'id': 'ltc_cad', 'symbol': 'LTC/CAD', 'base': 'LTC', 'quote': 'CAD', 'maker': 0.005, 'taker': 0.005},
                  'BCH/CAD': {'id': 'bch_cad', 'symbol': 'BCH/CAD', 'base': 'BCH', 'quote': 'CAD', 'maker': 0.005, 'taker': 0.005},
                  'BTG/CAD': {'id': 'btg_cad', 'symbol': 'BTG/CAD', 'base': 'BTG', 'quote': 'CAD', 'maker': 0.005, 'taker': 0.005},
              },
          })
  
      def fetch_balance(self, params={}):
          balances = self.privatePostBalance()
          result = {'info': balances}
          currencies = list(self.currencies.keys())
          for i in range(0, len(currencies)):
              currency = currencies[i]
              lowercase = currency.lower()
              account = {
                  'free': float(balances[lowercase + '_available']),
                  'used': float(balances[lowercase + '_reserved']),
                  'total': float(balances[lowercase + '_balance']),
              }
              result[currency] = account
          return self.parse_balance(result)
  
      def fetch_order_book(self, symbol, params={}):
          orderbook = self.publicGetOrderBook(self.extend({
              'book': self.market_id(symbol),
          }, params))
          timestamp = int(orderbook['timestamp']) * 1000
          return self.parse_order_book(orderbook, timestamp)
  
      def fetch_ticker(self, symbol, params={}):
          ticker = self.publicGetTicker(self.extend({
              'book': self.market_id(symbol),
          }, params))
          timestamp = int(ticker['timestamp']) * 1000
          vwap = float(ticker['vwap'])
          baseVolume = float(ticker['volume'])
          quoteVolume = baseVolume * vwap
          return {
              'symbol': symbol,
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
              'high': float(ticker['high']),
              'low': float(ticker['low']),
              'bid': float(ticker['bid']),
              'ask': float(ticker['ask']),
              'vwap': vwap,
              'open': None,
              'close': None,
              'first': None,
              'last': float(ticker['last']),
              'change': None,
              'percentage': None,
              'average': None,
              'baseVolume': baseVolume,
              'quoteVolume': quoteVolume,
              'info': ticker,
          }
  
      def parse_trade(self, trade, market):
          timestamp = int(trade['date']) * 1000
          return {
              'info': trade,
              'timestamp': timestamp,
              'datetime': self.iso8601(timestamp),
              'symbol': market['symbol'],
              'id': str(trade['tid']),
              'order': None,
              'type': None,
              'side': trade['side'],
              'price': float(trade['price']),
              'amount': float(trade['amount']),
          }
  
      def fetch_trades(self, symbol, since=None, limit=None, params={}):
          market = self.market(symbol)
          response = self.publicGetTransactions(self.extend({
              'book': market['id'],
          }, params))
          return self.parse_trades(response, market, since, limit)
  
      def create_order(self, symbol, type, side, amount, price=None, params={}):
          method = 'privatePost' + self.capitalize(side)
          order = {
              'amount': amount,
              'book': self.market_id(symbol),
          }
          if type == 'limit':
              order['price'] = price
          response = getattr(self, method)(self.extend(order, params))
          return {
              'info': response,
              'id': str(response['id']),
          }
  
      def cancel_order(self, id, symbol=None, params={}):
          return self.privatePostCancelOrder(self.extend({
              'id': id,
          }, params))
  
      def fetch_deposit_address(self, currency, params={}):
          method = 'privatePost' + self.get_currency_name(currency) + 'DepositAddress'
          response = getattr(self, method)(params)
          address = None
          status = None
          # [E|e]rror
          if response.find('rror') >= 0:
              status = 'error'
          else:
              address = response
              status = 'ok'
          return {
              'currency': currency,
              'address': address,
              'status': status,
              'info': self.last_http_response,
          }
  
      def get_currency_name(self, currency):
          if currency == 'ETH':
              return 'Ether'
          if currency == 'BTC':
              return 'Bitcoin'
  
      def withdraw(self, currency, amount, address, params={}):
          self.load_markets()
          request = {
              'amount': amount,
              'address': address
          }
          method = 'privatePost' + self.get_currency_name(currency) + 'Withdrawal'
          response = getattr(self, method)(self.extend(request, params))
          return {
              'info': response,
              'id': None,
          }
  
      def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
          url = self.urls['api'] + '/' + self.version + '/' + path
          if api == 'public':
              url += '?' + self.urlencode(params)
          else:
              self.check_required_credentials()
              nonce = self.nonce()
              request = ''.join([str(nonce), self.uid, self.apiKey])
              signature = self.hmac(self.encode(request), self.encode(self.secret))
              query = self.extend({
                  'key': self.apiKey,
                  'nonce': nonce,
                  'signature': signature,
              }, params)
              body = self.json(query)
              headers = {
                  'Content-Type': 'application/json',
              }
          return {'url': url, 'method': method, 'body': body, 'headers': headers}
  
      def request(self, path, api='public', method='GET', params={}, headers=None, body=None):
          response = self.fetch2(path, api, method, params, headers, body)
          if isinstance(response, basestring):
              return response
          if 'error' in response:
              raise ExchangeError(self.id + ' ' + self.json(response))
          return response
  