示例#1
0
def asset_from_uphold(symbol: str) -> Asset:
    """May raise:
    - DeserializationError
    - UnsupportedAsset
    - UnknownAsset
    """
    if not isinstance(symbol, str):
        raise DeserializationError(
            f'Got non-string type {type(symbol)} for uphold asset')

    name = UPHOLD_TO_WORLD.get(symbol, symbol)
    return symbol_to_asset_or_token(name)
示例#2
0
def deserialize_timestamp_from_date(date: str, formatstr: str,
                                    location: str) -> Timestamp:
    """Deserializes a timestamp from a date entry depending on the format str

    Can throw DeserializationError if the data is not as expected
    """
    if not date:
        raise DeserializationError(
            f'Failed to deserialize a timestamp from a null entry in {location}',
        )

    if not isinstance(date, str):
        raise DeserializationError(
            f'Failed to deserialize a timestamp from a {type(date)} entry in {location}',
        )

    try:
        return Timestamp(create_timestamp(datestr=date, formatstr=formatstr))
    except ValueError:
        raise DeserializationError(
            f'Failed to deserialize {date} {location} timestamp entry')
示例#3
0
def deserialize_timestamp_from_date(
    date: Optional[str],
    formatstr: str,
    location: str,
    skip_milliseconds: bool = False,
) -> Timestamp:
    """Deserializes a timestamp from a date entry depending on the format str

    formatstr can also have a special value of 'iso8601' in which case the iso8601
    function will be used.

    Can throw DeserializationError if the data is not as expected
    """
    if not date:
        raise DeserializationError(
            f'Failed to deserialize a timestamp from a null entry in {location}',
        )

    if not isinstance(date, str):
        raise DeserializationError(
            f'Failed to deserialize a timestamp from a {type(date)} entry in {location}',
        )

    if skip_milliseconds:
        # Seems that poloniex added milliseconds in their timestamps.
        # https://github.com/rotki/rotki/issues/1631
        # We don't deal with milliseconds in Rotki times so we can safely remove it
        splits = date.split('.', 1)
        if len(splits) == 2:
            date = splits[0]

    if formatstr == 'iso8601':
        return iso8601ts_to_timestamp(date)

    try:
        return Timestamp(create_timestamp(datestr=date, formatstr=formatstr))
    except ValueError as e:
        raise DeserializationError(
            f'Failed to deserialize {date} {location} timestamp entry',
        ) from e
示例#4
0
    def _deserialize_bond(
        self,
        raw_event: Dict[str, Any],
        identity_address_map: Dict[ChecksumAddress, ChecksumAddress],
    ) -> Bond:
        """Deserialize a bond event.

        May raise DeserializationError.
        """
        try:
            adex_event = self._deserialize_adex_staking_event(
                raw_event=raw_event,
                identity_address_map=identity_address_map,
                case='bond',
            )
            amount_int = int(raw_event['amount'])
            amount = FVal(raw_event['amount']) / ADX_AMOUNT_MANTISSA
            pool_id = raw_event['poolId']
            nonce = int(raw_event['nonce'])
            bond_id = self._get_bond_id(
                identity_address=adex_event.identity_address,
                amount=amount_int,
                pool_id=pool_id,
                nonce=nonce,
            )
            slashed_at = deserialize_timestamp(raw_event['slashedAtStart'])
        except (DeserializationError, KeyError, ValueError) as e:
            msg = str(e)
            if isinstance(e, KeyError):
                msg = f'Missing key in event: {msg}.'

            log.error(
                'Failed to deserialize an AdEx bond event',
                error=msg,
                raw_event=raw_event,
                identity_address_map=identity_address_map,
            )
            raise DeserializationError(
                'Failed to deserialize an AdEx bond event. Check logs for more details',
            ) from e

        return Bond(
            tx_hash=adex_event.tx_hash,
            address=adex_event.address,
            identity_address=adex_event.identity_address,
            timestamp=adex_event.timestamp,
            bond_id=bond_id,
            value=Balance(amount=amount),
            pool_id=pool_id,
            nonce=nonce,
            slashed_at=slashed_at,
        )
