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
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
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
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
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
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, )
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
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
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
def query_private(self, method: str, req: Optional[dict] = None) -> dict: return retry_calls(5, 'kraken', method, self._query_private, method, req)