Example #1
0
 def handle_errors(self, code, reason, url, method, headers, body):
     if code >= 400:
         if code == 418:
             raise DDoSProtection(self.id + ' ' + str(code) + ' ' + reason + ' ' + body)
         if body.find('MIN_NOTIONAL') >= 0:
             raise InvalidOrder(self.id + ' order cost = amount * price should be >(0.001 BTC or 0.01 ETH or 1 BNB or 1 USDT)' + body)
         if body.find('LOT_SIZE') >= 0:
             raise InvalidOrder(self.id + ' order amount should be evenly divisible by lot size, use self.amount_to_lots(symbol, amount) ' + body)
         if body.find('PRICE_FILTER') >= 0:
             raise InvalidOrder(self.id + ' order price exceeds allowed price precision or invalid, use self.price_to_precision(symbol, amount) ' + body)
         if body.find('Order does not exist') >= 0:
             raise OrderNotFound(self.id + ' ' + body)
     if body[0] == "{":
         response = json.loads(body)
         error = self.safe_value(response, 'code')
         if error == -2010:
             raise InsufficientFunds(self.id + ' ' + self.json(response))
         elif error == -2011:
             raise OrderNotFound(self.id + ' ' + self.json(response))
         elif error < 0:
             raise ExchangeError(self.id + ' ' + self.json(response))
Example #2
0
 def handle_rest_response(self, response, url, method='GET', headers=None, body=None):
     try:
         self.last_json_response = json.loads(response) if len(response) > 1 else None
         return self.last_json_response
     except Exception as e:
         ddos_protection = re.search('(cloudflare|incapsula)', response, flags=re.IGNORECASE)
         exchange_not_available = re.search('(offline|busy|retry|wait|unavailable|maintain|maintenance|maintenancing)', response, flags=re.IGNORECASE)
         if ddos_protection:
             raise DDoSProtection(' '.join([self.id, method, url, response]))
         if exchange_not_available:
             message = 'exchange downtime, exchange closed for maintenance or offline, DDoS protection or rate-limiting in effect'
             raise ExchangeNotAvailable(' '.join([
                 self.id,
                 method,
                 url,
                 response,
                 message,
             ]))
         if isinstance(e, ValueError):
             raise ExchangeError(' '.join([self.id, method, url, response, str(e)]))
         raise
Example #3
0
 def handle_errors(self, code, reason, url, method, headers, body,
                   response):
     if code == 429:
         raise DDoSProtection(self.id + ' ' + body)
     if code >= 400:
         if body:
             if body[0] == '{':
                 response = json.loads(body)
                 error = self.safe_value(response, 'error', {})
                 message = self.safe_string(error, 'message')
                 feedback = self.id + ' ' + body
                 exact = self.exceptions['exact']
                 if message in exact:
                     raise exact[message](feedback)
                 broad = self.exceptions['broad']
                 broadKey = self.findBroadlyMatchedKey(broad, message)
                 if broadKey is not None:
                     raise broad[broadKey](feedback)
                 if code == 400:
                     raise BadRequest(feedback)
                 raise ExchangeError(feedback)  # unknown message
Example #4
0
 def handle_errors(self, code, reason, url, method, headers, body, response,
                   requestHeaders, requestBody):
     if response is None:
         return  # fallback to default error handler
     #
     #     {"date":1570599531.4814300537,"error":"Out of balance -9.99243661 BTC"}
     #
     error = self.safe_string(response, 'error')
     feedback = self.id + ' ' + body
     if error is not None:
         self.throw_exactly_matched_exception(self.exceptions['exact'],
                                              error, feedback)
         self.throw_broadly_matched_exception(self.exceptions['broad'],
                                              error, feedback)
     if code == 401 or code == 403:
         raise AuthenticationError(feedback)
     elif code == 429:
         raise DDoSProtection(feedback)
     if code < 400:
         return
     raise ExchangeError(feedback)
Example #5
0
 def request(self,
             path,
             api='public',
             method='GET',
             params={},
             headers=None,
             body=None):
     response = self.fetch2(path, api, method, params, headers, body)
     if not isinstance(response, basestring):
         if 'error' in response:
             numErrors = len(response['error'])
             if numErrors:
                 for i in range(0, len(response['error'])):
                     if response['error'][i] == 'EService:Unavailable':
                         raise ExchangeNotAvailable(self.id + ' ' +
                                                    self.json(response))
                     if response['error'][i] == 'EService:Busy':
                         raise DDoSProtection(self.id + ' ' +
                                              self.json(response))
                 raise ExchangeError(self.id + ' ' + self.json(response))
     return response