示例#5
0
    def _deserialize_asset_movement(
            raw_movement: Dict[str, Any],
    ) -> AssetMovement:
        """Process a deposit/withdrawal user transaction from Bitstamp and
        deserialize it.

        Can raise DeserializationError.

        From Bitstamp documentation, deposits/withdrawals can have a fee
        (the amount is expected to be in the currency involved)
        https://www.bitstamp.net/fee-schedule/

        Endpoint docs:
        https://www.bitstamp.net/api/#user-transactions
        """
        type_ = deserialize_int_from_str(raw_movement['type'], 'bitstamp asset movement')
        category: AssetMovementCategory
        if type_ == 0:
            category = AssetMovementCategory.DEPOSIT
        elif type_ == 1:
            category = AssetMovementCategory.WITHDRAWAL
        else:
            raise AssertionError(f'Unexpected Bitstamp asset movement case: {type_}.')

        timestamp = deserialize_timestamp_from_bitstamp_date(raw_movement['datetime'])
        amount: FVal
        fee_asset: Asset
        for symbol in BITSTAMP_ASSET_MOVEMENT_SYMBOLS:
            amount = deserialize_asset_amount(raw_movement.get(symbol, '0'))
            if amount != ZERO:
                fee_asset = Asset(symbol)
                break

        if amount == ZERO:
            raise DeserializationError(
                'Could not deserialize Bitstamp asset movement from user transaction. '
                f'Unexpected asset amount combination found in: {raw_movement}.',
            )

        asset_movement = AssetMovement(
            timestamp=timestamp,
            location=Location.BITSTAMP,
            category=category,
            address=None,  # requires query "crypto_transactions" endpoint
            transaction_id=None,  # requires query "crypto_transactions" endpoint
            asset=fee_asset,
            amount=abs(amount),
            fee_asset=fee_asset,
            fee=deserialize_fee(raw_movement['fee']),
            link=str(raw_movement['id']),
        )
        return asset_movement
示例#6
0
def deserialize_int_from_hex(symbol: str, location: str) -> int:
    """Takes a hex string and turns it into an integer. Some apis returns 0x as
    a hex int and this may be an error. So we handle this as return 0 here.

    May Raise:
    - DeserializationError if the given data are in an unexpected format.
    """
    if not isinstance(symbol, str):
        raise DeserializationError(
            'Expected hex string but got {type(symbol)} at {location}')

    if symbol == '0x':
        return 0

    try:
        result = int(symbol, 16)
    except ValueError:
        raise DeserializationError(
            f'Could not turn string "{symbol}" into an integer at {location}',
        )

    return result
示例#7
0
    def deserialize(cls: Type['TradeType'], symbol: str) -> 'TradeType':
        """Overriding deserialize here since it can have different wordings for the same type
        so the automatic deserialization does not work
        """
        if not isinstance(symbol, str):
            raise DeserializationError(
                f'Failed to deserialize trade type symbol from {type(symbol)} entry',
            )

        if symbol in ('buy', 'LIMIT_BUY', 'BUY', 'Buy'):
            return TradeType.BUY
        if symbol in ('sell', 'LIMIT_SELL', 'SELL', 'Sell'):
            return TradeType.SELL
        if symbol in ('settlement_buy', 'settlement buy'):
            return TradeType.SETTLEMENT_BUY
        if symbol in ('settlement_sell', 'settlement sell'):
            return TradeType.SETTLEMENT_SELL

        # else
        raise DeserializationError(
            f'Failed to deserialize trade type symbol. Unknown symbol {symbol} for trade type',
        )
示例#8
0
def asset_from_binance(binance_name: str) -> Asset:
    if not isinstance(binance_name, str):
        raise DeserializationError(
            f'Got non-string type {type(binance_name)} for binance asset')

    if binance_name in UNSUPPORTED_BINANCE_ASSETS:
        raise UnsupportedAsset(binance_name)

    if binance_name in RENAMED_BINANCE_ASSETS:
        return Asset(RENAMED_BINANCE_ASSETS[binance_name])

    name = BINANCE_TO_WORLD.get(binance_name, binance_name)
    return Asset(name)
示例#9
0
def deserialize_blocknumber(symbol: Union[str, int]) -> int:
    """Takes a block number value which can either be an int or a hex string and
    turns it into an integer block number value

    May Raise:
    - DeserializationError if the given data are in an unexpected format.
    """
    if isinstance(symbol, int):
        block_number = symbol
    elif isinstance(symbol, str):
        try:
            block_number = int(symbol, 16)
        except ValueError:
            raise DeserializationError(
                f'Could not turn string "{symbol}" into an integer block number',
            )
    else:
        raise DeserializationError(
            f'Unexpected type {type(symbol)} given to deserialize_blocknumber()',
        )

    return block_number
