Module tronpytool.compile.basecore

Base wrapper class for accessing ethereum smart contracts.

Expand source code
#!/usr/bin/env python
"""Base wrapper class for accessing ethereum smart contracts."""

from typing import Any, Union, Tuple

from tronpytool import Tron
from tronpytool.common.abi import method_result_handler, decode_single
from tronpytool.common.key import to_hex_address, keccak256, is_address
from tronpytool.common.normalizers import to_checksum_address
from tronpytool.contract import Contract
from tronpytool.exceptions import DoubleSpending
from tronpytool.transactionbuilder import TransactionBuilder


# from trx import is_list, is_object

class Validator:
    """Base class for validating inputs to methods."""

    def __init__(
            self,
            web3_or_provider: Tron,
            contract_address: str,
    ):
        """Initialize the instance."""

    def assert_valid(
            self, method_name: str, parameter_name: str, argument_value: Any
    ):
        """Raise an exception if method input is not valid.

        :param method_name: Name of the method whose input is to be validated.
        :param parameter_name: Name of the parameter whose input is to be
            validated.
        :param argument_value: Value of argument to parameter to be validated.
        """


class ContractMethod:
    debug = True

    def __init__(self, abi: dict, contract: Contract, owner_address: str, contract_address: str,
                 validator: Validator = None):

        self._abi = abi
        self.validator = validator
        self._owner_address = owner_address
        self._client = contract.tron.trx
        self._tron: Tron = contract.tron
        self.transaction_builder = contract.tron.transaction_builder
        self.inputs = abi.get("inputs", [])
        self.outputs = abi.get("outputs", [])
        self.method_name = abi.get("name", "")
        self.element_type = abi.get("type", "")
        self.call_value = 0
        self.call_token_value = 0
        self.call_token_id = 0
        self.contract_address = contract_address

    def __str__(self):
        return self.function_type

    def setDebug(self, b: bool) -> None:
        self.debug = b

    @staticmethod
    def validate_and_checksum_address(address: str):
        """Validate the given address, and return it's checksum address."""
        if not is_address(address):
            raise TypeError("Invalid address provided: {}".format(address))
        return to_checksum_address(address)

    def normalize_tx_params(self, tx_params) -> dict:
        """Normalize and return the given transaction parameters."""
        params = dict()
        return params

    def with_owner(self, addr: str) -> "ContractMethod":
        """Set the calling owner address.

        Can also be changed through :meth:`TransactionBuilder.with_owner() <tronpy.tron.TransactionBuilder.with_owner>`.
        """
        self._owner_address = addr
        return self

    def with_transfer(self, amount: int) -> "ContractMethod":
        """Call a contract function with TRX transfer. ``amount`` in `SUN`."""
        self.call_value = amount
        return self

    def with_asset_transfer(self, amount: int, token_id: int) -> "ContractMethod":
        """Call a contract function with TRC10 token transfer."""
        self.call_token_value = amount
        self.call_token_id = token_id
        return self

    def call(self, *args, **kwargs) -> "TransactionBuilder":
        """Call the contract method."""
        return self.__call__(*args, **kwargs)

    def trackEventReceipt(self, trnId: str):
        event = self._tron.get_event_transaction_id(trnId)
        print("=======debug event returns on this Transaction ID {}".format(trnId))
        print(event)
        print("=======end event report ========")

    def handle_url_response(self, r: dict) -> any:
        ok, key, message = method_result_handler(r)
        if ok:
            print("transaction ID: {}".format(message))
            if len(key) > 0:
                display = self.parse_output(key)
                self.debug_raw_io(key)
                return display
            else:
                return ""
        else:
            raise KeyError('Request returns Error - {} msg:{} txt:{}'.format(key, message, self.parse_output(message)))

    def parse_output(self, raw: any) -> any:
        if type(raw) is bytes:
            """Parse contract result as result."""

            parsed_result = decode_single(self.output_type, bytes.fromhex(raw))
            if len(self.outputs) == 1:
                return parsed_result[0]
            if len(self.outputs) == 0:
                return None
            return parsed_result

        elif type(raw) is str:
            """Parse contract result as result."""

            parsed_result = decode_single(self.output_type, bytes.fromhex(raw))
            if len(self.outputs) == 1:
                return parsed_result[0]
            if len(self.outputs) == 0:
                return None
            return parsed_result

        elif type(raw) is list:
            """Parse contract result as result."""

            parsed_result = []
            for k in raw:
                p = decode_single(self.output_type, bytes.fromhex(k))
                parsed_result.append(p)
            if len(self.outputs) >= 1:
                self.debug_io(parsed_result)
                return parsed_result[0]
            if len(self.outputs) == 0:
                print("no returns.. ")
                return None

            return None

        else:

            print("there is not type were found.. ")
            print(self.output_type)
            return raw

    def debug_input_io(self, data_type, args):
        if self.debug:
            print("=======raw input ======== type-label: {}, type: {}".format(data_type, type(data_type)))
            print(args)
            print("=======end raw input ========")

    def debug_params(self, data):
        if self.debug:
            print("=======param input ========")
            print(data)
            print("=======end param input========")

    def debug_raw_io(self, data):
        if self.debug:
            print("=======raw output ========")
            print(data)
            print("=======end raw output ========")

    def debug_io(self, data):
        if self.debug:
            print("====testing output type")
            print("output type {}".format(type(data[0])))
            print("output type detail: {}".format(self.output_type))
            print("==end")

    def __call__(self, *args, **kwargs) -> any:
        """Call the contract method."""
        parameters = []

        if args and kwargs:
            raise ValueError("do not mix positional arguments and keyword arguments")

        if len(self.inputs) == 0:
            if args or kwargs:
                raise TypeError("{} expected {} arguments".format(self.name, len(self.inputs)))
        elif args:
            if len(args) != len(self.inputs):
                raise TypeError("wrong number of arguments, require {} got {}".format(len(self.inputs), len(args)))
            self.debug_input_io(self.input_type, args)
            argpos = 0
            # vals = encode_single(self.input_type, args).hex()
            # self.debug_params(vals)
            for type_label in self.input_type_list:
                parameters.append(dict(
                    type=type_label,
                    value=args[argpos],
                ))
                argpos = argpos + 1

        elif kwargs:
            if len(kwargs) != len(self.inputs):
                raise TypeError("wrong number of arguments, require {} got {}".format(len(self.inputs), len(args)))
            args = []
            for arg in self.inputs:
                try:
                    args.append(kwargs[arg["name"]])
                except KeyError:
                    raise TypeError("missing argument '{}'".format(arg["name"]))
            # parameter = encode_single(self.input_type, args).hex()
        else:
            raise TypeError("wrong number of arguments, require {}".format(len(self.inputs)))

        paramdict = dict(
            contract_address=self.contract_address,
            function_selector=self.function_signature,
            issuer_address=self._owner_address,
            fee_limit=30000,
            call_value=0
        )

        if len(parameters) > 0:
            paramdict['parameters'] = parameters

        if self._abi.get("stateMutability", None).lower() in ["view", "pure"]:
            # const call, contract ret
            ret = self.transaction_builder.trigger_smart_contract(paramdict)
            return self.handle_url_response(ret)
        else:
            ret = self.transaction_builder.trigger_smart_contract(paramdict)
            return self.handle_url_response(ret)

    @property
    def name(self) -> str:
        return self._abi["name"]

    @property
    def input_type(self) -> str:
        return "(" + (",".join(self.__format_json_abi_type_entry(arg) for arg in self.inputs)) + ")"

    @property
    def input_type_list(self) -> list:
        return self.input_type[1:len(self.input_type) - 1].split(",")

    @property
    def output_type(self) -> str:
        return "({})".format(",".join(self.__format_json_abi_type_entry(arg) for arg in self.outputs))

    def __format_json_abi_type_entry(self, entry) -> str:
        if entry['type'].startswith('tuple'):
            surfix = entry['type'][5:]
            if 'components' not in entry:
                raise ValueError("ABIEncoderV2 used, ABI should be set by hand")
            return "({}){}".format(
                ",".join(self.__format_json_abi_type_entry(arg) for arg in entry['components']), surfix
            )
        else:
            return entry['type']

    @property
    def function_signature(self) -> str:
        return self.name + self.input_type

    @property
    def function_signature_hash(self) -> str:
        return keccak256(self.function_signature.encode())[:4].hex()

    @property
    def function_type(self) -> str:
        types = ", ".join(arg["type"] + " " + arg.get("name", "") for arg in self.inputs)
        ret = "function {}({})".format(self.name, types)
        if self._abi.get("stateMutability", None).lower() == "view":
            ret += " view"
        elif self._abi.get("stateMutability", None).lower() == "pure":
            ret += " pure"
        if self.outputs:
            ret += " returns ({})".format(", ".join(arg["type"] + " " + arg.get("name", "") for arg in self.outputs))
        return ret

    def as_shielded_trc20(self, contractaddr: str) -> "ShieldedTRC20":
        return ShieldedTRC20(self._contract, self._tron, contractaddr)