Example #6
0
 def throw_exception_on_error(self, response):
     if 'message' in response:
         if response['message'] == 'APISIGN_NOT_PROVIDED':
             raise AuthenticationError(self.id + ' ' + self.json(response))
         if response['message'] == 'INVALID_SIGNATURE':
             raise AuthenticationError(self.id + ' ' + self.json(response))
         if response['message'] == 'INSUFFICIENT_FUNDS':
             raise InsufficientFunds(self.id + ' ' + self.json(response))
         if response['message'] == 'MIN_TRADE_REQUIREMENT_NOT_MET':
             raise InvalidOrder(self.id + ' ' + self.json(response))
         if response['message'] == 'APIKEY_INVALID':
             if self.hasAlreadyAuthenticatedSuccessfully:
                 raise DDoSProtection(self.id + ' ' + self.json(response))
             else:
                 raise AuthenticationError(self.id + ' ' +
                                           self.json(response))
         if response[
                 'message'] == 'DUST_TRADE_DISALLOWED_MIN_VALUE_50K_SAT':
             raise InvalidOrder(self.id +
                                ' order cost should be over 50k satoshi ' +
                                self.json(response))
Example #7
0
 def handle_errors(self, code, reason, url, method, headers, body):
     if code >= 400:
         if (code == 418) or (code == 429):
             raise DDoSProtection(self.id + ' ' + str(code) + ' ' + reason +
                                  ' ' + body)
         if body.find('Price * QTY is zero or less') >= 0:
             raise InvalidOrder(
                 self.id + ' order cost = amount * price is zero or less ' +
                 body)
         if body.find('MIN_NOTIONAL') >= 0:
             raise InvalidOrder(
                 self.id + ' order cost = amount * price is too small ' +
                 body)
         if body.find('LOT_SIZE') >= 0:
             raise InvalidOrder(
                 self.id +
                 ' order amount should be evenly divisible by lot size, use self.amount_to_lots(symbol, amount) '
                 + body)
         if body.find('PRICE_FILTER') >= 0:
             raise InvalidOrder(
                 self.id +
                 ' order price exceeds allowed price precision or invalid, use self.price_to_precision(symbol, amount) '
                 + body)
         if body.find('Order does not exist') >= 0:
             raise OrderNotFound(self.id + ' ' + body)
     if isinstance(body, basestring):
         if len(body) > 0:
             if body[0] == '{':
                 response = json.loads(body)
                 error = self.safe_value(response, 'code')
                 if error is not None:
                     if error == -2010:
                         raise InsufficientFunds(self.id + ' ' +
                                                 self.json(response))
                     elif error == -2011:
                         raise OrderNotFound(self.id + ' ' +
                                             self.json(response))
                     elif error == -1013:  # Invalid quantity
                         raise InvalidOrder(self.id + ' ' +
                                            self.json(response))
Example #8
0
 def handle_errors(self, code, reason, url, method, headers, body,
                   response):
     if code >= 200 and code < 300:
         return
     exceptions = self.exceptions
     if code == 401:
         # expected non-json response
         if body in exceptions:
             raise exceptions[body](self.id + ' ' + body)
         else:
             return
     if code == 429:
         raise DDoSProtection(self.id + ' ' + body)
     if response is None:
         return
     feedback = self.id + ' ' + body
     message = self.safe_string(response, 'message')
     errors = self.safe_value(response, 'errors')
     if message is not None:
         #
         #  {"message": "Order not found"}
         #
         if message in exceptions:
             raise exceptions[message](feedback)
     elif errors is not None:
         #
         #  {"errors": {"user": ["not_enough_free_balance"]}}
         #  {"errors": {"quantity": ["less_than_order_size"]}}
         #  {"errors": {"order": ["Can not update partially filled order"]}}
         #
         types = list(errors.keys())
         for i in range(0, len(types)):
             type = types[i]
             errorMessages = errors[type]
             for j in range(0, len(errorMessages)):
                 message = errorMessages[j]
                 if message in exceptions:
                     raise exceptions[message](feedback)
     else:
         raise ExchangeError(feedback)
