def get_all_asset_data( mapping: bool ) -> Union[List[AssetData], Dict[str, Dict[str, Any]]]: """Return all asset data from the DB TODO: This can be improved. Too many sql queries. If mapping is True, return them as a Dict of identifier to data If mapping is False, return them as a List of AssetData """ result: Union[List[AssetData], Dict[str, Dict[str, Any]]] if mapping: result = {} else: result = [] cursor = GlobalDBHandler()._conn.cursor() querystr = """ SELECT A.identifier, A.type, B.address, B.decimals, A.name, A.symbol, A.started, null, A.swapped_for, A.coingecko, A.cryptocompare, B.protocol from assets as A LEFT OUTER JOIN ethereum_tokens as B ON B.address = A.details_reference WHERE A.type=? UNION ALL SELECT A.identifier, A.type, null, null, A.name, A.symbol, A.started, B.forked, A.swapped_for, A.coingecko, A.cryptocompare, null from assets as A LEFT OUTER JOIN common_asset_details as B ON B.asset_id = A.identifier WHERE A.type!=?; """ # noqa: E501 eth_token_type = AssetType.ETHEREUM_TOKEN.serialize_for_db() # pylint: disable=no-member query = cursor.execute(querystr, (eth_token_type, eth_token_type)) for entry in query: asset_type = AssetType.deserialize_from_db(entry[1]) ethereum_address: Optional[ChecksumEthAddress] if asset_type == AssetType.ETHEREUM_TOKEN: ethereum_address = string_to_ethereum_address(entry[2]) else: ethereum_address = None data = AssetData( identifier=entry[0], asset_type=asset_type, ethereum_address=ethereum_address, decimals=entry[3], name=entry[4], symbol=entry[5], started=entry[6], forked=entry[7], swapped_for=entry[8], coingecko=entry[9], cryptocompare=entry[10], protocol=entry[11], ) if mapping: result[entry[0]] = data.serialize() # type: ignore else: result.append(data) # type: ignore return result
def _parse_full_insert(self, insert_text: str) -> AssetData: """Parses the full insert line for an asset to give information for the conflict to the user Note: In the future this needs to be different for each version May raise: - DeserializationError if the appropriate data is not found or if it can't be properly parsed. """ asset_data = self._parse_asset_data(insert_text) forked = address = decimals = protocol = None if asset_data.asset_type == AssetType.ETHEREUM_TOKEN: address, decimals, protocol = self._parse_ethereum_token_data(insert_text) else: match = self.common_asset_details_re.match(insert_text) if match is None: raise DeserializationError( f'At asset DB update could not parse common asset ' f'details data out of {insert_text}', ) forked = self._parse_optional_str(match.group(2), 'forked', insert_text) return AssetData( # types are not really proper here (except for asset_type) identifier=asset_data.identifier, name=asset_data.name, symbol=asset_data.symbol, asset_type=asset_data.asset_type, started=asset_data.started, forked=forked, swapped_for=asset_data.swapped_for, ethereum_address=address, decimals=decimals, cryptocompare=asset_data.cryptocompare, coingecko=asset_data.coingecko, protocol=protocol, )
def get_assets_with_symbol( symbol: str, asset_type: Optional[AssetType] = None ) -> List[AssetData]: # noqa: E501 """Find all asset entries that have the given symbol""" connection = GlobalDBHandler()._conn cursor = connection.cursor() query_tuples: Union[Tuple[str, str, str, str], Tuple[str, str, str, str, str]] eth_token_type = AssetType.ETHEREUM_TOKEN.serialize_for_db() # pylint: disable=no-member if asset_type is not None: asset_type_check = ' AND A.type=?' query_tuples = (symbol, eth_token_type, symbol, eth_token_type, asset_type.serialize_for_db()) # noqa: E501 else: asset_type_check = '' query_tuples = (symbol, eth_token_type, symbol, eth_token_type) querystr = f""" SELECT A.identifier, A.type, B.address, B.decimals, A.name, A.symbol, A.started, null, A.swapped_for, A.coingecko, A.cryptocompare, B.protocol from assets as A LEFT OUTER JOIN ethereum_tokens as B ON B.address = A.details_reference WHERE A.symbol=? COLLATE NOCASE AND A.type=? UNION ALL SELECT A.identifier, A.type, null, null, A.name, A.symbol, A.started, B.forked, A.swapped_for, A.coingecko, A.cryptocompare, null from assets as A LEFT OUTER JOIN common_asset_details as B ON B.asset_id = A.identifier WHERE A.symbol=? COLLATE NOCASE AND A.type!=?{asset_type_check}; """ # noqa: E501 query = cursor.execute(querystr, query_tuples) assets = [] for entry in query: asset_type = AssetType.deserialize_from_db(entry[1]) ethereum_address: Optional[ChecksumEthAddress] if asset_type == AssetType.ETHEREUM_TOKEN: ethereum_address = string_to_ethereum_address(entry[2]) else: ethereum_address = None assets.append( AssetData( identifier=entry[0], asset_type=asset_type, ethereum_address=ethereum_address, decimals=entry[3], name=entry[4], symbol=entry[5], started=entry[6], forked=entry[7], swapped_for=entry[8], coingecko=entry[9], cryptocompare=entry[10], protocol=entry[11], )) return assets
def test_get_all_asset_data_specific_ids(globaldb): btc_asset_data = AssetData( identifier='BTC', name='Bitcoin', symbol='BTC', asset_type=AssetType.OWN_CHAIN, started=Timestamp(1231006505), forked=None, swapped_for=None, ethereum_address=None, decimals=None, cryptocompare=None, coingecko='bitcoin', protocol=None, ) eth_asset_data = AssetData( identifier='ETH', name='Ethereum', symbol='ETH', asset_type=AssetType.OWN_CHAIN, started=Timestamp(1438214400), forked=None, swapped_for=None, ethereum_address=None, decimals=None, cryptocompare=None, coingecko='ethereum', protocol=None, ) asset_data = globaldb.get_all_asset_data( mapping=False, specific_ids=['BTC', 'ETH', selfkey_id, 'BIDR'], ) assert asset_data == [ selfkey_asset_data, bidr_asset_data, btc_asset_data, eth_asset_data, ] asset_data = globaldb.get_all_asset_data( mapping=True, serialized=True, specific_ids=['BTC', 'ETH', selfkey_id, 'BIDR'], ) assert asset_data == { selfkey_id: selfkey_asset_data.serialize(), 'BIDR': bidr_asset_data.serialize(), 'BTC': btc_asset_data.serialize(), 'ETH': eth_asset_data.serialize(), } asset_data = globaldb.get_all_asset_data( mapping=True, serialized=False, specific_ids=['BTC', 'ETH', selfkey_id, 'BIDR'], ) assert asset_data == { selfkey_id: selfkey_asset_data, 'BIDR': bidr_asset_data, 'BTC': btc_asset_data, 'ETH': eth_asset_data, } # unknown ids assert globaldb.get_all_asset_data( mapping=False, specific_ids=['INVALIDIDSS!@!1', 'DSAD#@$DSAD@EAS'], ) == [] assert globaldb.get_all_asset_data( mapping=True, specific_ids=['INVALIDIDSS!@!1', 'DSAD#@$DSAD@EAS'], ) == {} # empty list assert globaldb.get_all_asset_data( mapping=False, specific_ids=[], ) == [] assert globaldb.get_all_asset_data( mapping=True, specific_ids=[], ) == {}
def test_get_asset_with_symbol(globaldb): # both categories of assets asset_data = globaldb.get_assets_with_symbol('KEY') bihukey_address = string_to_ethereum_address( '0x4Cd988AfBad37289BAAf53C13e98E2BD46aAEa8c') aave_address = string_to_ethereum_address( '0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9') renbtc_address = string_to_ethereum_address( '0xEB4C2781e4ebA804CE9a9803C67d0893436bB27D') assert asset_data == [ selfkey_asset_data, AssetData( identifier=ethaddress_to_identifier(bihukey_address), name='Bihu KEY', symbol='KEY', asset_type=AssetType.ETHEREUM_TOKEN, started=1507822985, forked=None, swapped_for=None, ethereum_address=bihukey_address, decimals=18, cryptocompare='BIHU', coingecko='key', protocol=None, ), AssetData( identifier='KEY-3', name='KeyCoin', symbol='KEY', asset_type=AssetType.OWN_CHAIN, started=1405382400, forked=None, swapped_for=None, ethereum_address=None, decimals=None, cryptocompare='KEYC', coingecko='', protocol=None, ) ] # only non-ethereum token assert globaldb.get_assets_with_symbol('BIDR') == [bidr_asset_data] # only ethereum token assert globaldb.get_assets_with_symbol('AAVE') == [ AssetData( identifier=ethaddress_to_identifier(aave_address), name='Aave Token', symbol='AAVE', asset_type=AssetType.ETHEREUM_TOKEN, started=1600970788, forked=None, swapped_for=None, ethereum_address=aave_address, decimals=18, cryptocompare=None, coingecko='aave', protocol=None, ) ] # finally non existing asset assert globaldb.get_assets_with_symbol('DASDSADSDSDSAD') == [] # also check that symbol comparison is case insensitive for many arg combinations expected_renbtc = [ AssetData( identifier=ethaddress_to_identifier(renbtc_address), name='renBTC', symbol='renBTC', asset_type=AssetType.ETHEREUM_TOKEN, started=1585090944, forked=None, swapped_for=None, ethereum_address=renbtc_address, decimals=8, cryptocompare=None, coingecko='renbtc', protocol=None, ) ] for x in itertools.product(('ReNbTc', 'renbtc', 'RENBTC', 'rEnBTc'), (None, AssetType.ETHEREUM_TOKEN)): # noqa: E501 assert globaldb.get_assets_with_symbol(*x) == expected_renbtc
from rotkehlchen.serialization.deserialize import deserialize_asset_amount from rotkehlchen.tests.fixtures.globaldb import create_globaldb from rotkehlchen.tests.utils.factories import make_ethereum_address from rotkehlchen.tests.utils.globaldb import INITIAL_TOKENS from rotkehlchen.typing import Location, Price, Timestamp, TradeType selfkey_address = string_to_ethereum_address( '0x4CC19356f2D37338b9802aa8E8fc58B0373296E7') selfkey_id = ethaddress_to_identifier(selfkey_address) selfkey_asset_data = AssetData( identifier=selfkey_id, name='Selfkey', symbol='KEY', asset_type=AssetType.ETHEREUM_TOKEN, started=Timestamp(1508803200), forked=None, swapped_for=None, ethereum_address=selfkey_address, decimals=18, cryptocompare=None, coingecko='selfkey', protocol=None, ) bidr_asset_data = AssetData( identifier='BIDR', name='Binance IDR Stable Coin', symbol='BIDR', asset_type=AssetType.BINANCE_TOKEN, started=Timestamp(1593475200), forked=None, swapped_for=None, ethereum_address=None,
def get_asset_data( identifier: str, form_with_incomplete_data: bool, ) -> Optional[AssetData]: """Get all details of a single asset by identifier Returns None if identifier can't be matched to an asset """ cursor = GlobalDBHandler()._conn.cursor() query = cursor.execute( 'SELECT identifier, type, name, symbol, started, swapped_for, coingecko, ' 'cryptocompare, details_reference from assets WHERE identifier=?;', (identifier, ), ) result = query.fetchone() if result is None: return None # Since comparison is case insensitive let's return original identifier saved_identifier = result[0] # get the identifier as saved in the DB. db_serialized_type = result[1] name = result[2] symbol = result[3] started = result[4] swapped_for = result[5] coingecko = result[6] cryptocompare = result[7] details_reference = result[8] forked = None decimals = None protocol = None ethereum_address = None try: asset_type = AssetType.deserialize_from_db(db_serialized_type) except DeserializationError as e: log.debug( f'Failed to read asset {identifier} from the DB due to ' f'{str(e)}. Skipping', ) return None if asset_type == AssetType.ETHEREUM_TOKEN: ethereum_address = details_reference cursor.execute( 'SELECT decimals, protocol from ethereum_tokens ' 'WHERE address=?', (ethereum_address, ), ) result = query.fetchone() if result is None: log.error( f'Found token {saved_identifier} in the DB assets table but not ' f'in the token details table.', ) return None decimals = result[0] protocol = result[1] missing_basic_data = name is None or symbol is None or decimals is None if missing_basic_data and form_with_incomplete_data is False: log.debug( f'Considering ethereum token with address {details_reference} ' f'as unknown since its missing either decimals or name or symbol', ) return None else: cursor = GlobalDBHandler()._conn.cursor() query = cursor.execute( 'SELECT forked FROM common_asset_details WHERE asset_id = ?;', (details_reference, ), ) result = query.fetchone() if result is None: log.error( f'Found asset {saved_identifier} in the DB assets table but not ' f'in the common asset details table.', ) return None forked = result[0] return AssetData( identifier=saved_identifier, name=name, symbol=symbol, asset_type=asset_type, started=started, forked=forked, swapped_for=swapped_for, ethereum_address=ethereum_address, decimals=decimals, coingecko=coingecko, cryptocompare=cryptocompare, protocol=protocol, )
INSERT INTO ethereum_tokens(address, decimals, protocol) VALUES( "0xD178b20c6007572bD1FD01D205cC20D32B4A6015", 18, NULL ); INSERT INTO assets(identifier,type, name, symbol, started, swapped_for, coingecko, cryptocompare, details_reference) VALUES("_ceth_0xD178b20c6007572bD1FD01D205cC20D32B4A6015", "C", "Aidus", "AID" , 123, NULL, NULL, "AIDU", "0xD178b20c6007572bD1FD01D205cC20D32B4A6015"); """, AssetData( identifier='_ceth_0xD178b20c6007572bD1FD01D205cC20D32B4A6015', name='Aidus', symbol='AID', asset_type=AssetType.ETHEREUM_TOKEN, started=Timestamp(123), forked=None, swapped_for=None, ethereum_address=string_to_ethereum_address( '0xD178b20c6007572bD1FD01D205cC20D32B4A6015' ), # noqa: E501 decimals=18, cryptocompare='AIDU', coingecko=None, protocol=None, ), None, ), ( """ INSERT INTO assets(identifier,type, name, symbol, started, swapped_for, coingecko, cryptocompare, details_reference) VALUES("121-ada-FADS-as", "F", "A name", "SYMBOL" , NULL, NULL, "", "", "121-ada-FADS-as");