class ShieldedTRC20(object):
    """Shielded TRC20 Wrapper."""

    def __init__(self, contract: Contract, client: Tron, address: str):
        self.shielded = address
        """The shielded TRC20 contract."""
        self._client = client
        self._trx_module = client.trx
        self._contract = contract
        # lazy properties
        self._trc20 = None
        self._scale_factor = None

    @property
    def trc20(self) -> Contract:
        """The corresponding TRC20 contract."""
        if self._trc20 is None:
            trc20_address = "41" + str(self.shielded)._bytecode[-52:-32].hex()
            self._trc20 = self._trx_module.get_contract(trc20_address)
        return self._trc20

    @property
    def scale_factor(self) -> int:
        """Scaling factor of the shielded contract."""
        if self._scale_factor is None:
            self._scale_factor = self._contract.functions.scalingFactor()
        return self._scale_factor

    def get_rcm(self) -> str:
        return self._client.manager.request("wallet/getrcm")["value"]

    def mint(self, taddr: str, zaddr: str, amount: int, memo: str = "") -> "TransactionBuilder":
        """Mint, transfer from T-address to z-address."""
        rcm = self.get_rcm()
        payload = {
            "from_amount": str(amount),
            "shielded_receives": {
                "note": {
                    "value": amount // self.scale_factor,
                    "payment_address": zaddr,
                    "rcm": rcm,
                    "memo": memo.encode().hex(),
                }
            },
            "shielded_TRC20_contract_address": to_hex_address(self._contract.contract_address),
        }

        ret = self._client.manager.request("wallet/createshieldedcontractparameters", payload)
        self._client._handle_api_error(ret)
        parameter = ret["trigger_contract_input"]
        function_signature = self._contract.functions.mint.function_signature_hash
        return self._trx_module._build_transaction(
            "TriggerSmartContract",
            {
                "owner_address": to_hex_address(taddr),
                "contract_address": to_hex_address(self._contract.contract_address),
                "data": function_signature + parameter,
            },
            method=self._contract.functions.mint,
        )

    def transfer(
            self, zkey: dict, notes: Union[list, dict], *to: Union[Tuple[str, int], Tuple[str, int, str]],
    ) -> "tronpy.tron.TransactionBuilder":
        """Transfer from z-address to z-address."""
        if isinstance(notes, (dict,)):
            notes = [notes]

        assert 1 <= len(notes) <= 2

        spends = []
        spend_amount = 0
        for note in notes:
            if note.get("is_spent", False):
                raise DoubleSpending
            alpha = self.get_rcm()
            root, path = self.get_path(note.get("position", 0))
            spends.append(
                {"note": note["note"], "alpha": alpha, "root": root, "path": path, "pos": note.get("position", 0)}
            )
            spend_amount += note["note"]["value"]

        receives = []
        receive_amount = 0
        for recv in to:
            addr = recv[0]
            amount = recv[1]
            receive_amount += amount
            if len(recv) == 3:
                memo = recv[2]
            else:
                memo = ""

            rcm = self.get_rcm()

            receives.append(
                {"note": {"value": amount, "payment_address": addr, "rcm": rcm, "memo": memo.encode().hex()}}
            )

        if spend_amount != receive_amount:
            raise ValueError("spend amount is not equal to receive amount")

        payload = {
            "ask": zkey["ask"],
            "nsk": zkey["nsk"],
            "ovk": zkey["ovk"],
            "shielded_spends": spends,
            "shielded_receives": receives,
            "shielded_TRC20_contract_address": to_hex_address(self.shielded.contract_address),
        }
        ret = self._client.provider.make_request("wallet/createshieldedcontractparameters", payload)
        self._client._handle_api_error(ret)
        parameter = ret["trigger_contract_input"]
        function_signature = self.shielded.functions.transfer.function_signature_hash
        return self._trx_module._build_transaction(
            "TriggerSmartContract",
            {
                "owner_address": "0000000000000000000000000000000000000000",
                "contract_address": to_hex_address(self.shielded.contract_address),
                "data": function_signature + parameter,
            },
            method=self.shielded.functions.transfer,
        )

    def burn(
            self, zkey: dict, note: dict, *to: Union[Tuple[str, int], Tuple[str, int, str]]
    ) -> "tronpy.tron.TransactionBuilder":
        """Burn, transfer from z-address to T-address."""
        spends = []
        alpha = self.get_rcm()
        root, path = self.get_path(note.get("position", 0))
        if note.get("is_spent", False):
            raise DoubleSpending
        spends.append(
            {"note": note["note"], "alpha": alpha, "root": root, "path": path, "pos": note.get("position", 0)}
        )
        change_amount = 0
        receives = []
        to_addr = None
        to_amount = 0
        to_memo = ''
        if not to:
            raise ValueError('burn must have a output')
        for receive in to:
            addr = receive[0]
            amount = receive[1]
            if len(receive) == 3:
                memo = receive[2]
            else:
                memo = ""

            if addr.startswith('ztron1'):
                change_amount += amount
                rcm = self.get_rcm()
                receives = [
                    {"note": {"value": amount, "payment_address": addr, "rcm": rcm, "memo": memo.encode().hex()}}
                ]
            else:
                # assume T-address
                to_addr = addr
                to_amount = amount
                to_memo = memo

        if note["note"]["value"] * self.scale_factor - change_amount * self.scale_factor != to_amount:
            raise ValueError("Balance amount is wrong")

        payload = {
            "ask": zkey["ask"],
            "nsk": zkey["nsk"],
            "ovk": zkey["ovk"],
            "shielded_spends": spends,
            "shielded_receives": receives,
            "to_amount": str(to_amount),
            "transparent_to_address": to_hex_address(to_addr),
            "shielded_TRC20_contract_address": to_hex_address(self.shielded.contract_address),
        }

        ret = self._client.provider.make_request("wallet/createshieldedcontractparameters", payload)
        self._client._handle_api_error(ret)
        parameter = ret["trigger_contract_input"]
        function_signature = self.shielded.functions.burn.function_signature_hash
        txn = self._trx_module._build_transaction(
            "TriggerSmartContract",
            {
                "owner_address": "410000000000000000000000000000000000000000",
                "contract_address": to_hex_address(self.shielded.contract_address),
                "data": function_signature + parameter,
            },
            method=self.shielded.functions.burn,
        )
        if to_memo:
            txn = txn.memo(to_memo)
        return txn

    def _fix_notes(self, notes: list) -> list:
        for note in notes:
            if "position" not in note:
                note["position"] = 0
            if "is_spent" not in note:
                note["is_spent"] = False
            # if "memo" in note["note"]:
            #     note["note"]["memo"] = bytes.fromhex(note["note"]["memo"]).decode("utf8", 'ignore')
        return notes

    # use zkey pair from wallet/getnewshieldedaddress
    def scan_incoming_notes(self, zkey: dict, start_block_number: int, end_block_number: int = None) -> list:
        """Scan incoming notes using ivk, ak, nk."""
        if end_block_number is None:
            end_block_number = start_block_number + 1000
        payload = {
            "start_block_index": start_block_number,
            "end_block_index": end_block_number,
            "shielded_TRC20_contract_address": to_hex_address(self.shielded.contract_address),
            "ivk": zkey["ivk"],
            "ak": zkey["ak"],
            "nk": zkey["nk"],
        }
        ret = self._client.provider.make_request("wallet/scanshieldedtrc20notesbyivk", payload)
        self._client._handle_api_error(ret)
        return self._fix_notes(ret.get("noteTxs", []))

    def scan_outgoing_notes(
            self, zkey_or_ovk: Union[dict, str], start_block_number: int, end_block_number: int = None
    ) -> list:
        """Scan outgoing notes using ovk."""
        if end_block_number is None:
            end_block_number = start_block_number + 1000

        ovk = zkey_or_ovk
        if isinstance(zkey_or_ovk, (dict,)):
            ovk = zkey_or_ovk["ovk"]

        payload = {
            "start_block_index": start_block_number,
            "end_block_index": end_block_number,
            "shielded_TRC20_contract_address": to_hex_address(self.shielded.contract_address),
            "ovk": ovk,
        }
        ret = self._client.provider.make_request("wallet/scanshieldedtrc20notesbyovk", payload)
        self._client._handle_api_error(ret)
        return ret.get("noteTxs", [])

    # (root, path)
    def get_path(self, position: int = 0) -> (str, str):
        root, path = self.shielded.functions.getPath(position)
        root = root.hex()
        path = "".join(p.hex() for p in path)
        return (root, path)

    def is_note_spent(self, zkey: dict, note: dict) -> bool:
        """Is a note spent."""
        payload = dict(note)
        payload["shielded_TRC20_contract_address"] = to_hex_address(self.shielded.contract_address)
        if "position" not in note:
            payload["position"] = 0
        payload["ak"] = zkey["ak"]
        payload["nk"] = zkey["nk"]

        ret = self._client.provider.make_request("wallet/isshieldedtrc20contractnotespent", payload)

        return ret.get('is_spent', None)

