Example #1
0
def _handle_pooltogether(normalized_balance: FVal,
                         token_name: str) -> Optional[DefiBalance]:
    """Special handling for pooltogether

    https://github.com/rotki/rotki/issues/1429
    """
    if 'DAI' in token_name:
        dai_price = Inquirer.find_usd_price(A_DAI)
        return DefiBalance(
            token_address=string_to_ethereum_address(
                '0x49d716DFe60b37379010A75329ae09428f17118d'),
            token_name='Pool Together DAI token',
            token_symbol='plDAI',
            balance=Balance(
                amount=normalized_balance,
                usd_value=normalized_balance * dai_price,
            ),
        )
    if 'USDC' in token_name:
        usdc_price = Inquirer.find_usd_price(A_USDC)
        return DefiBalance(
            token_address=string_to_ethereum_address(
                '0xBD87447F48ad729C5c4b8bcb503e1395F62e8B98'),
            token_name='Pool Together USDC token',
            token_symbol='plUSDC',
            balance=Balance(
                amount=normalized_balance,
                usd_value=normalized_balance * usdc_price,
            ),
        )
    # else
    return None
Example #2
0
    def deserialize_from_db(
        cls,
        event_tuple: LiquidityPoolEventDBTuple,
    ) -> 'LiquidityPoolEvent':
        """Turns a tuple read from DB into an appropriate LiquidityPoolEvent.
        May raise a DeserializationError if something is wrong with the DB data
        Event_tuple index - Schema columns
        ----------------------------------
        0 - tx_hash
        1 - log_index
        2 - address
        3 - timestamp
        4 - type
        5 - pool_address
        6 - token0_identifier
        7 - token1_identifier
        8 - amount0
        9 - amount1
        10 - usd_price
        11 - lp_amount
        """
        db_event_type = event_tuple[4]
        if db_event_type not in {str(event_type) for event_type in EventType}:
            raise DeserializationError(
                f'Failed to deserialize event type. Unknown event: {db_event_type}.',
            )

        if db_event_type == str(EventType.MINT):
            event_type = EventType.MINT
        elif db_event_type == str(EventType.BURN):
            event_type = EventType.BURN
        else:
            raise ValueError(f'Unexpected event type case: {db_event_type}.')

        token0 = deserialize_ethereum_token_from_db(identifier=event_tuple[6])
        token1 = deserialize_ethereum_token_from_db(identifier=event_tuple[7])

        return cls(
            tx_hash=event_tuple[0],
            log_index=event_tuple[1],
            address=string_to_ethereum_address(event_tuple[2]),
            timestamp=deserialize_timestamp(event_tuple[3]),
            event_type=event_type,
            pool_address=string_to_ethereum_address(event_tuple[5]),
            token0=token0,
            token1=token1,
            amount0=deserialize_asset_amount(event_tuple[8]),
            amount1=deserialize_asset_amount(event_tuple[9]),
            usd_price=deserialize_price(event_tuple[10]),
            lp_amount=deserialize_asset_amount(event_tuple[11]),
        )
Example #3
0
    def deserialize_from_db(
        cls,
        event_tuple: BalancerEventDBTuple,
    ) -> 'BalancerEvent':
        """May raise DeserializationError

        Event_tuple index - Schema columns
        ----------------------------------
        0 - tx_hash
        1 - log_index
        2 - address
        3 - timestamp
        4 - type
        5 - pool_address
        6 - lp_amount
        7 - usd_value
        8 - amount0
        9 - amount1
        10 - amount2
        11 - amount3
        12 - amount4
        13 - amount5
        14 - amount6
        15 - amount7
        """
        event_tuple_type = event_tuple[4]
        try:
            event_type = getattr(BalancerBPTEventType,
                                 event_tuple_type.upper())
        except AttributeError as e:
            raise DeserializationError(
                f'Unexpected event type: {event_tuple_type}.') from e

        amounts: List[AssetAmount] = [
            deserialize_asset_amount(item) for item in event_tuple[8:16]
            if item is not None
        ]
        return cls(
            tx_hash=event_tuple[0],
            log_index=event_tuple[1],
            address=string_to_ethereum_address(event_tuple[2]),
            timestamp=deserialize_timestamp(event_tuple[3]),
            event_type=event_type,
            pool_address=string_to_ethereum_address(event_tuple[5]),
            lp_balance=Balance(
                amount=deserialize_asset_amount(event_tuple[6]),
                usd_value=deserialize_price(event_tuple[7]),
            ),
            amounts=amounts,
        )
Example #4
0
    def query_tokens_for_addresses(
        self,
        addresses: List[ChecksumEthAddress],
        force_detection: bool,
    ) -> TokensReturn:
        """Queries/detects token balances for a list of addresses

        If an address's tokens were recently autodetected they are not detected again but the
        balances are simply queried. Unless force_detection is True.

        Returns the token balances of each address and the usd prices of the tokens
        """
        log.debug(
            'Querying/detecting token balances for all addresses',
            force_detection=force_detection,
        )
        all_tokens = GlobalDBHandler().get_ethereum_tokens(exceptions=[
            # Ignore the veCRV balance in token query. It's already detected by
            # defi SDK as part of locked CRV in Vote Escrowed CRV. Which is the right way
            # to approach it as there is no way to assign a price to 1 veCRV. It
            # can be 1 CRV locked for 4 years or 4 CRV locked for 1 year etc.
            string_to_ethereum_address(
                '0x5f3b5DfEb7B28CDbD7FAba78963EE202a494e2A2'),
        ])
        # With etherscan with chunks > 120, we get request uri too large
        # so the limitation is not in the gas, but in the request uri length
        etherscan_chunks = list(
            get_chunks(all_tokens, n=ETHERSCAN_MAX_TOKEN_CHUNK_LENGTH))
        other_chunks = list(
            get_chunks(all_tokens, n=OTHER_MAX_TOKEN_CHUNK_LENGTH))
        now = ts_now()
        token_usd_price: Dict[EthereumToken, Price] = {}
        result = {}

        for address in addresses:
            saved_list = self.db.get_tokens_for_address_if_time(
                address=address, current_time=now)
            if force_detection or saved_list is None:
                balances = self.detect_tokens_for_address(
                    address=address,
                    token_usd_price=token_usd_price,
                    etherscan_chunks=etherscan_chunks,
                    other_chunks=other_chunks,
                )
            else:
                if len(saved_list) == 0:
                    continue  # Do not query if we know the address has no tokens

                balances = defaultdict(FVal)
                self._get_tokens_balance_and_price(
                    address=address,
                    tokens=[x.to_custom_ethereum_token() for x in saved_list],
                    balances=balances,
                    token_usd_price=token_usd_price,
                    call_order=None,  # use defaults
                )

            result[address] = balances

        return result, token_usd_price
