Source code for erc7730.convert.resolved.v2.parameters

from typing import Any, assert_never, cast

from erc7730.common.abi import ABIDataType
from erc7730.common.output import OutputAdder
from erc7730.convert.resolved.v2.constants import ConstantProvider
from erc7730.convert.resolved.v2.enums import get_enum, get_enum_id
from erc7730.convert.resolved.v2.values import resolve_path_or_constant_value
from erc7730.model.input.path import DescriptorPathStr
from erc7730.model.input.v2.display import (
    InputAddressNameParameters,
    InputCallDataParameters,
    InputDateParameters,
    InputEncryptionParameters,
    InputEnumParameters,
    InputFieldParameters,
    InputInteroperableAddressNameParameters,
    InputMapReference,
    InputNftNameParameters,
    InputTokenAmountParameters,
    InputTokenTickerParameters,
    InputUnitParameters,
)
from erc7730.model.paths import ContainerPath, DataPath
from erc7730.model.paths.path_ops import data_or_container_path_concat
from erc7730.model.resolved.display import ResolvedValue
from erc7730.model.resolved.metadata import EnumDefinition
from erc7730.model.resolved.v2.display import (
    ResolvedAddressNameParameters,
    ResolvedCallDataParameters,
    ResolvedDateParameters,
    ResolvedEncryptionParameters,
    ResolvedEnumParameters,
    ResolvedFieldParameters,
    ResolvedInteroperableAddressNameParameters,
    ResolvedNftNameParameters,
    ResolvedTokenAmountParameters,
    ResolvedTokenTickerParameters,
    ResolvedUnitParameters,
)
from erc7730.model.types import Address, HexStr, Id, MixedCaseAddress