Classes

class ContractMethod (abi: dict, contract: Contract, owner_address: str, contract_address: str, validator: Validator = None)
Expand source code
class ContractMethod:
    debug = True

    def __init__(self, abi: dict, contract: Contract, owner_address: str, contract_address: str,
                 validator: Validator = None):

        self._abi = abi
        self.validator = validator
        self._owner_address = owner_address
        self._client = contract.tron.trx
        self._tron: Tron = contract.tron
        self.transaction_builder = contract.tron.transaction_builder
        self.inputs = abi.get("inputs", [])
        self.outputs = abi.get("outputs", [])
        self.method_name = abi.get("name", "")
        self.element_type = abi.get("type", "")
        self.call_value = 0
        self.call_token_value = 0
        self.call_token_id = 0
        self.contract_address = contract_address

    def __str__(self):
        return self.function_type

    def setDebug(self, b: bool) -> None:
        self.debug = b

    @staticmethod
    def validate_and_checksum_address(address: str):
        """Validate the given address, and return it's checksum address."""
        if not is_address(address):
            raise TypeError("Invalid address provided: {}".format(address))
        return to_checksum_address(address)

    def normalize_tx_params(self, tx_params) -> dict:
        """Normalize and return the given transaction parameters."""
        params = dict()
        return params

    def with_owner(self, addr: str) -> "ContractMethod":
        """Set the calling owner address.

        Can also be changed through :meth:`TransactionBuilder.with_owner() <tronpy.tron.TransactionBuilder.with_owner>`.
        """
        self._owner_address = addr
        return self

    def with_transfer(self, amount: int) -> "ContractMethod":
        """Call a contract function with TRX transfer. ``amount`` in `SUN`."""
        self.call_value = amount
        return self

    def with_asset_transfer(self, amount: int, token_id: int) -> "ContractMethod":
        """Call a contract function with TRC10 token transfer."""
        self.call_token_value = amount
        self.call_token_id = token_id
        return self

    def call(self, *args, **kwargs) -> "TransactionBuilder":
        """Call the contract method."""
        return self.__call__(*args, **kwargs)

    def trackEventReceipt(self, trnId: str):
        event = self._tron.get_event_transaction_id(trnId)
        print("=======debug event returns on this Transaction ID {}".format(trnId))
        print(event)
        print("=======end event report ========")

    def handle_url_response(self, r: dict) -> any:
        ok, key, message = method_result_handler(r)
        if ok:
            print("transaction ID: {}".format(message))
            if len(key) > 0:
                display = self.parse_output(key)
                self.debug_raw_io(key)
                return display
            else:
                return ""
        else:
            raise KeyError('Request returns Error - {} msg:{} txt:{}'.format(key, message, self.parse_output(message)))

    def parse_output(self, raw: any) -> any:
        if type(raw) is bytes:
            """Parse contract result as result."""

            parsed_result = decode_single(self.output_type, bytes.fromhex(raw))
            if len(self.outputs) == 1:
                return parsed_result[0]
            if len(self.outputs) == 0:
                return None
            return parsed_result

        elif type(raw) is str:
            """Parse contract result as result."""

            parsed_result = decode_single(self.output_type, bytes.fromhex(raw))
            if len(self.outputs) == 1:
                return parsed_result[0]
            if len(self.outputs) == 0:
                return None
            return parsed_result

        elif type(raw) is list:
            """Parse contract result as result."""

            parsed_result = []
            for k in raw:
                p = decode_single(self.output_type, bytes.fromhex(k))
                parsed_result.append(p)
            if len(self.outputs) >= 1:
                self.debug_io(parsed_result)
                return parsed_result[0]
            if len(self.outputs) == 0:
                print("no returns.. ")
                return None

            return None

        else:

            print("there is not type were found.. ")
            print(self.output_type)
            return raw

    def debug_input_io(self, data_type, args):
        if self.debug:
            print("=======raw input ======== type-label: {}, type: {}".format(data_type, type(data_type)))
            print(args)
            print("=======end raw input ========")

    def debug_params(self, data):
        if self.debug:
            print("=======param input ========")
            print(data)
            print("=======end param input========")

    def debug_raw_io(self, data):
        if self.debug:
            print("=======raw output ========")
            print(data)
            print("=======end raw output ========")

    def debug_io(self, data):
        if self.debug:
            print("====testing output type")
            print("output type {}".format(type(data[0])))
            print("output type detail: {}".format(self.output_type))
            print("==end")

    def __call__(self, *args, **kwargs) -> any:
        """Call the contract method."""
        parameters = []

        if args and kwargs:
            raise ValueError("do not mix positional arguments and keyword arguments")

        if len(self.inputs) == 0:
            if args or kwargs:
                raise TypeError("{} expected {} arguments".format(self.name, len(self.inputs)))
        elif args:
            if len(args) != len(self.inputs):
                raise TypeError("wrong number of arguments, require {} got {}".format(len(self.inputs), len(args)))
            self.debug_input_io(self.input_type, args)
            argpos = 0
            # vals = encode_single(self.input_type, args).hex()
            # self.debug_params(vals)
            for type_label in self.input_type_list:
                parameters.append(dict(
                    type=type_label,
                    value=args[argpos],
                ))
                argpos = argpos + 1

        elif kwargs:
            if len(kwargs) != len(self.inputs):
                raise TypeError("wrong number of arguments, require {} got {}".format(len(self.inputs), len(args)))
            args = []
            for arg in self.inputs:
                try:
                    args.append(kwargs[arg["name"]])
                except KeyError:
                    raise TypeError("missing argument '{}'".format(arg["name"]))
            # parameter = encode_single(self.input_type, args).hex()
        else:
            raise TypeError("wrong number of arguments, require {}".format(len(self.inputs)))

        paramdict = dict(
            contract_address=self.contract_address,
            function_selector=self.function_signature,
            issuer_address=self._owner_address,
            fee_limit=30000,
            call_value=0
        )

        if len(parameters) > 0:
            paramdict['parameters'] = parameters

        if self._abi.get("stateMutability", None).lower() in ["view", "pure"]:
            # const call, contract ret
            ret = self.transaction_builder.trigger_smart_contract(paramdict)
            return self.handle_url_response(ret)
        else:
            ret = self.transaction_builder.trigger_smart_contract(paramdict)
            return self.handle_url_response(ret)

    @property
    def name(self) -> str:
        return self._abi["name"]

    @property
    def input_type(self) -> str:
        return "(" + (",".join(self.__format_json_abi_type_entry(arg) for arg in self.inputs)) + ")"

    @property
    def input_type_list(self) -> list:
        return self.input_type[1:len(self.input_type) - 1].split(",")

    @property
    def output_type(self) -> str:
        return "({})".format(",".join(self.__format_json_abi_type_entry(arg) for arg in self.outputs))

    def __format_json_abi_type_entry(self, entry) -> str:
        if entry['type'].startswith('tuple'):
            surfix = entry['type'][5:]
            if 'components' not in entry:
                raise ValueError("ABIEncoderV2 used, ABI should be set by hand")
            return "({}){}".format(
                ",".join(self.__format_json_abi_type_entry(arg) for arg in entry['components']), surfix
            )
        else:
            return entry['type']

    @property
    def function_signature(self) -> str:
        return self.name + self.input_type

    @property
    def function_signature_hash(self) -> str:
        return keccak256(self.function_signature.encode())[:4].hex()

    @property
    def function_type(self) -> str:
        types = ", ".join(arg["type"] + " " + arg.get("name", "") for arg in self.inputs)
        ret = "function {}({})".format(self.name, types)
        if self._abi.get("stateMutability", None).lower() == "view":
            ret += " view"
        elif self._abi.get("stateMutability", None).lower() == "pure":
            ret += " pure"
        if self.outputs:
            ret += " returns ({})".format(", ".join(arg["type"] + " " + arg.get("name", "") for arg in self.outputs))
        return ret

    def as_shielded_trc20(self, contractaddr: str) -> "ShieldedTRC20":
        return ShieldedTRC20(self._contract, self._tron, contractaddr)

