Example #1
0
 def handle_errors(self, code, reason, url, method, headers, body):
     response = None
     try:
         response = json.loads(body)
     except Exception as e:
         # syntax error, resort to default error handler
         return
     if 'error' in response:
         error = response['error']
         feedback = self.id + ' ' + self.json(response)
         if error == 'Invalid order number, or you are not the person who placed the order.':
             raise OrderNotFound(feedback)
         elif error == 'Internal error. Please try again.':
             raise ExchangeNotAvailable(feedback)
         elif error == 'Order not found, or you are not the person who placed it.':
             raise OrderNotFound(feedback)
         elif error == 'Invalid API key/secret pair.':
             raise AuthenticationError(feedback)
         elif error == 'Please do not make more than 8 API calls per second.':
             raise DDoSProtection(feedback)
         elif error.find('Total must be at least') >= 0:
             raise InvalidOrder(feedback)
         elif error.find('Not enough') >= 0:
             raise InsufficientFunds(feedback)
         elif error.find('Nonce must be greater') >= 0:
             raise InvalidNonce(feedback)
         elif error.find(
                 'You have already called cancelOrder or moveOrder on self order.'
         ) >= 0:
             raise CancelPending(feedback)
         else:
             raise ExchangeError(self.id + ': unknown error: ' +
                                 self.json(response))
Example #2
0
 def handle_errors(self, code, reason, url, method, headers, body):
     if body[0] == '{':
         response = json.loads(body)
         # {success: False, message: "message"}
         success = self.safe_value(response, 'success')
         if success is None:
             raise ExchangeError(self.id + ': malformed response: ' +
                                 self.json(response))
         if isinstance(success, basestring):
             # bleutrade uses string instead of boolean
             success = True if (success == 'true') else False
         if not success:
             message = self.safe_string(response, 'message')
             feedback = self.id + ' ' + self.json(response)
             exceptions = self.exceptions
             if message in exceptions:
                 raise exceptions[message](feedback)
             if message == 'APIKEY_INVALID':
                 if self.hasAlreadyAuthenticatedSuccessfully:
                     raise DDoSProtection(feedback)
                 else:
                     raise AuthenticationError(feedback)
             if message == 'DUST_TRADE_DISALLOWED_MIN_VALUE_50K_SAT':
                 raise InvalidOrder(
                     self.id + ' order cost should be over 50k satoshi ' +
                     self.json(response))
             raise ExchangeError(self.id + ' ' + self.json(response))
Example #3
0
 def sign(self,
          path,
          api='public',
          method='GET',
          params={},
          headers=None,
          body=None):
     if not self.apiKey:
         raise AuthenticationError(self.id +
                                   ' requires apiKey for all requests')
     url = self.urls['api'][api] + '/' + path
     if api == 'private':
         self.check_required_credentials()
         nonce = self.nonce()
         body = self.json(self.extend({'nonce': nonce}, params))
         headers = {
             'Content-Type':
             'application/json',
             'key':
             self.apiKey,
             'sign':
             self.hmac(self.encode(body), self.encode(self.secret),
                       hashlib.sha512),
         }
     return {'url': url, 'method': method, 'body': body, 'headers': headers}
Example #4
0
 async def create_order(self,
                        symbol,
                        type,
                        side,
                        amount,
                        price=None,
                        params={}):
     await self.load_markets()
     order = {
         'Code': self.market_id(symbol),
         'Way': 'Bid' if (side == 'buy') else 'Ask',
         'Amount': amount,
     }
     if type == 'limit':
         order['Price'] = price
     if self.twofa:
         if 'ValidationCode' in params:
             order['ValidationCode'] = params['ValidationCode']
         else:
             raise AuthenticationError(
                 self.id +
                 ' two-factor authentication requires a missing ValidationCode parameter'
             )
     response = await self.privatePostTradeOrders(self.extend(
         order, params))
     return {
         'info': response,
         'id': response['clOrderId'],
     }
Example #5
0
 def handle_errors(self,
                   code,
                   reason,
                   url,
                   method,
                   headers,
                   body,
                   response=None):
     # {success: 0, error: "invalid order."}
     # or
     # [{data, ...}, {...}, ...]
     if response is None:
         if body[0] == '{' or body[0] == '[':
             response = json.loads(body)
     if isinstance(response, list):
         return  # public endpoints may return []-arrays
     if not ('success' in list(response.keys())):
         return  # no 'success' property on public responses
     if response['success'] == 1:
         # {success: 1, return: {orders: []}}
         if not ('return' in list(response.keys())):
             raise ExchangeError(self.id + ': malformed response: ' +
                                 self.json(response))
         else:
             return
     message = response['error']
     feedback = self.id + ' ' + self.json(response)
     if message == 'Insufficient balance.':
         raise InsufficientFunds(feedback)
     elif message == 'invalid order.':
         raise OrderNotFound(feedback)  # cancelOrder(1)
     elif message.find('Minimum price ') >= 0:
         raise InvalidOrder(
             feedback
         )  # price < limits.price.min, on createLimitBuyOrder('ETH/BTC', 1, 0)
     elif message.find('Minimum order ') >= 0:
         raise InvalidOrder(
             feedback
         )  # cost < limits.cost.min on createLimitBuyOrder('ETH/BTC', 0, 1)
     elif message == 'Invalid credentials. API not found or session has expired.':
         raise AuthenticationError(feedback)  # on bad apiKey
     elif message == 'Invalid credentials. Bad sign.':
         raise AuthenticationError(feedback)  # on bad secret
     raise ExchangeError(self.id + ': unknown error: ' +
                         self.json(response))
