Example #1
0
def test_upgrade_v1_v2(globaldb):
    # at this point upgrade should have happened
    assert globaldb.get_setting_value('version', None) == 2

    for identifier, entry in globaldb.get_all_asset_data(mapping=True, serialized=False).items():
        if entry.asset_type == AssetType.ETHEREUM_TOKEN:
            assert identifier == ethaddress_to_identifier(entry.ethereum_address)

        swapped_for = entry.swapped_for

        # check the swapped_for key also changed for one we know
        if entry.name == 'Aurora DAO':
            assert entry.swapped_for == strethaddress_to_identifier('0xB705268213D593B8FD88d3FDEFF93AFF5CbDcfAE')  # noqa: E501

        if swapped_for and swapped_for not in ('AM', 'PHB', 'FIRO', 'DIVI', 'SCRT', 'HAI', 'MED', 'NOAHP', 'VET', 'XDC'):  # noqa: E501
            assert entry.swapped_for.startswith(ETHEREUM_DIRECTIVE)

    # Check some swapped for that we know should have changed. DIVX -> DIVI
    asset_data = globaldb.get_asset_data(strethaddress_to_identifier('0x13f11C9905A08ca76e3e853bE63D4f0944326C72'), form_with_incomplete_data=True)  # noqa: E501
    assert asset_data.swapped_for == 'DIVI'
    # GNT -> GLM
    asset_data = globaldb.get_asset_data(strethaddress_to_identifier('0xa74476443119A942dE498590Fe1f2454d7D4aC0d'), form_with_incomplete_data=True)  # noqa: E501
    assert asset_data.swapped_for == strethaddress_to_identifier('0x7DD9c5Cba05E151C895FDe1CF355C9A1D5DA6429')  # noqa: E501

    # Make sure the number of assets remained the same
    cursor = globaldb._conn.cursor()
    assert cursor.execute('SELECT COUNT(*) from assets').fetchone()[0] == 1886
    assert cursor.execute('SELECT COUNT(*) from user_owned_assets').fetchone()[0] == 105
    # Make sure that populated underlying assets are still there
    query = cursor.execute('SELECT * from underlying_tokens_list;')
    assert query.fetchall() == [
        ('0x42Fa37aC7c115bf17ca5DDfcb94b73b91B10B61B', '0.5', '0xBBc2AE13b23d715c30720F079fcd9B4a74093505'),  # noqa: E501
        ('0x647C4CD779043b3f00a4ccdec550F35Dd18792b3', '0.5', '0xBBc2AE13b23d715c30720F079fcd9B4a74093505'),  # noqa: E501
    ]
    # Make sure that the previous custom assets are still in the DB
    query = cursor.execute(
        'SELECT COUNT(*) from assets where identifier IN (?, ?, ?, ?);',
        ('_ceth_0x35bD01FC9d6D5D81CA9E055Db88Dc49aa2c699A8',
         '_ceth_0xBBc2AE13b23d715c30720F079fcd9B4a74093505',
         '_ceth_0x42Fa37aC7c115bf17ca5DDfcb94b73b91B10B61B',
         '_ceth_0x647C4CD779043b3f00a4ccdec550F35Dd18792b3',
         ),
    )
    assert query.fetchone()[0] == 4
    query = cursor.execute(
        'SELECT COUNT(*) from ethereum_tokens where address IN (?, ?, ?, ?);',
        ('0x35bD01FC9d6D5D81CA9E055Db88Dc49aa2c699A8',
         '0xBBc2AE13b23d715c30720F079fcd9B4a74093505',
         '0x42Fa37aC7c115bf17ca5DDfcb94b73b91B10B61B',
         '0x647C4CD779043b3f00a4ccdec550F35Dd18792b3',
         ),
    )
    assert query.fetchone()[0] == 4
Example #2
0
def asset_from_ftx(ftx_name: str) -> Asset:
    """May raise:
    - DeserializationError
    - UnsupportedAsset
    - UnknownAsset
    """
    if not isinstance(ftx_name, str):
        raise DeserializationError(
            f'Got non-string type {type(ftx_name)} for ftx asset')

    if ftx_name in UNSUPPORTED_FTX_ASSETS:
        raise UnsupportedAsset(ftx_name)

    if ftx_name == 'SRM_LOCKED':
        name = strethaddress_to_identifier(
            '0x476c5E26a75bd202a9683ffD34359C0CC15be0fF')  # SRM
    else:
        name = FTX_TO_WORLD.get(ftx_name, ftx_name)
    return symbol_to_asset_or_token(name)
Example #3
0
    def add_ethtoken_initialization(self, var_name: str, address: str) -> str:
        generated_text = ''
        token = self.globaldb.get_ethereum_token(address=address)
        var_swappedfor = 'None'
        if token.swapped_for:
            if token.swapped_for in self.id_to_variable:
                var_swappedfor = self.id_to_variable[token.swapped_for]
            else:
                var_swappedfor = f'{strethaddress_to_identifier(address).upper()}_swappedfor'
                generated_text += self.add_asset_initialization(var_swappedfor, token.swapped_for.identifier)  # noqa: E501

        name = f'"{token.name}"' if token.name else None
        symbol = f'\'{token.symbol}\'' if token.symbol else None
        started = f'Timestamp({token.started})' if token.started else None
        coingecko = f'\'{token.coingecko}\'' if token.coingecko else None
        cryptocompare = f'\'{token.cryptocompare}\'' if token.cryptocompare else None
        protocol = f'\'{token.protocol}\'' if token.protocol else None
        if token.underlying_tokens is not None:
            raise ValueError(
                f'Found token {address} with underlying tokens. Not supported '
                f'at constants asset generation yet. Can implement when needed.',
            )
        generated_text += (
            f'{var_name} = EthereumToken.initialize(\n'
            f'    address=string_to_ethereum_address(\'{address}\'),\n'
            f'    decimals={token.decimals},\n'
            f'    name={name},\n'
            f'    symbol={symbol},\n'
            f'    started={started},\n'
            f'    swapped_for={var_swappedfor},\n'
            f'    coingecko={coingecko},\n'
            f'    cryptocompare={cryptocompare},\n'
            f'    protocol={protocol},\n'
            f')\n'
            f'CONSTANT_ASSETS.append({var_name})\n'
        )
        identifier = strethaddress_to_identifier(address)
        if identifier in self.id_to_variable:
            raise ValueError(f'Token with identifier {identifier} and varname {var_name} is defined twice')  # noqa: E501
        self.id_to_variable[identifier] = var_name
        return generated_text