Class variables

var debug

Static methods

def validate_and_checksum_address(address: str)

Validate the given address, and return it's checksum address.

Expand source code
@staticmethod
def validate_and_checksum_address(address: str):
    """Validate the given address, and return it's checksum address."""
    if not is_address(address):
        raise TypeError("Invalid address provided: {}".format(address))
    return to_checksum_address(address)

Instance variables

var function_signature : str
Expand source code
@property
def function_signature(self) -> str:
    return self.name + self.input_type
var function_signature_hash : str
Expand source code
@property
def function_signature_hash(self) -> str:
    return keccak256(self.function_signature.encode())[:4].hex()
var function_type : str
Expand source code
@property
def function_type(self) -> str:
    types = ", ".join(arg["type"] + " " + arg.get("name", "") for arg in self.inputs)
    ret = "function {}({})".format(self.name, types)
    if self._abi.get("stateMutability", None).lower() == "view":
        ret += " view"
    elif self._abi.get("stateMutability", None).lower() == "pure":
        ret += " pure"
    if self.outputs:
        ret += " returns ({})".format(", ".join(arg["type"] + " " + arg.get("name", "") for arg in self.outputs))
    return ret
var input_type : str
Expand source code
@property
def input_type(self) -> str:
    return "(" + (",".join(self.__format_json_abi_type_entry(arg) for arg in self.inputs)) + ")"
