Skip to content

Commit

Permalink
fix parsing payload from node
Browse files Browse the repository at this point in the history
  • Loading branch information
droserasprout committed Jan 15, 2025
1 parent dc524cf commit a2f3e3a
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 20 deletions.
6 changes: 5 additions & 1 deletion src/dipdup/models/substrate.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

from dipdup.fetcher import HasLevel
from dipdup.runtimes import SubstrateRuntime
from dipdup.runtimes import get_event_arg_names


class _BlockHeader(TypedDict):
Expand Down Expand Up @@ -113,7 +114,10 @@ class SubstrateEvent(Generic[PayloadT]):
def payload(self) -> PayloadT:
# NOTE: We receive decoded args from node datasource and encoded from subsquid datasource
if self.data.decoded_args is not None:
payload = self.data.decoded_args
spec_version = self.runtime.get_spec_version(self.runtime.runtime_config.active_spec_version_id)
abi = spec_version.get_event_abi(self.data.name)
arg_names = get_event_arg_names(abi)
payload = dict(zip(arg_names, self.data.decoded_args, strict=False))
elif self.data.args is not None and self.data.header_extra is not None:
payload = self.runtime.decode_event_args(
name=self.data.name,
Expand Down
52 changes: 33 additions & 19 deletions src/dipdup/runtimes.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,17 @@ def get_event_abi(self, qualname: str) -> dict[str, Any]:
return self._events[qualname]


def get_event_arg_names(event_abi: dict[str, Any]) -> tuple[str, ...]:
arg_names = event_abi.get('args_name', [])
arg_names = [a for a in arg_names if a]

# NOTE: Old metadata
if not arg_names:
arg_names = extract_args_name(event_abi['docs'][0])

return tuple(arg_names)


class SubstrateRuntime:
def __init__(
self,
Expand Down Expand Up @@ -112,19 +123,24 @@ def runtime_config(self) -> 'RuntimeConfigurationObject':
def get_spec_version(self, name: str) -> SubstrateSpecVersion:
if name not in self._spec_versions:
_logger.info('loading spec version `%s`', name)
try:
metadata_path = self.abi_path.joinpath(f'v{name}.json')
metadata = orjson.loads(metadata_path.read_bytes())
self._spec_versions[name] = SubstrateSpecVersion(
name=f'v{name}',
metadata=metadata,
)
except FileNotFoundError:

metadata_path = self.abi_path.joinpath(f'v{name}.json')

if not metadata_path.is_file():
metadata_path = self._package.abi_local.joinpath(self._config.name, f'v{name}.json')

if not metadata_path.is_file():
# FIXME: Using last known version to help with missing abis
available = sorted_glob(self.abi_path, 'v*.json')
last_known = next(i for i in available if int(i.stem[1:]) >= int(name[1:]))
_logger.debug('using last known version `%s`', last_known.name)
self._spec_versions[name] = self.get_spec_version(last_known.stem[1:])
else:
metadata = orjson.loads(metadata_path.read_bytes())
self._spec_versions[name] = SubstrateSpecVersion(
name=f'v{name}',
metadata=metadata,
)

return self._spec_versions[name]

Expand All @@ -140,18 +156,14 @@ def decode_event_args(
event_abi = spec_obj.get_event_abi(
qualname=name,
)
arg_types = event_abi.get('args_type_name') or event_abi['args']

if isinstance(args, list):
arg_names = event_abi.get('args_name', [])
arg_names = [a for a in arg_names if a]
arg_names = get_event_arg_names(event_abi)

# NOTE: Old metadata
if not arg_names:
arg_names = extract_args_name(event_abi['docs'][0])
# NOTE: Optionals

args, unprocessed_args = [], [*args]
for arg_type in event_abi['args']:
for arg_type in arg_types:
if arg_type.startswith('option<'):
args.append(None)
else:
Expand All @@ -161,19 +173,21 @@ def decode_event_args(
else:
arg_names = event_abi['args_name']

arg_types = event_abi['args']

payload = {}
for (key, value), type_ in zip(args.items(), arg_types, strict=True):
if not isinstance(value, str) or not value.startswith('0x'):
if isinstance(value, int):
payload[key] = value
continue

scale_obj = self.runtime_config.create_scale_object(
type_string=type_,
data=ScaleBytes(value),
metadata=spec_obj._metadata,
)
scale_obj.decode()

# FIXME: padding

scale_obj.decode(check_remaining=False)
payload[key] = scale_obj.value_serialized

return payload

0 comments on commit a2f3e3a

Please sign in to comment.