Example #4
0
def test_asset_and_price_not_found_in_history_processing(accountant):
    """
    Make sure that in history processing if no price is found for a trade it's skipped
    and an error is logged.

    Regression for https://github.com/rotki/rotki/issues/432
    """
    fgp_identifier = strethaddress_to_identifier(
        '0xd9A8cfe21C232D485065cb62a96866799d4645f7')
    bad_trades = [{
        'timestamp': 1492685761,
        'base_asset': fgp_identifier,
        'quote_asset': 'BTC',
        'trade_type': 'buy',
        'rate': '0.100',
        'fee': '0.15',
        'fee_currency': fgp_identifier,
        'amount': 2.5,
        'location': 'kraken',
    }]
    result = accounting_history_process(
        accountant=accountant,
        start_ts=0,
        end_ts=1514764799,  # 31/12/2017
        history_list=bad_trades,
        loans_list=[],
        asset_movements_list=[],
        eth_transaction_list=[],
        margin_list=[],
    )
    result = result['overview']
    errors = accountant.msg_aggregator.consume_errors()
    assert len(errors) == 1
    assert 'due to inability to find a price at that point in time' in errors[
        0]
    # assert 'due to an asset unknown to cryptocompare being involved' in errors[1]
    assert FVal(result['total_profit_loss']) == FVal('0')
def test_simple_update(rotkehlchen_api_server, globaldb):
    """Test that the happy case of update works.

    - Test that up_to_version argument works
    - Test that only versions above current local are applied
    - Test that versions with min/max schema mismatch are skipped
    """
    async_query = random.choice([False, True])
    rotki = rotkehlchen_api_server.rest_api.rotkehlchen
    update_3 = """INSERT INTO ethereum_tokens(address, decimals, protocol) VALUES("0xC2FEC534c461c45533e142f724d0e3930650929c", 18, NULL);INSERT INTO assets(identifier,type, name, symbol,started, swapped_for, coingecko, cryptocompare, details_reference) VALUES("_ceth_0xC2FEC534c461c45533e142f724d0e3930650929c", "C", "AKB token", "AKB",123, NULL,   NULL, "AIDU", "0xC2FEC534c461c45533e142f724d0e3930650929c");
*
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");INSERT INTO common_asset_details(asset_id, forked) VALUES("121-ada-FADS-as", "BTC");
*
UPDATE assets SET name="Ευρώ" WHERE identifier="EUR";
INSERT INTO assets(identifier,type,name,symbol,started, swapped_for, coingecko, cryptocompare, details_reference) VALUES("EUR", "A","Ευρώ","EUR",NULL, NULL,NULL,NULL, "EUR");INSERT INTO common_asset_details(asset_id, forked) VALUES("EUR", NULL);
    """  # noqa: E501
    update_patch = mock_asset_updates(
        original_requests_get=requests.get,
        latest=999999996,
        updates={
            "999999991": {
                "changes": 1,
                "min_schema_version": GLOBAL_DB_VERSION,
                "max_schema_version": GLOBAL_DB_VERSION,
            },
            "999999992": {
                "changes": 1,
                "min_schema_version": GLOBAL_DB_VERSION,
                "max_schema_version": GLOBAL_DB_VERSION,
            },
            "999999993": {
                "changes": 3,
                "min_schema_version": GLOBAL_DB_VERSION,
                "max_schema_version": GLOBAL_DB_VERSION,
            },
            "999999994": {
                "changes": 5,
                "min_schema_version": GLOBAL_DB_VERSION + 1,
                "max_schema_version": GLOBAL_DB_VERSION - 1,
            },
            "999999995": {
                "changes": 5,
                "min_schema_version": GLOBAL_DB_VERSION,
                "max_schema_version": GLOBAL_DB_VERSION,
            },
            "999999996": {
                "changes": 5,
                "min_schema_version": GLOBAL_DB_VERSION,
                "max_schema_version": GLOBAL_DB_VERSION,
            },
        },
        sql_actions={
            "999999991": "",
            "999999992": "",
            "999999993": update_3,
            "999999994": "",
            "999999995": ""
        },  # noqa: E501
    )
    globaldb.add_setting_value(ASSETS_VERSION_KEY, 999999992)
    with update_patch:
        response = requests.get(
            api_url_for(
                rotkehlchen_api_server,
                'assetupdatesresource',
            ),
            json={'async_query': async_query},
        )
        if async_query:
            task_id = assert_ok_async_response(response)
            outcome = wait_for_async_task(
                rotkehlchen_api_server,
                task_id,
            )
            result = outcome['result']
            assert outcome['message'] == ''
        else:
            result = assert_proper_response_with_result(response)
        assert result['local'] == 999999992
        assert result['remote'] == 999999996
        assert result[
            'new_changes'] == 13  # changes from 99[3 + 4 + 6], skipping 5

        response = requests.post(
            api_url_for(
                rotkehlchen_api_server,
                'assetupdatesresource',
            ),
            json={
                'async_query': async_query,
                'up_to_version': 999999995
            },
        )
        if async_query:
            task_id = assert_ok_async_response(response)
            outcome = wait_for_async_task(
                rotkehlchen_api_server,
                task_id,
            )
            assert outcome['message'] == ''
            result = outcome['result']
        else:
            result = assert_proper_response_with_result(response)

        errors = rotki.msg_aggregator.consume_errors()
        warnings = rotki.msg_aggregator.consume_warnings()
        assert len(errors) == 0, f'Found errors: {errors}'
        assert len(warnings) == 1
        assert 'Skipping assets update 999999994 since it requires a min schema of' in warnings[
            0]

        assert result is True
        assert globaldb.get_setting_value(ASSETS_VERSION_KEY,
                                          None) == 999999995
        new_token = EthereumToken('0xC2FEC534c461c45533e142f724d0e3930650929c')
        assert new_token.identifier == strethaddress_to_identifier(
            '0xC2FEC534c461c45533e142f724d0e3930650929c')  # noqa: E501
        assert new_token.name == 'AKB token'
        assert new_token.symbol == 'AKB'
        assert new_token.asset_type == AssetType.ETHEREUM_TOKEN
        assert new_token.started == 123
        assert new_token.forked is None
        assert new_token.swapped_for is None
        assert new_token.coingecko is None
        assert new_token.cryptocompare == 'AIDU'
        assert new_token.ethereum_address == '0xC2FEC534c461c45533e142f724d0e3930650929c'
        assert new_token.decimals == 18
        assert new_token.protocol is None

        new_asset = Asset('121-ada-FADS-as')
        assert new_asset.identifier == '121-ada-FADS-as'
        assert new_asset.name == 'A name'
        assert new_asset.symbol == 'SYMBOL'
        assert new_asset.asset_type == AssetType.COUNTERPARTY_TOKEN
        assert new_asset.started is None
        assert new_asset.forked == 'BTC'
        assert new_asset.swapped_for is None
        assert new_asset.coingecko == ''
        assert new_asset.cryptocompare == ''

        assert Asset('EUR').name == 'Ευρώ'
