def get_poap_airdrop_data(name: str, data_dir: Path) -> Dict[str, Any]: airdrops_dir = data_dir / 'airdrops_poap' airdrops_dir.mkdir(parents=True, exist_ok=True) filename = airdrops_dir / f'{name}.json' if not filename.is_file(): # if not cached, get it from the gist try: request = requests.get(url=POAP_AIRDROPS[name][0], timeout=DEFAULT_TIMEOUT_TUPLE) except requests.exceptions.RequestException as e: raise RemoteError( f'POAP airdrops Gist request failed due to {str(e)}') from e try: json_data = jsonloads_dict(request.content.decode('utf-8')) except JSONDecodeError as e: raise RemoteError( f'POAP airdrops Gist contains an invalid JSON {str(e)}') from e with open(filename, 'w') as outfile: outfile.write(rlk_jsondumps(json_data)) infile = open(filename, 'r') data_dict = jsonloads_dict(infile.read()) return data_dict
def get_account_balances(self, account_id: int) -> Dict[Asset, Balance]: """Get the loopring balances of a given account id May Raise: - RemotError if there is a problem querying the loopring api or if the format of the response does not match expectations """ response = self._api_query('user/balances', {'accountId': account_id}) balances = {} for balance_entry in response: try: token_id = balance_entry['tokenId'] total = deserialize_int_from_str(balance_entry['total'], 'loopring_balances') except KeyError as e: raise RemoteError( f'Failed to query loopring balances because a balance entry ' f'{balance_entry} did not contain key {str(e)}', ) from e except DeserializationError as e: raise RemoteError( f'Failed to query loopring balances because a balance entry ' f'amount could not be deserialized {balance_entry}', ) from e if total == ZERO: continue asset = TOKENID_TO_ASSET.get(token_id, None) if asset is None: self.msg_aggregator.add_warning( f'Ignoring loopring balance of unsupported token with id {token_id}', ) continue # not checking for UnsupportedAsset since this should not happen thanks # to the mapping above amount = asset_normalized_value(amount=total, asset=asset) try: usd_price = Inquirer().find_usd_price(asset) except RemoteError as e: self.msg_aggregator.add_error( f'Error processing loopring balance entry due to inability to ' f'query USD price: {str(e)}. Skipping balance entry', ) continue balances[asset] = Balance(amount=amount, usd_value=amount * usd_price) return balances
def ethereum_account_to_loopring_id(self, l1_address: ChecksumEthAddress) -> int: """Get the integer corresponding to the loopring account id of the owner of the given ETH L1 address. First tries to get it from the DB and if not known queries loopring api It's possible there is no account id if loopring has not been used yet. In that case a RemoteError is raised and should be handled by the caller. May Raise: - RemotError if there is a problem querying the loopring api or if the format of the response does not match expectations or if there is no account id. """ db = DBLoopring(self.db) # type: ignore # we always know self.db is not None account_id = db.get_accountid_mapping(l1_address) if account_id: return account_id response = self._api_query('account', {'owner': l1_address}) account_id = response.get('accountId', None) if account_id is None: raise RemoteError( f'The loopring api account response {response} did not contain ' f'the account_id key', ) db.add_accountid_mapping(address=l1_address, account_id=account_id) return account_id
def get_airdrop_data(name: str, data_dir: Path) -> Tuple[Iterator, TextIO]: airdrops_dir = data_dir / 'airdrops' airdrops_dir.mkdir(parents=True, exist_ok=True) filename = airdrops_dir / f'{name}.csv' if not filename.is_file(): # if not cached, get it from the gist try: response = requests.get(url=AIRDROPS[name][0], timeout=DEFAULT_TIMEOUT_TUPLE) except requests.exceptions.RequestException as e: raise RemoteError( f'Airdrops Gist request failed due to {str(e)}') from e try: content = response.text if (not csv.Sniffer().has_header(content) or len(response.content) < SMALLEST_AIRDROP_SIZE): raise csv.Error with open(filename, 'w') as f: f.write(content) except csv.Error as e: log.debug( f'airdrop file {filename} contains invalid data {content}') raise UnableToDecryptRemoteData( f'File {filename} contains invalid data. Check logs.', ) from e # Verify the CSV file csvfile = open(filename, 'r') iterator = csv.reader(csvfile) next(iterator) # skip header return iterator, csvfile