Skip to content

Commit

Permalink
Fixed some errors handling
Browse files Browse the repository at this point in the history
  • Loading branch information
igorsereda committed Feb 5, 2025
1 parent c056812 commit 1fae624
Show file tree
Hide file tree
Showing 23 changed files with 210 additions and 162 deletions.
2 changes: 1 addition & 1 deletion dex_screener/dipdup.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ datasources:
node:
kind: substrate.node
url: https://rpc.hydradx.cloud
ws_url: wss://rpc.hydradx.cloud
ws_url: wss://hydration-rpc.n.dwellir.com

indexes:
hydradx_events:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from dex_screener.handlers.hydradx.asset.asset_location.abstract_asset_native_location import AbstractAssetNativeLocation
from dex_screener.handlers.hydradx.asset.asset_location.assethub_asset_native_location import AssetHubAssetNativeLocation
from dex_screener.handlers.hydradx.asset.asset_location.pendulum_asset_native_location import PendulumAssetNativeLocation
from dex_screener.handlers.hydradx.asset.asset_type.exception import InvalidEventDataError

ASSET_LOCATION_CLASS_LIST = [
AssetHubAssetNativeLocation,
Expand All @@ -18,7 +19,7 @@

def get_asset_location(parachain_id: int):
if parachain_id not in ASSET_LOCATION_CLASS_MAP:
raise ValueError(f'Unsupported parachain_id: {parachain_id}.')
raise InvalidEventDataError(f'Unsupported `parachain_id`: {parachain_id}.')
if parachain_id not in ASSET_LOCATION_MAP:
asset_location_class = ASSET_LOCATION_CLASS_MAP[parachain_id]
parachain_client = SubstrateInterface(asset_location_class.node_url)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from dex_screener.handlers.hydradx.asset.asset_location.dto import ExternalMetadataDTO
from dex_screener.handlers.hydradx.asset.asset_location.types import GeneralIndex
from dex_screener.handlers.hydradx.asset.asset_location.types import Interior
from dex_screener.handlers.hydradx.asset.asset_type.exception import InvalidEventDataError


class AssetHubAssetNativeLocation(AbstractAssetNativeLocation):
Expand All @@ -16,7 +17,7 @@ def _prepare_parachain_query_parameters(self, interior: Interior) -> list:
pass

case _:
raise ValueError('Unhandled interior value: %s.', interior)
raise InvalidEventDataError(f'Unhandled interior value: {interior}.')

return [external_id]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from dex_screener.handlers.hydradx.asset.asset_location.dto import ExternalMetadataDTO
from dex_screener.handlers.hydradx.asset.asset_location.types import AccountKey20
from dex_screener.handlers.hydradx.asset.asset_location.types import Interior
from dex_screener.handlers.hydradx.asset.asset_type.exception import InvalidEventDataError


class MoonbeamAssetNativeLocation(AbstractAssetNativeLocation):
Expand All @@ -15,7 +16,7 @@ def _prepare_parachain_query_parameters(self, interior: Interior) -> list:
case [*_, AccountKey20(external_id)]:
pass
case _:
raise ValueError('Unhandled interior value: %s.', interior)
raise InvalidEventDataError(f'Unhandled interior value: {interior}.')

return [external_id]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from dex_screener.handlers.hydradx.asset.asset_location.dto import ExternalMetadataDTO
from dex_screener.handlers.hydradx.asset.asset_location.types import GeneralKey
from dex_screener.handlers.hydradx.asset.asset_location.types import Interior
from dex_screener.handlers.hydradx.asset.asset_type.exception import InvalidEventDataError


class PendulumAssetNativeLocation(AbstractAssetNativeLocation):
Expand All @@ -19,7 +20,7 @@ def _prepare_parachain_query_parameters(self, interior: Interior) -> list:
]:
return [{'Stellar': {'AlphaNum4': {'code': str(asset_code), 'issuer': str(issuer)}}}]

raise ValueError('Unhandled interior value: %s.', interior)
raise InvalidEventDataError(f'Unhandled interior value: {interior}.')

async def _request_parachain_query(self, params: list) -> Any:
return await self._client.query('AssetRegistry', 'Metadata', params)
Expand Down
141 changes: 30 additions & 111 deletions dex_screener/handlers/hydradx/asset/asset_type/__init__.py
Original file line number Diff line number Diff line change
@@ -1,111 +1,30 @@
from __future__ import annotations

from abc import ABC
from abc import abstractmethod
from typing import TYPE_CHECKING
from typing import Any

from dex_screener.models import Asset

if TYPE_CHECKING:
from dipdup.models.substrate import SubstrateEvent


class AbstractHydrationAsset(ABC):
asset_type: str = ...