Example #5
0
    def deserialize_from_db(
        cls,
        event_tuple: BalancerEventDBTuple,
    ) -> 'BalancerEvent':
        """May raise DeserializationError

        Event_tuple index - Schema columns
        ----------------------------------
        0 - tx_hash
        1 - log_index
        2 - address
        3 - timestamp
        4 - type
        5 - pool_address_token
        6 - lp_amount
        7 - usd_value
        8 - amount0
        9 - amount1
        10 - amount2
        11 - amount3
        12 - amount4
        13 - amount5
        14 - amount6
        15 - amount7
        """
        event_tuple_type = event_tuple[4]
        try:
            event_type = getattr(BalancerBPTEventType,
                                 event_tuple_type.upper())
        except AttributeError as e:
            raise DeserializationError(
                f'Unexpected event type: {event_tuple_type}.') from e

        pool_address_token = EthereumToken.from_identifier(
            event_tuple[5],
            form_with_incomplete_data=
            True,  # since some may not have decimals input correctly
        )
        if pool_address_token is None:
            raise DeserializationError(
                f'Balancer event pool token: {event_tuple[5]} not found in the DB.',
            )

        amounts: List[AssetAmount] = [
            deserialize_asset_amount(item) for item in event_tuple[8:16]
            if item is not None
        ]
        return cls(
            tx_hash=event_tuple[0],
            log_index=event_tuple[1],
            address=string_to_ethereum_address(event_tuple[2]),
            timestamp=deserialize_timestamp(event_tuple[3]),
            event_type=event_type,
            pool_address_token=pool_address_token,
            lp_balance=Balance(
                amount=deserialize_asset_amount(event_tuple[6]),
                usd_value=deserialize_price(event_tuple[7]),
            ),
            amounts=amounts,
        )
Example #6
0
    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
Example #7
0
    def deserialize_from_db(
        cls,
        event_tuple: LiquidityPoolEventDBTuple,
    ) -> 'LiquidityPoolEvent':
        """Turns a tuple read from DB into an appropriate LiquidityPoolEvent.
        May raise a DeserializationError if something is wrong with the DB data
        Event_tuple index - Schema columns
        ----------------------------------
        0 - tx_hash
        1 - log_index
        2 - address
        3 - timestamp
        4 - type
        5 - pool_address
        6 - token0_identifier
        7 - token1_identifier
        8 - amount0
        9 - amount1
        10 - usd_price
        11 - lp_amount
        """
        event_type = EventType.deserialize_from_db(event_tuple[4])
        token0 = deserialize_ethereum_token_from_db(identifier=event_tuple[6])
        token1 = deserialize_ethereum_token_from_db(identifier=event_tuple[7])

        return cls(
            tx_hash=event_tuple[0],
            log_index=event_tuple[1],
            address=string_to_ethereum_address(event_tuple[2]),
            timestamp=deserialize_timestamp(event_tuple[3]),
            event_type=event_type,
            pool_address=string_to_ethereum_address(event_tuple[5]),
            token0=token0,
            token1=token1,
            amount0=deserialize_asset_amount(event_tuple[8]),
            amount1=deserialize_asset_amount(event_tuple[9]),
            usd_price=deserialize_price(event_tuple[10]),
            lp_amount=deserialize_asset_amount(event_tuple[11]),
        )
Example #8
0
    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
Example #9
0
    def have_archive(self, requery: bool = False) -> bool:
        """Checks to see if our own connected node is an archive node

        If requery is True it always queries the node. Otherwise it remembers last query.
        """
        if self.queried_archive_connection and requery is False:
            return self.archive_connection

        balance = self.get_historical_eth_balance(
            address=string_to_ethereum_address(
                '0x50532e4Be195D1dE0c2E6DfA46D9ec0a4Fee6861'),
            block_number=87042,
        )
        self.archive_connection = balance is not None and balance == FVal(
            '5.1063307')
        self.queried_archive_connection = True
        return self.archive_connection
Example #10
0
def deserialize_unknown_ethereum_token_from_db(
    ethereum_address: str,
    symbol: str,
    name: Optional[str],
    decimals: Optional[int],
) -> UnknownEthereumToken:
    """Takes at least an ethereum address and a symbol, and returns an
    <UnknownEthereumToken>
    """
    try:
        unknown_ethereum_token = UnknownEthereumToken(
            ethereum_address=string_to_ethereum_address(ethereum_address),
            symbol=symbol,
            name=name,
            decimals=decimals,
        )
    except Exception as e:
        raise DeserializationError(
            f'Failed deserializing an unknown ethereum token with '
            f'address {ethereum_address}, symbol {symbol}, name {name}, '
            f'decimals {decimals}.', ) from e

    return unknown_ethereum_token
Example #11
0
import random

import pytest
import requests

from rotkehlchen.chain.ethereum.typing import string_to_ethereum_address
from rotkehlchen.constants.assets import A_ETH, A_LQTY, A_LUSD
from rotkehlchen.fval import FVal
from rotkehlchen.tests.utils.api import (
    api_url_for,
    assert_ok_async_response,
    assert_proper_response_with_result,
    wait_for_async_task_with_result,
)

LQTY_ADDR = string_to_ethereum_address(
    '0x063c26fF1592688B73d8e2A18BA4C23654e2792E')
LQTY_STAKING = string_to_ethereum_address(
    '0x018565899A88f75E6edfEA0639183adF8c205641')
LQTY_PROXY = string_to_ethereum_address(
    '0x9476832d4687c14b2c1a04E2ee4693162a7340B6')
ADDR_WITHOUT_TROVE = string_to_ethereum_address(
    '0xA0446D8804611944F1B527eCD37d7dcbE442caba')