def test_foreignkey_conflict(rotkehlchen_api_server, globaldb):
    """Test that when a conflict that's not solvable happens the entry is ignored

    One such case is when the update of an asset would violate a foreign key constraint"""
    async_query = random.choice([False, True])
    rotki = rotkehlchen_api_server.rest_api.rotkehlchen
    update_1 = """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");INSERT INTO common_asset_details(asset_id, forked) VALUES("121-ada-FADS-as", "BTC");
*
UPDATE assets SET swapped_for="_ceth_0xA8d35739EE92E69241A2Afd9F513d41021A07972" WHERE identifier="_ceth_0xa74476443119A942dE498590Fe1f2454d7D4aC0d";
INSERT INTO ethereum_tokens(address, decimals, protocol) VALUES("0xa74476443119A942dE498590Fe1f2454d7D4aC0d", 18, NULL);INSERT INTO assets(identifier,type, name, symbol,started, swapped_for, coingecko, cryptocompare, details_reference) VALUES("_ceth_0xa74476443119A942dE498590Fe1f2454d7D4aC0d", "C", "Golem", "GNT", 1478810650, "_ceth_0xA8d35739EE92E69241A2Afd9F513d41021A07972", "golem", NULL, "0xa74476443119A942dE498590Fe1f2454d7D4aC0d");
    """  # noqa: E501
    update_patch = mock_asset_updates(
        original_requests_get=requests.get,
        latest=999999991,
        updates={
            "999999991": {
                "changes": 2,
                "min_schema_version": GLOBAL_DB_VERSION,
                "max_schema_version": GLOBAL_DB_VERSION,
            }
        },
        sql_actions={"999999991": update_1},
    )
    globaldb.add_setting_value(ASSETS_VERSION_KEY, 999999990)
    start_assets_num = len(globaldb.get_all_asset_data(mapping=False))
    with update_patch:
        response = requests.get(
            api_url_for(
                rotkehlchen_api_server,
                'assetupdatesresource',
            ),
            json={'async_query': async_query},
        )
        if async_query:
            task_id = assert_ok_async_response(response)
            outcome = wait_for_async_task(
                rotkehlchen_api_server,
                task_id,
            )
            result = outcome['result']
            assert outcome['message'] == ''
        else:
            result = assert_proper_response_with_result(response)
        assert result['local'] == 999999990
        assert result['remote'] == 999999991
        assert result['new_changes'] == 2

        response = requests.post(
            api_url_for(
                rotkehlchen_api_server,
                'assetupdatesresource',
            ),
            json={'async_query': async_query},
        )
        if async_query:
            task_id = assert_ok_async_response(response)
            outcome = wait_for_async_task(
                rotkehlchen_api_server,
                task_id,
            )
            assert outcome[
                'message'] == 'Found conflicts during assets upgrade'
            result = outcome['result']
        else:
            result = assert_proper_response_with_result(
                response,
                message='Found conflicts during assets upgrade',
                status_code=HTTPStatus.CONFLICT,
            )

        # Make sure that nothing was committed
        assert globaldb.get_setting_value(ASSETS_VERSION_KEY,
                                          None) == 999999990
        assert len(
            globaldb.get_all_asset_data(mapping=False)) == start_assets_num
        with pytest.raises(UnknownAsset):
            Asset('121-ada-FADS-as')
        errors = rotki.msg_aggregator.consume_errors()
        warnings = rotki.msg_aggregator.consume_warnings()
        assert len(errors) == 0, f'Found errors: {errors}'
        assert len(warnings) == 0, f'Found warnings: {warnings}'
        # See that we get a conflict
        expected_result = [{
            'identifier': '_ceth_0xa74476443119A942dE498590Fe1f2454d7D4aC0d',
            'local': {
                'name': 'Golem',
                'symbol': 'GNT',
                'asset_type': 'ethereum token',
                'started': 1478810650,
                'forked': None,
                'swapped_for':
                '_ceth_0x7DD9c5Cba05E151C895FDe1CF355C9A1D5DA6429',
                'ethereum_address':
                '0xa74476443119A942dE498590Fe1f2454d7D4aC0d',
                'decimals': 18,
                'cryptocompare': None,
                'coingecko': 'golem',
                'protocol': None,
            },
            'remote': {
                'name': 'Golem',
                'symbol': 'GNT',
                'asset_type': 'ethereum token',
                'started': 1478810650,
                'forked': None,
                'swapped_for':
                '_ceth_0xA8d35739EE92E69241A2Afd9F513d41021A07972',
                'ethereum_address':
                '0xa74476443119A942dE498590Fe1f2454d7D4aC0d',
                'decimals': 18,
                'cryptocompare': None,
                'coingecko': 'golem',
                'protocol': None,
            },
        }]
        assert result == expected_result

        # now try the update again but specify the conflicts resolution
        conflicts = {
            '_ceth_0xa74476443119A942dE498590Fe1f2454d7D4aC0d': 'remote'
        }
        response = requests.post(
            api_url_for(
                rotkehlchen_api_server,
                'assetupdatesresource',
            ),
            json={
                'async_query': async_query,
                'conflicts': conflicts
            },
        )
        if async_query:
            task_id = assert_ok_async_response(response)
            outcome = wait_for_async_task(
                rotkehlchen_api_server,
                task_id,
            )
            assert outcome['message'] == ''
            result = outcome['result']
        else:
            result = assert_proper_response_with_result(
                response,
                message='',
                status_code=HTTPStatus.OK,
            )

        # check new asset was added and conflict was ignored with an error due to
        # inability to do anything with the missing swapped_for
        assert result is True
        assert globaldb.get_setting_value(ASSETS_VERSION_KEY,
                                          None) == 999999991
        gnt = EthereumToken('0xa74476443119A942dE498590Fe1f2454d7D4aC0d')
        assert gnt.identifier == strethaddress_to_identifier(
            '0xa74476443119A942dE498590Fe1f2454d7D4aC0d')  # noqa: E501
        assert gnt.name == 'Golem'
        assert gnt.symbol == 'GNT'
        assert gnt.asset_type == AssetType.ETHEREUM_TOKEN
        assert gnt.started == 1478810650
        assert gnt.forked is None
        assert gnt.swapped_for == A_GLM.identifier
        assert gnt.coingecko == 'golem'
        assert gnt.cryptocompare is None
        assert gnt.ethereum_address == '0xa74476443119A942dE498590Fe1f2454d7D4aC0d'
        assert gnt.decimals == 18
        assert gnt.protocol is None

        new_asset = Asset('121-ada-FADS-as')
        assert new_asset.identifier == '121-ada-FADS-as'
        assert new_asset.name == 'A name'
        assert new_asset.symbol == 'SYMBOL'
        assert new_asset.asset_type == AssetType.COUNTERPARTY_TOKEN
        assert new_asset.started is None
        assert new_asset.forked == 'BTC'
        assert new_asset.swapped_for is None
        assert new_asset.coingecko == ''
        assert new_asset.cryptocompare == ''

        errors = rotki.msg_aggregator.consume_errors()
        warnings = rotki.msg_aggregator.consume_warnings()
        assert len(errors) == 0, f'Found errors: {errors}'
        assert len(warnings) == 1
        assert f'Failed to resolve conflict for {gnt.identifier} in the DB during the v999999991 assets update. Skipping entry' in warnings[
            0]  # noqa: E501