@classmethod
@abstractmethod
async def handle_register_asset(cls, event: SubstrateEvent) -> Asset: ...

@classmethod
@abstractmethod
async def handle_update_asset(cls, event: SubstrateEvent) -> Asset: ...

@classmethod
@abstractmethod
async def create_asset(cls, asset_id: int, event: SubstrateEvent, fields: dict[str, Any] | None) -> Asset: ...

@classmethod
@abstractmethod
async def update_asset(cls, asset_id: int, updated_fields: dict[str, Any], event: SubstrateEvent) -> Asset: ...


class InvalidEventDataError(ValueError):
pass


class BaseHydrationAsset(AbstractHydrationAsset):
@classmethod
async def handle_register_asset(cls, event: SubstrateEvent) -> Asset:
match event.payload:
case {
'asset_id': int(asset_id),
'name': str(asset_name),
}:
pass
case {
'asset_id': int(asset_id),
'asset_name': str(asset_name),
}:
pass
case _:
raise InvalidEventDataError('Unhandled Event Payload.')

return await cls.create_asset(asset_id, event, {'name': asset_name})

@classmethod
async def handle_update_asset(cls, event: SubstrateEvent) -> Asset:
match event.payload:
case {
'asset_id': int(asset_id),
'asset_name': str(asset_name),
}:
updated_fields = {
'name': asset_name,
}
case _:
raise InvalidEventDataError('Unhandled Event Data.')

return await cls.update_asset(
asset_id=asset_id,
updated_fields=updated_fields,
event=event,
)

@classmethod
async def create_asset(cls, asset_id: int, event: SubstrateEvent, fields: dict[str, Any] | None = None) -> Asset:
if fields is None:
fields = {}

return await Asset.create(
id=asset_id,
asset_type=cls.asset_type,
updated_at_block_id=event.level,
**fields,
)

@classmethod
async def update_asset(cls, asset_id: int, updated_fields: dict[str, Any], event: SubstrateEvent) -> Asset:
updated_fields.setdefault('asset_type', cls.asset_type)
updated_fields.setdefault('updated_at_block_id', event.level)
asset, _ = await Asset.update_or_create(
id=asset_id,
defaults=updated_fields,
)
return asset


class HexNamedHydrationAsset(BaseHydrationAsset):
@classmethod
async def handle_register_asset(cls, event: SubstrateEvent) -> Asset:
match event.data.args:
case {
'assetId': int(asset_id),
'assetName': str(asset_name),
}:
pass
case _:
raise InvalidEventDataError('Unhandled Event Data.')

return await cls.create_asset(asset_id, event, {'name': asset_name})
from scalecodec.exceptions import RemainingScaleBytesNotEmptyException

DipDupEventDataCollectPayloadUnhandledError = (RemainingScaleBytesNotEmptyException, NotImplementedError, ValueError)

def validate_framework_exception(exception):
match exception:
case ValueError(
args=(
'zip() argument 2 is longer than argument 1'
|
'zip() argument 2 is shorter than argument 1',
)
):
pass
case NotImplementedError(
args=(
'Decoder class for "bounded_collections:bounded_vec:BoundedVec@65" not found'
|
'Decoder class for "bounded_collections:bounded_vec:BoundedVec@68" not found'
|
'Decoder class for "bounded_collections:bounded_vec:BoundedVec@70" not found'
|
'Decoder class for "bounded_collections:bounded_vec:BoundedVec@193" not found',
)
):
pass
case RemainingScaleBytesNotEmptyException():
pass
case _:
raise
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
from __future__ import annotations

from abc import ABC
from abc import abstractmethod
from typing import Any

from dipdup.models.substrate import SubstrateEvent

from dex_screener.handlers.hydradx.asset.asset_type.exception import InvalidEventDataError
from dex_screener.models import Asset


class AbstractHydrationAsset(ABC):
asset_type: str = ...

@classmethod
@abstractmethod
async def handle_register_asset(cls, event: SubstrateEvent) -> Asset: ...

@classmethod
@abstractmethod
async def handle_update_asset(cls, event: SubstrateEvent) -> Asset: ...

@classmethod
@abstractmethod
async def create_asset(cls, asset_id: int, event: SubstrateEvent, fields: dict[str, Any] | None) -> Asset: ...

@classmethod
@abstractmethod
async def update_asset(cls, asset_id: int, updated_fields: dict[str, Any], event: SubstrateEvent) -> Asset: ...


class BaseHydrationAsset(AbstractHydrationAsset):
@classmethod
async def handle_register_asset(cls, event: SubstrateEvent) -> Asset:
match event.payload:
case {
'asset_id': int(asset_id),
'name': str(asset_name),
}:
pass
case {
'asset_id': int(asset_id),
'asset_name': str(asset_name),
}:
pass
case _:
raise InvalidEventDataError('Unhandled Event Payload.')