liquity_mocked_historical_prices = {
    A_ETH: {
        'USD': {
            1627818194: FVal('3000'),
            1627818617: FVal('3000'),
            1627827057: FVal('3500'),
            1641529258: FVal('3395'),
        },
Example #12
0
    ValidatorPerformance,
    string_to_ethereum_address,
)
from rotkehlchen.constants.misc import ZERO
from rotkehlchen.fval import FVal
from rotkehlchen.serialization.serialize import process_result_list
from rotkehlchen.tests.utils.ethereum import (
    ETHEREUM_TEST_PARAMETERS,
    wait_until_all_nodes_connected,
)
from rotkehlchen.tests.utils.factories import make_ethereum_address
from rotkehlchen.tests.utils.mock import MockResponse
from rotkehlchen.typing import Timestamp
from rotkehlchen.user_messages import MessagesAggregator

ADDR1 = string_to_ethereum_address(
    '0xfeF0E7635281eF8E3B705e9C5B86e1d3B0eAb397')
ADDR2 = string_to_ethereum_address(
    '0x00F8a0D8EE1c21151BCcB416bCa1C152f9952D19')
ADDR3 = string_to_ethereum_address(
    '0x3266F3546a1e5Dc6A15588f3324741A0E20a3B6c')

# List of ADDR1, ADDR2 and ADDR3 deposit events from 1604506685 to 1605044577
# sorted by (timestamp, log_index).
EXPECTED_DEPOSITS = [
    Eth2Deposit(
        from_address=ADDR1,
        pubkey=
        '0xb016e31f633a21fbe42a015152399361184f1e2c0803d89823c224994af74a561c4ad8cfc94b18781d589d03e952cd5b',  # noqa: E501
        withdrawal_credentials=
        '0x004c7691c2085648f394ffaef851f3b1d51b95f7263114bc923fc5338f5fc499',  # noqa: E501
        value=Balance(FVal(32), FVal(64)),
Example #13
0
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
Example #14
0
from rotkehlchen.assets.utils import symbol_to_asset_or_token
from rotkehlchen.chain.ethereum.typing import string_to_ethereum_address
from rotkehlchen.constants.assets import A_BAT, A_CRV, A_DAI, A_PICKLE
from rotkehlchen.constants.misc import NFT_DIRECTIVE
from rotkehlchen.constants.resolver import ethaddress_to_identifier
from rotkehlchen.errors import InputError
from rotkehlchen.exchanges.data_structures import Trade
from rotkehlchen.globaldb.handler import GLOBAL_DB_VERSION, GlobalDBHandler
from rotkehlchen.history.typing import HistoricalPriceOracle
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,
)
Example #15
0
File: utils.py Project: rotki/rotki
from rotkehlchen.serialization.deserialize import (
    deserialize_asset_amount,
    deserialize_ethereum_address,
    deserialize_timestamp,
)

from .typing import AdexEventDBTuple, AdexEventType, Bond, ChannelWithdraw, Unbond, UnbondRequest

# Constants from the AdExNetwork repo
IDENTITY_FACTORY_ADDR = '0x9fe0d438E3c29C7CFF949aD8e8dA9403A531cC1A'
IDENTITY_PROXY_INIT_CODE = (
    '0x608060405234801561001057600080fd5b5060026000803073ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908360ff160217905550600260008073'  # noqa: E501
    '{signer_address}'
    '73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908360ff1602179055506000734470bb87d77b963a013db939be332f927f2b992e9050600073ade00c28244d5ce17d72e40330b1c318cd12b7c3905060008273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016101429190610501565b60206040518083038186803b15801561015a57600080fd5b505afa15801561016e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610192919061045a565b90506000811115610276578273ffffffffffffffffffffffffffffffffffffffff1663095ea7b383836040518363ffffffff1660e01b81526004016101d892919061051c565b600060405180830381600087803b1580156101f257600080fd5b505af1158015610206573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff166394b918de826040518263ffffffff1660e01b81526004016102439190610560565b600060405180830381600087803b15801561025d57600080fd5b505af1158015610271573d6000803e3d6000fd5b505050505b60008273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016102b19190610501565b60206040518083038186803b1580156102c957600080fd5b505afa1580156102dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610301919061045a565b9050600081111561043c576000734846c6837ec670bbd1f5b485471c8f64ecb9c53490508373ffffffffffffffffffffffffffffffffffffffff1663095ea7b382846040518363ffffffff1660e01b815260040161036092919061051c565b600060405180830381600087803b15801561037a57600080fd5b505af115801561038e573d6000803e3d6000fd5b505050508073ffffffffffffffffffffffffffffffffffffffff1663b4dca72460405180606001604052808581526020017f2ce0c96383fb229d9776f33846e983a956a7d95844fac57b180ed0071d93bb2860001b8152602001428152506040518263ffffffff1660e01b81526004016104089190610545565b600060405180830381600087803b15801561042257600080fd5b505af1158015610436573d6000803e3d6000fd5b50505050505b505050506105d8565b600081519050610454816105c1565b92915050565b60006020828403121561046c57600080fd5b600061047a84828501610445565b91505092915050565b61048c8161057b565b82525050565b61049b8161058d565b82525050565b6060820160008201516104b760008501826104e3565b5060208201516104ca6020850182610492565b5060408201516104dd60408501826104e3565b50505050565b6104ec816105b7565b82525050565b6104fb816105b7565b82525050565b60006020820190506105166000830184610483565b92915050565b60006040820190506105316000830185610483565b61053e60208301846104f2565b9392505050565b600060608201905061055a60008301846104a1565b92915050565b600060208201905061057560008301846104f2565b92915050565b600061058682610597565b9050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6105ca816105b7565b81146105d557600080fd5b50565b6101b7806105e76000396000f3fe608060405234801561001057600080fd5b506004361061002f5760003560e01c8063c066a5b11461007357610030565b5b60007396e3cb4b4632ed45363ff2c9f0fbec9b583d9d3a90503660008037600080366000846127105a03f43d6000803e806000811461006e573d6000f35b3d6000fd5b61008d600480360381019061008891906100d8565b6100a3565b60405161009a9190610110565b60405180910390f35b60006020528060005260406000206000915054906101000a900460ff1681565b6000813590506100d28161016a565b92915050565b6000602082840312156100ea57600080fd5b60006100f8848285016100c3565b91505092915050565b61010a8161015d565b82525050565b60006020820190506101256000830184610101565b92915050565b60006101368261013d565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600060ff82169050919050565b6101738161012b565b811461017e57600080fd5b5056fea26469706673582212200e40aa3025d54e828fb973089b64ce06688fedcd71b98ae68521a0217652c59564736f6c634300060c0033'  # noqa: E501
)
STAKING_ADDR = string_to_ethereum_address(
    '0x4846C6837ec670Bbd1f5b485471c8f64ECB9c534')
CREATE2_SALT = f'0x{bytearray(32).hex()}'
ADX_AMOUNT_MANTISSA = FVal(10**18)

ADEX_EVENTS_PREFIX = 'adex_events'

# Defines the expected order of the events given the same timestamp and sorting
# in ascending mode
EVENT_TYPE_ORDER_IN_ASC = {
    Bond: 3,
    ChannelWithdraw: 1,
    Unbond: 2,
    UnbondRequest: 4,
}

Example #16
0
def get_balancer_test_addr2_expected_trades():
    """In a function since the new(unknown) assets needs to have been loaded in the DB"""
    A_WCRES = EthereumToken.initialize(  # noqa: N806
        address=string_to_ethereum_address(
            '0xa0afAA285Ce85974c3C881256cB7F225e3A1178a'),
        decimals=18,
        symbol='wCRES',
    )
    return [
        AMMTrade(
            trade_type=TradeType.BUY,
            base_asset=A_WETH,
            quote_asset=A_AAVE,
            amount=AssetAmount(FVal('1.616934038985744521')),
            rate=Price(FVal('6.963972908793392530935439799')),
            trade_index=1,
            swaps=[
                AMMSwap(
                    tx_hash=
                    '0x3c457da9b541ae39a7dc781ab04a03938b98b5649512aec2a2d32635c9bbf589',  # noqa: E501
                    log_index=24,
                    address=string_to_ethereum_address(
                        '0x029f388aC4D5C8BfF490550ce0853221030E822b'
                    ),  # noqa: E501
                    from_address=string_to_ethereum_address(
                        '0x0000000000007F150Bd6f54c40A34d7C3d5e9f56'
                    ),  # noqa: E501
                    to_address=string_to_ethereum_address(
                        '0x7c90a3cd7Ec80dd2F633ed562480AbbEEd3bE546'
                    ),  # noqa: E501
                    timestamp=Timestamp(1607008178),
                    location=Location.BALANCER,
                    token0=A_AAVE,
                    token1=A_WETH,
                    amount0_in=AssetAmount(FVal('11.260284842802604032')),
                    amount1_in=AssetAmount(ZERO),
                    amount0_out=AssetAmount(ZERO),
                    amount1_out=AssetAmount(FVal('1.616934038985744521')),
                ),
            ],
        ),
        AMMTrade(
            trade_type=TradeType.BUY,
            base_asset=A_AAVE,
            quote_asset=A_WETH,
            amount=AssetAmount(FVal('11.260286362820602094')),
            rate=Price(FVal('0.1416068599966922676173010716')),
            trade_index=0,
            swaps=[
                AMMSwap(
                    tx_hash=
                    '0x3c457da9b541ae39a7dc781ab04a03938b98b5649512aec2a2d32635c9bbf589',  # noqa: E501
                    log_index=18,
                    address=string_to_ethereum_address(
                        '0x029f388aC4D5C8BfF490550ce0853221030E822b'
                    ),  # noqa: E501
                    from_address=string_to_ethereum_address(
                        '0x0000000000007F150Bd6f54c40A34d7C3d5e9f56'
                    ),  # noqa: E501
                    to_address=string_to_ethereum_address(
                        '0x70985E557aE0CD6dC88189a532e54FbC61927BAd'
                    ),  # noqa: E501
                    timestamp=Timestamp(1607008178),
                    location=Location.BALANCER,
                    token0=A_WETH,
                    token1=A_AAVE,
                    amount0_in=AssetAmount(FVal('1.594533794502600192')),
                    amount1_in=AssetAmount(ZERO),
                    amount0_out=AssetAmount(ZERO),
                    amount1_out=AssetAmount(FVal('11.260286362820602094')),
                ),
            ],
        ),
        AMMTrade(
            trade_type=TradeType.BUY,
            base_asset=A_WETH,
            quote_asset=A_SYN,
            amount=AssetAmount(FVal('1.352902561458047718')),
            rate=Price(FVal('724.4303350385182691258363763')),
            trade_index=0,
            swaps=[
                AMMSwap(
                    tx_hash=
                    '0x5e235216cb03e4eb234014f5ccf3efbfddd40c4576424e2a8204f1d12b96ed35',  # noqa: E501
                    log_index=143,
                    address=string_to_ethereum_address(
                        '0x029f388aC4D5C8BfF490550ce0853221030E822b'
                    ),  # noqa: E501
                    from_address=string_to_ethereum_address(
                        '0x0000000000007F150Bd6f54c40A34d7C3d5e9f56'
                    ),  # noqa: E501
                    to_address=string_to_ethereum_address(
                        '0x8982E9bBf7AC6A49c434aD81D2fF8e16895318e5'
                    ),  # noqa: E501
                    timestamp=Timestamp(1607008218),
                    location=Location.BALANCER,
                    token0=A_SYN,
                    token1=A_WETH,
                    amount0_in=AssetAmount(FVal('980.08365587152306176')),
                    amount1_in=AssetAmount(ZERO),
                    amount0_out=AssetAmount(ZERO),
                    amount1_out=AssetAmount(FVal('1.352902561458047718')),
                ),
            ],
        ),
        AMMTrade(
            trade_type=TradeType.BUY,
            base_asset=A_WETH,
            quote_asset=A_WCRES,
            amount=AssetAmount(FVal('0.205709519074945018')),
            rate=Price(FVal('232.7409943164679514496089589')),
            trade_index=0,
            swaps=[
                AMMSwap(
                    tx_hash=
                    '0xf54be824b4619777f1db0e3da91b0cd52f6dba730c95a75644e2b085e6ab9824',  # noqa: E501
                    log_index=300,
                    address=string_to_ethereum_address(
                        '0x029f388aC4D5C8BfF490550ce0853221030E822b'
                    ),  # noqa: E501
                    from_address=string_to_ethereum_address(
                        '0x0000000000007F150Bd6f54c40A34d7C3d5e9f56'
                    ),  # noqa: E501
                    to_address=string_to_ethereum_address(
                        '0x10996eC4f3E7A1b314EbD966Fa8b1ad0fE0f8307'
                    ),  # noqa: E501
                    timestamp=Timestamp(1607009877),
                    location=Location.BALANCER,
                    token0=A_WCRES,
                    token1=A_WETH,
                    amount0_in=AssetAmount(FVal('47.87703800986513408')),
                    amount1_in=AssetAmount(ZERO),
                    amount0_out=AssetAmount(ZERO),
                    amount1_out=AssetAmount(FVal('0.205709519074945018')),
                ),
            ],
        ),
        AMMTrade(
            trade_type=TradeType.BUY,
            base_asset=A_API3,
            quote_asset=A_WETH,
            amount=AssetAmount(FVal('295.881648100500428692')),
            rate=Price(FVal('0.003346787723157288562491614498')),
            trade_index=0,
            swaps=[
                AMMSwap(
                    tx_hash=
                    '0xfed4e15051e3ce4dc0d2816f719701e5920e40bf41614b5feaa3c5a6a0186c03',  # noqa: E501
                    log_index=22,
                    address=string_to_ethereum_address(
                        '0x029f388aC4D5C8BfF490550ce0853221030E822b'
                    ),  # noqa: E501
                    from_address=string_to_ethereum_address(
                        '0x0000000000007F150Bd6f54c40A34d7C3d5e9f56'
                    ),  # noqa: E501
                    to_address=string_to_ethereum_address(
                        '0x997c0fc9578a8194EFDdE2E0cD7aa6A69cFCD7c1'
                    ),  # noqa: E501
                    timestamp=Timestamp(1607010888),
                    location=Location.BALANCER,
                    token0=A_WETH,
                    token1=A_API3,
                    amount0_in=AssetAmount(FVal('0.990253067370299904')),
                    amount1_in=AssetAmount(ZERO),
                    amount0_out=AssetAmount(ZERO),
                    amount1_out=AssetAmount(FVal('295.881648100500428692')),
                ),
            ],
        ),
        AMMTrade(
            trade_type=TradeType.BUY,
            base_asset=A_WETH,
            quote_asset=A_MFT,
            amount=AssetAmount(FVal('0.686544199299304057')),
            rate=Price(FVal('243775.0324093115004367119900')),
            trade_index=0,
            swaps=[
                AMMSwap(
                    tx_hash=
                    '0xf0147c4b81098676c08ae20ae5bf8f8b60d0ad79eec484f3f93ac6ab49a3c51c',  # noqa: E501
                    log_index=97,
                    address=string_to_ethereum_address(
                        '0x029f388aC4D5C8BfF490550ce0853221030E822b'
                    ),  # noqa: E501
                    from_address=string_to_ethereum_address(
                        '0x0000000000007F150Bd6f54c40A34d7C3d5e9f56'
                    ),  # noqa: E501
                    to_address=string_to_ethereum_address(
                        '0x2Eb6CfbFFC8785Cd0D9f2d233d0a617bF4269eeF'
                    ),  # noqa: E501
                    timestamp=Timestamp(1607015059),
                    location=Location.BALANCER,
                    token0=A_MFT,
                    token1=A_WETH,
                    amount0_in=AssetAmount(FVal('167362.334434612660404224')),
                    amount1_in=AssetAmount(ZERO),
                    amount0_out=AssetAmount(ZERO),
                    amount1_out=AssetAmount(FVal('0.686544199299304057')),
                ),
            ],
        ),
        AMMTrade(
            trade_type=TradeType.BUY,
            base_asset=A_WETH,
            quote_asset=A_AAVE,
            amount=AssetAmount(FVal('3.055412574642681758')),
            rate=Price(FVal('6.916116208273240607778771150')),
            trade_index=1,
            swaps=[
                AMMSwap(
                    tx_hash=
                    '0x67c0e9a0fdd002d0b9d1cca0c8e4ca4d30435bbf57bbf0091396275efaea414b',  # noqa: E501
                    log_index=37,
                    address=string_to_ethereum_address(
                        '0x029f388aC4D5C8BfF490550ce0853221030E822b'
                    ),  # noqa: E501
                    from_address=string_to_ethereum_address(
                        '0x0000000000007F150Bd6f54c40A34d7C3d5e9f56'
                    ),  # noqa: E501
                    to_address=string_to_ethereum_address(
                        '0x0E552307659E70bF61f918f96AA880Cdec40d7E2'
                    ),  # noqa: E501
                    timestamp=Timestamp(1607015339),
                    location=Location.BALANCER,
                    token0=A_AAVE,
                    token1=A_WETH,
                    amount0_in=AssetAmount(FVal('21.131588430448123904')),
                    amount1_in=AssetAmount(ZERO),
                    amount0_out=AssetAmount(ZERO),
                    amount1_out=AssetAmount(FVal('3.055412574642681758')),
                ),
            ],
        ),
        AMMTrade(
            trade_type=TradeType.BUY,
            base_asset=A_AAVE,
            quote_asset=A_WETH,
            amount=AssetAmount(FVal('21.131588567541018817')),
            rate=Price(FVal('0.1435213742524287826717337545')),
            trade_index=0,
            swaps=[
                AMMSwap(
                    tx_hash=
                    '0x67c0e9a0fdd002d0b9d1cca0c8e4ca4d30435bbf57bbf0091396275efaea414b',  # noqa: E501
                    log_index=31,
                    address=string_to_ethereum_address(
                        '0x029f388aC4D5C8BfF490550ce0853221030E822b'
                    ),  # noqa: E501
                    from_address=string_to_ethereum_address(
                        '0x0000000000007F150Bd6f54c40A34d7C3d5e9f56'
                    ),  # noqa: E501
                    to_address=string_to_ethereum_address(
                        '0x7c90a3cd7Ec80dd2F633ed562480AbbEEd3bE546'
                    ),  # noqa: E501
                    timestamp=Timestamp(1607015339),
                    location=Location.BALANCER,
                    token0=A_WETH,
                    token1=A_AAVE,
                    amount0_in=AssetAmount(FVal('3.0328346313504')),
                    amount1_in=AssetAmount(ZERO),
                    amount0_out=AssetAmount(ZERO),
                    amount1_out=AssetAmount(FVal('21.131588567541018817')),
                ),
            ],
        ),
    ]
Example #17
0
A_DASH = Asset('DASH')
A_WAVES = Asset('WAVES')
A_EWT = Asset('EWT')
A_XTZ = Asset('XTZ')
A_IOTA = Asset('IOTA')
A_BSV = Asset('BSV')
A_BCH = Asset('BCH')
A_CNY = Asset('CNY')
A_JPY = Asset('JPY')
A_ZEC = Asset('ZEC')
A_DOT = Asset('DOT')
A_GBP = Asset('GBP')
A_CHF = Asset('CHF')
A_AUD = Asset('AUD')
A_EUR = Asset('EUR')
A_KRW = Asset('KRW')
A_CAD = Asset('CAD')

ETH_ADDRESS1 = string_to_ethereum_address('0x5153493bB1E1642A63A098A65dD3913daBB6AE24')
ETH_ADDRESS2 = string_to_ethereum_address('0x4FED1fC4144c223aE3C1553be203cDFcbD38C581')
ETH_ADDRESS3 = string_to_ethereum_address('0x267FdC6F9F1C1a783b36126c1A59a9fbEBf42f84')

TX_HASH_STR1 = '0x9c81f44c29ff0226f835cd0a8a2f2a7eca6db52a711f8211b566fd15d3e0e8d4'
TX_HASH_STR2 = '0x1c81f44c29ff0236f835cd0a8a2f2a7eca6db52a711f8211b566fd15d3e0e899'
TX_HASH_STR3 = '0x3c81144c29f60236f735cd0a8a2f2a7e3a6db52a713f8211b562fd15d3e0e192'

MOCK_INPUT_DATA = b'123'
MOCK_INPUT_DATA_HEX = '0x313233'

DEFAULT_TESTS_MAIN_CURRENCY = A_EUR
 );
 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");
 INSERT INTO common_asset_details(asset_id, forked) VALUES(
Example #19
0

TEST_ACCOUNTS = [
    # For mint/redeem
    '0x2B888954421b424C5D3D9Ce9bB67c9bD47537d12',
    # For borrowing/liquidations
    '0xC440f3C87DC4B6843CABc413916220D4f4FeD117',
    # For mint/redeem + comp
    '0xF59D4937BF1305856C3a267bB07791507a3377Ee',
    # For repay
    '0x65304d6aff5096472519ca86a6a1fea31cb47Ced',
]

EXPECTED_EVENTS = [CompoundEvent(
    event_type='mint',
    address=string_to_ethereum_address('0x2B888954421b424C5D3D9Ce9bB67c9bD47537d12'),
    block_number=9443573,
    timestamp=Timestamp(1581184577),
    asset=A_DAI,
    value=Balance(amount=FVal('2988.4343'), usd_value=FVal('3012.3417744')),
    to_asset=A_CDAI,
    to_value=Balance(amount=FVal('148015.6966153'), usd_value=FVal('3012.3417744')),
    realized_pnl=None,
    tx_hash='0xacc2e21f911a4e438966694e9ad16747878a15dae52de62a09f1ebabc8b26c8d',
    log_index=130,
), CompoundEvent(
    event_type='redeem',
    address=string_to_ethereum_address('0x2B888954421b424C5D3D9Ce9bB67c9bD47537d12'),
    block_number=9533397,
    timestamp=Timestamp(1582378248),
    asset=A_CDAI,
Example #20
0
    LiquidityPool,
    LiquidityPoolAsset,
    LiquidityPoolEvent,
    LiquidityPoolEventsBalance,
)
from rotkehlchen.chain.ethereum.typing import string_to_ethereum_address
from rotkehlchen.constants import ZERO
from rotkehlchen.constants.assets import A_USDT, A_WETH
from rotkehlchen.fval import FVal
from rotkehlchen.tests.utils.constants import A_DOLLAR_BASED
from rotkehlchen.typing import AssetAmount, Price, Timestamp

# Logic: Get balances

# Addresses
TEST_ADDRESS_1 = string_to_ethereum_address(
    '0xfeF0E7635281eF8E3B705e9C5B86e1d3B0eAb397')
TEST_ADDRESS_2 = string_to_ethereum_address(
    '0xcf2B8EeC2A9cE682822b252a1e9B78EedebEFB02')
TEST_ADDRESS_3 = string_to_ethereum_address(
    '0x7777777777777777777777777777777777777777')

# Unknown tokens
ASSET_SHUF = UnknownEthereumToken(
    ethereum_address=string_to_ethereum_address(
        '0x3A9FfF453d50D4Ac52A6890647b823379ba36B9E'),
    symbol='SHUF',
    name='Shuffle.Monster V3',
    decimals=18,
)
ASSET_TGX = UnknownEthereumToken(
    ethereum_address=string_to_ethereum_address(
Example #21
0
from rotkehlchen.chain.ethereum.modules.balancer import Balancer
from rotkehlchen.chain.ethereum.modules.balancer.utils import get_trades_from_tx_swaps
from rotkehlchen.chain.ethereum.trades import AMMSwap, AMMTrade
from rotkehlchen.chain.ethereum.typing import string_to_ethereum_address
from rotkehlchen.constants.assets import A_REN, A_SNX, A_USDC, A_WETH
from rotkehlchen.constants.misc import ZERO
from rotkehlchen.fval import FVal
from rotkehlchen.tests.api.test_balancer import get_balancer_test_addr2_expected_trades
from rotkehlchen.tests.utils.constants import A_AMPL
from rotkehlchen.typing import AssetAmount, Location, Price, Timestamp, TradeType

TEST_SWAPS_TX_1 = [
    AMMSwap(
        tx_hash='0x1b0d3525964d8e5fbcc0dcdeebcced4bec9017f648e97c3c9761fda1ca6e7b22',
        log_index=254,
        address=string_to_ethereum_address('0x8e670b4d6651C4051e65B21AA4a575F3f99b8B83'),
        from_address=string_to_ethereum_address('0x65003947dC16956AfC4400008606001500940000'),
        to_address=string_to_ethereum_address('0x7860E28ebFB8Ae052Bfe279c07aC5d94c9cD2937'),
        timestamp=Timestamp(1614094145),
        location=Location.BALANCER,
        token0=A_USDC,
        token1=A_AMPL,
        amount0_in=AssetAmount(FVal('12401.224639')),
        amount1_in=AssetAmount(ZERO),
        amount0_out=AssetAmount(ZERO),
        amount1_out=AssetAmount(FVal('14285.153512382')),
    ),
]
TEST_SWAPS_TX_2 = [
    AMMSwap(
        tx_hash='0x1b0d3525964d8e5fbcc0dcdeebcced4bec9017f648e97c3c9761fda1ca6e7b22',
Example #22
0
# flake8: noqa

import json
import os
from typing import Any, Dict, List, Optional

from rotkehlchen.chain.ethereum.contracts import EthereumContract
from rotkehlchen.chain.ethereum.typing import string_to_ethereum_address

MAX_BLOCKTIME_CACHE = 250  # 55 mins with 13 secs avg block time
ZERO_ADDRESS = string_to_ethereum_address(
    '0x0000000000000000000000000000000000000000')
AAVE_ETH_RESERVE_ADDRESS = string_to_ethereum_address(
    '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE')


class EthereumConstants():
    __instance = None
    contracts: Dict[str, Dict[str, Any]] = {}
    abi_entries: Dict[str, List[Dict[str, Any]]] = {}

    def __new__(cls) -> 'EthereumConstants':
        if EthereumConstants.__instance is not None:
            return EthereumConstants.__instance  # type: ignore

        EthereumConstants.__instance = object.__new__(cls)

        dir_path = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
        with open(os.path.join(dir_path, 'data', 'eth_contracts.json'),
                  'r') as f:
            contracts = json.loads(f.read())
Example #23
0
from rotkehlchen.chain.ethereum.modules.adex.adex import Adex
from rotkehlchen.chain.ethereum.modules.adex.typing import TOM_POOL_ID
from rotkehlchen.chain.ethereum.typing import string_to_ethereum_address

TEST_ADDR = string_to_ethereum_address(
    '0x494B9728BECA6C03269c38Ed86179757F77Cc0dd')
TEST_ADDR_USER_IDENTITY = string_to_ethereum_address(
    '0xaC29E71ACA2ff1C121673f0FC9d47e7616F692Ae')  # noqa: E501


def test_get_user_identity():
    """Test our Python port of AdEX `getUserIdentity()` works as expected.

    AdEX `getUserIdentity()`:
    https://github.com/AdExNetwork/adex-staking/blob/master/src/helpers/identity.js#L12
    """
    contract_address = Adex._get_user_identity(address=TEST_ADDR)
    assert contract_address == TEST_ADDR_USER_IDENTITY


def test_get_bond_id():
    """Test our Python port of AdEX `getBondId()` calculates the expected
    bond id using the LogBond event data.

    Bond tx (origin of `owner`, `amount`, `pool_id` and `nonce`):
    0x7944c10032e2a079d3f03ad57a90a93bde468b0baba84121be79790162215855

    Unbond tx (claiming and re-staking), its log index 283 contains the expected
    bond id:
    0xc59d65bc6c18e11a3650e8d7ec41a11f58016bbf843376c7f4cb0833402399f1
Example #24
0
    LiquidityPool,
    LiquidityPoolAsset,
    LiquidityPoolEvent,
    LiquidityPoolEventsBalance,
)
from rotkehlchen.chain.ethereum.typing import string_to_ethereum_address
from rotkehlchen.constants import ZERO
from rotkehlchen.constants.assets import A_USDT, A_WETH
from rotkehlchen.fval import FVal
from rotkehlchen.tests.utils.constants import A_DOLLAR_BASED
from rotkehlchen.typing import AssetAmount, Price, Timestamp

# Logic: Get balances

# Addresses
TEST_ADDRESS_1 = string_to_ethereum_address('0xfeF0E7635281eF8E3B705e9C5B86e1d3B0eAb397')
TEST_ADDRESS_2 = string_to_ethereum_address('0xcf2B8EeC2A9cE682822b252a1e9B78EedebEFB02')
TEST_ADDRESS_3 = string_to_ethereum_address('0x7777777777777777777777777777777777777777')


# Tokens without oracle data (unknown tokens)
A_SHL = EthereumToken('0x8542325B72C6D9fC0aD2Ca965A78435413a915A0')
A_CAR = EthereumToken('0x4D9e23a3842fE7Eb7682B9725cF6c507C424A41B')
A_BTR = EthereumToken('0xcbf15FB8246F679F9Df0135881CB29a3746f734b')

# Method: `_get_balances_graph`
# 'liquidityPositions' subgraph response data for TEST_ADDRESS_1
LIQUIDITY_POSITION_1 = {
    'id': '0x260e069dead76baac587b5141bb606ef8b9bab6c-0xfef0e7635281ef8e3b705e9c5b86e1d3b0eab397',
    'liquidityTokenBalance': '52.974048199782328795',
    'pair': {
Example #25
0
    def deserialize_from_db(
        cls,
        event_tuple: LiquidityPoolEventDBTuple,
    ) -> 'LiquidityPoolEvent':
        """Turns a tuple read from DB into an appropriate LiquidityPoolEvent.
        May raise a DeserializationError if something is wrong with the DB data
        Event_tuple index - Schema columns
        ----------------------------------
        0 - tx_hash
        1 - log_index
        2 - address
        3 - timestamp
        4 - type
        5 - pool_address
        6 - is_token0_unknown
        7 - token0_address
        8 - token0_symbol
        9 - token0_name
        10 - token0_decimals
        11 - is_token1_unknown
        12 - token1_address
        13 - token1_symbol
        14 - token1_name
        15 - token1_decimals
        16 - amount0
        17 - amount1
        18 - usd_price
        19 - lp_amount
        """
        db_event_type = event_tuple[4]
        if db_event_type not in {str(event_type) for event_type in EventType}:
            raise DeserializationError(
                f'Failed to deserialize event type. Unknown event: {db_event_type}.',
            )

        if db_event_type == str(EventType.MINT):
            event_type = EventType.MINT
        elif db_event_type == str(EventType.BURN):
            event_type = EventType.BURN
        else:
            raise ValueError(f'Unexpected event type case: {db_event_type}.')

        is_token0_unknown = event_tuple[6]
        is_token1_unknown = event_tuple[11]

        token0: Union[EthereumToken, UnknownEthereumToken]
        token1: Union[EthereumToken, UnknownEthereumToken]
        if is_token0_unknown:
            token0 = deserialize_unknown_ethereum_token_from_db(
                ethereum_address=event_tuple[7],
                symbol=event_tuple[8],
                name=event_tuple[9],
                decimals=event_tuple[10],
            )
        else:
            token0 = deserialize_ethereum_token_from_db(
                identifier=event_tuple[8])

        if is_token1_unknown:
            token1 = deserialize_unknown_ethereum_token_from_db(
                ethereum_address=event_tuple[12],
                symbol=event_tuple[13],
                name=event_tuple[14],
                decimals=event_tuple[15],
            )
        else:
            token1 = deserialize_ethereum_token_from_db(
                identifier=event_tuple[13])

        return cls(
            tx_hash=event_tuple[0],
            log_index=event_tuple[1],
            address=string_to_ethereum_address(event_tuple[2]),
            timestamp=deserialize_timestamp(event_tuple[3]),
            event_type=event_type,
            pool_address=string_to_ethereum_address(event_tuple[5]),
            token0=token0,
            token1=token1,
            amount0=deserialize_asset_amount(event_tuple[16]),
            amount1=deserialize_asset_amount(event_tuple[17]),
            usd_price=deserialize_price(event_tuple[18]),
            lp_amount=deserialize_asset_amount(event_tuple[19]),
        )
Example #26
0
import pytest
import requests

from rotkehlchen.chain.ethereum.typing import string_to_ethereum_address
from rotkehlchen.constants.assets import A_ETH, A_EUR
from rotkehlchen.constants.misc import ZERO
from rotkehlchen.exchanges.data_structures import Trade
from rotkehlchen.fval import FVal
from rotkehlchen.tests.utils.api import api_url_for, assert_proper_response_with_result
from rotkehlchen.tests.utils.exchanges import mock_exchange_data_in_db
from rotkehlchen.typing import AssetAmount, Fee, Location, Price, Timestamp, TradeType

UNISWAP_ADDR = string_to_ethereum_address('0xcaf012cB72f2c7152b255E091837E3a628F739e7')


@pytest.mark.parametrize('added_exchanges', [(Location.BINANCE, Location.POLONIEX)])
@pytest.mark.parametrize('ethereum_accounts', [[UNISWAP_ADDR]])
@pytest.mark.parametrize('ethereum_modules', [['uniswap']])
@pytest.mark.parametrize('start_with_valid_premium', [True])
def test_get_associated_locations(
    rotkehlchen_api_server_with_exchanges,
    added_exchanges,
    ethereum_accounts,  # pylint: disable=unused-argument
    start_with_valid_premium,  # pylint: disable=unused-argument
):
    rotki = rotkehlchen_api_server_with_exchanges.rest_api.rotkehlchen
    mock_exchange_data_in_db(added_exchanges, rotki)
    db = rotki.data.db

    db.add_trades([Trade(
        timestamp=Timestamp(1595833195),
Example #27
0
    A_ZRX,
)
from rotkehlchen.fval import FVal
from rotkehlchen.tests.utils.api import (
    api_url_for,
    assert_error_response,
    assert_ok_async_response,
    assert_proper_response_with_result,
    wait_for_async_task,
)
from rotkehlchen.tests.utils.constants import A_API3, A_BAND, A_MFT, A_SYN
from rotkehlchen.tests.utils.rotkehlchen import setup_balances
from rotkehlchen.typing import AssetAmount, Location, Price, Timestamp, TradeType

# Top holder of WBTC-WETH pool (0x1eff8af5d577060ba4ac8a29a13525bb0ee2a3d5)
BALANCER_TEST_ADDR1 = string_to_ethereum_address(
    '0x49a2DcC237a65Cc1F412ed47E0594602f6141936')
BALANCER_TEST_ADDR2 = string_to_ethereum_address(
    '0x029f388aC4D5C8BfF490550ce0853221030E822b')
BALANCER_TEST_ADDR3 = string_to_ethereum_address(
    '0x7716a99194d758c8537F056825b75Dd0C8FDD89f')
BALANCER_TEST_ADDR4 = string_to_ethereum_address(
    '0x231DC6af3C66741f6Cf618884B953DF0e83C1A2A')
BALANCER_TEST_ADDR3_POOL1 = EthereumToken.initialize(
    address=string_to_ethereum_address(
        '0x59A19D8c652FA0284f44113D0ff9aBa70bd46fB4'),
    symbol='BPT',
    protocol='balancer',
    underlying_tokens=[
        UnderlyingToken(address=string_to_ethereum_address(
            '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'),
                        weight=FVal(0.2)),  # noqa: E501  # WETH
Example #28
0
def test_avax_query_token_with_info(rotkehlchen_api_server):
    """Query DAI token to retrieve basic information"""

    response = requests.get(
        api_url_for(
            rotkehlchen_api_server,
            'erc20tokeninfoavax',
        ),
        json={
            'address':
            string_to_ethereum_address(
                '0xba7deebbfc5fa1100fb055a87773e1e99cd3507a'),
        },
    )

    result = assert_proper_response_with_result(response)
    assert result['decimals'] == 18
    assert result['symbol'] == 'DAI'
    assert result['name'] == 'Dai Stablecoin'

    # Test a contract without decimals/name/symbol methods
    response_2 = requests.get(
        api_url_for(
            rotkehlchen_api_server,
            'erc20tokeninfoavax',
        ),
        json={
            'address':
            string_to_ethereum_address(
                '0x7d655c57f71464B6f83811C55D84009Cd9f5221C'),
        },
    )

    result_2 = assert_proper_response_with_result(response_2)
    assert len(result_2.keys()) == 3
    assert all((value is None for value in result_2.values()))

    # Test an address that is not a contract

    response_3 = requests.get(
        api_url_for(
            rotkehlchen_api_server,
            'erc20tokeninfoavax',
        ),
        json={
            'address':
            string_to_ethereum_address(
                '0x00f195C9ed671173d618e7c03e4A987ef906C739'),
        },
    )

    result_3 = assert_proper_response_with_result(response_3)
    assert len(result_3.keys()) == 3
    assert all((value is None for value in result_3.values()))

    # Test an address that is not valid (this one has extra chars)
    response_4 = requests.get(
        api_url_for(
            rotkehlchen_api_server,
            'erc20tokeninfoavax',
        ),
        json={
            'address':
            string_to_ethereum_address(
                '0x4652D63f4750bCd9d5f5dAds96087485d31554b10F'),
        },
    )

    assert_error_response(
        response=response_4,
        contained_in_msg='is not an ethereum address',
        status_code=HTTPStatus.BAD_REQUEST,
    )
Example #29
0
def test_get_trade_with_1_token_pool(
        rotkehlchen_api_server,
        ethereum_accounts,  # pylint: disable=unused-argument
        rotki_premium_credentials,  # pylint: disable=unused-argument
        start_with_valid_premium,  # pylint: disable=unused-argument
):
    """
    Test the special case of a swap within an 1 token pool.
    This can probably happen if the controller has since removed tokens from the pool.
    """
    rotki = rotkehlchen_api_server.rest_api.rotkehlchen
    setup = setup_balances(
        rotki,
        ethereum_accounts=ethereum_accounts,
        btc_accounts=None,
        original_queries=['zerion', 'logs', 'blocknobytime'],
    )
    with ExitStack() as stack:
        # patch ethereum/etherscan to not autodetect tokens
        setup.enter_ethereum_patches(stack)
        response = requests.get(
            api_url_for(rotkehlchen_api_server,
                        'balancertradeshistoryresource'),
            json={
                'from_timestamp': 1621358338,
                'to_timestamp': 1621358340,
            },
        )
        result = assert_proper_response_with_result(response)

    db_trades = rotki.data.db.get_amm_swaps()
    assert len(db_trades) == 29

    address_trades = result[BALANCER_TEST_ADDR4]
    assert len(address_trades) == 1
    assert address_trades[0] == AMMTrade(
        trade_type=TradeType.BUY,
        base_asset=A_WETH,
        quote_asset=A_WBTC,
        amount=AssetAmount(FVal('0.205421420618533148')),
        rate=Price(FVal('0.07606382992071615428519015532')),
        trade_index=0,
        swaps=[
            AMMSwap(
                tx_hash=
                '0x4f9e0d8aa660a5d3db276a1ade038f7027f29838dd22d5276571d2e4ea7131ae',  # noqa: E501
                log_index=84,
                address=string_to_ethereum_address(
                    BALANCER_TEST_ADDR4),  # noqa: E501
                from_address=string_to_ethereum_address(
                    '0xFD3dFB524B2dA40c8a6D703c62BE36b5D8540626'
                ),  # noqa: E501
                to_address=string_to_ethereum_address(
                    '0x582818356331877553F3E9Cf9557b48e5DdbD54a'
                ),  # noqa: E501
                timestamp=Timestamp(1621358339),
                location=Location.BALANCER,
                token0=A_WBTC,
                token1=A_WETH,
                amount0_in=AssetAmount(FVal('0.01562514')),
                amount1_in=AssetAmount(ZERO),
                amount0_out=AssetAmount(ZERO),
                amount1_out=AssetAmount(FVal('0.205421420618533148')),
            ),
        ],
    ).serialize()
Example #30
0
    def query_tokens_for_addresses(
        self,
        addresses: List[ChecksumEthAddress],
        force_detection: bool,
    ) -> TokensReturn:
        """Queries/detects token balances for a list of addresses

        If an address's tokens were recently autodetected they are not detected again but the
        balances are simply queried. Unless force_detection is True.

        Returns the token balances of each address and the usd prices of the tokens
        """
        log.debug(
            'Querying/detecting token balances for all addresses',
            force_detection=force_detection,
        )
        ignored_assets = self.db.get_ignored_assets()
        exceptions = [
            # Ignore the veCRV balance in token query. It's already detected by
            # defi SDK as part of locked CRV in Vote Escrowed CRV. Which is the right way
            # to approach it as there is no way to assign a price to 1 veCRV. It
            # can be 1 CRV locked for 4 years or 4 CRV locked for 1 year etc.
            string_to_ethereum_address(
                '0x5f3b5DfEb7B28CDbD7FAba78963EE202a494e2A2'),
            # Ignore for now xsushi since is queried by defi SDK. We'll do it for now
            # since the SDK entry might return other tokens from sushi and we don't
            # fully support sushi now.
            string_to_ethereum_address(
                '0x8798249c2E607446EfB7Ad49eC89dD1865Ff4272'),
            # Ignore the following tokens. They are old tokens of upgraded contracts which
            # duplicated the balances at upgrade instead of doing a token swap.
            # e.g.: https://github.com/rotki/rotki/issues/3548
            # TODO: At some point we should actually remove them from the DB and
            # upgrade possible occurences in the user DB
            #
            # Old contract of Fetch.ai
            string_to_ethereum_address(
                '0x1D287CC25dAD7cCaF76a26bc660c5F7C8E2a05BD'),
        ]
        for asset in ignored_assets:  # don't query for the ignored tokens
            if asset.is_eth_token(
            ):  # type ignore since we know asset is a token
                exceptions.append(
                    EthereumToken.from_asset(
                        asset).ethereum_address)  # type: ignore
        all_tokens = GlobalDBHandler().get_ethereum_tokens(
            exceptions=exceptions,
            except_protocols=['balancer'],
        )
        # With etherscan with chunks > 120, we get request uri too large
        # so the limitation is not in the gas, but in the request uri length
        etherscan_chunks = list(
            get_chunks(all_tokens, n=ETHERSCAN_MAX_TOKEN_CHUNK_LENGTH))
        other_chunks = list(
            get_chunks(all_tokens, n=OTHER_MAX_TOKEN_CHUNK_LENGTH))
        now = ts_now()
        token_usd_price: Dict[EthereumToken, Price] = {}
        result = {}

        for address in addresses:
            saved_list = self.db.get_tokens_for_address_if_time(
                address=address, current_time=now)
            if force_detection or saved_list is None:
                balances = self.detect_tokens_for_address(
                    address=address,
                    token_usd_price=token_usd_price,
                    etherscan_chunks=etherscan_chunks,
                    other_chunks=other_chunks,
                )
            else:
                if len(saved_list) == 0:
                    continue  # Do not query if we know the address has no tokens

                balances = defaultdict(FVal)
                self._get_tokens_balance_and_price(
                    address=address,
                    tokens=saved_list,
                    balances=balances,
                    token_usd_price=token_usd_price,
                    call_order=None,  # use defaults
                )

            result[address] = balances

        return result, token_usd_price