Example #6
0
 async def request(self, path, api='public', method='GET', params={}, headers=None, body=None):
     response = await self.fetch2(path, api, method, params, headers, body)
     code = self.safe_integer(response, 'code')
     message = self.safe_string(response, 'message')
     if code and code != 100 and message:
         if code == 103:
             raise AuthenticationError(message)
         raise ExchangeError(message)
     return response
Example #7
0
 def handle_errors(self, statusCode, statusText, url, method, headers, body):
     if not isinstance(body, basestring):
         return  # fallback to default error handler
     if len(body) < 2:
         return
     # Here is a sample QuadrigaCX response in case of authentication failure:
     # {"error":{"code":101,"message":"Invalid API Code or Invalid Signature"}}
     if statusCode == 200 and body.find('Invalid API Code or Invalid Signature') >= 0:
         raise AuthenticationError(self.id + ' ' + body)
Example #8
0
 def sign(self,
          path,
          api='public',
          method='GET',
          params={},
          headers=None,
          body=None):
     if not self.apiKey:
         raise AuthenticationError(
             self.id +
             ' requires apiKey for all requests, their public API is always busy'
         )
     if not self.uid:
         raise AuthenticationError(
             self.id +
             ' requires uid property for authentication and trading, their public API is always busy'
         )
     url = self.urls['api'] + '/' + self.version
     if api == 'public':
         url += '/' + api
     url += '/' + 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 = {'Accept-Encoding': 'gzip, deflate'}
         nonce = str(self.nonce())
         if method == 'POST':
             if query:
                 headers['Content-Type'] = 'application/json'
                 body = self.json(query)
             else:
                 url += '?' + self.urlencode(query)
         auth = nonce + self.uid + self.apiKey + method + url
         if body:
             auth += body
         signature = self.hmac(self.encode(auth), self.encode(self.secret),
                               hashlib.sha256, 'base64')
         credentials = self.uid + ':' + self.apiKey + ':' + nonce + ':' + self.binary_to_string(
             signature)
         headers['Authorization'] = 'HMAC ' + credentials
     return {'url': url, 'method': method, 'body': body, 'headers': headers}
Example #9
0
 def handle_errors(self, httpCode, reason, url, method, headers, body):
     if not isinstance(body, basestring):
         return  # fallback to default error handler
     if len(body) < 2:
         return  # fallback to default error handler
     if (body[0] == '{') or (body[0] == '['):
         response = json.loads(body)
         status = self.safe_string(response, 'status')
         if status == 'error':
             code = self.safe_string(response, 'code')
             if code is not None:
                 if code == 'API0005':
                     raise AuthenticationError(self.id + ' invalid signature, use the uid for the main account if you have subaccounts')
             raise ExchangeError(self.id + ' ' + self.json(response))
Example #10
0
 def handle_errors(self, code, reason, url, method, headers, body):
     if code == 429:
         raise DDoSProtection(self.id + ' ' + body)
     if code >= 400:
         if body:
             if body[0] == '{':
                 response = json.loads(body)
                 if 'error' in response:
                     if 'message' in response['error']:
                         message = self.safe_value(response['error'], 'message')
                         if message is not None:
                             if message == 'Invalid API Key.':
                                 raise AuthenticationError(self.id + ' ' + self.json(response))
                         # stub code, need proper handling
                         raise ExchangeError(self.id + ' ' + self.json(response))
Example #11
0
 def request(self,
             path,
             api='public',
             method='GET',
             params={},
             headers=None,
             body=None):
     response = self.fetch2(path, api, method, params, headers, body)
     if 'success' in response:
         success = self.safe_integer(response, 'success')
         if success == 0:
             message = self.safe_string(response, 'message')
             if message == 'Invalid APIKey':
                 raise AuthenticationError(message)
             raise ExchangeError(message)
     return response
Example #12
0
 def request(self, path, api='public', method='GET', params={}, headers=None, body=None):
     response = self.fetch2(path, api, method, params, headers, body)
     errors = self.safe_value(response, 'errors')
     data = self.safe_value(response, 'response')
     if errors or not data:
         authErrorKeys = ['Key', 'user_id', 'Sign']
         for i in range(0, len(authErrorKeys)):
             errorKey = authErrorKeys[i]
             errorMessage = self.safe_string(errors, errorKey)
             if not errorMessage:
                 continue
             if errorKey == 'user_id' and errorMessage.find('authorization') < 0:
                 continue
             raise AuthenticationError(errorMessage)
         raise ExchangeError(self.json(errors))
     return response