return await cls.create_asset(asset_id, event, {'name': asset_name})

@classmethod
async def handle_update_asset(cls, event: SubstrateEvent) -> Asset:
match event.payload:
case {
'asset_id': int(asset_id),
'asset_name': str(asset_name),
}:
updated_fields = {
'name': asset_name,
}
case _:
raise InvalidEventDataError('Unhandled Event Data.')

return await cls.update_asset(
asset_id=asset_id,
updated_fields=updated_fields,
event=event,
)

@classmethod
async def create_asset(cls, asset_id: int, event: SubstrateEvent, fields: dict[str, Any] | None = None) -> Asset:
if fields is None:
fields = {}

return await Asset.create(
id=asset_id,
asset_type=cls.asset_type,
updated_at_block_id=event.level,
**fields,
)

@classmethod
async def update_asset(cls, asset_id: int, updated_fields: dict[str, Any], event: SubstrateEvent) -> Asset:
updated_fields.setdefault('asset_type', cls.asset_type)
updated_fields.setdefault('updated_at_block_id', event.level)
asset, _ = await Asset.update_or_create(
id=asset_id,
defaults=updated_fields,
)
return asset


class HexNamedHydrationAsset(BaseHydrationAsset):
@classmethod
async def handle_register_asset(cls, event: SubstrateEvent) -> Asset:
match event.data.args:
case {
'assetId': int(asset_id),
'assetName': str(asset_name),
}:
pass
case _:
raise InvalidEventDataError('Unhandled Event Data.')

return await cls.create_asset(asset_id, event, {'name': asset_name})
2 changes: 1 addition & 1 deletion dex_screener/handlers/hydradx/asset/asset_type/const.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from dex_screener.handlers.hydradx.asset.asset_type import AbstractHydrationAsset
from dex_screener.handlers.hydradx.asset.asset_type.abstract_hydration_asset import AbstractHydrationAsset
from dex_screener.handlers.hydradx.asset.asset_type.enum import HydrationAssetType as AssetType
from dex_screener.handlers.hydradx.asset.asset_type.hydration_bond_asset import HydrationBondAsset
from dex_screener.handlers.hydradx.asset.asset_type.hydration_erc20_asset import HydrationERC20Asset
Expand Down
2 changes: 2 additions & 0 deletions dex_screener/handlers/hydradx/asset/asset_type/exception.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class InvalidEventDataError(ValueError):
pass
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from dex_screener.handlers.hydradx.asset.asset_type import HexNamedHydrationAsset
from dex_screener.handlers.hydradx.asset.asset_type.abstract_hydration_asset import HexNamedHydrationAsset
from dex_screener.handlers.hydradx.asset.asset_type.enum import HydrationAssetType


Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from dipdup.models.substrate import SubstrateEvent

from dex_screener.handlers.hydradx.asset.asset_type import BaseHydrationAsset
from dex_screener.handlers.hydradx.asset.asset_type import InvalidEventDataError
from dex_screener.handlers.hydradx.asset.asset_type.abstract_hydration_asset import BaseHydrationAsset
from dex_screener.handlers.hydradx.asset.asset_type.exception import InvalidEventDataError
from dex_screener.handlers.hydradx.asset.asset_type.enum import HydrationAssetType
from dex_screener.models import Asset

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from dipdup.models.substrate import SubstrateEvent

from dex_screener.handlers.hydradx.asset.asset_type import BaseHydrationAsset
from dex_screener.handlers.hydradx.asset.asset_type import InvalidEventDataError
from dex_screener.handlers.hydradx.asset.asset_type.abstract_hydration_asset import BaseHydrationAsset
from dex_screener.handlers.hydradx.asset.asset_type.exception import InvalidEventDataError
from dex_screener.handlers.hydradx.asset.asset_type.enum import HydrationAssetType
from dex_screener.models import Asset

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from dex_screener.handlers.hydradx.asset.asset_type import HexNamedHydrationAsset
from dex_screener.handlers.hydradx.asset.asset_type.abstract_hydration_asset import HexNamedHydrationAsset
from dex_screener.handlers.hydradx.asset.asset_type.enum import HydrationAssetType


Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from dex_screener.handlers.hydradx.asset.asset_type import BaseHydrationAsset
from dex_screener.handlers.hydradx.asset.asset_type.abstract_hydration_asset import BaseHydrationAsset
from dex_screener.handlers.hydradx.asset.asset_type.enum import HydrationAssetType


Expand Down
Loading

0 comments on commit 1fae624

Please sign in to comment.