
class {{toPythonClassname this.languageSpecificName}}Method(ContractMethod):
    """Various interfaces to the {{this.name}} method."""

    def __init__(self, provider: BaseProvider, contract_address: str, contract_function: ContractFunction, validator: Validator=None):
        """Persist instance data."""
        super().__init__(provider, contract_address, validator)
        self.underlying_method = contract_function

    {{#if inputs}}
    def validate_and_normalize_inputs(self, {{> typed_params inputs=inputs}}):
        """Validate the inputs to the {{this.name}} method."""
        {{#each this.inputs}}
        self.validator.assert_valid(
            method_name='{{../name}}',
            parameter_name='{{name}}',
            argument_value={{toPythonIdentifier name}},
        )
        {{#if (equal type 'address')}}
        {{toPythonIdentifier this.name}} = self.validate_and_checksum_address({{toPythonIdentifier this.name}})
        {{else if (equal type 'uint256')}}
        # safeguard against fractional inputs
        {{toPythonIdentifier this.name}} = int({{toPythonIdentifier this.name}})
        {{else if (equal type 'bytes')}}
        {{toPythonIdentifier this.name}} = bytes.fromhex({{toPythonIdentifier this.name}}.decode("utf-8"))
        {{else if (equal type 'bytes[]')}}
        {{toPythonIdentifier this.name}} = [
            bytes.fromhex({{toPythonIdentifier this.name}}_element.decode("utf-8"))
            for {{toPythonIdentifier this.name}}_element in {{toPythonIdentifier this.name}}
        ]
{{/if}}
{{/each}}
        return ({{> params }})

    {{/if}}
    def call(self, {{#if inputs}}{{> typed_params inputs=inputs}}, {{/if}}tx_params: Optional[TxParams] = None) -> {{> return_type outputs=outputs type='call'~}}:
        """Execute underlying contract method via eth_call.
{{sanitizeDevdocDetails this.name this.devdoc.details 8}}{{~#if this.devdoc.params~}}{{#each this.devdoc.params}}
{{makeParameterDocstringRole @key this 8}}{{/each}}{{/if}}
        :param tx_params: transaction parameters
        {{#if this.constant~}}
        {{#if this.devdoc.return}}
{{makeReturnDocstringRole this.devdoc.return 8}}{{/if}}
        {{else}}
        :returns: the return value of the underlying method.
        {{/if}}
        """
        {{#if inputs}}
        ({{> params }}) = self.validate_and_normalize_inputs({{> params}})
        {{/if}}
        tx_params = super().normalize_tx_params(tx_params)
        return self.underlying_method({{> params}}).call(tx_params.as_dict())

    def send_transaction(self, {{#if inputs}}{{> typed_params inputs=inputs}}, {{/if}}tx_params: Optional[TxParams] = None) -> Union[HexBytes, bytes]:
        """Execute underlying contract method via eth_sendTransaction.
{{sanitizeDevdocDetails this.name this.devdoc.details 8}}{{~#if this.devdoc.params~}}{{#each this.devdoc.params}}
{{makeParameterDocstringRole @key this 8}}{{/each}}{{/if}}
        :param tx_params: transaction parameters
        {{#if this.constant~}}
        {{#if this.devdoc.return}}
{{makeReturnDocstringRole this.devdoc.return 8}}{{/if}}
        {{/if}}
        """
        {{#if inputs}}
        ({{> params }}) = self.validate_and_normalize_inputs({{> params}})
        {{/if}}
        tx_params = super().normalize_tx_params(tx_params)
        return self.underlying_method({{> params}}).transact(tx_params.as_dict())

    def estimate_gas(self, {{#if inputs}}{{> typed_params inputs=inputs}}, {{/if}}tx_params: Optional[TxParams] = None) -> int:
        """Estimate gas consumption of method call."""
        {{#if inputs}}
        ({{> params }}) = self.validate_and_normalize_inputs({{> params}})
        {{/if}}
        tx_params = super().normalize_tx_params(tx_params)
        return self.underlying_method({{> params}}).estimateGas(tx_params.as_dict())