示例#10
0
def deserialize_trade_type_from_db(symbol: str) -> TradeType:
    """Takes a string from the DB and attempts to turn it into a TradeType

    Can throw DeserializationError if the symbol is not as expected
    """
    if not isinstance(symbol, str):
        raise DeserializationError(
            f'Failed to deserialize trade type symbol from {type(symbol)} entry',
        )

    if symbol == 'A':
        return TradeType.BUY
    elif symbol == 'B':
        return TradeType.SELL
    elif symbol == 'C':
        return TradeType.SETTLEMENT_BUY
    elif symbol == 'D':
        return TradeType.SETTLEMENT_SELL
    else:
        raise DeserializationError(
            f'Failed to deserialize trade type symbol. Unknown DB symbol {symbol} for trade type',
        )
示例#11
0
def deserialize_timestamp(timestamp: Union[int, str, FVal]) -> Timestamp:
    """Deserializes a timestamp from a json entry. Given entry can either be a
    string or an int.

    Can throw DeserializationError if the data is not as expected
    """
    if timestamp is None:
        raise DeserializationError(
            'Failed to deserialize a timestamp entry from a null entry')

    if isinstance(timestamp, int):
        processed_timestamp = Timestamp(timestamp)
    elif isinstance(timestamp, FVal):
        try:
            processed_timestamp = Timestamp(timestamp.to_int(exact=True))
        except ConversionError:
            # An fval was not representing an exact int
            raise DeserializationError(
                'Tried to deserialize a timestamp fron a non-exact int FVal entry',
            )
    elif isinstance(timestamp, str):
        try:
            processed_timestamp = Timestamp(int(timestamp))
        except ValueError:
            # String could not be turned to an int
            raise DeserializationError(
                f'Failed to deserialize a timestamp entry from string {timestamp}',
            )
    else:
        raise DeserializationError(
            f'Failed to deserialize a timestamp entry. Unexpected type {type(timestamp)} given',
        )

    if processed_timestamp < 0:
        raise DeserializationError(
            f'Failed to deserialize a timestamp entry. Timestamps can not have'
            f' negative values. Given value was {processed_timestamp}', )

    return processed_timestamp
示例#12
0
def deserialize_timestamp_from_binance(time: int) -> Timestamp:
    """Deserializes a timestamp from a binance api query result entry
    Kraken has timestamps in integer but also including milliseconds


    Can throw DeserializationError if the data is not as expected
    """
    if not isinstance(time, int):
        raise DeserializationError(
            f'Failed to deserialize a timestamp entry from a {type(time)} entry in binance',
        )

    return Timestamp(int(time / 1000))
示例#13
0
def deserialize_trade_type(symbol: str) -> TradeType:
    """Takes a string and attempts to turn it into a TradeType

    Can throw DeserializationError if the symbol is not as expected
    """
    if not isinstance(symbol, str):
        raise DeserializationError(
            f'Failed to deserialize trade type symbol from {type(symbol)} entry',
        )

    if symbol in ('buy', 'LIMIT_BUY', 'BUY', 'Buy'):
        return TradeType.BUY
    elif symbol in ('sell', 'LIMIT_SELL', 'SELL', 'Sell'):
        return TradeType.SELL
    elif symbol == 'settlement_buy':
        return TradeType.SETTLEMENT_BUY
    elif symbol == 'settlement_sell':
        return TradeType.SETTLEMENT_SELL
    else:
        raise DeserializationError(
            f'Failed to deserialize trade type symbol. Unknown symbol {symbol} for trade type',
        )
示例#14
0
def asset_from_iconomi(symbol: str) -> Asset:
    """May raise:
    - DeserializationError
    - UnsupportedAsset
    - UnknownAsset
    """
    if not isinstance(symbol, str):
        raise DeserializationError(f'Got non-string type {type(symbol)} for iconomi asset')
    symbol = symbol.upper()
    if symbol in UNSUPPORTED_ICONOMI_ASSETS:
        raise UnsupportedAsset(symbol)
    name = ICONOMI_TO_WORLD.get(symbol, symbol)
    return symbol_to_asset_or_token(name)
示例#15
0
def asset_from_cryptocom(cryptocom_name: str) -> Asset:
    """May raise:
    - DeserializationError
    - UnsupportedAsset
    - UnknownAsset
    """
    if not isinstance(cryptocom_name, str):
        raise DeserializationError(
            f'Got non-string type {type(cryptocom_name)} for cryptocom asset',
        )

    symbol = CRYPTOCOM_TO_WORLD.get(cryptocom_name, cryptocom_name)
    return symbol_to_asset_or_token(symbol)