var input_type_list : list
Expand source code
@property
def input_type_list(self) -> list:
    return self.input_type[1:len(self.input_type) - 1].split(",")
var name : str
Expand source code
@property
def name(self) -> str:
    return self._abi["name"]
var output_type : str
Expand source code
@property
def output_type(self) -> str:
    return "({})".format(",".join(self.__format_json_abi_type_entry(arg) for arg in self.outputs))

Methods

def as_shielded_trc20(self, contractaddr: str) ‑> ShieldedTRC20
Expand source code
def as_shielded_trc20(self, contractaddr: str) -> "ShieldedTRC20":
    return ShieldedTRC20(self._contract, self._tron, contractaddr)
def call(self, *args, **kwargs) ‑> TransactionBuilder

Call the contract method.

Expand source code
def call(self, *args, **kwargs) -> "TransactionBuilder":
    """Call the contract method."""
    return self.__call__(*args, **kwargs)
def debug_input_io(self, data_type, args)
Expand source code
def debug_input_io(self, data_type, args):
    if self.debug:
        print("=======raw input ======== type-label: {}, type: {}".format(data_type, type(data_type)))
        print(args)
        print("=======end raw input ========")
def debug_io(self, data)
Expand source code
def debug_io(self, data):
    if self.debug:
        print("====testing output type")
        print("output type {}".format(type(data[0])))
        print("output type detail: {}".format(self.output_type))
        print("==end")
def debug_params(self, data)
Expand source code
def debug_params(self, data):
    if self.debug:
        print("=======param input ========")
        print(data)
        print("=======end param input========")
def debug_raw_io(self, data)
Expand source code
def debug_raw_io(self, data):
    if self.debug:
        print("=======raw output ========")
        print(data)
        print("=======end raw output ========")
def handle_url_response(self, r: dict) ‑> 
Expand source code
def handle_url_response(self, r: dict) -> any:
    ok, key, message = method_result_handler(r)
    if ok:
        print("transaction ID: {}".format(message))
        if len(key) > 0:
            display = self.parse_output(key)
            self.debug_raw_io(key)
            return display
        else:
            return ""
    else:
        raise KeyError('Request returns Error - {} msg:{} txt:{}'.format(key, message, self.parse_output(message)))
def normalize_tx_params(self, tx_params) ‑> dict

Normalize and return the given transaction parameters.

Expand source code
def normalize_tx_params(self, tx_params) -> dict:
    """Normalize and return the given transaction parameters."""
    params = dict()
    return params
def parse_output(self, raw: ) ‑> 
Expand source code
def parse_output(self, raw: any) -> any:
    if type(raw) is bytes:
        """Parse contract result as result."""

        parsed_result = decode_single(self.output_type, bytes.fromhex(raw))
        if len(self.outputs) == 1:
            return parsed_result[0]
        if len(self.outputs) == 0:
            return None
        return parsed_result

    elif type(raw) is str:
        """Parse contract result as result."""

        parsed_result = decode_single(self.output_type, bytes.fromhex(raw))
        if len(self.outputs) == 1:
            return parsed_result[0]
        if len(self.outputs) == 0:
            return None
        return parsed_result

    elif type(raw) is list:
        """Parse contract result as result."""

        parsed_result = []
        for k in raw:
            p = decode_single(self.output_type, bytes.fromhex(k))
            parsed_result.append(p)
        if len(self.outputs) >= 1:
            self.debug_io(parsed_result)
            return parsed_result[0]
        if len(self.outputs) == 0:
            print("no returns.. ")
            return None

        return None

    else:

        print("there is not type were found.. ")
        print(self.output_type)
        return raw
def setDebug(self, b: bool) ‑> NoneType
Expand source code
def setDebug(self, b: bool) -> None:
    self.debug = b
def trackEventReceipt(self, trnId: str)
Expand source code
def trackEventReceipt(self, trnId: str):
    event = self._tron.get_event_transaction_id(trnId)
    print("=======debug event returns on this Transaction ID {}".format(trnId))
    print(event)
    print("=======end event report ========")
def with_asset_transfer(self, amount: int, token_id: int) ‑> ContractMethod

Call a contract function with TRC10 token transfer.

Expand source code
def with_asset_transfer(self, amount: int, token_id: int) -> "ContractMethod":
    """Call a contract function with TRC10 token transfer."""
    self.call_token_value = amount
    self.call_token_id = token_id
    return self
def with_owner(self, addr: str) ‑> ContractMethod

Set the calling owner address.

Can also be changed through :meth:TransactionBuilder.with_owner() <tronpy.tron.TransactionBuilder.with_owner>.

Expand source code
def with_owner(self, addr: str) -> "ContractMethod":
    """Set the calling owner address.

    Can also be changed through :meth:`TransactionBuilder.with_owner() <tronpy.tron.TransactionBuilder.with_owner>`.
    """
    self._owner_address = addr
    return self
def with_transfer(self, amount: int) ‑> ContractMethod

Call a contract function with TRX transfer. amount in SUN.

Expand source code
def with_transfer(self, amount: int) -> "ContractMethod":
    """Call a contract function with TRX transfer. ``amount`` in `SUN`."""
    self.call_value = amount
    return self
class ShieldedTRC20 (contract: Contract, client: Tron, address: str)

Shielded TRC20 Wrapper.