Example #9
0
 def handle_errors(self, code, reason, url, method, headers, body, response,
                   requestHeaders, requestBody):
     if (code == 418) or (code == 429):
         raise DDoSProtection(self.id + ' ' + str(code) + ' ' + reason +
                              ' ' + body)
     if code == 404:
         raise ExchangeError(self.id + ' ' + str(code) +
                             ' endpoint not found')
     if response is not None:
         success = self.safe_value(response, 'success')
         if not success:
             feedback = self.id + ' ' + body
             message = self.safe_value(response, 'message')
             if isinstance(message, basestring):
                 exact = self.safe_value(self.exceptions, 'exact', {})
                 if message in exact:
                     raise exact[message](feedback)
             broad = self.safe_value(self.exceptions, 'broad', {})
             broadKey = self.findBroadlyMatchedKey(broad, body)
             if broadKey is not None:
                 raise broad[broadKey](feedback)
             raise ExchangeError(feedback)
Example #10
0
 def handle_errors(self,
                   code,
                   reason,
                   url,
                   method,
                   headers,
                   body,
                   response=None):
     if code < 400:
         return
     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)
         message = self.id + ' ' + self.safe_value(response, 'detail', body)
         if code == 401 or code == 403:
             raise AuthenticationError(message)
         elif code == 429:
             raise DDoSProtection(message)
         raise ExchangeError(message)
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)
     message = self.id + ' ' + self.json(response)
     if 'error' in response:
         if 'code' in response['error']:
             code = response['error']['code']
             if code == '2033':
                 # \u64cd\u4f5c\u5931\u8d25\uff01\u8ba2\u5355\u5df2\u5b8c\u6210\u6216\u5df2\u64a4\u9500
                 # operation failednot  Orders have been completed or revoked
                 # e.g. trying to cancel a filled order
                 raise OrderNotFound(message)
             elif code == '2068':
                 # \u4e0b\u5355\u6570\u91cf\u4e0d\u80fd\u4f4e\u4e8e
                 # The number of orders can not be less than
                 raise InvalidOrder(message)
             elif code == '3012':
                 raise AuthenticationError(message)  # invalid api key
             elif code == '3025':
                 raise AuthenticationError(message)  # signature failed
             elif code == '4000':
                 # \u5f53\u524d\u7f51\u7edc\u8fde\u63a5\u4e0d\u7a33\u5b9a\uff0c\u8bf7\u7a0d\u5019\u91cd\u8bd5
                 # The current network connection is unstable. Please try again later
                 raise ExchangeNotAvailable(message)
             elif code == '4003':
                 raise DDoSProtection(
                     message)  # server is busy, try again later
         raise ExchangeError(message)
     if not ('result' in list(response.keys())):
         raise ExchangeError(message)
     if method == 'GET':
         return response
     else:
         return response['result'][0]
Example #12
0
 def handle_errors(self, code, reason, url, method, headers, body):
     if code >= 400:
         if code == 418:
             raise DDoSProtection(self.id + ' ' + str(code) + ' ' + reason +
                                  ' ' + body)
         if body.find('MIN_NOTIONAL') >= 0:
             raise InvalidOrder(
                 self.id +
                 ' order cost = amount * price should be > 0.001 BTC ' +
                 body)
         if body.find('LOT_SIZE') >= 0:
             raise InvalidOrder(
                 self.id +
                 ' order amount should be evenly divisible by lot size, use self.amount_to_lots(symbol, amount) '
                 + body)
         if body.find('PRICE_FILTER') >= 0:
             raise InvalidOrder(
                 self.id +
                 ' order price exceeds allowed price precision or invalid, use self.price_to_precision(symbol, amount) '
                 + body)
         if body.find('Order does not exist') >= 0:
             raise OrderNotFound(self.id + ' ' + body)
Example #13
0
 def request(self,
             path,
             api='public',
             method='GET',
             params={},
             headers=None,
             body=None):
     response = self.fetch2(path, api, method, params, headers, body)
     message = self.id + ' ' + self.json(response)
     if 'error' in response:
         if 'code' in response['error']:
             code = response['error']['code']
             if code == '3012':
                 raise AuthenticationError(message)  # invalid api key
             elif code == '3025':
                 raise AuthenticationError(message)  # signature failed
             elif code == '4003':
                 raise DDoSProtection(
                     message)  # server is busy, try again later
         raise ExchangeError(message)
     if not ('result' in list(response.keys())):
         raise ExchangeError(message)
     return response['result'][0]
