Esempio n. 1
0
    def _deserialize_channel_withdraw(
            raw_event: Dict[str, Any],
            identity_address_map: Dict[ChecksumAddress, ChecksumAddress],
    ) -> ChannelWithdraw:
        """Deserialize a channel withdraw event. Only for Tom pool.

        It may raise KeyError.

        TODO: use bidict or already pass the inverse identity_address_map.
        """
        inverse_identity_address_map = {
            address: identity for identity, address in identity_address_map.items()
        }
        address = to_checksum_address(raw_event['user'])
        identity_address = inverse_identity_address_map[address]
        amount = FVal(raw_event['amount']) / ADX_AMOUNT_MANTISSA
        return ChannelWithdraw(
            tx_hash=HexStr(raw_event['id'].split(':')[0]),
            address=address,
            identity_address=identity_address,
            timestamp=Timestamp(raw_event['timestamp']),
            value=Balance(amount=amount),
            channel_id=HexStr(raw_event['channelId']),
            pool_id=TOM_POOL_ID,
        )
Esempio n. 2
0
 def _get_user_identity(address: ChecksumAddress) -> ChecksumEthAddress:
     """Given an address (signer) returns its protocol user identity.
     """
     return generate_address_via_create2(
         address=HexAddress(HexStr(IDENTITY_FACTORY_ADDR)),
         salt=HexStr(CREATE2_SALT),
         init_code=HexStr(IDENTITY_PROXY_INIT_CODE.format(signer_address=address)),
     )
Esempio n. 3
0
def test_generate_address_via_create2(
    address,
    salt,
    init_code,
    expected_contract_address,
):
    """Test the CREATE2 opcode Python implementation.
    """
    contract_address = generate_address_via_create2(
        address=HexAddress(address),
        salt=HexStr(salt),
        init_code=HexStr(init_code),
    )
    assert contract_address == to_checksum_address(expected_contract_address)
Esempio n. 4
0
    def _deserialize_bond(
            self,
            raw_event: Dict[str, Any],
            identity_address_map: Dict[ChecksumAddress, ChecksumAddress],
    ) -> Bond:
        """Deserialize a bond event.

        It may raise KeyError.
        """
        event_core_data = self._deserialize_event_core_data(
            raw_event=raw_event,
            identity_address_map=identity_address_map,
        )
        amount_int = int(raw_event['amount'])
        amount = FVal(raw_event['amount']) / ADX_AMOUNT_MANTISSA
        pool_id = HexStr(raw_event['poolId'])
        nonce = int(raw_event['nonce'])
        bond_id = self._get_bond_id(
            identity_address=event_core_data.identity_address,
            amount=amount_int,
            pool_id=pool_id,
            nonce=nonce,
        )
        return Bond(
            tx_hash=event_core_data.tx_hash,
            address=event_core_data.address,
            identity_address=event_core_data.identity_address,
            timestamp=event_core_data.timestamp,
            bond_id=bond_id,
            value=Balance(amount=amount),
            pool_id=pool_id,
            nonce=nonce,
            slashed_at=Timestamp(int(raw_event['slashedAtStart'])),
        )
Esempio n. 5
0
 def _get_bond_id(
         identity_address: ChecksumAddress,
         amount: int,
         pool_id: HexStr,
         nonce: int,
 ) -> HexStr:
     """Given a LogBond event data, return its `bondId`.
     """
     arg_types = ['address', 'address', 'uint', 'bytes32', 'uint']
     args = [STAKING_ADDR, identity_address, amount, pool_id, nonce]
     return HexStr(Web3.keccak(Web3().codec.encode_abi(arg_types, args)).hex())
Esempio n. 6
0
    def _deserialize_event_core_data(
            raw_event: Dict[str, Any],
            identity_address_map: Dict[ChecksumAddress, ChecksumAddress],
    ) -> EventCoreData:
        """Deserialize the common event attributes.

        It may raise KeyError.
        Id for unbond and unbond request events is 'tx_hash:address'.
        """
        identity_address = to_checksum_address(raw_event['owner'])
        return EventCoreData(
            tx_hash=HexStr(raw_event['id'].split(':')[0]),
            address=identity_address_map[identity_address],
            identity_address=identity_address,
            timestamp=Timestamp(raw_event['timestamp']),
        )