Expand source code
class ShieldedTRC20(object):
    """Shielded TRC20 Wrapper."""

    def __init__(self, contract: Contract, client: Tron, address: str):
        self.shielded = address
        """The shielded TRC20 contract."""
        self._client = client
        self._trx_module = client.trx
        self._contract = contract
        # lazy properties
        self._trc20 = None
        self._scale_factor = None

    @property
    def trc20(self) -> Contract:
        """The corresponding TRC20 contract."""
        if self._trc20 is None:
            trc20_address = "41" + str(self.shielded)._bytecode[-52:-32].hex()
            self._trc20 = self._trx_module.get_contract(trc20_address)
        return self._trc20

    @property
    def scale_factor(self) -> int:
        """Scaling factor of the shielded contract."""
        if self._scale_factor is None:
            self._scale_factor = self._contract.functions.scalingFactor()
        return self._scale_factor

    def get_rcm(self) -> str:
        return self._client.manager.request("wallet/getrcm")["value"]

    def mint(self, taddr: str, zaddr: str, amount: int, memo: str = "") -> "TransactionBuilder":
        """Mint, transfer from T-address to z-address."""
        rcm = self.get_rcm()
        payload = {
            "from_amount": str(amount),
            "shielded_receives": {
                "note": {
                    "value": amount // self.scale_factor,
                    "payment_address": zaddr,
                    "rcm": rcm,
                    "memo": memo.encode().hex(),
                }
            },
            "shielded_TRC20_contract_address": to_hex_address(self._contract.contract_address),
        }

        ret = self._client.manager.request("wallet/createshieldedcontractparameters", payload)
        self._client._handle_api_error(ret)
        parameter = ret["trigger_contract_input"]
        function_signature = self._contract.functions.mint.function_signature_hash
        return self._trx_module._build_transaction(
            "TriggerSmartContract",
            {
                "owner_address": to_hex_address(taddr),
                "contract_address": to_hex_address(self._contract.contract_address),
                "data": function_signature + parameter,
            },
            method=self._contract.functions.mint,
        )

    def transfer(
            self, zkey: dict, notes: Union[list, dict], *to: Union[Tuple[str, int], Tuple[str, int, str]],
    ) -> "tronpy.tron.TransactionBuilder":
        """Transfer from z-address to z-address."""
        if isinstance(notes, (dict,)):
            notes = [notes]

        assert 1 <= len(notes) <= 2

        spends = []
        spend_amount = 0
        for note in notes:
            if note.get("is_spent", False):
                raise DoubleSpending
            alpha = self.get_rcm()
            root, path = self.get_path(note.get("position", 0))
            spends.append(
                {"note": note["note"], "alpha": alpha, "root": root, "path": path, "pos": note.get("position", 0)}
            )
            spend_amount += note["note"]["value"]

        receives = []
        receive_amount = 0
        for recv in to:
            addr = recv[0]
            amount = recv[1]
            receive_amount += amount
            if len(recv) == 3:
                memo = recv[2]
            else:
                memo = ""

            rcm = self.get_rcm()

            receives.append(
                {"note": {"value": amount, "payment_address": addr, "rcm": rcm, "memo": memo.encode().hex()}}
            )

        if spend_amount != receive_amount:
            raise ValueError("spend amount is not equal to receive amount")

        payload = {
            "ask": zkey["ask"],
            "nsk": zkey["nsk"],
            "ovk": zkey["ovk"],
            "shielded_spends": spends,
            "shielded_receives": receives,
            "shielded_TRC20_contract_address": to_hex_address(self.shielded.contract_address),
        }
        ret = self._client.provider.make_request("wallet/createshieldedcontractparameters", payload)
        self._client._handle_api_error(ret)
        parameter = ret["trigger_contract_input"]
        function_signature = self.shielded.functions.transfer.function_signature_hash
        return self._trx_module._build_transaction(
            "TriggerSmartContract",
            {
                "owner_address": "0000000000000000000000000000000000000000",
                "contract_address": to_hex_address(self.shielded.contract_address),
                "data": function_signature + parameter,
            },
            method=self.shielded.functions.transfer,
        )

    def burn(
            self, zkey: dict, note: dict, *to: Union[Tuple[str, int], Tuple[str, int, str]]
    ) -> "tronpy.tron.TransactionBuilder":
        """Burn, transfer from z-address to T-address."""
        spends = []
        alpha = self.get_rcm()
        root, path = self.get_path(note.get("position", 0))
        if note.get("is_spent", False):
            raise DoubleSpending
        spends.append(
            {"note": note["note"], "alpha": alpha, "root": root, "path": path, "pos": note.get("position", 0)}
        )
        change_amount = 0
        receives = []
        to_addr = None
        to_amount = 0
        to_memo = ''
        if not to:
            raise ValueError('burn must have a output')
        for receive in to:
            addr = receive[0]
            amount = receive[1]
            if len(receive) == 3:
                memo = receive[2]
            else:
                memo = ""

            if addr.startswith('ztron1'):
                change_amount += amount
                rcm = self.get_rcm()
                receives = [
                    {"note": {"value": amount, "payment_address": addr, "rcm": rcm, "memo": memo.encode().hex()}}
                ]
            else:
                # assume T-address
                to_addr = addr
                to_amount = amount
                to_memo = memo

        if note["note"]["value"] * self.scale_factor - change_amount * self.scale_factor != to_amount:
            raise ValueError("Balance amount is wrong")

        payload = {
            "ask": zkey["ask"],
            "nsk": zkey["nsk"],
            "ovk": zkey["ovk"],
            "shielded_spends": spends,
            "shielded_receives": receives,
            "to_amount": str(to_amount),
            "transparent_to_address": to_hex_address(to_addr),
            "shielded_TRC20_contract_address": to_hex_address(self.shielded.contract_address),
        }

        ret = self._client.provider.make_request("wallet/createshieldedcontractparameters", payload)
        self._client._handle_api_error(ret)
        parameter = ret["trigger_contract_input"]
        function_signature = self.shielded.functions.burn.function_signature_hash
        txn = self._trx_module._build_transaction(
            "TriggerSmartContract",
            {
                "owner_address": "410000000000000000000000000000000000000000",
                "contract_address": to_hex_address(self.shielded.contract_address),
                "data": function_signature + parameter,
            },
            method=self.shielded.functions.burn,
        )
        if to_memo:
            txn = txn.memo(to_memo)
        return txn

    def _fix_notes(self, notes: list) -> list:
        for note in notes:
            if "position" not in note:
                note["position"] = 0
            if "is_spent" not in note:
                note["is_spent"] = False
            # if "memo" in note["note"]:
            #     note["note"]["memo"] = bytes.fromhex(note["note"]["memo"]).decode("utf8", 'ignore')
        return notes

    # use zkey pair from wallet/getnewshieldedaddress
    def scan_incoming_notes(self, zkey: dict, start_block_number: int, end_block_number: int = None) -> list:
        """Scan incoming notes using ivk, ak, nk."""
        if end_block_number is None:
            end_block_number = start_block_number + 1000
        payload = {
            "start_block_index": start_block_number,
            "end_block_index": end_block_number,
            "shielded_TRC20_contract_address": to_hex_address(self.shielded.contract_address),
            "ivk": zkey["ivk"],
            "ak": zkey["ak"],
            "nk": zkey["nk"],
        }
        ret = self._client.provider.make_request("wallet/scanshieldedtrc20notesbyivk", payload)
        self._client._handle_api_error(ret)
        return self._fix_notes(ret.get("noteTxs", []))

    def scan_outgoing_notes(
            self, zkey_or_ovk: Union[dict, str], start_block_number: int, end_block_number: int = None
    ) -> list:
        """Scan outgoing notes using ovk."""
        if end_block_number is None:
            end_block_number = start_block_number + 1000

        ovk = zkey_or_ovk
        if isinstance(zkey_or_ovk, (dict,)):
            ovk = zkey_or_ovk["ovk"]

        payload = {
            "start_block_index": start_block_number,
            "end_block_index": end_block_number,
            "shielded_TRC20_contract_address": to_hex_address(self.shielded.contract_address),
            "ovk": ovk,
        }
        ret = self._client.provider.make_request("wallet/scanshieldedtrc20notesbyovk", payload)
        self._client._handle_api_error(ret)
        return ret.get("noteTxs", [])

    # (root, path)
    def get_path(self, position: int = 0) -> (str, str):
        root, path = self.shielded.functions.getPath(position)
        root = root.hex()
        path = "".join(p.hex() for p in path)
        return (root, path)

    def is_note_spent(self, zkey: dict, note: dict) -> bool:
        """Is a note spent."""
        payload = dict(note)
        payload["shielded_TRC20_contract_address"] = to_hex_address(self.shielded.contract_address)
        if "position" not in note:
            payload["position"] = 0
        payload["ak"] = zkey["ak"]
        payload["nk"] = zkey["nk"]

        ret = self._client.provider.make_request("wallet/isshieldedtrc20contractnotespent", payload)

        return ret.get('is_spent', None)