[docs] def resolve_field_parameters( prefix: DataPath, params: InputFieldParameters | None, enums: dict[Id, EnumDefinition], constants: ConstantProvider, out: OutputAdder, ) -> ResolvedFieldParameters | None: match params: case None: return None case InputAddressNameParameters(): return resolve_address_name_parameters(prefix, params, constants, out) case InputInteroperableAddressNameParameters(): return resolve_interoperable_address_name_parameters(prefix, params, constants, out) case InputCallDataParameters(): return resolve_calldata_parameters(prefix, params, constants, out) case InputTokenAmountParameters(): return resolve_token_amount_parameters(prefix, params, constants, out) case InputTokenTickerParameters(): return resolve_token_ticker_parameters(prefix, params, constants, out) case InputNftNameParameters(): return resolve_nft_parameters(prefix, params, constants, out) case InputDateParameters(): return resolve_date_parameters(prefix, params, constants, out) case InputUnitParameters(): return resolve_unit_parameters(prefix, params, constants, out) case InputEnumParameters(): return resolve_enum_parameters(prefix, params, enums, constants, out) case _: assert_never(params)
[docs] def resolve_address_name_parameters( prefix: DataPath, params: InputAddressNameParameters, constants: ConstantProvider, out: OutputAdder ) -> ResolvedAddressNameParameters | None: sender_address: list[Address] | None = None if (sender_addr_input := params.senderAddress) is not None: # InputMapReference is passed through to resolved model for runtime resolution if isinstance(sender_addr_input, InputMapReference): # Map references in senderAddress cannot be resolved at conversion time out.warning( title="Unresolved map reference", message="Map reference in senderAddress cannot be resolved at conversion time and will be dropped.", ) sender_address = None else: resolved_sender = constants.resolve_or_none(sender_addr_input, out) if resolved_sender is None: sender_address = None elif isinstance(resolved_sender, str): sender_address = [Address(resolved_sender)] elif isinstance(resolved_sender, list): sender_address = [Address(addr) for addr in resolved_sender] else: raise Exception("Invalid senderAddress type") return ResolvedAddressNameParameters( types=constants.resolve_or_none(params.types, out), sources=constants.resolve_or_none(params.sources, out), senderAddress=sender_address, )
[docs] def resolve_interoperable_address_name_parameters( prefix: DataPath, params: InputInteroperableAddressNameParameters, constants: ConstantProvider, out: OutputAdder ) -> ResolvedInteroperableAddressNameParameters | None: sender_address: list[Address] | None = None if (sender_addr_input := params.senderAddress) is not None: # InputMapReference is passed through - similar to address_name if isinstance(sender_addr_input, InputMapReference): out.warning( title="Unresolved map reference", message="Map reference in senderAddress cannot be resolved at conversion time and will be dropped.", ) sender_address = None else: resolved_sender = constants.resolve_or_none(sender_addr_input, out) if resolved_sender is None: sender_address = None elif isinstance(resolved_sender, str): sender_address = [Address(resolved_sender)] elif isinstance(resolved_sender, list): sender_address = [Address(addr) for addr in resolved_sender] else: raise Exception("Invalid senderAddress type") return ResolvedInteroperableAddressNameParameters( types=constants.resolve_or_none(params.types, out), sources=constants.resolve_or_none(params.sources, out), senderAddress=sender_address, )
[docs] def resolve_calldata_parameters( prefix: DataPath, params: InputCallDataParameters, constants: ConstantProvider, out: OutputAdder ) -> ResolvedCallDataParameters | None: # Resolve callee - can be path, constant, or map reference callee_resolved = None if params.callee is not None and isinstance(params.callee, InputMapReference): out.warning( title="Unresolved map reference", message="Map reference in callee cannot be resolved at conversion time and will be dropped.", ) return None elif params.callee is not None or params.calleePath is not None: callee_resolved = resolve_path_or_constant_value( prefix=prefix, input_path=params.calleePath, input_value=params.callee, abi_type=ABIDataType.ADDRESS, constants=constants, out=out, ) if callee_resolved is None: return None # Resolve selector selector_resolved = None if params.selector is not None and isinstance(params.selector, InputMapReference): out.warning( title="Unresolved map reference", message="Map reference in selector cannot be resolved at conversion time and will be dropped.", ) elif params.selector is not None or params.selectorPath is not None: selector_resolved = resolve_path_or_constant_value( prefix=prefix, input_path=params.selectorPath, input_value=params.selector, abi_type=ABIDataType.STRING, constants=constants, out=out, ) # Resolve amount amount_resolved = None if params.amount is not None and isinstance(params.amount, InputMapReference): out.warning( title="Unresolved map reference", message="Map reference in amount cannot be resolved at conversion time and will be dropped.", ) elif params.amount is not None or params.amountPath is not None: amount_resolved = resolve_path_or_constant_value( prefix=prefix, input_path=params.amountPath, input_value=params.amount, abi_type=ABIDataType.UINT, constants=constants, out=out, ) # Resolve spender spender_resolved = None if params.spender is not None and isinstance(params.spender, InputMapReference): out.warning( title="Unresolved map reference", message="Map reference in spender cannot be resolved at conversion time and will be dropped.", ) elif params.spender is not None or params.spenderPath is not None: spender_resolved = resolve_path_or_constant_value( prefix=prefix, input_path=params.spenderPath, input_value=params.spender, abi_type=ABIDataType.ADDRESS, constants=constants, out=out, ) return ResolvedCallDataParameters( callee=cast(ResolvedValue, callee_resolved), selector=selector_resolved, amount=amount_resolved, spender=spender_resolved, )
[docs] def resolve_token_amount_parameters( prefix: DataPath, params: InputTokenAmountParameters, constants: ConstantProvider, out: OutputAdder ) -> ResolvedTokenAmountParameters | None: # Resolve token into a ResolvedValue (path or constant), like v1. token_value = params.token token_resolved = None if token_value is not None and isinstance(token_value, InputMapReference): # Map reference needs runtime resolution and is dropped in resolved model out.warning( title="Unresolved map reference", message="Map reference in token cannot be resolved at conversion time and will be dropped.", ) else: token_resolved = resolve_path_or_constant_value( prefix=prefix, input_path=params.tokenPath, input_value=token_value, abi_type=ABIDataType.ADDRESS, constants=constants, out=out, ) input_addresses = cast( list[DescriptorPathStr | MixedCaseAddress] | MixedCaseAddress | None, constants.resolve_or_none(params.nativeCurrencyAddress, out), ) resolved_addresses: list[Address] | None if input_addresses is None: resolved_addresses = None elif isinstance(input_addresses, list): resolved_addresses = [] for input_address in input_addresses: if (resolved_address := constants.resolve(input_address, out)) is None: return None resolved_addresses.append(Address(resolved_address)) elif isinstance(input_addresses, str): resolved_addresses = [Address(input_addresses)] else: raise Exception("Invalid nativeCurrencyAddress type") input_threshold = cast(HexStr | int | None, constants.resolve_or_none(params.threshold, out)) resolved_threshold: HexStr | None if input_threshold is not None: if isinstance(input_threshold, int): resolved_threshold = "0x" + input_threshold.to_bytes(byteorder="big", signed=False).hex() else: resolved_threshold = input_threshold else: resolved_threshold = None # Resolve chainId - can be int, descriptor path, or map reference chain_id_value = params.chainId resolved_chain_id: int | None = None if chain_id_value is not None and not isinstance(chain_id_value, InputMapReference): if isinstance(chain_id_value, int): resolved_chain_id = chain_id_value else: # Descriptor path resolved_value: Any = constants.resolve(chain_id_value, out) if isinstance(resolved_value, int): resolved_chain_id = resolved_value return ResolvedTokenAmountParameters( token=token_resolved, nativeCurrencyAddress=resolved_addresses, threshold=resolved_threshold, message=constants.resolve_or_none(params.message, out), chainId=resolved_chain_id, chainIdPath=params.chainIdPath, )
[docs] def resolve_token_ticker_parameters( prefix: DataPath, params: InputTokenTickerParameters, constants: ConstantProvider, out: OutputAdder ) -> ResolvedTokenTickerParameters | None: # Resolve chainId - can be int, descriptor path, or map reference chain_id_value = params.chainId resolved_chain_id: int | None = None if chain_id_value is not None and not isinstance(chain_id_value, InputMapReference): if isinstance(chain_id_value, int): resolved_chain_id = chain_id_value else: # Descriptor path resolved_value: Any = constants.resolve(chain_id_value, out) if isinstance(resolved_value, int): resolved_chain_id = resolved_value # Resolve and normalize chainIdPath using constants and the current prefix resolved_chain_id_path: DataPath | ContainerPath | None = None if params.chainIdPath is not None: relative_chain_id_path = constants.resolve_path(params.chainIdPath, out) if relative_chain_id_path is not None: resolved_chain_id_path = data_or_container_path_concat(prefix, relative_chain_id_path) return ResolvedTokenTickerParameters( chainId=resolved_chain_id, chainIdPath=resolved_chain_id_path, )
[docs] def resolve_nft_parameters( prefix: DataPath, params: InputNftNameParameters, constants: ConstantProvider, out: OutputAdder ) -> ResolvedNftNameParameters | None: # Resolve collection - can be path, constant, or map reference collection_value = params.collection if collection_value is not None and isinstance(collection_value, InputMapReference): # Map reference - needs runtime resolution out.warning( title="Unresolved map reference", message="Map reference in collection cannot be resolved at conversion time and will be dropped.", ) return None else: collection_resolved = resolve_path_or_constant_value( prefix=prefix, input_path=params.collectionPath, input_value=collection_value, abi_type=ABIDataType.ADDRESS, constants=constants, out=out, ) if collection_resolved is None: return None return ResolvedNftNameParameters(collection=collection_resolved)
[docs] def resolve_date_parameters( prefix: DataPath, params: InputDateParameters, constants: ConstantProvider, out: OutputAdder ) -> ResolvedDateParameters | None: return ResolvedDateParameters(encoding=constants.resolve(params.encoding, out))
[docs] def resolve_unit_parameters( prefix: DataPath, params: InputUnitParameters, constants: ConstantProvider, out: OutputAdder ) -> ResolvedUnitParameters | None: return ResolvedUnitParameters( base=constants.resolve(params.base, out), decimals=constants.resolve_or_none(params.decimals, out), prefix=constants.resolve_or_none(params.prefix, out), )
[docs] def resolve_enum_parameters( prefix: DataPath, params: InputEnumParameters, enums: dict[Id, EnumDefinition], constants: ConstantProvider, out: OutputAdder, ) -> ResolvedEnumParameters | None: if get_enum_id(params.ref, out) is None: return None if get_enum(params.ref, enums, out) is None: return None return ResolvedEnumParameters.model_validate({"$ref": str(params.ref)})
[docs] def resolve_encryption_parameters( prefix: DataPath, params: InputEncryptionParameters, constants: ConstantProvider, out: OutputAdder ) -> ResolvedEncryptionParameters | None: # Encryption parameters are passed through as-is return ResolvedEncryptionParameters( scheme=params.scheme, plaintextType=params.plaintextType, fallbackLabel=params.fallbackLabel, )