Esempio n. 7
0
    def _deserialize_unbond(
            self,
            raw_event: Dict[str, Any],
            identity_address_map: Dict[ChecksumAddress, ChecksumAddress],
    ) -> Unbond:
        """Deserialize an unbond event.

        It may raise KeyError.
        """
        event_core_data = self._deserialize_event_core_data(
            raw_event=raw_event,
            identity_address_map=identity_address_map,
        )
        return Unbond(
            tx_hash=event_core_data.tx_hash,
            address=event_core_data.address,
            identity_address=event_core_data.identity_address,
            timestamp=event_core_data.timestamp,
            bond_id=HexStr(raw_event['bondId']),
            value=Balance(),
        )
Esempio n. 8
0
class UnbondRequest:
    tx_hash: HexStr  # from unbond.id
    address: ChecksumAddress
    identity_address: ChecksumAddress
    timestamp: Timestamp
    bond_id: HexStr
    unlock_at: Timestamp  # from unbondRequest.willUnlock
    value: Balance  # from bond.amount
    pool_id: HexStr = HexStr('')  # from bond.pool_id

    def serialize(self) -> Dict[str, Any]:
        return {
            'tx_hash': self.tx_hash,
            'identity_address': self.identity_address,
            'timestamp': self.timestamp,
            'bond_id': self.bond_id,
            'pool_id': self.pool_id,
            'pool_name': POOL_ID_POOL_NAME.get(self.pool_id, None),
            'value': self.value.serialize(),
            'event_type': str(AdexEventType.UNBOND_REQUEST),
        }

    def to_db_tuple(self) -> AdexEventDBTuple:
        return (
            str(self.tx_hash),
            str(self.address),
            str(self.identity_address),
            int(self.timestamp),
            str(AdexEventType.UNBOND_REQUEST),
            str(self.pool_id),
            str(self.value.amount),
            str(self.value.usd_value),
            str(self.bond_id),
            None,  # nonce
            None,  # slashed_at
            int(self.unlock_at),
            None,  # channel_id
            None,  # token
        )