Instance variables

var scale_factor : int

Scaling factor of the shielded contract.

Expand source code
@property
def scale_factor(self) -> int:
    """Scaling factor of the shielded contract."""
    if self._scale_factor is None:
        self._scale_factor = self._contract.functions.scalingFactor()
    return self._scale_factor
var shielded

The shielded TRC20 contract.

var trc20Contract

The corresponding TRC20 contract.

Expand source code
@property
def trc20(self) -> Contract:
    """The corresponding TRC20 contract."""
    if self._trc20 is None:
        trc20_address = "41" + str(self.shielded)._bytecode[-52:-32].hex()
        self._trc20 = self._trx_module.get_contract(trc20_address)
    return self._trc20

Methods

def burn(self, zkey: dict, note: dict, *to: Union[Tuple[str, int], Tuple[str, int, str]]) ‑> tronpy.tron.TransactionBuilder

Burn, transfer from z-address to T-address.

Expand source code
def burn(
        self, zkey: dict, note: dict, *to: Union[Tuple[str, int], Tuple[str, int, str]]
) -> "tronpy.tron.TransactionBuilder":
    """Burn, transfer from z-address to T-address."""
    spends = []
    alpha = self.get_rcm()
    root, path = self.get_path(note.get("position", 0))
    if note.get("is_spent", False):
        raise DoubleSpending
    spends.append(
        {"note": note["note"], "alpha": alpha, "root": root, "path": path, "pos": note.get("position", 0)}
    )
    change_amount = 0
    receives = []
    to_addr = None
    to_amount = 0
    to_memo = ''
    if not to:
        raise ValueError('burn must have a output')
    for receive in to:
        addr = receive[0]
        amount = receive[1]
        if len(receive) == 3:
            memo = receive[2]
        else:
            memo = ""

        if addr.startswith('ztron1'):
            change_amount += amount
            rcm = self.get_rcm()
            receives = [
                {"note": {"value": amount, "payment_address": addr, "rcm": rcm, "memo": memo.encode().hex()}}
            ]
        else:
            # assume T-address
            to_addr = addr
            to_amount = amount
            to_memo = memo

    if note["note"]["value"] * self.scale_factor - change_amount * self.scale_factor != to_amount:
        raise ValueError("Balance amount is wrong")

    payload = {
        "ask": zkey["ask"],
        "nsk": zkey["nsk"],
        "ovk": zkey["ovk"],
        "shielded_spends": spends,
        "shielded_receives": receives,
        "to_amount": str(to_amount),
        "transparent_to_address": to_hex_address(to_addr),
        "shielded_TRC20_contract_address": to_hex_address(self.shielded.contract_address),
    }

    ret = self._client.provider.make_request("wallet/createshieldedcontractparameters", payload)
    self._client._handle_api_error(ret)
    parameter = ret["trigger_contract_input"]
    function_signature = self.shielded.functions.burn.function_signature_hash
    txn = self._trx_module._build_transaction(
        "TriggerSmartContract",
        {
            "owner_address": "410000000000000000000000000000000000000000",
            "contract_address": to_hex_address(self.shielded.contract_address),
            "data": function_signature + parameter,
        },
        method=self.shielded.functions.burn,
    )
    if to_memo:
        txn = txn.memo(to_memo)
    return txn
def get_path(self, position: int = 0) ‑> ()
Expand source code
def get_path(self, position: int = 0) -> (str, str):
    root, path = self.shielded.functions.getPath(position)
    root = root.hex()
    path = "".join(p.hex() for p in path)
    return (root, path)
def get_rcm(self) ‑> str
Expand source code
def get_rcm(self) -> str:
    return self._client.manager.request("wallet/getrcm")["value"]
def is_note_spent(self, zkey: dict, note: dict) ‑> bool

Is a note spent.

Expand source code
def is_note_spent(self, zkey: dict, note: dict) -> bool:
    """Is a note spent."""
    payload = dict(note)
    payload["shielded_TRC20_contract_address"] = to_hex_address(self.shielded.contract_address)
    if "position" not in note:
        payload["position"] = 0
    payload["ak"] = zkey["ak"]
    payload["nk"] = zkey["nk"]

    ret = self._client.provider.make_request("wallet/isshieldedtrc20contractnotespent", payload)

    return ret.get('is_spent', None)