Example #14
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)
     message = self.id + ' ' + self.json(response)
     if 'error' in response:
         if 'code' in response['error']:
             code = response['error']['code']
             if code == '2068':
                 # \u4e0b\u5355\u6570\u91cf\u4e0d\u80fd\u4f4e\u4e8e
                 # The number of orders can not be less than
                 raise InvalidOrder(message)
             elif code == '3012':
                 raise AuthenticationError(message)  # invalid api key
             elif code == '3025':
                 raise AuthenticationError(message)  # signature failed
             elif code == '4003':
                 raise DDoSProtection(message)  # server is busy, try again later
         raise ExchangeError(message)
     if not('result' in list(response.keys())):
         raise ExchangeError(message)
     if method == 'GET':
         return response
     else:
         return response['result'][0]
Example #15
0
 def handle_errors(self,
                   code,
                   reason,
                   url,
                   method,
                   headers,
                   body,
                   response=None):
     if not self.is_json_encoded_object(body):
         return  # fallback to default error handler
     if (code >= 200) and (code < 300):
         return  # no error
     response = json.loads(body)
     message = self.safe_string(response, 'errorDescription')
     feedback = self.id + ' ' + self.json(response)
     exact = self.exceptions['exact']
     if message in exact:
         raise exact[message](feedback)
     broad = self.exceptions['broad']
     broadKey = self.findBroadlyMatchedKey(broad, message)
     if broadKey is not None:
         raise broad[broadKey](feedback)
     if code == 400:
         raise BadRequest(feedback)
     elif code == 401:
         raise AuthenticationError(feedback)
     elif code == 403:
         raise AuthenticationError(feedback)
     elif code == 429:
         raise DDoSProtection(feedback)
     elif code == 500:
         raise ExchangeError(feedback)
     elif code == 503:
         raise ExchangeNotAvailable(feedback)
     elif code == 504:
         raise RequestTimeout(feedback)
     raise ExchangeError(feedback)  # unknown message
Example #16
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:
         message = response['error']
         feedback = self.id + ' ' + self.json(response)
         if message == 'Invalid order number, or you are not the person who placed the order.':
             raise OrderNotFound(feedback)
         elif message == 'Connection timed out. Please try again.':
             raise RequestTimeout(feedback)
         elif message == 'Internal error. Please try again.':
             raise ExchangeNotAvailable(feedback)
         elif message == 'Order not found, or you are not the person who placed it.':
             raise OrderNotFound(feedback)
         elif message == 'Invalid API key/secret pair.':
             raise AuthenticationError(feedback)
         elif message == 'Please do not make more than 8 API calls per second.':
             raise DDoSProtection(feedback)
         elif message.find('Total must be at least') >= 0:
             raise InvalidOrder(feedback)
         elif message.find('This account is frozen.') >= 0:
             raise AccountSuspended(feedback)
         elif message.find('Not enough') >= 0:
             raise InsufficientFunds(feedback)
         elif message.find('Nonce must be greater') >= 0:
             raise InvalidNonce(feedback)
         elif message.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 #17
0
 def handle_errors(self, httpCode, reason, url, method, headers, body,
                   response, requestHeaders, requestBody):
     if (httpCode == 418) or (httpCode == 429):
         raise DDoSProtection(self.id + ' ' + str(httpCode) + ' ' + reason +
                              ' ' + body)
     # error response in a form: {"code": -1013, "msg": "Invalid quantity."}
     # following block cointains legacy checks against message patterns in "msg" property
     # will switch "code" checks eventually, when we know all of them
     if httpCode >= 400:
         if body.find('Price * QTY is zero or less') >= 0:
             raise InvalidOrder(
                 self.id + ' order cost = amount * price is zero or less ' +
                 body)
         if body.find('LOT_SIZE') >= 0:
             raise InvalidOrder(
                 self.id +
                 ' order amount should be evenly divisible by lot size ' +
                 body)
         if body.find('PRICE_FILTER') >= 0:
             raise InvalidOrder(
                 self.id +
                 ' order price is invalid, i.e. exceeds allowed price precision, exceeds min price or max price limits or is invalid float value in general, use self.price_to_precision(symbol, amount) '
                 + body)
     if response is None:
         return  # fallback to default error handler
     #
     #     {"code":-1128,"msg":"Combination of optional parameters invalid."}
     #
     errorCode = self.safe_string(response, 'code')
     if (errorCode is not None) and (errorCode != '0'):
         feedback = self.id + ' ' + self.json(response)
         self.throw_exactly_matched_exception(self.exceptions['exact'],
                                              errorCode, feedback)
         message = self.safe_string(response, 'msg')
         self.throw_broadly_matched_exception(self.exceptions['broad'],
                                              message, feedback)
         raise ExchangeError(feedback)
