예제 #1
0
def query_etherscan_for_transactions(accounts: List[EthAddress]) -> List[EthereumTransaction]:
    transactions: List[EthereumTransaction] = list()
    for account in accounts:
        transactions.extend(
            retry_calls(
                5,
                'etherscan',
                'query_ethereum_txlist',
                query_ethereum_txlist,
                account,
                False,
            ),
        )
        transactions.extend(
            retry_calls(
                5,
                'etherscan',
                'query_ethereum_txlist_internal',
                query_ethereum_txlist,
                account,
                True,
            ),
        )

    transactions.sort(key=lambda tx: tx.timestamp)
    return transactions
예제 #2
0
def query_etherscan_for_transactions(
    db: 'DBHandler',
    msg_aggregator: MessagesAggregator,
    from_ts: Optional[Timestamp] = None,
    to_ts: Optional[Timestamp] = None,
) -> List[EthereumTransaction]:
    transactions: List[EthereumTransaction] = list()

    accounts = db.get_blockchain_accounts()
    for address in accounts.eth:
        # If we already have any transactions in the DB for this from_address
        # from to_ts and on then that means the range has already been queried
        if to_ts:
            existing_txs = db.get_ethereum_transactions(from_ts=to_ts,
                                                        address=address)
            if len(existing_txs) > 0:
                # So just query the DB only here
                transactions.extend(
                    db.get_ethereum_transactions(from_ts=from_ts,
                                                 to_ts=to_ts,
                                                 address=address), )
                continue

        # else we have to query etherscan for this address
        new_transactions = retry_calls(
            times=5,
            location='etherscan',
            handle_429=False,
            backoff_in_seconds=0,
            method_name='query_ethereum_txlist',
            function=query_ethereum_txlist,
            # function's arguments
            address=address,
            msg_aggregator=msg_aggregator,
            internal=False,
        )
        new_transactions.extend(
            retry_calls(
                times=5,
                location='etherscan',
                handle_429=False,
                backoff_in_seconds=0,
                method_name='query_ethereum_txlist_internal',
                function=query_ethereum_txlist,
                # function's arguments
                address=address,
                msg_aggregator=msg_aggregator,
                internal=True,
            ), )

        # and finally also save the transactions in the DB
        db.add_ethereum_transactions(ethereum_transactions=new_transactions,
                                     from_etherscan=True)
        transactions.extend(new_transactions)

    transactions.sort(key=lambda tx: tx.timestamp)
    return transactions
예제 #3
0
def query_cryptocompare_for_fiat_price(asset: Asset) -> Price:
    log.debug('Get usd price from cryptocompare', asset=asset)
    cc_asset_str = asset.to_cryptocompare()
    resp = retry_calls(
        5,
        'find_usd_price',
        'requests.get',
        requests.get,
        u'https://min-api.cryptocompare.com/data/price?'
        'fsym={}&tsyms=USD'.format(cc_asset_str),
    )

    if resp.status_code != 200:
        raise RemoteError(
            'Cant reach cryptocompare to get USD value of {}'.format(asset))

    resp = rlk_jsonloads_dict(resp.text)

    # If there is an error in the response skip this token
    if 'USD' not in resp:
        error_message = ''
        if resp['Response'] == 'Error':
            error_message = resp['Message']

        log.error(
            'Cryptocompare usd price query failed',
            asset=asset,
            error=error_message,
        )
        return Price(ZERO)

    price = Price(FVal(resp['USD']))
    log.debug('Got usd price from cryptocompare', asset=asset, price=price)
    return price
예제 #4
0
    def query_historical_fiat_exchange_rates(
            from_fiat_currency: Asset,
            to_fiat_currency: Asset,
            timestamp: Timestamp,
    ) -> Optional[Price]:
        assert from_fiat_currency.is_fiat(), 'fiat currency should have been provided'
        assert to_fiat_currency.is_fiat(), 'fiat currency should have been provided'
        date = timestamp_to_date(timestamp, formatstr='%Y-%m-%d')
        instance = Inquirer()
        rate = instance._get_cached_forex_data(date, from_fiat_currency, to_fiat_currency)
        if rate:
            return rate

        log.debug(
            'Querying exchangeratesapi',
            from_fiat_currency=from_fiat_currency.identifier,
            to_fiat_currency=to_fiat_currency.identifier,
            timestamp=timestamp,
        )

        query_str = (
            f'https://api.exchangeratesapi.io/{date}?'
            f'base={from_fiat_currency.identifier}'
        )
        resp = retry_calls(
            times=5,
            location='query_exchangeratesapi',
            handle_429=False,
            backoff_in_seconds=0,
            method_name='requests.get',
            function=requests.get,
            # function's arguments
            url=query_str,
        )

        if resp.status_code != 200:
            return None

        try:
            result = rlk_jsonloads_dict(resp.text)
        except JSONDecodeError:
            return None

        if 'rates' not in result or to_fiat_currency.identifier not in result['rates']:
            return None

        if date not in instance._cached_forex_data:
            instance._cached_forex_data[date] = {}

        if from_fiat_currency not in instance._cached_forex_data[date]:
            instance._cached_forex_data[date][from_fiat_currency] = {}

        for key, value in result['rates'].items():
            instance._cached_forex_data[date][from_fiat_currency][key] = FVal(value)

        rate = Price(FVal(result['rates'][to_fiat_currency.identifier]))
        log.debug('Exchangeratesapi query succesful', rate=rate)
        return rate