def test_update_conflicts(rotkehlchen_api_server, globaldb):
    """Test that conflicts in an asset update are handled properly"""
    async_query = random.choice([False, True])
    rotki = rotkehlchen_api_server.rest_api.rotkehlchen
    update_1 = """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");INSERT INTO common_asset_details(asset_id, forked) VALUES("121-ada-FADS-as", "BTC");
*
INSERT INTO ethereum_tokens(address, decimals, protocol) VALUES("0x6B175474E89094C44Da98b954EedeAC495271d0F", 8, "maker");INSERT INTO assets(identifier,type, name, symbol,started, swapped_for, coingecko, cryptocompare, details_reference) VALUES("_ceth_0x6B175474E89094C44Da98b954EedeAC495271d0F", "C", "New Multi Collateral DAI", "NDAI", 1573672677, NULL, "dai", NULL, "0x6B175474E89094C44Da98b954EedeAC495271d0F");
*
INSERT INTO assets(identifier,type,name,symbol,started, swapped_for, coingecko, cryptocompare, details_reference) VALUES("DASH", "B","Dash","DASH",1337, NULL, "dash-coingecko", NULL, "DASH");INSERT INTO common_asset_details(asset_id, forked) VALUES("DASH", "BTC");
*
    """  # noqa: E501
    update_patch = mock_asset_updates(
        original_requests_get=requests.get,
        latest=999999991,
        updates={
            "999999991": {
                "changes": 3,
                "min_schema_version": GLOBAL_DB_VERSION,
                "max_schema_version": GLOBAL_DB_VERSION,
            }
        },
        sql_actions={"999999991": update_1},
    )
    globaldb.add_setting_value(ASSETS_VERSION_KEY, 999999990)
    start_assets_num = len(globaldb.get_all_asset_data(mapping=False))
    with update_patch:
        response = requests.get(
            api_url_for(
                rotkehlchen_api_server,
                'assetupdatesresource',
            ),
            json={'async_query': async_query},
        )
        if async_query:
            task_id = assert_ok_async_response(response)
            outcome = wait_for_async_task(
                rotkehlchen_api_server,
                task_id,
            )
            result = outcome['result']
            assert outcome['message'] == ''
        else:
            result = assert_proper_response_with_result(response)
        assert result['local'] == 999999990
        assert result['remote'] == 999999991
        assert result['new_changes'] == 3

        response = requests.post(
            api_url_for(
                rotkehlchen_api_server,
                'assetupdatesresource',
            ),
            json={'async_query': async_query},
        )
        if async_query:
            task_id = assert_ok_async_response(response)
            outcome = wait_for_async_task(
                rotkehlchen_api_server,
                task_id,
            )
            assert outcome[
                'message'] == 'Found conflicts during assets upgrade'
            result = outcome['result']
        else:
            result = assert_proper_response_with_result(
                response,
                message='Found conflicts during assets upgrade',
                status_code=HTTPStatus.CONFLICT,
            )

        # Make sure that nothing was committed
        assert globaldb.get_setting_value(ASSETS_VERSION_KEY,
                                          None) == 999999990
        assert len(
            globaldb.get_all_asset_data(mapping=False)) == start_assets_num
        with pytest.raises(UnknownAsset):
            Asset('121-ada-FADS-as')
        errors = rotki.msg_aggregator.consume_errors()
        warnings = rotki.msg_aggregator.consume_warnings()
        assert len(errors) == 0, f'Found errors: {errors}'
        assert len(warnings) == 0, f'Found warnings: {warnings}'
        # See that we get two conflicts
        expected_result = [{
            'identifier': '_ceth_0x6B175474E89094C44Da98b954EedeAC495271d0F',
            'local': {
                'name': 'Multi Collateral Dai',
                'symbol': 'DAI',
                'asset_type': 'ethereum token',
                'started': 1573672677,
                'forked': None,
                'swapped_for': None,
                'ethereum_address':
                '0x6B175474E89094C44Da98b954EedeAC495271d0F',
                'decimals': 18,
                'cryptocompare': None,
                'coingecko': 'dai',
                'protocol': None,
            },
            'remote': {
                'name': 'New Multi Collateral DAI',
                'symbol': 'NDAI',
                'asset_type': 'ethereum token',
                'started': 1573672677,
                'forked': None,
                'swapped_for': None,
                'ethereum_address':
                '0x6B175474E89094C44Da98b954EedeAC495271d0F',
                'decimals': 8,
                'cryptocompare': None,
                'coingecko': 'dai',
                'protocol': 'maker',
            },
        }, {
            'identifier': 'DASH',
            'local': {
                'name': 'Dash',
                'symbol': 'DASH',
                'asset_type': 'own chain',
                'started': 1390095618,
                'forked': None,
                'swapped_for': None,
                'ethereum_address': None,
                'decimals': None,
                'cryptocompare': None,
                'coingecko': 'dash',
                'protocol': None,
            },
            'remote': {
                'name': 'Dash',
                'symbol': 'DASH',
                'asset_type': 'own chain',
                'started': 1337,
                'forked': 'BTC',
                'swapped_for': None,
                'ethereum_address': None,
                'decimals': None,
                'cryptocompare': None,
                'coingecko': 'dash-coingecko',
                'protocol': None,
            },
        }]
        assert result == expected_result

        # now try the update again but specify the conflicts resolution
        conflicts = {
            '_ceth_0x6B175474E89094C44Da98b954EedeAC495271d0F': 'remote',
            'DASH': 'local'
        }
        response = requests.post(
            api_url_for(
                rotkehlchen_api_server,
                'assetupdatesresource',
            ),
            json={
                'async_query': async_query,
                'conflicts': conflicts
            },
        )
        if async_query:
            task_id = assert_ok_async_response(response)
            outcome = wait_for_async_task(
                rotkehlchen_api_server,
                task_id,
            )
            assert outcome['message'] == ''
            result = outcome['result']
        else:
            result = assert_proper_response_with_result(
                response,
                message='',
                status_code=HTTPStatus.OK,
            )

        # check conflicts were solved as per the given choices and new asset also added
        assert result is True
        assert globaldb.get_setting_value(ASSETS_VERSION_KEY,
                                          None) == 999999991
        errors = rotki.msg_aggregator.consume_errors()
        warnings = rotki.msg_aggregator.consume_warnings()
        assert len(errors) == 0, f'Found errors: {errors}'
        assert len(warnings) == 0, f'Found warnings: {warnings}'
        dai = EthereumToken('0x6B175474E89094C44Da98b954EedeAC495271d0F')
        assert dai.identifier == strethaddress_to_identifier(
            '0x6B175474E89094C44Da98b954EedeAC495271d0F')  # noqa: E501
        assert dai.name == 'New Multi Collateral DAI'
        assert dai.symbol == 'NDAI'
        assert dai.asset_type == AssetType.ETHEREUM_TOKEN
        assert dai.started == 1573672677
        assert dai.forked is None
        assert dai.swapped_for is None
        assert dai.coingecko == 'dai'
        assert dai.cryptocompare is None
        assert dai.ethereum_address == '0x6B175474E89094C44Da98b954EedeAC495271d0F'
        assert dai.decimals == 8
        assert dai.protocol == 'maker'

        dash = Asset('DASH')
        assert dash.identifier == 'DASH'
        assert dash.name == 'Dash'
        assert dash.symbol == 'DASH'
        assert dash.asset_type == AssetType.OWN_CHAIN
        assert dash.started == 1390095618
        assert dash.forked is None
        assert dash.swapped_for is None
        assert dash.coingecko == 'dash'
        assert dash.cryptocompare is None

        new_asset = Asset('121-ada-FADS-as')
        assert new_asset.identifier == '121-ada-FADS-as'
        assert new_asset.name == 'A name'
        assert new_asset.symbol == 'SYMBOL'
        assert new_asset.asset_type == AssetType.COUNTERPARTY_TOKEN
        assert new_asset.started is None
        assert new_asset.forked == 'BTC'
        assert new_asset.swapped_for is None
        assert new_asset.coingecko == ''
        assert new_asset.cryptocompare == ''