Example #18
0
 def handle_errors(self, code, reason, url, method, headers, body, response, requestHeaders, requestBody):
     if (code == 418) or (code == 429):
         raise DDoSProtection(self.id + ' ' + str(code) + ' ' + reason + ' ' + body)
     # error response in a form: {"code": -1013, "msg": "Invalid quantity."}
     # following block cointains legacy checks against message patterns in "msg" property
     # will switch "code" checks eventually, when we know all of them
     if code >= 400:
         if body.find('Price * QTY is zero or less') >= 0:
             raise InvalidOrder(self.id + ' order cost = amount * price is zero or less ' + body)
         if body.find('LOT_SIZE') >= 0:
             raise InvalidOrder(self.id + ' order amount should be evenly divisible by lot size ' + body)
         if body.find('PRICE_FILTER') >= 0:
             raise InvalidOrder(self.id + ' order price is invalid, i.e. exceeds allowed price precision, exceeds min price or max price limits or is invalid float value in general, use self.price_to_precision(symbol, amount) ' + body)
     if response is None:
         return  # fallback to default error handler
     # check success value for wapi endpoints
     # response in format {'msg': 'The coin does not exist.', 'success': True/false}
     success = self.safe_value(response, 'success', True)
     if not success:
         message = self.safe_string(response, 'msg')
         parsedMessage = None
         if message is not None:
             try:
                 parsedMessage = json.loads(message)
             except Exception as e:
                 # do nothing
                 parsedMessage = None
             if parsedMessage is not None:
                 response = parsedMessage
     exceptions = self.exceptions
     message = self.safe_string(response, 'msg')
     if message in exceptions:
         ExceptionClass = exceptions[message]
         raise ExceptionClass(self.id + ' ' + message)
     if not success:
         raise ExchangeError(self.id + ' ' + body)
Example #19
0
 def handle_errors(self, code, reason, url, method, headers, body):
     if code >= 300:
         if body[0] == '{':
             response = json.loads(body)
             if 'errorCode' in response:
                 error = response['errorCode']
                 # todo: rework for error-maps, like in liqui or okcoinusd
                 if error == 1:
                     raise ExchangeError(self.id + ' ' + self.json(response))
                 elif error == 2:
                     if 'errorMessage' in response:
                         if response['errorMessage'] == 'User not found':
                             raise AuthenticationError(self.id + ' ' + response['errorMessage'])
                     else:
                         raise ExchangeError(self.id + ' ' + self.json(response))
                 elif (error == 10) or (error == 11) or (error == 12) or (error == 20) or (error == 30) or (error == 101) or (error == 102):
                     raise AuthenticationError(self.id + ' ' + self.json(response))
                 elif error == 31:
                     raise NotSupported(self.id + ' ' + self.json(response))
                 elif error == 32:
                     raise ExchangeError(self.id + ' ' + self.json(response))
                 elif error == 100:
                     raise ExchangeError(self.id + ': Invalid parameters ' + self.json(response))
                 elif error == 103:
                     raise InvalidOrder(self.id + ': Invalid currency ' + self.json(response))
                 elif error == 104:
                     raise InvalidOrder(self.id + ': Invalid amount ' + self.json(response))
                 elif error == 105:
                     raise InvalidOrder(self.id + ': Unable to block funds ' + self.json(response))
                 elif error == 503:
                     raise ExchangeNotAvailable(self.id + ': Exchange is not available ' + self.json(response))
                 elif error == 429:
                     raise DDoSProtection(self.id + ': Too many requests' + self.json(response))
                 else:
                     raise ExchangeError(self.id + ' ' + self.json(response))
         raise ExchangeError(self.id + ' ' + body)
Example #20
0
 def handle_errors(self, code, reason, url, method, headers, body, response, requestHeaders, requestBody):
     if not self.is_json_encoded_object(body):
         return  # fallback to default error handler
     if (code >= 200) and (code < 300):
         return  # no error
     message = self.safe_string(response, 'errorDescription')
     feedback = self.id + ' ' + body
     self.throw_exactly_matched_exception(self.exceptions['exact'], message, feedback)
     self.throw_broadly_matched_exception(self.exceptions['broad'], message, feedback)
     if code == 400:
         raise BadRequest(feedback)
     elif code == 401:
         raise AuthenticationError(feedback)
     elif code == 403:
         raise AuthenticationError(feedback)
     elif code == 429:
         raise DDoSProtection(feedback)
     elif code == 500:
         raise ExchangeError(feedback)
     elif code == 503:
         raise ExchangeNotAvailable(feedback)
     elif code == 504:
         raise RequestTimeout(feedback)
     raise ExchangeError(feedback)  # unknown message