示例#16
0
def hex_or_bytes_to_address(value: Union[bytes, str]) -> ChecksumEthAddress:
    """Turns a 32bit bytes/HexBytes or a hexstring into an address

    May raise:
    - DeserializationError if it can't convert a value to an int or if an unexpected
    type is given.
    """
    try:
        hexstr = hex_or_bytes_to_str(value)
    except ConversionError as e:
        raise DeserializationError(
            f'Could not turn {value!r} to an ethereum address') from e
    return ChecksumEthAddress(to_checksum_address('0x' + hexstr[26:]))
示例#17
0
def deserialize_fval(
    value: AcceptableFValInitInput,
    name: str,
    location: str,
) -> FVal:
    try:
        result = FVal(value)
    except ValueError as e:
        raise DeserializationError(
            f'Failed to deserialize value entry: {str(e)} for {name} during {location}'
        ) from e  # noqa: E501

    return result
示例#18
0
def deserialize_ethereum_address(symbol: str) -> ChecksumEthAddress:
    """Deserialize a symbol, check that it's a valid ethereum address
    and return it checksummed.

    This function can raise DeserializationError if the address is not
    valid
    """
    try:
        return to_checksum_address(symbol)
    except ValueError as e:
        raise DeserializationError(
            f'Invalid ethereum address: {symbol}',
        ) from e
示例#19
0
    def _get_trade_pair_data_from_transaction(raw_result: Dict[str, Any]) -> TradePairData:
        """Given a user transaction that contains the base and quote assets'
        symbol as keys, return the Bitstamp trade pair data (raw pair str,
        base/quote assets raw symbols, and TradePair).

        NB: any custom pair conversion (e.g. from Bitstamp asset symbol to world)
        should happen here.

        Can raise DeserializationError.
        """
        try:
            pair = [key for key in raw_result.keys() if '_' in key and key != 'order_id'][0]
        except IndexError as e:
            raise DeserializationError(
                'Could not deserialize Bitstamp trade pair from user transaction. '
                f'Trade pair not found in: {raw_result}.',
            ) from e

        # NB: `pair_get_assets()` is not used for simplifying the calls and
        # storing the raw pair strings.
        base_asset_symbol, quote_asset_symbol = pair.split('_')
        try:
            base_asset = asset_from_bitstamp(base_asset_symbol)
            quote_asset = asset_from_bitstamp(quote_asset_symbol)
        except (UnknownAsset, UnsupportedAsset) as e:
            log.error(str(e))
            asset_tag = 'Unknown' if isinstance(e, UnknownAsset) else 'Unsupported'
            raise DeserializationError(
                f'{asset_tag} {e.asset_name} found while processing trade pair.',
            ) from e

        return TradePairData(
            pair=pair,
            base_asset_symbol=base_asset_symbol,
            quote_asset_symbol=quote_asset_symbol,
            base_asset=base_asset,
            quote_asset=quote_asset,
            trade_pair=TradePair(f'{base_asset.identifier}_{quote_asset.identifier}'),
        )
示例#20
0
文件: typing.py 项目: jsloane/rotki
    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]),
        )
示例#21
0
def deserialize_action_type_from_db(symbol: str) -> ActionType:
    """Takes a string from the DB and attempts to turn it into an ActionType

    Can throw DeserializationError if the symbol is not as expected
    """
    if not isinstance(symbol, str):
        raise DeserializationError(
            f'Failed to deserialize action type symbol from {type(symbol)} entry',
        )

    if symbol == 'A':
        return ActionType.TRADE
    if symbol == 'B':
        return ActionType.ASSET_MOVEMENT
    if symbol == 'C':
        return ActionType.ETHEREUM_TX
    if symbol == 'D':
        return ActionType.LEDGER_ACTION

    # else
    raise DeserializationError(
        f'Failed to deserialize action type symbol. Unknown DB '
        f'symbol {symbol} for trade type', )
示例#22
0
def deserialize_optional_to_fval(
    value: Optional[AcceptableFValInitInput],
    name: str,
    location: str,
) -> FVal:
    """
    Deserializes an FVal from a field that was optional and if None raises DeserializationError
    """
    if value is None:
        raise DeserializationError(
            f'Failed to deserialize value entry for {name} during {location} since null was given',
        )

    return deserialize_fval(value=value, name=name, location=location)