Example #13
0
 def handle_errors(self, code, reason, url, method, headers, body):
     if (code == 400) or (code == 404):
         if body[0] == '{':
             response = json.loads(body)
             message = response['message']
             error = self.id + ' ' + message
             if message.find('price too small') >= 0:
                 raise InvalidOrder(error)
             elif message.find('price too precise') >= 0:
                 raise InvalidOrder(error)
             elif message == 'Insufficient funds':
                 raise InsufficientFunds(error)
             elif message == 'NotFound':
                 raise OrderNotFound(error)
             elif message == 'Invalid API Key':
                 raise AuthenticationError(error)
             raise ExchangeError(self.id + ' ' + message)
         raise ExchangeError(self.id + ' ' + body)
Example #14
0
 def throw_exception_on_error(self, response):
     #
     # API endpoints return the following formats
     #     {success: False, code: "ERROR", msg: "Min price:100.0"}
     #     {success: True,  code: "OK",    msg: "Operation succeeded."}
     #
     # Web OHLCV endpoint returns self:
     #     {s: "ok", o: [], h: [], l: [], c: [], v: []}
     #
     # This particular method handles API responses only
     #
     if not ('success' in list(response.keys())):
         return
     if response['success'] is True:
         return  # not an error
     if not ('code' in list(response.keys())) or not ('msg' in list(
             response.keys())):
         raise ExchangeError(self.id + ': malformed response: ' +
                             self.json(response))
     code = self.safe_string(response, 'code')
     message = self.safe_string(response, 'msg')
     feedback = self.id + ' ' + self.json(response)
     if code == 'UNAUTH':
         if message == 'Invalid nonce':
             raise InvalidNonce(feedback)
         raise AuthenticationError(feedback)
     elif code == 'ERROR':
         if message.find('The precision of amount') >= 0:
             raise InvalidOrder(
                 feedback)  # amount violates precision.amount
         if message.find('Min amount each order') >= 0:
             raise InvalidOrder(feedback)  # amount < limits.amount.min
         if message.find('Min price:') >= 0:
             raise InvalidOrder(feedback)  # price < limits.price.min
         if message.find('The precision of price') >= 0:
             raise InvalidOrder(feedback)  # price violates precision.price
     elif code == 'NO_BALANCE':
         if message.find('Insufficient balance') >= 0:
             raise InsufficientFunds(feedback)
     raise ExchangeError(self.id + ': unknown response: ' +
                         self.json(response))
Example #15
0
 def handle_errors(self, httpCode, reason, url, method, headers, body):
     if not isinstance(body, basestring):
         return  # fallback to default error handler
     if len(body) < 2:
         return  # fallback to default error handler
     if (body[0] == '{') or (body[0] == '['):
         response = json.loads(body)
         if 'success' in response:
             #
             # 1 - Liqui only returns the integer 'success' key from their private API
             #
             #     {"success": 1, ...} httpCode == 200
             #     {"success": 0, ...} httpCode == 200
             #
             # 2 - However, exchanges derived from Liqui, can return non-integers
             #
             #     It can be a numeric string
             #     {"sucesss": "1", ...}
             #     {"sucesss": "0", ...}, httpCode >= 200(can be 403, 502, etc)
             #
             #     Or just a string
             #     {"success": "true", ...}
             #     {"success": "false", ...}, httpCode >= 200
             #
             #     Or a boolean
             #     {"success": True, ...}
             #     {"success": False, ...}, httpCode >= 200
             #
             # 3 - Oversimplified, Python PEP8 forbids comparison operator(==) of different types
             #
             # 4 - We do not want to copy-paste and duplicate the code of self handler to other exchanges derived from Liqui
             #
             # To cover points 1, 2, 3 and 4 combined self handler should work like self:
             #
             success = self.safe_value(response, 'success', False)
             if isinstance(success, basestring):
                 if (success == 'true') or (success == '1'):
                     success = True
                 else:
                     success = False
             if not success:
                 code = self.safe_string(response, 'code')
                 message = self.safe_string(response, 'error')
                 feedback = self.id + ' ' + self.json(response)
                 exceptions = self.exceptions
                 if code in exceptions:
                     raise exceptions[code](feedback)
                 # need a second error map for these messages, apparently...
                 # in fact, we can use the same .exceptions with string-keys to save some loc here
                 if message == 'invalid api key':
                     raise AuthenticationError(feedback)
                 elif message == 'api key dont have trade permission':
                     raise AuthenticationError(feedback)
                 elif message.find(
                         'invalid parameter'
                 ) >= 0:  # errorCode 0, returned on buy(symbol, 0, 0)
                     raise InvalidOrder(feedback)
                 elif message == 'invalid order':
                     raise InvalidOrder(feedback)
                 elif message == 'Requests too often':
                     raise DDoSProtection(feedback)
                 elif message == 'not available':
                     raise DDoSProtection(feedback)
                 elif message == 'data unavailable':
                     raise DDoSProtection(feedback)
                 elif message == 'external service unavailable':
                     raise DDoSProtection(feedback)
                 else:
                     raise ExchangeError(self.id +
                                         ' unknown "error" value: ' +
                                         self.json(response))