Example #8
0
            weight=FVal(entry[1]),
        )


WORLD_TO_BITTREX = {
    # In Rotkehlchen Bitswift is BITS-2 but in Bittrex it's BITS
    'BITS-2':
    'BITS',
    # In Rotkehlchen NuBits is USNBT but in Bittrex it's NBT
    'USNBT':
    'NBT',
    # In Rotkehlchen BTM-2 is Bytom but in Bittrex it's BTM
    'BTM-2':
    'BTM',
    # Bittrex PI shoould map to rotki's PCHAIN
    strethaddress_to_identifier('0xB9bb08AB7E9Fa0A1356bd4A39eC0ca267E03b0b3'):
    'PI',
    # Bittrex PLA should map to rotki's PlayChip
    strethaddress_to_identifier('0x0198f46f520F33cd4329bd4bE380a25a90536CD5'):
    'PLA',
    # In Rotkehlchen LUNA-2 is Terra Luna but in Bittrex it's LUNA
    'LUNA-2':
    'LUNA',
    # WASP in binance maps to WorldWideAssetExchange in rotki
    # In Rotkehlchen WorldWideAssetExchange is WAX but in Bittrex it's WASP
    strethaddress_to_identifier('0x39Bb259F66E1C59d5ABEF88375979b4D20D98022'):
    'WAXP',
    # In Rotkehlchen Validity is RADS, the old name but in Bittrex it's VAL
    'RADS':
    'VAL',
    # make sure bittrex matches ADX latest contract
Example #9
0
if TYPE_CHECKING:
    from rotkehlchen.chain.ethereum.typing import CustomEthereumTokenWithIdentifier

WORLD_TO_BITTREX = {
    # In Rotkehlchen Bitswift is BITS-2 but in Bittrex it's BITS
    'BITS-2':
    'BITS',
    # In Rotkehlchen NuBits is USNBT but in Bittrex it's NBT
    'USNBT':
    'NBT',
    # In Rotkehlchen BTM-2 is Bytom but in Bittrex it's BTM
    'BTM-2':
    'BTM',
    # Bittrex PI shoould map to rotki's PCHAIN
    strethaddress_to_identifier('0xB9bb08AB7E9Fa0A1356bd4A39eC0ca267E03b0b3'):
    'PI',
    # Bittrex PLA should map to rotki's PlayChip
    strethaddress_to_identifier('0x0198f46f520F33cd4329bd4bE380a25a90536CD5'):
    'PLA',
    # In Rotkehlchen LUNA-2 is Terra Luna but in Bittrex it's LUNA
    'LUNA-2':
    'LUNA',
    # WASP in binance maps to WorldWideAssetExchange in rotki
    # In Rotkehlchen WorldWideAssetExchange is WAX but in Bittrex it's WASP
    strethaddress_to_identifier('0x39Bb259F66E1C59d5ABEF88375979b4D20D98022'):
    'WAXP',
    # In Rotkehlchen Validity is RADS, the old name but in Bittrex it's VAL
    'RADS':
    'VAL',
    # make sure bittrex matches ADX latest contract
Example #10
0
 'JFI': A_USDT,
 'PEARL': A_USDT,
 'TAI': A_USDT,
 'KLV': A_USDT,
 'KRT': A_KRW,
 'RVC': A_USDT,
 'SDT': A_USDT,
 'BAKE': A_BNB,
 'BURGER': A_BNB,
 'CAKE': A_BNB,
 'FILDOWN': A_USDT,
 'FILUP': A_USDT,
 'YFIDOWN': A_USDT,
 'YFIUP': A_USDT,
 'SPARTA': A_BNB,
 strethaddress_to_identifier('0x679131F591B4f369acB8cd8c51E68596806c3916'): A_WETH,  # Trustlines  # noqa: E501
 strethaddress_to_identifier('0xf8aD7dFe656188A23e89da09506Adf7ad9290D5d'): A_USDT,  # Blocery
 A_CDAI: A_DAI,  # Compound DAI
 strethaddress_to_identifier('0x70e36f6BF80a52b3B46b3aF8e106CC0ed743E8e4'): A_COMP,  # Compound Comp  # noqa: E501
 A_CBAT: A_BAT,  # Comppound BAT
 A_CREP: A_REP,  # Compound REP
 strethaddress_to_identifier('0xF5DCe57282A584D2746FaF1593d3121Fcac444dC'): A_SAI,  # Compound SAI  # noqa: E501
 A_CUSDC: A_USDC,  # Compound USDC
 A_CUSDT: A_USDT,  # Compound USDT
 A_CWBTC: A_WBTC,  # Compound WBTC
 strethaddress_to_identifier('0x35A18000230DA775CAc24873d00Ff85BccdeD550'): A_UNI,  # Compound UNI  # noqa: E501
 A_CZRX: A_ZRX,  # Compound ZRX
 strethaddress_to_identifier('0x26CE25148832C04f3d7F26F32478a9fe55197166'): A_USDT,  # DEXTools
 strethaddress_to_identifier('0x0A913beaD80F321E7Ac35285Ee10d9d922659cB7'): A_USDT,  # DOS Network token  # noqa: E501
 strethaddress_to_identifier('0x6B9f031D718dDed0d681c20cB754F97b3BB81b78'): A_USDT,  # GEEQ
 A_STAKE: A_USDT,  # xDAI STAKE
Example #11
0
            weight=FVal(entry[1]),
        )


WORLD_TO_BITTREX = {
    # In Rotkehlchen Bitswift is BITS-2 but in Bittrex it's BITS
    'BITS-2':
    'BITS',
    # In Rotkehlchen NuBits is USNBT but in Bittrex it's NBT
    'USNBT':
    'NBT',
    # In Rotkehlchen BTM-2 is Bytom but in Bittrex it's BTM
    'BTM-2':
    'BTM',
    # Bittrex PI shoould map to rotki's PCHAIN
    strethaddress_to_identifier('0xB9bb08AB7E9Fa0A1356bd4A39eC0ca267E03b0b3'):
    'PI',
    # Bittrex PLA should map to rotki's PlayChip
    strethaddress_to_identifier('0x0198f46f520F33cd4329bd4bE380a25a90536CD5'):
    'PLA',
    # In Rotkehlchen LUNA-2 is Terra Luna but in Bittrex it's LUNA
    'LUNA-2':
    'LUNA',
    # WASP in binance maps to WorldWideAssetExchange in rotki
    # In Rotkehlchen WorldWideAssetExchange is WAX but in Bittrex it's WASP
    strethaddress_to_identifier('0x39Bb259F66E1C59d5ABEF88375979b4D20D98022'):
    'WAXP',
    # In Rotkehlchen Validity is RADS, the old name but in Bittrex it's VAL
    'RADS':
    'VAL',
    # make sure bittrex matches ADX latest contract
Example #12
0
 A_BNB,
 'BURGER':
 A_BNB,
 'CAKE':
 A_BNB,
 'FILDOWN':
 A_USDT,
 'FILUP':
 A_USDT,
 'YFIDOWN':
 A_USDT,
 'YFIUP':
 A_USDT,
 'SPARTA':
 A_BNB,
 strethaddress_to_identifier('0x679131F591B4f369acB8cd8c51E68596806c3916'):
 A_WETH,  # Trustlines  # noqa: E501
 strethaddress_to_identifier('0xf8aD7dFe656188A23e89da09506Adf7ad9290D5d'):
 A_USDT,  # Blocery
 A_CDAI:
 A_DAI,  # Compound DAI
 strethaddress_to_identifier('0x70e36f6BF80a52b3B46b3aF8e106CC0ed743E8e4'):
 A_COMP,  # Compound Comp  # noqa: E501
 A_CBAT:
 A_BAT,  # Comppound BAT
 A_CREP:
 A_REP,  # Compound REP
 strethaddress_to_identifier('0xF5DCe57282A584D2746FaF1593d3121Fcac444dC'):
 A_SAI,  # Compound SAI  # noqa: E501
 A_CUSDC:
 A_USDC,  # Compound USDC
Example #13
0
def test_replace_asset_edge_cases(rotkehlchen_api_server, globaldb):
    """Test that the edge cases/errors are treated properly in the replace assets endpoint"""
    rotki = rotkehlchen_api_server.rest_api.rotkehlchen
    cursor = rotki.data.db.conn.cursor()

    # Test that completely unknown source asset returns error
    notexisting_id = 'boo-boo-ga-ga'
    response = requests.put(
        api_url_for(
            rotkehlchen_api_server,
            'assetsreplaceresource',
        ),
        json={
            'source_identifier': notexisting_id,
            'target_asset': 'ICP'
        },
    )
    assert_error_response(
        response=response,
        contained_in_msg=f'Unknown asset {notexisting_id} provided',
        status_code=HTTPStatus.CONFLICT,
    )

    # Test that trying to replace an asset that's used as a foreign key elsewhere in
    # the global DB does not work, error is returned and no changes happen
    # in the global DB and in the user DB
    glm_id = strethaddress_to_identifier(
        '0x7DD9c5Cba05E151C895FDe1CF355C9A1D5DA6429')
    balances: List[Dict[str, Any]] = [{
        'asset': glm_id,
        'label': 'ICP account',
        'amount': '50.315',
        'location': 'blockchain',
    }]
    response = requests.put(
        api_url_for(
            rotkehlchen_api_server,
            'manuallytrackedbalancesresource',
        ),
        json={
            'async_query': False,
            'balances': balances
        },
    )
    assert_proper_response_with_result(response)
    global_cursor = globaldb._conn.cursor()

    def assert_db() -> None:
        assert global_cursor.execute(
            'SELECT COUNT(*) FROM user_owned_assets WHERE asset_id=?',
            (glm_id, ),
        ).fetchone()[0] == 1
        assert global_cursor.execute(
            'SELECT COUNT(*) FROM assets WHERE swapped_for=?',
            (glm_id, ),
        ).fetchone()[0] == 1
        assert cursor.execute(
            'SELECT COUNT(*) FROM assets WHERE identifier=?',
            (glm_id, ),
        ).fetchone()[0] == 1

    assert_db()
    response = requests.put(
        api_url_for(
            rotkehlchen_api_server,
            'assetsreplaceresource',
        ),
        json={
            'source_identifier': glm_id,
            'target_asset': 'ICP'
        },
    )
    assert_error_response(
        response=response,
        contained_in_msg='Tried to delete ethereum token with address',
        status_code=HTTPStatus.CONFLICT,
    )
    assert_db()

    # Test non-string source identifier
    response = requests.put(
        api_url_for(
            rotkehlchen_api_server,
            'assetsreplaceresource',
        ),
        json={
            'source_identifier': 55.1,
            'target_asset': 'ICP'
        },
    )
    assert_error_response(
        response=response,
        contained_in_msg='Not a valid string',
        status_code=HTTPStatus.BAD_REQUEST,
    )

    # Test unknown target asset
    response = requests.put(
        api_url_for(
            rotkehlchen_api_server,
            'assetsreplaceresource',
        ),
        json={
            'source_identifier': 'ETH',
            'target_asset': 'bobobobobo'
        },
    )
    assert_error_response(
        response=response,
        contained_in_msg='Unknown asset bobobobobo provided',
        status_code=HTTPStatus.BAD_REQUEST,
    )

    # Test invalid target asset
    response = requests.put(
        api_url_for(
            rotkehlchen_api_server,
            'assetsreplaceresource',
        ),
        json={
            'source_identifier': 'ETH',
            'target_asset': 55
        },
    )
    assert_error_response(
        response=response,
        contained_in_msg=
        'Tried to initialize an asset out of a non-string identifier',
        status_code=HTTPStatus.BAD_REQUEST,
    )
Example #14
0
logger = logging.getLogger(__name__)
log = RotkehlchenLogsAdapter(logger)

COINGECKO_QUERY_RETRY_TIMES = 4


class CoingeckoAssetData(NamedTuple):
    identifier: str
    symbol: str
    name: str
    description: str
    image_url: str


DELISTED_ASSETS = [
    strethaddress_to_identifier('0x0F72714B35a366285Df85886A2eE174601292A17'),
    'FLUZ',
    'EBCH',
    'GOLOS',
    'NPER',
    strethaddress_to_identifier('0xCA29db4221c111888a7e80b12eAc8a266Da3Ee0d'),
    'ADN',
    'PIX',
    strethaddress_to_identifier('0xdfdc0D82d96F8fd40ca0CFB4A288955bECEc2088'),
    'LKY',
    strethaddress_to_identifier('0xaFBeC4D65BC7b116d85107FD05d912491029Bf46'),
    strethaddress_to_identifier('0x37D40510a2F5Bc98AA7a0f7BF4b3453Bcfb90Ac1'),
    'BITCAR',
    strethaddress_to_identifier('0x499A6B77bc25C26bCf8265E2102B1B3dd1617024'),
    'OLE',
    'ROC',
Example #15
0
         1479510304: FVal(8.9145),
         1483313925: FVal(7.764),
         1491062063: FVal(47.865),
         1493291104: FVal(53.175),
         1493737200: FVal(69.505),
         1496979735: FVal(251.36),
         1501062063: FVal(175.44),
         1511626623: FVal(396.56),
         1512561941: FVal(380.34),
         1512561942: FVal(380.34),
         1539713117: FVal(178.615),
         1539713237: FVal(178.615),
         1539713238: FVal(178.615),
     },
 },
 strethaddress_to_identifier('0x255Aa6DF07540Cb5d3d297f0D0D4D84cb52bc8e6'):
 {
     'EUR': {
         1512561942: ZERO,
     },
 },
 'CHF': {
     'EUR': {
         1496979735: FVal(1.001),
     },
 },
 'LTC': {
     'EUR': {
         1493650800: FVal(14.07),
         1493737200: FVal(14.56),
     },
Example #16
0
class CoingeckoImageURLs(NamedTuple):
    thumb: str
    small: str
    large: str


class CoingeckoAssetData(NamedTuple):
    identifier: str
    symbol: str
    name: str
    description: str
    images: CoingeckoImageURLs


DELISTED_ASSETS = [
    strethaddress_to_identifier('0x0F72714B35a366285Df85886A2eE174601292A17'),
    'FLUZ',
    'EBCH',
    'GOLOS',
    'NPER',
    strethaddress_to_identifier('0xCA29db4221c111888a7e80b12eAc8a266Da3Ee0d'),
    'ADN',
    'PIX',
    strethaddress_to_identifier('0xdfdc0D82d96F8fd40ca0CFB4A288955bECEc2088'),
    'LKY',
    strethaddress_to_identifier('0xaFBeC4D65BC7b116d85107FD05d912491029Bf46'),
    strethaddress_to_identifier('0x37D40510a2F5Bc98AA7a0f7BF4b3453Bcfb90Ac1'),
    'BITCAR',
    strethaddress_to_identifier('0x499A6B77bc25C26bCf8265E2102B1B3dd1617024'),
    'OLE',
    'ROC',
Example #17
0
logger = logging.getLogger(__name__)
log = RotkehlchenLogsAdapter(logger)

COINGECKO_QUERY_RETRY_TIMES = 4


class CoingeckoAssetData(NamedTuple):
    identifier: str
    symbol: str
    name: str
    description: str
    image_url: str


DELISTED_ASSETS = [
    strethaddress_to_identifier('0x0F72714B35a366285Df85886A2eE174601292A17'),
    'FLUZ',
    'EBCH',
    'GOLOS',
    'NPER',
    strethaddress_to_identifier('0xCA29db4221c111888a7e80b12eAc8a266Da3Ee0d'),
    'ADN',
    'PIX',
    strethaddress_to_identifier('0xdfdc0D82d96F8fd40ca0CFB4A288955bECEc2088'),
    'LKY',
    strethaddress_to_identifier('0xaFBeC4D65BC7b116d85107FD05d912491029Bf46'),
    strethaddress_to_identifier('0x37D40510a2F5Bc98AA7a0f7BF4b3453Bcfb90Ac1'),
    'BITCAR',
    strethaddress_to_identifier('0x499A6B77bc25C26bCf8265E2102B1B3dd1617024'),
    'OLE',
    'ROC',