async def request(self, path, api='public', method='GET', params={}, headers=None, body=None): response = await self.fetch2(path, api, method, params, headers, body) if not isinstance(response, basestring): if 'error' in response: numErrors = len(response['error']) if numErrors: message = self.id + ' ' + self.json(response) for i in range(0, len(response['error'])): if response['error'][ i] == 'EFunding:Unknown withdraw key': raise ExchangeError(message) if response['error'][i] == 'EService:Unavailable': raise ExchangeNotAvailable(message) if response['error'][i] == 'EDatabase:Internal error': raise ExchangeNotAvailable(message) if response['error'][i] == 'EService:Busy': raise DDoSProtection(message) raise ExchangeError(message) return response
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))
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))
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: 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)
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: if not response['success']: if response['error'].find( 'Insufficient funds' ) >= 0: # not enougTh is a typo inside Liqui's own API... raise InsufficientFunds(self.id + ' ' + self.json(response)) elif response['error'] == 'Requests too often': raise DDoSProtection(self.id + ' ' + self.json(response)) elif (response['error'] == 'not available') or ( response['error'] == 'external service unavailable'): raise DDoSProtection(self.id + ' ' + self.json(response)) else: raise ExchangeError(self.id + ' ' + self.json(response)) return response
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))
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))