Example #21
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 #22
0
 def handle_errors(self,
                   code,
                   reason,
                   url,
                   method,
                   headers,
                   body,
                   response=None):
     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 == 'APIKEY_INVALID':
                 if self.options['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))
             if message == 'INVALID_ORDER':
                 # Bittrex will return an ambiguous INVALID_ORDER message
                 # upon canceling already-canceled and closed orders
                 # therefore self special case for cancelOrder
                 # url = 'https://bittrex.com/api/v1.1/market/cancel?apikey=API_KEY&uuid=ORDER_UUID'
                 cancel = 'cancel'
                 indexOfCancel = url.find(cancel)
                 if indexOfCancel >= 0:
                     parts = url.split('&')
                     orderId = None
                     for i in range(0, len(parts)):
                         part = parts[i]
                         keyValue = part.split('=')
                         if keyValue[0] == 'uuid':
                             orderId = keyValue[1]
                             break
                     if orderId is not None:
                         raise OrderNotFound(self.id + ' cancelOrder ' +
                                             orderId + ' ' +
                                             self.json(response))
                     else:
                         raise OrderNotFound(self.id + ' cancelOrder ' +
                                             self.json(response))
             if message in exceptions:
                 raise exceptions[message](feedback)
             if message is not None:
                 if message.find('throttled. Try again') >= 0:
                     raise DDoSProtection(feedback)
                 if message.find('problem') >= 0:
                     raise ExchangeNotAvailable(
                         feedback
                     )  # 'There was a problem processing your request.  If self problem persists, please contact...')
             raise ExchangeError(feedback)
Example #23
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))
Example #24
0
 def handle_errors(self, code, reason, url, method, headers, body):
     if (code == 418) or (code == 429):
         raise DDoSProtection(self.id + ' ' + str(code) + ' ' + reason +
                              ' ' + body)
     # error response in a form: {"code": -1013, "msg": "Invalid quantity."}
     # following block cointains legacy checks against message patterns in "msg" property
     # will switch "code" checks eventually, when we know all of them
     if code >= 400:
         if body.find('Price * QTY is zero or less') >= 0:
             raise InvalidOrder(
                 self.id + ' order cost = amount * price is zero or less ' +
                 body)
         if body.find('LOT_SIZE') >= 0:
             raise InvalidOrder(
                 self.id +
                 ' order amount should be evenly divisible by lot size, use self.amount_to_lots(symbol, amount) '
                 + body)
         if body.find('PRICE_FILTER') >= 0:
             raise InvalidOrder(
                 self.id +
                 ' order price exceeds allowed price precision or invalid, use self.price_to_precision(symbol, amount) '
                 + body)
     if len(body) > 0:
         if body[0] == '{':
             response = json.loads(body)
             # check success value for wapi endpoints
             # response in format {'msg': 'The coin does not exist.', 'success': True/false}
             success = self.safe_value(response, 'success', True)
             if not success:
                 if 'msg' in response:
                     try:
                         response = json.loads(response['msg'])
                     except Exception as e:
                         response = {}
             # checks against error codes
             error = self.safe_string(response, 'code')
             if error is not None:
                 exceptions = self.exceptions
                 if error in exceptions:
                     # a workaround for {"code":-2015,"msg":"Invalid API-key, IP, or permissions for action."}
                     # despite that their message is very confusing, it is raised by Binance
                     # on a temporary ban(the API key is valid, but disabled for a while)
                     if (error == '-2015') and self.options[
                             'hasAlreadyAuthenticatedSuccessfully']:
                         raise DDoSProtection(self.id +
                                              ' temporary banned: ' + body)
                     message = self.safe_string(response, 'msg')
                     if message == 'Order would trigger immediately.':
                         raise InvalidOrder(self.id + ' ' + body)
                     elif message == 'Account has insufficient balance for requested action.':
                         raise InsufficientFunds(self.id + ' ' + body)
                     elif message == 'Rest API trading is not enabled.':
                         raise InsufficientFunds(self.id + ' ' + body)
                     raise exceptions[error](self.id + ' ' + body)
                 else:
                     raise ExchangeError(self.id +
                                         ': unknown error code: ' + body +
                                         ' ' + error)
             if not success:
                 raise ExchangeError(self.id + ': success value False: ' +
                                     body)