Esempio n. 9
0
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

    AdEX `getBondId()`:
    https://github.com/AdExNetwork/adex-staking/blob/master/src/helpers/bonds.js#L5
    """
    expected_bond_id = '0xf1570226030766ce222ffa240231bbfc2a8de995516e63927c672b1b46c7f2c6'
    bond_id = Adex._get_bond_id(
        identity_address=TEST_ADDR_USER_IDENTITY,
        amount=10661562521452745365522,
        pool_id=HexStr(TOM_POOL_ID),
        nonce=1596569185,
    )
    assert bond_id == expected_bond_id
Esempio n. 10
0
def deserialize_ethereum_address(symbol: str) -> ChecksumEthAddress:
    return ChecksumEthAddress(HexAddress(HexStr(symbol)))
Esempio n. 11
0
def deserialize_adex_event_from_db(
    event_tuple: AdexEventDBTuple,
) -> Union[Bond, Unbond, UnbondRequest, ChannelWithdraw]:
    """Turns a tuple read from DB into an appropriate AdEx event.
    May raise a DeserializationError if something is wrong with the DB data.

    Event_tuple index - Schema columns
    ----------------------------------
    0 - tx_hash
    1 - address
    2 - identity_address
    3 - timestamp
    4 - type
    5 - pool_id
    6 - amount
    7 - usd_value
    8 - bond_id
    9 - nonce
    10 - slashed_at
    11 - unlock_at
    12 - channel_id
    13 - token
    """
    db_event_type = event_tuple[4]
    if db_event_type not in {str(event_type) for event_type in AdexEventType}:
        raise DeserializationError(
            f'Failed to deserialize event type. Unknown event: {db_event_type}.',
        )

    tx_hash = HexStr(event_tuple[0])
    address = deserialize_ethereum_address(event_tuple[1])
    identity_address = deserialize_ethereum_address(event_tuple[2])
    timestamp = deserialize_timestamp(event_tuple[3])
    pool_id = HexStr(event_tuple[5])
    amount = deserialize_asset_amount(event_tuple[6])
    usd_value = deserialize_asset_amount(event_tuple[7])
    value = Balance(amount=amount, usd_value=usd_value)

    if db_event_type == str(AdexEventType.BOND):
        if any(event_tuple[idx] is None for idx in (8, 9, 10)):
            raise DeserializationError(
                f'Failed to deserialize bond event. Unexpected data: {event_tuple}.',
            )

        return Bond(
            tx_hash=tx_hash,
            address=address,
            identity_address=identity_address,
            timestamp=timestamp,
            pool_id=pool_id,
            value=value,
            bond_id=HexStr(cast(str, event_tuple[8])),
            nonce=cast(int, event_tuple[9]),
            slashed_at=Timestamp(cast(int, event_tuple[10])),
        )

    if db_event_type == str(AdexEventType.UNBOND):
        if any(event_tuple[idx] is None for idx in (8, )):
            raise DeserializationError(
                f'Failed to deserialize bond event. Unexpected data: {event_tuple}.',
            )

        return Unbond(
            tx_hash=tx_hash,
            address=address,
            identity_address=identity_address,
            timestamp=timestamp,
            pool_id=pool_id,
            value=value,
            bond_id=HexStr(cast(str, event_tuple[8])),
        )

    if db_event_type == str(AdexEventType.UNBOND_REQUEST):
        if any(event_tuple[idx] is None for idx in (8, 11)):
            raise DeserializationError(
                f'Failed to deserialize unbond request event. Unexpected data: {event_tuple}.',
            )

        return UnbondRequest(
            tx_hash=tx_hash,
            address=address,
            identity_address=identity_address,
            timestamp=timestamp,
            pool_id=pool_id,
            value=value,
            bond_id=HexStr(cast(str, event_tuple[8])),
            unlock_at=Timestamp(cast(int, event_tuple[11])),
        )

    if db_event_type == str(AdexEventType.CHANNEL_WITHDRAW):
        # NB: `token` (event_tuple[13]) could be None, do not check below.
        if any(event_tuple[idx] is None for idx in (12, )):
            raise DeserializationError(
                f'Failed to deserialize unbond request event. Unexpected data: {event_tuple}.',
            )

        token = None
        if event_tuple[13] is not None:
            try:
                token = EthereumToken(event_tuple[13])
            except (UnknownAsset, UnsupportedAsset) as e:
                asset_tag = 'Unknown' if isinstance(
                    e, UnknownAsset) else 'Unsupported'
                raise DeserializationError(
                    f'{asset_tag} {e.asset_name} found while processing adex event. '
                    f'Unexpected data: {event_tuple}', ) from e

        return ChannelWithdraw(
            tx_hash=tx_hash,
            address=address,
            identity_address=identity_address,
            timestamp=timestamp,
            value=value,
            pool_id=pool_id,
            channel_id=HexStr(cast(str, event_tuple[12])),
            token=token,
        )

    raise DeserializationError(
        f'Failed to deserialize event. Unexpected event type case: {db_event_type}.',
    )
Esempio n. 12
0
from dataclasses import asdict

from eth_utils.typing import HexAddress, HexStr

from rotkehlchen.assets.asset import EthereumToken
from rotkehlchen.assets.unknown_asset import UnknownEthereumToken
from rotkehlchen.typing import ChecksumEthAddress

SHUF_ETHEREUM_ADDRESS = ChecksumEthAddress(
    HexAddress(HexStr('0x3A9FfF453d50D4Ac52A6890647b823379ba36B9E')), )
SHUF_SYMBOL = 'SHUF'
SHUF_NAME = 'Shuffle.Monster V3'
SHUF_DECIMALS = 18


# Test initialization
def test_init_default():
    ue_token = UnknownEthereumToken(
        ethereum_address=SHUF_ETHEREUM_ADDRESS,
        symbol=SHUF_SYMBOL,
    )
    assert ue_token.ethereum_address == SHUF_ETHEREUM_ADDRESS
    assert ue_token.symbol == SHUF_SYMBOL
    assert ue_token.name is None
    assert ue_token.decimals is None


# Test operators
def test_eq():
    ue_token_1 = UnknownEthereumToken(
        ethereum_address=SHUF_ETHEREUM_ADDRESS,
Esempio n. 13
0
from dataclasses import dataclass
from enum import Enum
from typing import Any, Callable, Dict, List, NamedTuple, Optional, Tuple, Union

from eth_typing.evm import ChecksumAddress
from eth_utils.typing import HexStr

from rotkehlchen.accounting.structures import Balance
from rotkehlchen.assets.asset import EthereumToken
from rotkehlchen.fval import FVal
from rotkehlchen.typing import Timestamp

# Pools data
TOM_POOL_ID = HexStr(
    '0x2ce0c96383fb229d9776f33846e983a956a7d95844fac57b180ed0071d93bb28')
POOL_ID_POOL_NAME = {
    TOM_POOL_ID: 'Tom',
}

AdexEventDBTuple = (
    Tuple[str,  # tx_hash
          str,  # address
          str,  # identity_address
          int,  # timestamp
          str,  # type
          str,  # pool_id
          str,  # amount
          str,  # usd_value
          Optional[str],  # bond_id
          Optional[int],  # nonce
          Optional[int],  # slashed_at