def mint(self, taddr: str, zaddr: str, amount: int, memo: str = '') ‑> TransactionBuilder

Mint, transfer from T-address to z-address.

Expand source code
def mint(self, taddr: str, zaddr: str, amount: int, memo: str = "") -> "TransactionBuilder":
    """Mint, transfer from T-address to z-address."""
    rcm = self.get_rcm()
    payload = {
        "from_amount": str(amount),
        "shielded_receives": {
            "note": {
                "value": amount // self.scale_factor,
                "payment_address": zaddr,
                "rcm": rcm,
                "memo": memo.encode().hex(),
            }
        },
        "shielded_TRC20_contract_address": to_hex_address(self._contract.contract_address),
    }

    ret = self._client.manager.request("wallet/createshieldedcontractparameters", payload)
    self._client._handle_api_error(ret)
    parameter = ret["trigger_contract_input"]
    function_signature = self._contract.functions.mint.function_signature_hash
    return self._trx_module._build_transaction(
        "TriggerSmartContract",
        {
            "owner_address": to_hex_address(taddr),
            "contract_address": to_hex_address(self._contract.contract_address),
            "data": function_signature + parameter,
        },
        method=self._contract.functions.mint,
    )
def scan_incoming_notes(self, zkey: dict, start_block_number: int, end_block_number: int = None) ‑> list

Scan incoming notes using ivk, ak, nk.

Expand source code
def scan_incoming_notes(self, zkey: dict, start_block_number: int, end_block_number: int = None) -> list:
    """Scan incoming notes using ivk, ak, nk."""
    if end_block_number is None:
        end_block_number = start_block_number + 1000
    payload = {
        "start_block_index": start_block_number,
        "end_block_index": end_block_number,
        "shielded_TRC20_contract_address": to_hex_address(self.shielded.contract_address),
        "ivk": zkey["ivk"],
        "ak": zkey["ak"],
        "nk": zkey["nk"],
    }
    ret = self._client.provider.make_request("wallet/scanshieldedtrc20notesbyivk", payload)
    self._client._handle_api_error(ret)
    return self._fix_notes(ret.get("noteTxs", []))
def scan_outgoing_notes(self, zkey_or_ovk: Union[dict, str], start_block_number: int, end_block_number: int = None) ‑> list

Scan outgoing notes using ovk.

Expand source code
def scan_outgoing_notes(
        self, zkey_or_ovk: Union[dict, str], start_block_number: int, end_block_number: int = None
) -> list:
    """Scan outgoing notes using ovk."""
    if end_block_number is None:
        end_block_number = start_block_number + 1000

    ovk = zkey_or_ovk
    if isinstance(zkey_or_ovk, (dict,)):
        ovk = zkey_or_ovk["ovk"]

    payload = {
        "start_block_index": start_block_number,
        "end_block_index": end_block_number,
        "shielded_TRC20_contract_address": to_hex_address(self.shielded.contract_address),
        "ovk": ovk,
    }
    ret = self._client.provider.make_request("wallet/scanshieldedtrc20notesbyovk", payload)
    self._client._handle_api_error(ret)
    return ret.get("noteTxs", [])
def transfer(self, zkey: dict, notes: Union[list, dict], *to: Union[Tuple[str, int], Tuple[str, int, str]]) ‑> tronpy.tron.TransactionBuilder

Transfer from z-address to z-address.

Expand source code
def transfer(
        self, zkey: dict, notes: Union[list, dict], *to: Union[Tuple[str, int], Tuple[str, int, str]],
) -> "tronpy.tron.TransactionBuilder":
    """Transfer from z-address to z-address."""
    if isinstance(notes, (dict,)):
        notes = [notes]

    assert 1 <= len(notes) <= 2

    spends = []
    spend_amount = 0
    for note in notes:
        if note.get("is_spent", False):
            raise DoubleSpending
        alpha = self.get_rcm()
        root, path = self.get_path(note.get("position", 0))
        spends.append(
            {"note": note["note"], "alpha": alpha, "root": root, "path": path, "pos": note.get("position", 0)}
        )
        spend_amount += note["note"]["value"]

    receives = []
    receive_amount = 0
    for recv in to:
        addr = recv[0]
        amount = recv[1]
        receive_amount += amount
        if len(recv) == 3:
            memo = recv[2]
        else:
            memo = ""

        rcm = self.get_rcm()

        receives.append(
            {"note": {"value": amount, "payment_address": addr, "rcm": rcm, "memo": memo.encode().hex()}}
        )

    if spend_amount != receive_amount:
        raise ValueError("spend amount is not equal to receive amount")

    payload = {
        "ask": zkey["ask"],
        "nsk": zkey["nsk"],
        "ovk": zkey["ovk"],
        "shielded_spends": spends,
        "shielded_receives": receives,
        "shielded_TRC20_contract_address": to_hex_address(self.shielded.contract_address),
    }
    ret = self._client.provider.make_request("wallet/createshieldedcontractparameters", payload)
    self._client._handle_api_error(ret)
    parameter = ret["trigger_contract_input"]
    function_signature = self.shielded.functions.transfer.function_signature_hash
    return self._trx_module._build_transaction(
        "TriggerSmartContract",
        {
            "owner_address": "0000000000000000000000000000000000000000",
            "contract_address": to_hex_address(self.shielded.contract_address),
            "data": function_signature + parameter,
        },
        method=self.shielded.functions.transfer,
    )
class Validator (web3_or_provider: Tron, contract_address: str)

Base class for validating inputs to methods.

Initialize the instance.

Expand source code
class Validator:
    """Base class for validating inputs to methods."""

    def __init__(
            self,
            web3_or_provider: Tron,
            contract_address: str,
    ):
        """Initialize the instance."""

    def assert_valid(
            self, method_name: str, parameter_name: str, argument_value: Any
    ):
        """Raise an exception if method input is not valid.

        :param method_name: Name of the method whose input is to be validated.
        :param parameter_name: Name of the parameter whose input is to be
            validated.
        :param argument_value: Value of argument to parameter to be validated.
        """

Methods

def assert_valid(self, method_name: str, parameter_name: str, argument_value: Any)

Raise an exception if method input is not valid.

:param method_name: Name of the method whose input is to be validated. :param parameter_name: Name of the parameter whose input is to be validated. :param argument_value: Value of argument to parameter to be validated.

Expand source code
def assert_valid(
        self, method_name: str, parameter_name: str, argument_value: Any
):
    """Raise an exception if method input is not valid.

    :param method_name: Name of the method whose input is to be validated.
    :param parameter_name: Name of the parameter whose input is to be
        validated.
    :param argument_value: Value of argument to parameter to be validated.
    """