Пример #1
0
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
Пример #2
0
    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
Пример #3
0
    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
Пример #4
0
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