示例#23
0
文件: asset.py 项目: zalam003/rotki
    def __post_init__(self, form_with_incomplete_data: bool = False) -> None:
        super().__post_init__()

        # TODO: figure out a way to move this out. Moved in here due to cyclic imports
        from rotkehlchen.assets.resolver import AssetResolver  # isort:skip  # noqa: E501  # pylint: disable=import-outside-toplevel

        data = AssetResolver().get_asset_data(self.identifier)  # pylint: disable=no-member

        if not data.ethereum_address:
            raise DeserializationError(
                'Tried to initialize a non Ethereum asset as Ethereum Token', )

        object.__setattr__(self, 'ethereum_address', data.ethereum_address)
        object.__setattr__(self, 'decimals', data.decimals)
示例#24
0
def asset_from_bittrex(bittrex_name: str) -> Asset:
    """May raise:
    - DeserializationError
    - UnsupportedAsset
    - UnknownAsset
    """
    if not isinstance(bittrex_name, str):
        raise DeserializationError(f'Got non-string type {type(bittrex_name)} for bittrex asset')

    if bittrex_name in UNSUPPORTED_BITTREX_ASSETS:
        raise UnsupportedAsset(bittrex_name)

    name = BITTREX_TO_WORLD.get(bittrex_name, bittrex_name)
    return Asset(name)
示例#25
0
def hexstr_to_int(value: str) -> int:
    """Turns a hexstring into an int

    May raise:
    - DeserializationError if it can't convert a value to an int or if an unexpected
    type is given.
    """
    try:
        int_value = int(value, 16)
    except ValueError as e:
        raise DeserializationError(
            f'Could not convert string "{value}" to an int') from e

    return int_value
示例#26
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)

    name = FTX_TO_WORLD.get(ftx_name, ftx_name)
    return symbol_to_asset_or_token(name)
示例#27
0
def asset_from_poloniex(poloniex_name: str) -> Asset:
    """May raise:
    - DeserializationError
    - UnsupportedAsset
    - UnknownAsset
    """
    if not isinstance(poloniex_name, str):
        raise DeserializationError(f'Got non-string type {type(poloniex_name)} for poloniex asset')

    if poloniex_name in UNSUPPORTED_POLONIEX_ASSETS:
        raise UnsupportedAsset(poloniex_name)

    our_name = POLONIEX_TO_WORLD.get(poloniex_name, poloniex_name)
    return Asset(our_name)
示例#28
0
 def deserialize(value: str) -> 'LiquityStakeEventType':
     if value == 'stakeCreated':
         return LiquityStakeEventType.STAKE_CREATED
     if value == 'stakeIncreased':
         return LiquityStakeEventType.STAKE_INCREASED
     if value == 'stakeDecreased':
         return LiquityStakeEventType.STAKE_DECREASED
     if value == 'stakeRemoved':
         return LiquityStakeEventType.STAKE_REMOVED
     if value == 'gainsWithdrawn':
         return LiquityStakeEventType.STAKE_WITHDRAWN
     # else
     raise DeserializationError(
         f'Encountered unknown LiquityStakeEventType value {value}')
示例#29
0
def asset_from_kucoin(kucoin_name: str) -> Asset:
    """May raise:
    - DeserializationError
    - UnsupportedAsset
    - UnknownAsset
    """
    if not isinstance(kucoin_name, str):
        raise DeserializationError(f'Got non-string type {type(kucoin_name)} for kucoin asset')

    if kucoin_name in UNSUPPORTED_KUCOIN_ASSETS:
        raise UnsupportedAsset(kucoin_name)

    name = KUCOIN_TO_WORLD.get(kucoin_name, kucoin_name)
    return Asset(name)
示例#30
0
def deserialize_int_from_hex_or_int(symbol: Union[str, int],
                                    location: str) -> int:
    """Takes a symbol which can either be an int or a hex string and
    turns it into an integer

    May Raise:
    - DeserializationError if the given data are in an unexpected format.
    """
    if isinstance(symbol, int):
        result = symbol
    elif isinstance(symbol, str):
        try:
            result = int(symbol, 16)
        except ValueError:
            raise DeserializationError(
                f'Could not turn string "{symbol}" into an integer {location}',
            )
    else:
        raise DeserializationError(
            f'Unexpected type {type(symbol)} given to '
            f'deserialize_int_from_hex_or_int() for {location}', )

    return result