예제 #5
0
 def api_query(self, command: str, req: Optional[Dict] = None) -> Union[Dict, List]:
     result = retry_calls(5, 'poloniex', command, self._api_query, command, req)
     if 'error' in result:
         raise PoloniexError(
             'Poloniex query for "{}" returned error: {}'.format(
                 command,
                 result['error'],
             ))
     return result
예제 #6
0
 def query_private(self, method: str, req: Optional[dict] = None) -> dict:
     return retry_calls(
         times=5, location='kraken',
         handle_429=False,
         backoff_in_seconds=0,
         method_name=method,
         function=self._query_private,
         # function's arguments
         method=method,
         req=req,
     )
예제 #7
0
    def query_historical_fiat_exchange_rates(
        from_fiat_currency: FiatAsset,
        to_fiat_currency: FiatAsset,
        timestamp: Timestamp,
    ) -> Optional[Price]:
        date = tsToDate(timestamp, formatstr='%Y-%m-%d')
        instance = Inquirer()
        rate = instance._get_cached_forex_data(date, from_fiat_currency,
                                               to_fiat_currency)
        if rate:
            return rate

        log.debug(
            'Querying exchangeratesapi',
            from_fiat_currency=from_fiat_currency,
            to_fiat_currency=to_fiat_currency,
            timestamp=timestamp,
        )

        query_str = (f'https://api.exchangeratesapi.io/{date}?'
                     f'base={from_fiat_currency}')
        resp = retry_calls(
            5,
            'query_exchangeratesapi',
            'requests.get',
            requests.get,
            query_str,
        )

        if resp.status_code != 200:
            return None

        try:
            result = rlk_jsonloads_dict(resp.text)
        except JSONDecodeError:
            return None

        if 'rates' not in result or to_fiat_currency not in result['rates']:
            return None

        if date not in instance._cached_forex_data:
            instance._cached_forex_data[date] = {}

        if from_fiat_currency not in instance._cached_forex_data[date]:
            instance._cached_forex_data[date][from_fiat_currency] = {}

        for key, value in result['rates'].items():
            instance._cached_forex_data[date][from_fiat_currency][key] = FVal(
                value)

        rate = Price(FVal(result['rates'][to_fiat_currency]))
        log.debug('Exchangeratesapi query succesful', rate=rate)
        return rate
예제 #8
0
 def api_query(self, command: str, req: Optional[Dict] = None) -> Union[Dict, List]:
     result = retry_calls(
         times=5,
         location='poloniex',
         handle_429=False,
         backoff_in_seconds=0,
         method_name=command,
         function=self._api_query,
         # function's arguments
         command=command,
         req=req,
     )
     if 'error' in result:
         raise PoloniexError(
             'Poloniex query for "{}" returned error: {}'.format(
                 command,
                 result['error'],
             ))
     return result
예제 #9
0
파일: inquirer.py 프로젝트: sponnet/rotki
def query_cryptocompare_for_fiat_price(asset: Asset) -> Price:
    log.debug('Get usd price from cryptocompare', asset=asset)
    cc_asset_str = asset.to_cryptocompare()
    resp = retry_calls(
        times=5,
        location='find_usd_price',
        handle_429=False,
        backoff_in_seconds=0,
        method_name='requests.get',
        function=requests.get,
        # function's arguments
        url=(
            u'https://min-api.cryptocompare.com/data/price?'
            'fsym={}&tsyms=USD'.format(cc_asset_str)
        ),
    )

    if resp.status_code != 200:
        raise RemoteError('Cant reach cryptocompare to get USD value of {}'.format(asset))

    resp = rlk_jsonloads_dict(resp.text)

    # If there is an error in the response skip this token
    if 'USD' not in resp:
        error_message = ''
        if resp.get('Response', None) == 'Error':
            error_message = resp.get('Message', '')

        log.error(
            'Cryptocompare usd price query failed',
            asset=asset,
            error=error_message,
        )
        return Price(ZERO)

    price = Price(FVal(resp['USD']))
    log.debug('Got usd price from cryptocompare', asset=asset, price=price)
    return price
예제 #10
0
 def query_private(self, method: str, req: Optional[dict] = None) -> dict:
     return retry_calls(5, 'kraken', method, self._query_private, method,
                        req)