Source code for erc7730.convert.calldata.v1.descriptor
"""
Conversion of a root ERC-7730 descriptor to calldata descriptors (1 per chain + selector).
"""
from typing import cast
from pydantic_string_url import HttpUrl
from erc7730.common.abi import get_functions
from erc7730.common.ledger import ledger_network_id
from erc7730.common.output import OutputAdder
from erc7730.convert.calldata.v1.selector import convert_selector
from erc7730.convert.resolved.convert_erc7730_input_to_resolved import (
ERC7730InputToResolved,
)
from erc7730.model.abi import Function
from erc7730.model.calldata.descriptor import CalldataDescriptor
from erc7730.model.input.descriptor import InputERC7730Descriptor
from erc7730.model.resolved.context import ResolvedContractContext
from erc7730.model.types import Selector
[docs]
def convert_descriptor(
input_descriptor: InputERC7730Descriptor,
source: HttpUrl | None,
chain_id: int | None,
out: OutputAdder,
) -> list[CalldataDescriptor]:
"""
Generate output calldata descriptors from an input ERC-7730 descriptor with contract context.
If descriptor is invalid, an empty list is returned. If the descriptor is partially invalid, a partial list is
returned. Errors are logged as warnings.
:param input_descriptor: deserialized input ERC-7730 descriptor
:param source: source of the descriptor file
:param chain_id: if set, only emit calldata descriptors for given chain IDs
:param out: error handler
:return: output calldata descriptors (1 per chain + selector)
"""
if (resolved_descriptor := ERC7730InputToResolved().convert(input_descriptor, out)) is None:
return []
context = cast(ResolvedContractContext, resolved_descriptor.context)
abis: dict[Selector, Function] = get_functions(context.contract.abi).functions
output_descriptors = []
for deployment in context.contract.deployments:
if chain_id is not None and chain_id != deployment.chainId:
continue
if ledger_network_id(deployment.chainId) is None:
out.warning(f"Chain id {deployment.chainId} is not known, skipping it")
continue
for selector, format in resolved_descriptor.display.formats.items():
if (abi := abis.get(selector)) is None:
out.error(
title="Invalid selector",
message=f"Selector {selector} not found in ABI.",
)
continue
descriptor = convert_selector(
descriptor=resolved_descriptor,
deployment=deployment,
selector=selector,
format=format,
abi=abi,
source=source,
out=out,
)
if descriptor is not None:
output_descriptors.append(descriptor)
return output_descriptors