From de07f8f0d4b75324ecdf0dfdf763dbd8158d0f98 Mon Sep 17 00:00:00 2001 From: "Chris Kim (Hyunggun)" Date: Fri, 25 Oct 2024 14:56:31 -0700 Subject: [PATCH 01/23] initial commit to set up arc4 types examples --- .../smart_contracts/arc4_types/contract.py | 9 + .../arc4_types/deploy_config.py | 36 ++ .../arc4_types/Arc4Types.approval.teal | 61 +++ .../artifacts/arc4_types/Arc4Types.arc32.json | 55 ++ .../artifacts/arc4_types/Arc4Types.clear.teal | 5 + .../artifacts/arc4_types/arc4_types_client.py | 492 ++++++++++++++++++ 6 files changed, 658 insertions(+) create mode 100644 projects/python-contract-examples/smart_contracts/arc4_types/contract.py create mode 100644 projects/python-contract-examples/smart_contracts/arc4_types/deploy_config.py create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.approval.teal create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.arc32.json create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.clear.teal create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_types_client.py diff --git a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py new file mode 100644 index 0000000..0146742 --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py @@ -0,0 +1,9 @@ +# pyright: reportMissingModuleSource=false +from algopy import ARC4Contract, String +from algopy.arc4 import abimethod + + +class Arc4Types(ARC4Contract): + @abimethod() + def hello(self, name: String) -> String: + return "Hello, " + name diff --git a/projects/python-contract-examples/smart_contracts/arc4_types/deploy_config.py b/projects/python-contract-examples/smart_contracts/arc4_types/deploy_config.py new file mode 100644 index 0000000..bc1a7db --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/arc4_types/deploy_config.py @@ -0,0 +1,36 @@ +import logging + +import algokit_utils +from algosdk.v2client.algod import AlgodClient +from algosdk.v2client.indexer import IndexerClient +from smart_contracts.artifacts.arc4_types.arc4_types_client import ( + Arc4TypesClient, + ) + +logger = logging.getLogger(__name__) + + +# define deployment behaviour based on supplied app spec +def deploy( + algod_client: AlgodClient, + indexer_client: IndexerClient, + app_spec: algokit_utils.ApplicationSpecification, + deployer: algokit_utils.Account, +) -> None: + + + app_client = Arc4TypesClient( + algod_client, + creator=deployer, + indexer_client=indexer_client, + ) + app_client.deploy( + on_schema_break=algokit_utils.OnSchemaBreak.AppendApp, + on_update=algokit_utils.OnUpdate.AppendApp, + ) + name = "world" + response = app_client.hello(name=name) + logger.info( + f"Called hello on {app_spec.contract.name} ({app_client.app_id}) " + f"with name={name}, received: {response.return_value}" + ) diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.approval.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.approval.teal new file mode 100644 index 0000000..8c52292 --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.approval.teal @@ -0,0 +1,61 @@ +#pragma version 10 + +smart_contracts.arc4_types.contract.Arc4Types.approval_program: + callsub __puya_arc4_router__ + return + + +// smart_contracts.arc4_types.contract.Arc4Types.__puya_arc4_router__() -> uint64: +__puya_arc4_router__: + proto 0 1 + txn NumAppArgs + bz __puya_arc4_router___bare_routing@5 + method "hello(string)string" + txna ApplicationArgs 0 + match __puya_arc4_router___hello_route@2 + int 0 + retsub + +__puya_arc4_router___hello_route@2: + txn OnCompletion + ! + assert // OnCompletion is NoOp + txn ApplicationID + assert // is not creating + txna ApplicationArgs 1 + extract 2 0 + callsub hello + dup + len + itob + extract 6 2 + swap + concat + byte 0x151f7c75 + swap + concat + log + int 1 + retsub + +__puya_arc4_router___bare_routing@5: + txn OnCompletion + bnz __puya_arc4_router___after_if_else@9 + txn ApplicationID + ! + assert // is creating + int 1 + retsub + +__puya_arc4_router___after_if_else@9: + int 0 + retsub + + +// smart_contracts.arc4_types.contract.Arc4Types.hello(name: bytes) -> bytes: +hello: + proto 1 1 + byte "Hello, " + frame_dig -1 + concat + retsub diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.arc32.json b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.arc32.json new file mode 100644 index 0000000..62d9090 --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.arc32.json @@ -0,0 +1,55 @@ +{ + "hints": { + "hello(string)string": { + "call_config": { + "no_op": "CALL" + } + } + }, + "source": { + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANQogICAgbWV0aG9kICJoZWxsbyhzdHJpbmcpc3RyaW5nIgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAogICAgbWF0Y2ggX19wdXlhX2FyYzRfcm91dGVyX19faGVsbG9fcm91dGVAMgogICAgaW50IDAKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19faGVsbG9fcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGV4dHJhY3QgMiAwCiAgICBjYWxsc3ViIGhlbGxvCiAgICBkdXAKICAgIGxlbgogICAgaXRvYgogICAgZXh0cmFjdCA2IDIKICAgIHN3YXAKICAgIGNvbmNhdAogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDU6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBibnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUA5CiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgIQogICAgYXNzZXJ0IC8vIGlzIGNyZWF0aW5nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDk6CiAgICBpbnQgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmhlbGxvKG5hbWU6IGJ5dGVzKSAtPiBieXRlczoKaGVsbG86CiAgICBwcm90byAxIDEKICAgIGJ5dGUgIkhlbGxvLCAiCiAgICBmcmFtZV9kaWcgLTEKICAgIGNvbmNhdAogICAgcmV0c3ViCg==", + "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" + }, + "state": { + "global": { + "num_byte_slices": 0, + "num_uints": 0 + }, + "local": { + "num_byte_slices": 0, + "num_uints": 0 + } + }, + "schema": { + "global": { + "declared": {}, + "reserved": {} + }, + "local": { + "declared": {}, + "reserved": {} + } + }, + "contract": { + "name": "Arc4Types", + "methods": [ + { + "name": "hello", + "args": [ + { + "type": "string", + "name": "name" + } + ], + "readonly": false, + "returns": { + "type": "string" + } + } + ], + "networks": {} + }, + "bare_call_config": { + "no_op": "CREATE" + } +} \ No newline at end of file diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.clear.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.clear.teal new file mode 100644 index 0000000..7b46465 --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.clear.teal @@ -0,0 +1,5 @@ +#pragma version 10 + +smart_contracts.arc4_types.contract.Arc4Types.clear_state_program: + int 1 + return diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_types_client.py b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_types_client.py new file mode 100644 index 0000000..f41074f --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_types_client.py @@ -0,0 +1,492 @@ +# flake8: noqa +# fmt: off +# mypy: disable-error-code="no-any-return, no-untyped-call, misc, type-arg" +# This file was automatically generated by algokit-client-generator. +# DO NOT MODIFY IT BY HAND. +# requires: algokit-utils@^1.2.0 +import base64 +import dataclasses +import decimal +import typing +from abc import ABC, abstractmethod + +import algokit_utils +import algosdk +from algosdk.v2client import models +from algosdk.atomic_transaction_composer import ( + AtomicTransactionComposer, + AtomicTransactionResponse, + SimulateAtomicTransactionResponse, + TransactionSigner, + TransactionWithSigner +) + +_APP_SPEC_JSON = r"""{ + "hints": { + "hello(string)string": { + "call_config": { + "no_op": "CALL" + } + } + }, + "source": { + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANQogICAgbWV0aG9kICJoZWxsbyhzdHJpbmcpc3RyaW5nIgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAogICAgbWF0Y2ggX19wdXlhX2FyYzRfcm91dGVyX19faGVsbG9fcm91dGVAMgogICAgaW50IDAKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19faGVsbG9fcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGV4dHJhY3QgMiAwCiAgICBjYWxsc3ViIGhlbGxvCiAgICBkdXAKICAgIGxlbgogICAgaXRvYgogICAgZXh0cmFjdCA2IDIKICAgIHN3YXAKICAgIGNvbmNhdAogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDU6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBibnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUA5CiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgIQogICAgYXNzZXJ0IC8vIGlzIGNyZWF0aW5nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDk6CiAgICBpbnQgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmhlbGxvKG5hbWU6IGJ5dGVzKSAtPiBieXRlczoKaGVsbG86CiAgICBwcm90byAxIDEKICAgIGJ5dGUgIkhlbGxvLCAiCiAgICBmcmFtZV9kaWcgLTEKICAgIGNvbmNhdAogICAgcmV0c3ViCg==", + "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" + }, + "state": { + "global": { + "num_byte_slices": 0, + "num_uints": 0 + }, + "local": { + "num_byte_slices": 0, + "num_uints": 0 + } + }, + "schema": { + "global": { + "declared": {}, + "reserved": {} + }, + "local": { + "declared": {}, + "reserved": {} + } + }, + "contract": { + "name": "Arc4Types", + "methods": [ + { + "name": "hello", + "args": [ + { + "type": "string", + "name": "name" + } + ], + "returns": { + "type": "string" + } + } + ], + "networks": {} + }, + "bare_call_config": { + "no_op": "CREATE" + } +}""" +APP_SPEC = algokit_utils.ApplicationSpecification.from_json(_APP_SPEC_JSON) +_TReturn = typing.TypeVar("_TReturn") + + +class _ArgsBase(ABC, typing.Generic[_TReturn]): + @staticmethod + @abstractmethod + def method() -> str: + ... + + +_TArgs = typing.TypeVar("_TArgs", bound=_ArgsBase[typing.Any]) + + +@dataclasses.dataclass(kw_only=True) +class _TArgsHolder(typing.Generic[_TArgs]): + args: _TArgs + + +def _filter_none(value: dict | typing.Any) -> dict | typing.Any: + if isinstance(value, dict): + return {k: _filter_none(v) for k, v in value.items() if v is not None} + return value + + +def _as_dict(data: typing.Any, *, convert_all: bool = True) -> dict[str, typing.Any]: + if data is None: + return {} + if not dataclasses.is_dataclass(data): + raise TypeError(f"{data} must be a dataclass") + if convert_all: + result = dataclasses.asdict(data) # type: ignore[call-overload] + else: + result = {f.name: getattr(data, f.name) for f in dataclasses.fields(data)} + return _filter_none(result) + + +def _convert_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, +) -> algokit_utils.TransactionParametersDict: + return typing.cast(algokit_utils.TransactionParametersDict, _as_dict(transaction_parameters)) + + +def _convert_call_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, +) -> algokit_utils.OnCompleteCallParametersDict: + return typing.cast(algokit_utils.OnCompleteCallParametersDict, _as_dict(transaction_parameters)) + + +def _convert_create_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, + on_complete: algokit_utils.OnCompleteActionName, +) -> algokit_utils.CreateCallParametersDict: + result = typing.cast(algokit_utils.CreateCallParametersDict, _as_dict(transaction_parameters)) + on_complete_enum = on_complete.replace("_", " ").title().replace(" ", "") + "OC" + result["on_complete"] = getattr(algosdk.transaction.OnComplete, on_complete_enum) + return result + + +def _convert_deploy_args( + deploy_args: algokit_utils.DeployCallArgs | None, +) -> algokit_utils.ABICreateCallArgsDict | None: + if deploy_args is None: + return None + + deploy_args_dict = typing.cast(algokit_utils.ABICreateCallArgsDict, _as_dict(deploy_args)) + if isinstance(deploy_args, _TArgsHolder): + deploy_args_dict["args"] = _as_dict(deploy_args.args) + deploy_args_dict["method"] = deploy_args.args.method() + + return deploy_args_dict + + +@dataclasses.dataclass(kw_only=True) +class HelloArgs(_ArgsBase[str]): + name: str + + @staticmethod + def method() -> str: + return "hello(string)string" + + +@dataclasses.dataclass(kw_only=True) +class SimulateOptions: + allow_more_logs: bool = dataclasses.field(default=False) + allow_empty_signatures: bool = dataclasses.field(default=False) + extra_opcode_budget: int = dataclasses.field(default=0) + exec_trace_config: models.SimulateTraceConfig | None = dataclasses.field(default=None) + + +class Composer: + + def __init__(self, app_client: algokit_utils.ApplicationClient, atc: AtomicTransactionComposer): + self.app_client = app_client + self.atc = atc + + def build(self) -> AtomicTransactionComposer: + return self.atc + + def simulate(self, options: SimulateOptions | None = None) -> SimulateAtomicTransactionResponse: + request = models.SimulateRequest( + allow_more_logs=options.allow_more_logs, + allow_empty_signatures=options.allow_empty_signatures, + extra_opcode_budget=options.extra_opcode_budget, + exec_trace_config=options.exec_trace_config, + txn_groups=[] + ) if options else None + result = self.atc.simulate(self.app_client.algod_client, request) + return result + + def execute(self) -> AtomicTransactionResponse: + return self.app_client.execute_atc(self.atc) + + def hello( + self, + *, + name: str, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> "Composer": + """Adds a call to `hello(string)string` ABI method + + :param str name: The `name` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + args = HelloArgs( + name=name, + ) + self.app_client.compose_call( + self.atc, + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return self + + def create_bare( + self, + *, + on_complete: typing.Literal["no_op"] = "no_op", + transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, + ) -> "Composer": + """Adds a call to create an application using the no_op bare method + + :param typing.Literal[no_op] on_complete: On completion type to use + :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + self.app_client.compose_create( + self.atc, + call_abi_method=False, + transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), + ) + return self + + def clear_state( + self, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + app_args: list[bytes] | None = None, + ) -> "Composer": + """Adds a call to the application with on completion set to ClearState + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :param list[bytes] | None app_args: (optional) Application args to pass""" + + self.app_client.compose_clear_state(self.atc, _convert_transaction_parameters(transaction_parameters), app_args) + return self + + +class Arc4TypesClient: + """A class for interacting with the Arc4Types app providing high productivity and + strongly typed methods to deploy and call the app""" + + @typing.overload + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + app_id: int = 0, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + ... + + @typing.overload + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + creator: str | algokit_utils.Account, + indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, + existing_deployments: algokit_utils.AppLookup | None = None, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + ... + + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + creator: str | algokit_utils.Account | None = None, + indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, + existing_deployments: algokit_utils.AppLookup | None = None, + app_id: int = 0, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + """ + Arc4TypesClient can be created with an app_id to interact with an existing application, alternatively + it can be created with a creator and indexer_client specified to find existing applications by name and creator. + + :param AlgodClient algod_client: AlgoSDK algod client + :param int app_id: The app_id of an existing application, to instead find the application by creator and name + use the creator and indexer_client parameters + :param str | Account creator: The address or Account of the app creator to resolve the app_id + :param IndexerClient indexer_client: AlgoSDK indexer client, only required if deploying or finding app_id by + creator and app name + :param AppLookup existing_deployments: + :param TransactionSigner | Account signer: Account or signer to use to sign transactions, if not specified and + creator was passed as an Account will use that. + :param str sender: Address to use as the sender for all transactions, will use the address associated with the + signer if not specified. + :param TemplateValueMapping template_values: Values to use for TMPL_* template variables, dictionary keys should + *NOT* include the TMPL_ prefix + :param str | None app_name: Name of application to use when deploying, defaults to name defined on the + Application Specification + """ + + self.app_spec = APP_SPEC + + # calling full __init__ signature, so ignoring mypy warning about overloads + self.app_client = algokit_utils.ApplicationClient( # type: ignore[call-overload, misc] + algod_client=algod_client, + app_spec=self.app_spec, + app_id=app_id, + creator=creator, + indexer_client=indexer_client, + existing_deployments=existing_deployments, + signer=signer, + sender=sender, + suggested_params=suggested_params, + template_values=template_values, + app_name=app_name, + ) + + @property + def algod_client(self) -> algosdk.v2client.algod.AlgodClient: + return self.app_client.algod_client + + @property + def app_id(self) -> int: + return self.app_client.app_id + + @app_id.setter + def app_id(self, value: int) -> None: + self.app_client.app_id = value + + @property + def app_address(self) -> str: + return self.app_client.app_address + + @property + def sender(self) -> str | None: + return self.app_client.sender + + @sender.setter + def sender(self, value: str) -> None: + self.app_client.sender = value + + @property + def signer(self) -> TransactionSigner | None: + return self.app_client.signer + + @signer.setter + def signer(self, value: TransactionSigner) -> None: + self.app_client.signer = value + + @property + def suggested_params(self) -> algosdk.transaction.SuggestedParams | None: + return self.app_client.suggested_params + + @suggested_params.setter + def suggested_params(self, value: algosdk.transaction.SuggestedParams | None) -> None: + self.app_client.suggested_params = value + + def hello( + self, + *, + name: str, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> algokit_utils.ABITransactionResponse[str]: + """Calls `hello(string)string` ABI method + + :param str name: The `name` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.ABITransactionResponse[str]: The result of the transaction""" + + args = HelloArgs( + name=name, + ) + result = self.app_client.call( + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return result + + def create_bare( + self, + *, + on_complete: typing.Literal["no_op"] = "no_op", + transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, + ) -> algokit_utils.TransactionResponse: + """Creates an application using the no_op bare method + + :param typing.Literal[no_op] on_complete: On completion type to use + :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.TransactionResponse: The result of the transaction""" + + result = self.app_client.create( + call_abi_method=False, + transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), + ) + return result + + def clear_state( + self, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + app_args: list[bytes] | None = None, + ) -> algokit_utils.TransactionResponse: + """Calls the application with on completion set to ClearState + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :param list[bytes] | None app_args: (optional) Application args to pass + :returns algokit_utils.TransactionResponse: The result of the transaction""" + + return self.app_client.clear_state(_convert_transaction_parameters(transaction_parameters), app_args) + + def deploy( + self, + version: str | None = None, + *, + signer: TransactionSigner | None = None, + sender: str | None = None, + allow_update: bool | None = None, + allow_delete: bool | None = None, + on_update: algokit_utils.OnUpdate = algokit_utils.OnUpdate.Fail, + on_schema_break: algokit_utils.OnSchemaBreak = algokit_utils.OnSchemaBreak.Fail, + template_values: algokit_utils.TemplateValueMapping | None = None, + create_args: algokit_utils.DeployCallArgs | None = None, + update_args: algokit_utils.DeployCallArgs | None = None, + delete_args: algokit_utils.DeployCallArgs | None = None, + ) -> algokit_utils.DeployResponse: + """Deploy an application and update client to reference it. + + Idempotently deploy (create, update/delete if changed) an app against the given name via the given creator + account, including deploy-time template placeholder substitutions. + To understand the architecture decisions behind this functionality please see + + + ```{note} + If there is a breaking state schema change to an existing app (and `on_schema_break` is set to + 'ReplaceApp' the existing app will be deleted and re-created. + ``` + + ```{note} + If there is an update (different TEAL code) to an existing app (and `on_update` is set to 'ReplaceApp') + the existing app will be deleted and re-created. + ``` + + :param str version: version to use when creating or updating app, if None version will be auto incremented + :param algosdk.atomic_transaction_composer.TransactionSigner signer: signer to use when deploying app + , if None uses self.signer + :param str sender: sender address to use when deploying app, if None uses self.sender + :param bool allow_delete: Used to set the `TMPL_DELETABLE` template variable to conditionally control if an app + can be deleted + :param bool allow_update: Used to set the `TMPL_UPDATABLE` template variable to conditionally control if an app + can be updated + :param OnUpdate on_update: Determines what action to take if an application update is required + :param OnSchemaBreak on_schema_break: Determines what action to take if an application schema requirements + has increased beyond the current allocation + :param dict[str, int|str|bytes] template_values: Values to use for `TMPL_*` template variables, dictionary keys + should *NOT* include the TMPL_ prefix + :param algokit_utils.DeployCallArgs | None create_args: Arguments used when creating an application + :param algokit_utils.DeployCallArgs | None update_args: Arguments used when updating an application + :param algokit_utils.DeployCallArgs | None delete_args: Arguments used when deleting an application + :return DeployResponse: details action taken and relevant transactions + :raises DeploymentError: If the deployment failed""" + + return self.app_client.deploy( + version, + signer=signer, + sender=sender, + allow_update=allow_update, + allow_delete=allow_delete, + on_update=on_update, + on_schema_break=on_schema_break, + template_values=template_values, + create_args=_convert_deploy_args(create_args), + update_args=_convert_deploy_args(update_args), + delete_args=_convert_deploy_args(delete_args), + ) + + def compose(self, atc: AtomicTransactionComposer | None = None) -> Composer: + return Composer(self.app_client, atc or AtomicTransactionComposer()) From 144bd341a32db9dcfe849830029374408efc5657 Mon Sep 17 00:00:00 2001 From: "Chris Kim (Hyunggun)" Date: Fri, 25 Oct 2024 19:22:33 -0700 Subject: [PATCH 02/23] examples added. test wip --- .../smart_contracts/arc4_types/contract.py | 115 ++- .../arc4_types/Arc4StaticArray.approval.teal | 76 ++ .../arc4_types/Arc4StaticArray.arc32.json | 51 ++ .../arc4_types/Arc4StaticArray.clear.teal | 5 + .../arc4_types/Arc4Struct.approval.teal | 567 ++++++++++++++ .../arc4_types/Arc4Struct.arc32.json | 111 +++ .../arc4_types/Arc4Struct.clear.teal | 5 + .../arc4_types/Arc4Types.approval.teal | 62 +- .../artifacts/arc4_types/Arc4Types.arc32.json | 35 +- .../arc4_types/arc4_static_array_client.py | 484 ++++++++++++ .../arc4_types/arc4_struct_client.py | 695 ++++++++++++++++++ .../artifacts/arc4_types/arc4_types_client.py | 134 +++- .../tests/arc4_types_integration_test.py | 188 +++++ 13 files changed, 2481 insertions(+), 47 deletions(-) create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.approval.teal create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.arc32.json create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.clear.teal create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.approval.teal create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.arc32.json create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.clear.teal create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_static_array_client.py create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_struct_client.py create mode 100644 projects/python-contract-examples/tests/arc4_types_integration_test.py diff --git a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py index 0146742..e309b54 100644 --- a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py +++ b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py @@ -1,9 +1,118 @@ # pyright: reportMissingModuleSource=false -from algopy import ARC4Contract, String +from algopy import * from algopy.arc4 import abimethod +import typing as t + class Arc4Types(ARC4Contract): + + @abimethod() + def arc4_uint64(self, a: arc4.UInt64, b: arc4.UInt64) -> arc4.UInt64: + """ + This won't compile because you can't do math operations on arc4.UInt64 type. + All arc4 types are backed by byte arrays on the AVM. + c = a + b + """ + + # This is how you can do math operations on arc4.UInt64 type. + c = a.native + b.native + + return arc4.UInt64(c) + + @abimethod() + def arc4_address(self, address: arc4.Address) -> arc4.Address: + underlying_bytes = address.bytes # This will return the underlying bytes of the address. + + account = address.native # This will return the account type of the given address. + bal = account.balance + num_asset_holding = account.total_assets + + """ + You can't return an Account type because it is a reference type. + Convert the Account type to arc4.Address type and return it. + """ + converted_address = arc4.Address(account) + + assert converted_address == address + + return converted_address + +AliasedStaticArray: t.TypeAlias = arc4.StaticArray[arc4.UInt8, t.Literal[1]] + +class Arc4StaticArray(ARC4Contract): + @abimethod() - def hello(self, name: String) -> String: - return "Hello, " + name + def arc4_static_array(self) -> None: + """ + You can create a static array directly from the contract. + """ + static_uint32_array = arc4.StaticArray(arc4.UInt32(1), arc4.UInt32(10), arc4.UInt32(255), arc4.UInt32(128)) + + total = UInt64(0) + for uint32_item in static_uint32_array: + total += uint32_item.native + + assert total == 1 + 10 + 255 + 128 + + """ + You can also create a static array using a type alias. + """ + aliased_static = AliasedStaticArray(arc4.UInt8(101)) + + index = UInt64(0) + + assert (aliased_static[0].native + aliased_static[index].native) == 202 + + """ + You can't modify the elements of a static array. + so this won't compile: + aliased_static[0] = arc4.UInt8(100) + aliased_static.pop() + """ + +class Todo(arc4.Struct): + task: arc4.String + completed: arc4.Bool + +Todos: t.TypeAlias = arc4.DynamicArray[Todo] + +class Arc4Struct(ARC4Contract): + + def __init__(self) -> None: + self.todos = GlobalState(Todos()) + + @abimethod() + def add_todo(self, task: arc4.String) -> Todos: + todo = Todo(task=task, completed=arc4.Bool(False)) + + if self.todos.value.length == 0: + self.todos.value = Todos(todo.copy()) + else: + self.todos.value.append(todo.copy()) + + return self.todos.value + + @abimethod() + def complete_todo(self, task: arc4.String) -> None: + + for index in urange(self.todos.value.length): + if self.todos.value[index].task == task: + self.todos.value[index].completed = arc4.Bool(True) + break + + @abimethod() + def return_todo(self, task: arc4.String) -> Todo: + todo_to_return: Todo + + exist = False + for index in urange(self.todos.value.length): + + if self.todos.value[index].task == task: + todo_to_return = self.todos.value[index].copy() + exist = True + + assert exist + + return todo_to_return + diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.approval.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.approval.teal new file mode 100644 index 0000000..34832b9 --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.approval.teal @@ -0,0 +1,76 @@ +#pragma version 10 + +smart_contracts.arc4_types.contract.Arc4StaticArray.approval_program: + callsub __puya_arc4_router__ + return + + +// smart_contracts.arc4_types.contract.Arc4StaticArray.__puya_arc4_router__() -> uint64: +__puya_arc4_router__: + proto 0 1 + txn NumAppArgs + bz __puya_arc4_router___bare_routing@5 + method "arc4_static_array()void" + txna ApplicationArgs 0 + match __puya_arc4_router___arc4_static_array_route@2 + int 0 + retsub + +__puya_arc4_router___arc4_static_array_route@2: + txn OnCompletion + ! + assert // OnCompletion is NoOp + txn ApplicationID + assert // is not creating + callsub arc4_static_array + int 1 + retsub + +__puya_arc4_router___bare_routing@5: + txn OnCompletion + bnz __puya_arc4_router___after_if_else@9 + txn ApplicationID + ! + assert // is creating + int 1 + retsub + +__puya_arc4_router___after_if_else@9: + int 0 + retsub + + +// smart_contracts.arc4_types.contract.Arc4StaticArray.arc4_static_array() -> void: +arc4_static_array: + proto 0 0 + int 0 + dup + +arc4_static_array_for_header@1: + frame_dig 1 + int 4 + < + bz arc4_static_array_after_for@4 + frame_dig 1 + dup + int 4 + * + byte 0x000000010000000a000000ff00000080 + swap + int 4 + extract3 // on error: Index access is out of bounds + btoi + frame_dig 0 + + + frame_bury 0 + int 1 + + + frame_bury 1 + b arc4_static_array_for_header@1 + +arc4_static_array_after_for@4: + frame_dig 0 + int 394 + == + assert + retsub diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.arc32.json b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.arc32.json new file mode 100644 index 0000000..e3c51ca --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.arc32.json @@ -0,0 +1,51 @@ +{ + "hints": { + "arc4_static_array()void": { + "call_config": { + "no_op": "CALL" + } + } + }, + "source": { + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RhdGljQXJyYXkuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRTdGF0aWNBcnJheS5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANQogICAgbWV0aG9kICJhcmM0X3N0YXRpY19hcnJheSgpdm9pZCIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfc3RhdGljX2FycmF5X3JvdXRlQDIKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfc3RhdGljX2FycmF5X3JvdXRlQDI6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICBjYWxsc3ViIGFyYzRfc3RhdGljX2FycmF5CiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANToKICAgIHR4biBPbkNvbXBsZXRpb24KICAgIGJueiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDkKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICAhCiAgICBhc3NlcnQgLy8gaXMgY3JlYXRpbmcKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAOToKICAgIGludCAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RhdGljQXJyYXkuYXJjNF9zdGF0aWNfYXJyYXkoKSAtPiB2b2lkOgphcmM0X3N0YXRpY19hcnJheToKICAgIHByb3RvIDAgMAogICAgaW50IDAKICAgIGR1cAoKYXJjNF9zdGF0aWNfYXJyYXlfZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDEKICAgIGludCA0CiAgICA8CiAgICBieiBhcmM0X3N0YXRpY19hcnJheV9hZnRlcl9mb3JANAogICAgZnJhbWVfZGlnIDEKICAgIGR1cAogICAgaW50IDQKICAgICoKICAgIGJ5dGUgMHgwMDAwMDAwMTAwMDAwMDBhMDAwMDAwZmYwMDAwMDA4MAogICAgc3dhcAogICAgaW50IDQKICAgIGV4dHJhY3QzIC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgYnRvaQogICAgZnJhbWVfZGlnIDAKICAgICsKICAgIGZyYW1lX2J1cnkgMAogICAgaW50IDEKICAgICsKICAgIGZyYW1lX2J1cnkgMQogICAgYiBhcmM0X3N0YXRpY19hcnJheV9mb3JfaGVhZGVyQDEKCmFyYzRfc3RhdGljX2FycmF5X2FmdGVyX2ZvckA0OgogICAgZnJhbWVfZGlnIDAKICAgIGludCAzOTQKICAgID09CiAgICBhc3NlcnQKICAgIHJldHN1Ygo=", + "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RhdGljQXJyYXkuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" + }, + "state": { + "global": { + "num_byte_slices": 0, + "num_uints": 0 + }, + "local": { + "num_byte_slices": 0, + "num_uints": 0 + } + }, + "schema": { + "global": { + "declared": {}, + "reserved": {} + }, + "local": { + "declared": {}, + "reserved": {} + } + }, + "contract": { + "name": "Arc4StaticArray", + "methods": [ + { + "name": "arc4_static_array", + "args": [], + "readonly": false, + "returns": { + "type": "void" + }, + "desc": "You can create a static array directly from the contract." + } + ], + "networks": {} + }, + "bare_call_config": { + "no_op": "CREATE" + } +} \ No newline at end of file diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.clear.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.clear.teal new file mode 100644 index 0000000..2fb8183 --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.clear.teal @@ -0,0 +1,5 @@ +#pragma version 10 + +smart_contracts.arc4_types.contract.Arc4StaticArray.clear_state_program: + int 1 + return diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.approval.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.approval.teal new file mode 100644 index 0000000..eda3118 --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.approval.teal @@ -0,0 +1,567 @@ +#pragma version 10 + +smart_contracts.arc4_types.contract.Arc4Struct.approval_program: + txn ApplicationID + bnz main_entrypoint@2 + callsub __init__ + +main_entrypoint@2: + callsub __puya_arc4_router__ + return + + +// smart_contracts.arc4_types.contract.Arc4Struct.__puya_arc4_router__() -> uint64: +__puya_arc4_router__: + proto 0 1 + txn NumAppArgs + bz __puya_arc4_router___bare_routing@7 + method "add_todo(string)(string,bool)[]" + method "complete_todo(string)void" + method "return_todo(string)(string,bool)" + txna ApplicationArgs 0 + match __puya_arc4_router___add_todo_route@2 __puya_arc4_router___complete_todo_route@3 __puya_arc4_router___return_todo_route@4 + int 0 + retsub + +__puya_arc4_router___add_todo_route@2: + txn OnCompletion + ! + assert // OnCompletion is NoOp + txn ApplicationID + assert // is not creating + txna ApplicationArgs 1 + callsub add_todo + byte 0x151f7c75 + swap + concat + log + int 1 + retsub + +__puya_arc4_router___complete_todo_route@3: + txn OnCompletion + ! + assert // OnCompletion is NoOp + txn ApplicationID + assert // is not creating + txna ApplicationArgs 1 + callsub complete_todo + int 1 + retsub + +__puya_arc4_router___return_todo_route@4: + txn OnCompletion + ! + assert // OnCompletion is NoOp + txn ApplicationID + assert // is not creating + txna ApplicationArgs 1 + callsub return_todo + byte 0x151f7c75 + swap + concat + log + int 1 + retsub + +__puya_arc4_router___bare_routing@7: + txn OnCompletion + bnz __puya_arc4_router___after_if_else@11 + txn ApplicationID + ! + assert // is creating + int 1 + retsub + +__puya_arc4_router___after_if_else@11: + int 0 + retsub + + +// smart_contracts.arc4_types.contract.Arc4Struct.add_todo(task: bytes) -> bytes: +add_todo: + proto 1 1 + byte 0x000300 + frame_dig -1 + concat + int 0 + byte "todos" + app_global_get_ex + assert // check self.todos exists + int 0 + extract_uint16 + bnz add_todo_else_body@2 + byte 0x0002 + swap + concat + byte 0x0001 + swap + concat + byte "todos" + swap + app_global_put + b add_todo_after_if_else@3 + +add_todo_else_body@2: + int 0 + byte "todos" + app_global_get_ex + assert // check self.todos exists + byte 0x0002 + uncover 2 + concat + swap + dup + int 0 + extract_uint16 + swap + extract 2 0 + int 1 + uncover 3 + callsub dynamic_array_concat_dynamic_element + byte "todos" + swap + app_global_put + +add_todo_after_if_else@3: + int 0 + byte "todos" + app_global_get_ex + assert // check self.todos exists + retsub + + +// smart_contracts.arc4_types.contract.Arc4Struct.complete_todo(task: bytes) -> void: +complete_todo: + proto 1 0 + byte "" + dup + int 0 + byte "todos" + app_global_get_ex + assert // check self.todos exists + int 0 + extract_uint16 + int 0 + +complete_todo_for_header@1: + frame_dig 3 + frame_dig 2 + < + bz complete_todo_after_for@6 + int 0 + byte "todos" + app_global_get_ex + assert // check self.todos exists + dup + extract 2 0 + frame_dig 3 + dup + cover 3 + int 2 + * + dup + frame_bury 0 + dig 1 + swap + extract_uint16 + cover 3 + swap + int 0 + extract_uint16 + uncover 2 + int 1 + + + dup + cover 4 + dup + cover 2 + - // on error: Index access is out of bounds + swap + dig 2 + len + cover 2 + int 2 + * + dup + frame_bury 1 + dig 3 + swap + extract_uint16 + swap + select + swap + cover 2 + substring3 + dup + int 0 + extract_uint16 + swap + dup + len + swap + cover 2 + substring3 + frame_dig -1 + == + bz complete_todo_after_if_else@4 + int 0 + byte "todos" + app_global_get_ex + assert // check self.todos exists + dup + extract 2 0 + dup + frame_dig 0 + extract_uint16 + cover 2 + swap + int 0 + extract_uint16 + uncover 3 + - // on error: Index access is out of bounds + dig 1 + len + swap + dig 2 + frame_dig 1 + extract_uint16 + swap + select + swap + cover 2 + substring3 + int 16 + int 1 + setbit + int 0 + byte "todos" + app_global_get_ex + assert // check self.todos exists + swap + frame_dig 3 + callsub dynamic_array_replace_dynamic_element + byte "todos" + swap + app_global_put + b complete_todo_after_for@6 + +complete_todo_after_if_else@4: + frame_bury 3 + b complete_todo_for_header@1 + +complete_todo_after_for@6: + retsub + + +// smart_contracts.arc4_types.contract.Arc4Struct.return_todo(task: bytes) -> bytes: +return_todo: + proto 1 1 + int 0 + byte "" + dup + int 0 + dup + byte "todos" + app_global_get_ex + assert // check self.todos exists + int 0 + extract_uint16 + int 0 + +return_todo_for_header@1: + frame_dig 5 + frame_dig 4 + < + bz return_todo_after_for@6 + int 0 + byte "todos" + app_global_get_ex + assert // check self.todos exists + dup + extract 2 0 + frame_dig 5 + dup + cover 3 + int 2 + * + dup + frame_bury 1 + dig 1 + swap + extract_uint16 + cover 3 + swap + int 0 + extract_uint16 + uncover 2 + int 1 + + + dup + frame_bury 5 + dup + cover 2 + - // on error: Index access is out of bounds + swap + dig 2 + len + cover 2 + int 2 + * + dup + frame_bury 2 + dig 3 + swap + extract_uint16 + swap + select + swap + cover 2 + substring3 + dup + int 0 + extract_uint16 + swap + dup + len + swap + cover 2 + substring3 + frame_dig -1 + == + bz return_todo_for_header@1 + int 0 + byte "todos" + app_global_get_ex + assert // check self.todos exists + dup + extract 2 0 + dup + frame_dig 1 + extract_uint16 + cover 2 + swap + int 0 + extract_uint16 + frame_dig 5 + - // on error: Index access is out of bounds + dig 1 + len + swap + dig 2 + frame_dig 2 + extract_uint16 + swap + select + swap + cover 2 + substring3 + frame_bury 0 + int 1 + frame_bury 3 + b return_todo_for_header@1 + +return_todo_after_for@6: + frame_dig 3 + assert + retsub + + +// smart_contracts.arc4_types.contract.Arc4Struct.__init__() -> void: +__init__: + proto 0 0 + byte "todos" + byte 0x0000 + app_global_put + retsub + + +// _puya_lib.arc4.dynamic_array_concat_dynamic_element(array_items_count: uint64, array_head_and_tail: bytes, new_items_count: uint64, new_head_and_tail: bytes) -> bytes: +dynamic_array_concat_dynamic_element: + proto 4 1 + byte "" + byte 0x + frame_dig -2 + int 2 + * + frame_dig -4 + int 2 + * + int 0 + +dynamic_array_concat_dynamic_element_for_header@1: + frame_dig 4 + frame_dig 3 + < + bz dynamic_array_concat_dynamic_element_after_for@4 + frame_dig -3 + frame_dig 4 + dup + cover 2 + extract_uint16 + frame_dig 2 + + + itob + extract 6 2 + frame_dig 1 + swap + concat + frame_bury 1 + int 2 + + + frame_bury 4 + b dynamic_array_concat_dynamic_element_for_header@1 + +dynamic_array_concat_dynamic_element_after_for@4: + frame_dig -3 + len + frame_bury 0 + int 0 + frame_bury 4 + +dynamic_array_concat_dynamic_element_for_header@5: + frame_dig 4 + frame_dig 2 + < + bz dynamic_array_concat_dynamic_element_after_for@8 + frame_dig -1 + frame_dig 4 + dup + cover 2 + extract_uint16 + frame_dig 0 + + + itob + extract 6 2 + frame_dig 1 + swap + concat + frame_bury 1 + int 2 + + + frame_bury 4 + b dynamic_array_concat_dynamic_element_for_header@5 + +dynamic_array_concat_dynamic_element_after_for@8: + frame_dig -4 + frame_dig -2 + + + itob + extract 6 2 + frame_dig 1 + concat + frame_dig -3 + frame_dig 3 + frame_dig 0 + substring3 + concat + frame_dig -1 + len + frame_dig -1 + frame_dig 2 + uncover 2 + substring3 + concat + frame_bury 0 + retsub + + +// _puya_lib.arc4.dynamic_array_replace_dynamic_element(source: bytes, new_item: bytes, index: uint64) -> bytes: +dynamic_array_replace_dynamic_element: + proto 3 1 + frame_dig -3 + substring 0 2 + dup + btoi + frame_dig -3 + extract 2 0 + frame_dig -2 + frame_dig -1 + uncover 3 + callsub static_array_replace_dynamic_element + concat + retsub + + +// _puya_lib.arc4.static_array_replace_dynamic_element(array_head_and_tail: bytes, new_item: bytes, index: uint64, array_length: uint64) -> bytes: +static_array_replace_dynamic_element: + proto 4 1 + frame_dig -2 + int 2 + * + frame_dig -4 + swap + extract_uint16 + frame_dig -2 + int 1 + + + int 2 + * + dup + cover 2 + frame_dig -4 + swap + extract_uint16 + frame_dig -4 + len + frame_dig -1 + frame_dig -2 + - + int 1 + - + dig 1 + uncover 3 + uncover 2 + select + dup + dig 3 + - + cover 3 + frame_dig -3 + len + cover 3 + frame_dig -4 + int 0 + uncover 4 + substring3 + frame_dig -3 + concat + frame_dig -4 + uncover 2 + uncover 3 + substring3 + concat + frame_dig -1 + int 2 + * + +static_array_replace_dynamic_element_for_header@1: + frame_dig 0 + frame_dig 4 + < + bz static_array_replace_dynamic_element_after_for@4 + frame_dig 3 + dup + frame_dig 0 + dup + cover 3 + extract_uint16 + frame_dig 2 + + + frame_dig 1 + - + itob + extract 6 2 + dig 2 + swap + replace3 + frame_bury 3 + int 2 + + + frame_bury 0 + b static_array_replace_dynamic_element_for_header@1 + +static_array_replace_dynamic_element_after_for@4: + frame_dig 3 + frame_bury 0 + retsub diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.arc32.json b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.arc32.json new file mode 100644 index 0000000..e9a1bf4 --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.arc32.json @@ -0,0 +1,111 @@ +{ + "hints": { + "add_todo(string)(string,bool)[]": { + "call_config": { + "no_op": "CALL" + } + }, + "complete_todo(string)void": { + "call_config": { + "no_op": "CALL" + } + }, + "return_todo(string)(string,bool)": { + "call_config": { + "no_op": "CALL" + }, + "structs": { + "output": { + "name": "Todo", + "elements": [ + [ + "task", + "string" + ], + [ + "completed", + "bool" + ] + ] + } + } + } + }, + "source": { + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RydWN0LmFwcHJvdmFsX3Byb2dyYW06CiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYm56IG1haW5fZW50cnlwb2ludEAyCiAgICBjYWxsc3ViIF9faW5pdF9fCgptYWluX2VudHJ5cG9pbnRAMjoKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRTdHJ1Y3QuX19wdXlhX2FyYzRfcm91dGVyX18oKSAtPiB1aW50NjQ6Cl9fcHV5YV9hcmM0X3JvdXRlcl9fOgogICAgcHJvdG8gMCAxCiAgICB0eG4gTnVtQXBwQXJncwogICAgYnogX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDcKICAgIG1ldGhvZCAiYWRkX3RvZG8oc3RyaW5nKShzdHJpbmcsYm9vbClbXSIKICAgIG1ldGhvZCAiY29tcGxldGVfdG9kbyhzdHJpbmcpdm9pZCIKICAgIG1ldGhvZCAicmV0dXJuX3RvZG8oc3RyaW5nKShzdHJpbmcsYm9vbCkiCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAwCiAgICBtYXRjaCBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZGRfdG9kb19yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2NvbXBsZXRlX3RvZG9fcm91dGVAMyBfX3B1eWFfYXJjNF9yb3V0ZXJfX19yZXR1cm5fdG9kb19yb3V0ZUA0CiAgICBpbnQgMAogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZGRfdG9kb19yb3V0ZUAyOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgY2FsbHN1YiBhZGRfdG9kbwogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fY29tcGxldGVfdG9kb19yb3V0ZUAzOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgY2FsbHN1YiBjb21wbGV0ZV90b2RvCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19yZXR1cm5fdG9kb19yb3V0ZUA0OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgY2FsbHN1YiByZXR1cm5fdG9kbwogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDc6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBibnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMQogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgICEKICAgIGFzc2VydCAvLyBpcyBjcmVhdGluZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMToKICAgIGludCAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RydWN0LmFkZF90b2RvKHRhc2s6IGJ5dGVzKSAtPiBieXRlczoKYWRkX3RvZG86CiAgICBwcm90byAxIDEKICAgIGJ5dGUgMHgwMDAzMDAKICAgIGZyYW1lX2RpZyAtMQogICAgY29uY2F0CiAgICBpbnQgMAogICAgYnl0ZSAidG9kb3MiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIHNlbGYudG9kb3MgZXhpc3RzCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGJueiBhZGRfdG9kb19lbHNlX2JvZHlAMgogICAgYnl0ZSAweDAwMDIKICAgIHN3YXAKICAgIGNvbmNhdAogICAgYnl0ZSAweDAwMDEKICAgIHN3YXAKICAgIGNvbmNhdAogICAgYnl0ZSAidG9kb3MiCiAgICBzd2FwCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgYiBhZGRfdG9kb19hZnRlcl9pZl9lbHNlQDMKCmFkZF90b2RvX2Vsc2VfYm9keUAyOgogICAgaW50IDAKICAgIGJ5dGUgInRvZG9zIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBzZWxmLnRvZG9zIGV4aXN0cwogICAgYnl0ZSAweDAwMDIKICAgIHVuY292ZXIgMgogICAgY29uY2F0CiAgICBzd2FwCiAgICBkdXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgc3dhcAogICAgZXh0cmFjdCAyIDAKICAgIGludCAxCiAgICB1bmNvdmVyIDMKICAgIGNhbGxzdWIgZHluYW1pY19hcnJheV9jb25jYXRfZHluYW1pY19lbGVtZW50CiAgICBieXRlICJ0b2RvcyIKICAgIHN3YXAKICAgIGFwcF9nbG9iYWxfcHV0CgphZGRfdG9kb19hZnRlcl9pZl9lbHNlQDM6CiAgICBpbnQgMAogICAgYnl0ZSAidG9kb3MiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIHNlbGYudG9kb3MgZXhpc3RzCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RydWN0LmNvbXBsZXRlX3RvZG8odGFzazogYnl0ZXMpIC0+IHZvaWQ6CmNvbXBsZXRlX3RvZG86CiAgICBwcm90byAxIDAKICAgIGJ5dGUgIiIKICAgIGR1cAogICAgaW50IDAKICAgIGJ5dGUgInRvZG9zIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBzZWxmLnRvZG9zIGV4aXN0cwogICAgaW50IDAKICAgIGV4dHJhY3RfdWludDE2CiAgICBpbnQgMAoKY29tcGxldGVfdG9kb19mb3JfaGVhZGVyQDE6CiAgICBmcmFtZV9kaWcgMwogICAgZnJhbWVfZGlnIDIKICAgIDwKICAgIGJ6IGNvbXBsZXRlX3RvZG9fYWZ0ZXJfZm9yQDYKICAgIGludCAwCiAgICBieXRlICJ0b2RvcyIKICAgIGFwcF9nbG9iYWxfZ2V0X2V4CiAgICBhc3NlcnQgLy8gY2hlY2sgc2VsZi50b2RvcyBleGlzdHMKICAgIGR1cAogICAgZXh0cmFjdCAyIDAKICAgIGZyYW1lX2RpZyAzCiAgICBkdXAKICAgIGNvdmVyIDMKICAgIGludCAyCiAgICAqCiAgICBkdXAKICAgIGZyYW1lX2J1cnkgMAogICAgZGlnIDEKICAgIHN3YXAKICAgIGV4dHJhY3RfdWludDE2CiAgICBjb3ZlciAzCiAgICBzd2FwCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIHVuY292ZXIgMgogICAgaW50IDEKICAgICsKICAgIGR1cAogICAgY292ZXIgNAogICAgZHVwCiAgICBjb3ZlciAyCiAgICAtIC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgc3dhcAogICAgZGlnIDIKICAgIGxlbgogICAgY292ZXIgMgogICAgaW50IDIKICAgICoKICAgIGR1cAogICAgZnJhbWVfYnVyeSAxCiAgICBkaWcgMwogICAgc3dhcAogICAgZXh0cmFjdF91aW50MTYKICAgIHN3YXAKICAgIHNlbGVjdAogICAgc3dhcAogICAgY292ZXIgMgogICAgc3Vic3RyaW5nMwogICAgZHVwCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIHN3YXAKICAgIGR1cAogICAgbGVuCiAgICBzd2FwCiAgICBjb3ZlciAyCiAgICBzdWJzdHJpbmczCiAgICBmcmFtZV9kaWcgLTEKICAgID09CiAgICBieiBjb21wbGV0ZV90b2RvX2FmdGVyX2lmX2Vsc2VANAogICAgaW50IDAKICAgIGJ5dGUgInRvZG9zIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBzZWxmLnRvZG9zIGV4aXN0cwogICAgZHVwCiAgICBleHRyYWN0IDIgMAogICAgZHVwCiAgICBmcmFtZV9kaWcgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGNvdmVyIDIKICAgIHN3YXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgdW5jb3ZlciAzCiAgICAtIC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgZGlnIDEKICAgIGxlbgogICAgc3dhcAogICAgZGlnIDIKICAgIGZyYW1lX2RpZyAxCiAgICBleHRyYWN0X3VpbnQxNgogICAgc3dhcAogICAgc2VsZWN0CiAgICBzd2FwCiAgICBjb3ZlciAyCiAgICBzdWJzdHJpbmczCiAgICBpbnQgMTYKICAgIGludCAxCiAgICBzZXRiaXQKICAgIGludCAwCiAgICBieXRlICJ0b2RvcyIKICAgIGFwcF9nbG9iYWxfZ2V0X2V4CiAgICBhc3NlcnQgLy8gY2hlY2sgc2VsZi50b2RvcyBleGlzdHMKICAgIHN3YXAKICAgIGZyYW1lX2RpZyAzCiAgICBjYWxsc3ViIGR5bmFtaWNfYXJyYXlfcmVwbGFjZV9keW5hbWljX2VsZW1lbnQKICAgIGJ5dGUgInRvZG9zIgogICAgc3dhcAogICAgYXBwX2dsb2JhbF9wdXQKICAgIGIgY29tcGxldGVfdG9kb19hZnRlcl9mb3JANgoKY29tcGxldGVfdG9kb19hZnRlcl9pZl9lbHNlQDQ6CiAgICBmcmFtZV9idXJ5IDMKICAgIGIgY29tcGxldGVfdG9kb19mb3JfaGVhZGVyQDEKCmNvbXBsZXRlX3RvZG9fYWZ0ZXJfZm9yQDY6CiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RydWN0LnJldHVybl90b2RvKHRhc2s6IGJ5dGVzKSAtPiBieXRlczoKcmV0dXJuX3RvZG86CiAgICBwcm90byAxIDEKICAgIGludCAwCiAgICBieXRlICIiCiAgICBkdXAKICAgIGludCAwCiAgICBkdXAKICAgIGJ5dGUgInRvZG9zIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBzZWxmLnRvZG9zIGV4aXN0cwogICAgaW50IDAKICAgIGV4dHJhY3RfdWludDE2CiAgICBpbnQgMAoKcmV0dXJuX3RvZG9fZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDUKICAgIGZyYW1lX2RpZyA0CiAgICA8CiAgICBieiByZXR1cm5fdG9kb19hZnRlcl9mb3JANgogICAgaW50IDAKICAgIGJ5dGUgInRvZG9zIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBzZWxmLnRvZG9zIGV4aXN0cwogICAgZHVwCiAgICBleHRyYWN0IDIgMAogICAgZnJhbWVfZGlnIDUKICAgIGR1cAogICAgY292ZXIgMwogICAgaW50IDIKICAgICoKICAgIGR1cAogICAgZnJhbWVfYnVyeSAxCiAgICBkaWcgMQogICAgc3dhcAogICAgZXh0cmFjdF91aW50MTYKICAgIGNvdmVyIDMKICAgIHN3YXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgdW5jb3ZlciAyCiAgICBpbnQgMQogICAgKwogICAgZHVwCiAgICBmcmFtZV9idXJ5IDUKICAgIGR1cAogICAgY292ZXIgMgogICAgLSAvLyBvbiBlcnJvcjogSW5kZXggYWNjZXNzIGlzIG91dCBvZiBib3VuZHMKICAgIHN3YXAKICAgIGRpZyAyCiAgICBsZW4KICAgIGNvdmVyIDIKICAgIGludCAyCiAgICAqCiAgICBkdXAKICAgIGZyYW1lX2J1cnkgMgogICAgZGlnIDMKICAgIHN3YXAKICAgIGV4dHJhY3RfdWludDE2CiAgICBzd2FwCiAgICBzZWxlY3QKICAgIHN3YXAKICAgIGNvdmVyIDIKICAgIHN1YnN0cmluZzMKICAgIGR1cAogICAgaW50IDAKICAgIGV4dHJhY3RfdWludDE2CiAgICBzd2FwCiAgICBkdXAKICAgIGxlbgogICAgc3dhcAogICAgY292ZXIgMgogICAgc3Vic3RyaW5nMwogICAgZnJhbWVfZGlnIC0xCiAgICA9PQogICAgYnogcmV0dXJuX3RvZG9fZm9yX2hlYWRlckAxCiAgICBpbnQgMAogICAgYnl0ZSAidG9kb3MiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIHNlbGYudG9kb3MgZXhpc3RzCiAgICBkdXAKICAgIGV4dHJhY3QgMiAwCiAgICBkdXAKICAgIGZyYW1lX2RpZyAxCiAgICBleHRyYWN0X3VpbnQxNgogICAgY292ZXIgMgogICAgc3dhcAogICAgaW50IDAKICAgIGV4dHJhY3RfdWludDE2CiAgICBmcmFtZV9kaWcgNQogICAgLSAvLyBvbiBlcnJvcjogSW5kZXggYWNjZXNzIGlzIG91dCBvZiBib3VuZHMKICAgIGRpZyAxCiAgICBsZW4KICAgIHN3YXAKICAgIGRpZyAyCiAgICBmcmFtZV9kaWcgMgogICAgZXh0cmFjdF91aW50MTYKICAgIHN3YXAKICAgIHNlbGVjdAogICAgc3dhcAogICAgY292ZXIgMgogICAgc3Vic3RyaW5nMwogICAgZnJhbWVfYnVyeSAwCiAgICBpbnQgMQogICAgZnJhbWVfYnVyeSAzCiAgICBiIHJldHVybl90b2RvX2Zvcl9oZWFkZXJAMQoKcmV0dXJuX3RvZG9fYWZ0ZXJfZm9yQDY6CiAgICBmcmFtZV9kaWcgMwogICAgYXNzZXJ0CiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RydWN0Ll9faW5pdF9fKCkgLT4gdm9pZDoKX19pbml0X186CiAgICBwcm90byAwIDAKICAgIGJ5dGUgInRvZG9zIgogICAgYnl0ZSAweDAwMDAKICAgIGFwcF9nbG9iYWxfcHV0CiAgICByZXRzdWIKCgovLyBfcHV5YV9saWIuYXJjNC5keW5hbWljX2FycmF5X2NvbmNhdF9keW5hbWljX2VsZW1lbnQoYXJyYXlfaXRlbXNfY291bnQ6IHVpbnQ2NCwgYXJyYXlfaGVhZF9hbmRfdGFpbDogYnl0ZXMsIG5ld19pdGVtc19jb3VudDogdWludDY0LCBuZXdfaGVhZF9hbmRfdGFpbDogYnl0ZXMpIC0+IGJ5dGVzOgpkeW5hbWljX2FycmF5X2NvbmNhdF9keW5hbWljX2VsZW1lbnQ6CiAgICBwcm90byA0IDEKICAgIGJ5dGUgIiIKICAgIGJ5dGUgMHgKICAgIGZyYW1lX2RpZyAtMgogICAgaW50IDIKICAgICoKICAgIGZyYW1lX2RpZyAtNAogICAgaW50IDIKICAgICoKICAgIGludCAwCgpkeW5hbWljX2FycmF5X2NvbmNhdF9keW5hbWljX2VsZW1lbnRfZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDQKICAgIGZyYW1lX2RpZyAzCiAgICA8CiAgICBieiBkeW5hbWljX2FycmF5X2NvbmNhdF9keW5hbWljX2VsZW1lbnRfYWZ0ZXJfZm9yQDQKICAgIGZyYW1lX2RpZyAtMwogICAgZnJhbWVfZGlnIDQKICAgIGR1cAogICAgY292ZXIgMgogICAgZXh0cmFjdF91aW50MTYKICAgIGZyYW1lX2RpZyAyCiAgICArCiAgICBpdG9iCiAgICBleHRyYWN0IDYgMgogICAgZnJhbWVfZGlnIDEKICAgIHN3YXAKICAgIGNvbmNhdAogICAgZnJhbWVfYnVyeSAxCiAgICBpbnQgMgogICAgKwogICAgZnJhbWVfYnVyeSA0CiAgICBiIGR5bmFtaWNfYXJyYXlfY29uY2F0X2R5bmFtaWNfZWxlbWVudF9mb3JfaGVhZGVyQDEKCmR5bmFtaWNfYXJyYXlfY29uY2F0X2R5bmFtaWNfZWxlbWVudF9hZnRlcl9mb3JANDoKICAgIGZyYW1lX2RpZyAtMwogICAgbGVuCiAgICBmcmFtZV9idXJ5IDAKICAgIGludCAwCiAgICBmcmFtZV9idXJ5IDQKCmR5bmFtaWNfYXJyYXlfY29uY2F0X2R5bmFtaWNfZWxlbWVudF9mb3JfaGVhZGVyQDU6CiAgICBmcmFtZV9kaWcgNAogICAgZnJhbWVfZGlnIDIKICAgIDwKICAgIGJ6IGR5bmFtaWNfYXJyYXlfY29uY2F0X2R5bmFtaWNfZWxlbWVudF9hZnRlcl9mb3JAOAogICAgZnJhbWVfZGlnIC0xCiAgICBmcmFtZV9kaWcgNAogICAgZHVwCiAgICBjb3ZlciAyCiAgICBleHRyYWN0X3VpbnQxNgogICAgZnJhbWVfZGlnIDAKICAgICsKICAgIGl0b2IKICAgIGV4dHJhY3QgNiAyCiAgICBmcmFtZV9kaWcgMQogICAgc3dhcAogICAgY29uY2F0CiAgICBmcmFtZV9idXJ5IDEKICAgIGludCAyCiAgICArCiAgICBmcmFtZV9idXJ5IDQKICAgIGIgZHluYW1pY19hcnJheV9jb25jYXRfZHluYW1pY19lbGVtZW50X2Zvcl9oZWFkZXJANQoKZHluYW1pY19hcnJheV9jb25jYXRfZHluYW1pY19lbGVtZW50X2FmdGVyX2ZvckA4OgogICAgZnJhbWVfZGlnIC00CiAgICBmcmFtZV9kaWcgLTIKICAgICsKICAgIGl0b2IKICAgIGV4dHJhY3QgNiAyCiAgICBmcmFtZV9kaWcgMQogICAgY29uY2F0CiAgICBmcmFtZV9kaWcgLTMKICAgIGZyYW1lX2RpZyAzCiAgICBmcmFtZV9kaWcgMAogICAgc3Vic3RyaW5nMwogICAgY29uY2F0CiAgICBmcmFtZV9kaWcgLTEKICAgIGxlbgogICAgZnJhbWVfZGlnIC0xCiAgICBmcmFtZV9kaWcgMgogICAgdW5jb3ZlciAyCiAgICBzdWJzdHJpbmczCiAgICBjb25jYXQKICAgIGZyYW1lX2J1cnkgMAogICAgcmV0c3ViCgoKLy8gX3B1eWFfbGliLmFyYzQuZHluYW1pY19hcnJheV9yZXBsYWNlX2R5bmFtaWNfZWxlbWVudChzb3VyY2U6IGJ5dGVzLCBuZXdfaXRlbTogYnl0ZXMsIGluZGV4OiB1aW50NjQpIC0+IGJ5dGVzOgpkeW5hbWljX2FycmF5X3JlcGxhY2VfZHluYW1pY19lbGVtZW50OgogICAgcHJvdG8gMyAxCiAgICBmcmFtZV9kaWcgLTMKICAgIHN1YnN0cmluZyAwIDIKICAgIGR1cAogICAgYnRvaQogICAgZnJhbWVfZGlnIC0zCiAgICBleHRyYWN0IDIgMAogICAgZnJhbWVfZGlnIC0yCiAgICBmcmFtZV9kaWcgLTEKICAgIHVuY292ZXIgMwogICAgY2FsbHN1YiBzdGF0aWNfYXJyYXlfcmVwbGFjZV9keW5hbWljX2VsZW1lbnQKICAgIGNvbmNhdAogICAgcmV0c3ViCgoKLy8gX3B1eWFfbGliLmFyYzQuc3RhdGljX2FycmF5X3JlcGxhY2VfZHluYW1pY19lbGVtZW50KGFycmF5X2hlYWRfYW5kX3RhaWw6IGJ5dGVzLCBuZXdfaXRlbTogYnl0ZXMsIGluZGV4OiB1aW50NjQsIGFycmF5X2xlbmd0aDogdWludDY0KSAtPiBieXRlczoKc3RhdGljX2FycmF5X3JlcGxhY2VfZHluYW1pY19lbGVtZW50OgogICAgcHJvdG8gNCAxCiAgICBmcmFtZV9kaWcgLTIKICAgIGludCAyCiAgICAqCiAgICBmcmFtZV9kaWcgLTQKICAgIHN3YXAKICAgIGV4dHJhY3RfdWludDE2CiAgICBmcmFtZV9kaWcgLTIKICAgIGludCAxCiAgICArCiAgICBpbnQgMgogICAgKgogICAgZHVwCiAgICBjb3ZlciAyCiAgICBmcmFtZV9kaWcgLTQKICAgIHN3YXAKICAgIGV4dHJhY3RfdWludDE2CiAgICBmcmFtZV9kaWcgLTQKICAgIGxlbgogICAgZnJhbWVfZGlnIC0xCiAgICBmcmFtZV9kaWcgLTIKICAgIC0KICAgIGludCAxCiAgICAtCiAgICBkaWcgMQogICAgdW5jb3ZlciAzCiAgICB1bmNvdmVyIDIKICAgIHNlbGVjdAogICAgZHVwCiAgICBkaWcgMwogICAgLQogICAgY292ZXIgMwogICAgZnJhbWVfZGlnIC0zCiAgICBsZW4KICAgIGNvdmVyIDMKICAgIGZyYW1lX2RpZyAtNAogICAgaW50IDAKICAgIHVuY292ZXIgNAogICAgc3Vic3RyaW5nMwogICAgZnJhbWVfZGlnIC0zCiAgICBjb25jYXQKICAgIGZyYW1lX2RpZyAtNAogICAgdW5jb3ZlciAyCiAgICB1bmNvdmVyIDMKICAgIHN1YnN0cmluZzMKICAgIGNvbmNhdAogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMgogICAgKgoKc3RhdGljX2FycmF5X3JlcGxhY2VfZHluYW1pY19lbGVtZW50X2Zvcl9oZWFkZXJAMToKICAgIGZyYW1lX2RpZyAwCiAgICBmcmFtZV9kaWcgNAogICAgPAogICAgYnogc3RhdGljX2FycmF5X3JlcGxhY2VfZHluYW1pY19lbGVtZW50X2FmdGVyX2ZvckA0CiAgICBmcmFtZV9kaWcgMwogICAgZHVwCiAgICBmcmFtZV9kaWcgMAogICAgZHVwCiAgICBjb3ZlciAzCiAgICBleHRyYWN0X3VpbnQxNgogICAgZnJhbWVfZGlnIDIKICAgICsKICAgIGZyYW1lX2RpZyAxCiAgICAtCiAgICBpdG9iCiAgICBleHRyYWN0IDYgMgogICAgZGlnIDIKICAgIHN3YXAKICAgIHJlcGxhY2UzCiAgICBmcmFtZV9idXJ5IDMKICAgIGludCAyCiAgICArCiAgICBmcmFtZV9idXJ5IDAKICAgIGIgc3RhdGljX2FycmF5X3JlcGxhY2VfZHluYW1pY19lbGVtZW50X2Zvcl9oZWFkZXJAMQoKc3RhdGljX2FycmF5X3JlcGxhY2VfZHluYW1pY19lbGVtZW50X2FmdGVyX2ZvckA0OgogICAgZnJhbWVfZGlnIDMKICAgIGZyYW1lX2J1cnkgMAogICAgcmV0c3ViCg==", + "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RydWN0LmNsZWFyX3N0YXRlX3Byb2dyYW06CiAgICBpbnQgMQogICAgcmV0dXJuCg==" + }, + "state": { + "global": { + "num_byte_slices": 1, + "num_uints": 0 + }, + "local": { + "num_byte_slices": 0, + "num_uints": 0 + } + }, + "schema": { + "global": { + "declared": { + "todos": { + "type": "bytes", + "key": "todos" + } + }, + "reserved": {} + }, + "local": { + "declared": {}, + "reserved": {} + } + }, + "contract": { + "name": "Arc4Struct", + "methods": [ + { + "name": "add_todo", + "args": [ + { + "type": "string", + "name": "task" + } + ], + "readonly": false, + "returns": { + "type": "(string,bool)[]" + } + }, + { + "name": "complete_todo", + "args": [ + { + "type": "string", + "name": "task" + } + ], + "readonly": false, + "returns": { + "type": "void" + } + }, + { + "name": "return_todo", + "args": [ + { + "type": "string", + "name": "task" + } + ], + "readonly": false, + "returns": { + "type": "(string,bool)" + } + } + ], + "networks": {} + }, + "bare_call_config": { + "no_op": "CREATE" + } +} \ No newline at end of file diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.clear.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.clear.teal new file mode 100644 index 0000000..095349f --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.clear.teal @@ -0,0 +1,5 @@ +#pragma version 10 + +smart_contracts.arc4_types.contract.Arc4Struct.clear_state_program: + int 1 + return diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.approval.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.approval.teal index 8c52292..3190f48 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.approval.teal +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.approval.teal @@ -9,28 +9,38 @@ smart_contracts.arc4_types.contract.Arc4Types.approval_program: __puya_arc4_router__: proto 0 1 txn NumAppArgs - bz __puya_arc4_router___bare_routing@5 - method "hello(string)string" + bz __puya_arc4_router___bare_routing@6 + method "arc4_uint64(uint64,uint64)uint64" + method "arc4_address(address)address" txna ApplicationArgs 0 - match __puya_arc4_router___hello_route@2 + match __puya_arc4_router___arc4_uint64_route@2 __puya_arc4_router___arc4_address_route@3 int 0 retsub -__puya_arc4_router___hello_route@2: +__puya_arc4_router___arc4_uint64_route@2: txn OnCompletion ! assert // OnCompletion is NoOp txn ApplicationID assert // is not creating txna ApplicationArgs 1 - extract 2 0 - callsub hello - dup - len - itob - extract 6 2 + txna ApplicationArgs 2 + callsub arc4_uint64 + byte 0x151f7c75 swap concat + log + int 1 + retsub + +__puya_arc4_router___arc4_address_route@3: + txn OnCompletion + ! + assert // OnCompletion is NoOp + txn ApplicationID + assert // is not creating + txna ApplicationArgs 1 + callsub arc4_address byte 0x151f7c75 swap concat @@ -38,24 +48,42 @@ __puya_arc4_router___hello_route@2: int 1 retsub -__puya_arc4_router___bare_routing@5: +__puya_arc4_router___bare_routing@6: txn OnCompletion - bnz __puya_arc4_router___after_if_else@9 + bnz __puya_arc4_router___after_if_else@10 txn ApplicationID ! assert // is creating int 1 retsub -__puya_arc4_router___after_if_else@9: +__puya_arc4_router___after_if_else@10: int 0 retsub -// smart_contracts.arc4_types.contract.Arc4Types.hello(name: bytes) -> bytes: -hello: +// smart_contracts.arc4_types.contract.Arc4Types.arc4_uint64(a: bytes, b: bytes) -> bytes: +arc4_uint64: + proto 2 1 + frame_dig -2 + btoi + frame_dig -1 + btoi + + + itob + retsub + + +// smart_contracts.arc4_types.contract.Arc4Types.arc4_address(address: bytes) -> bytes: +arc4_address: proto 1 1 - byte "Hello, " frame_dig -1 - concat + acct_params_get AcctBalance + bury 1 + assert // account funded + frame_dig -1 + acct_params_get AcctTotalAssets + bury 1 + assert // account funded + frame_dig -1 retsub diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.arc32.json b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.arc32.json index 62d9090..f87d165 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.arc32.json +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.arc32.json @@ -1,13 +1,18 @@ { "hints": { - "hello(string)string": { + "arc4_uint64(uint64,uint64)uint64": { + "call_config": { + "no_op": "CALL" + } + }, + "arc4_address(address)address": { "call_config": { "no_op": "CALL" } } }, "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANQogICAgbWV0aG9kICJoZWxsbyhzdHJpbmcpc3RyaW5nIgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAogICAgbWF0Y2ggX19wdXlhX2FyYzRfcm91dGVyX19faGVsbG9fcm91dGVAMgogICAgaW50IDAKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19faGVsbG9fcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGV4dHJhY3QgMiAwCiAgICBjYWxsc3ViIGhlbGxvCiAgICBkdXAKICAgIGxlbgogICAgaXRvYgogICAgZXh0cmFjdCA2IDIKICAgIHN3YXAKICAgIGNvbmNhdAogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDU6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBibnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUA5CiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgIQogICAgYXNzZXJ0IC8vIGlzIGNyZWF0aW5nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDk6CiAgICBpbnQgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmhlbGxvKG5hbWU6IGJ5dGVzKSAtPiBieXRlczoKaGVsbG86CiAgICBwcm90byAxIDEKICAgIGJ5dGUgIkhlbGxvLCAiCiAgICBmcmFtZV9kaWcgLTEKICAgIGNvbmNhdAogICAgcmV0c3ViCg==", + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANgogICAgbWV0aG9kICJhcmM0X3VpbnQ2NCh1aW50NjQsdWludDY0KXVpbnQ2NCIKICAgIG1ldGhvZCAiYXJjNF9hZGRyZXNzKGFkZHJlc3MpYWRkcmVzcyIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdWludDY0X3JvdXRlQDIgX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9hZGRyZXNzX3JvdXRlQDMKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdWludDY0X3JvdXRlQDI6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAyCiAgICBjYWxsc3ViIGFyYzRfdWludDY0CiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2FkZHJlc3Nfcm91dGVAMzoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF9hZGRyZXNzCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgIGJueiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDEwCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgIQogICAgYXNzZXJ0IC8vIGlzIGNyZWF0aW5nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDEwOgogICAgaW50IDAKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X3VpbnQ2NChhOiBieXRlcywgYjogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X3VpbnQ2NDoKICAgIHByb3RvIDIgMQogICAgZnJhbWVfZGlnIC0yCiAgICBidG9pCiAgICBmcmFtZV9kaWcgLTEKICAgIGJ0b2kKICAgICsKICAgIGl0b2IKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X2FkZHJlc3MoYWRkcmVzczogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X2FkZHJlc3M6CiAgICBwcm90byAxIDEKICAgIGZyYW1lX2RpZyAtMQogICAgYWNjdF9wYXJhbXNfZ2V0IEFjY3RCYWxhbmNlCiAgICBidXJ5IDEKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgZnJhbWVfZGlnIC0xCiAgICBhY2N0X3BhcmFtc19nZXQgQWNjdFRvdGFsQXNzZXRzCiAgICBidXJ5IDEKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgZnJhbWVfZGlnIC0xCiAgICByZXRzdWIK", "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" }, "state": { @@ -34,16 +39,34 @@ "name": "Arc4Types", "methods": [ { - "name": "hello", + "name": "arc4_uint64", + "args": [ + { + "type": "uint64", + "name": "a" + }, + { + "type": "uint64", + "name": "b" + } + ], + "readonly": false, + "returns": { + "type": "uint64" + }, + "desc": "This won't compile because you can't do math operations on arc4.UInt64 type.\nAll arc4 types are backed by byte arrays on the AVM. c = a + b" + }, + { + "name": "arc4_address", "args": [ { - "type": "string", - "name": "name" + "type": "address", + "name": "address" } ], "readonly": false, "returns": { - "type": "string" + "type": "address" } } ], diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_static_array_client.py b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_static_array_client.py new file mode 100644 index 0000000..69fa2b4 --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_static_array_client.py @@ -0,0 +1,484 @@ +# flake8: noqa +# fmt: off +# mypy: disable-error-code="no-any-return, no-untyped-call, misc, type-arg" +# This file was automatically generated by algokit-client-generator. +# DO NOT MODIFY IT BY HAND. +# requires: algokit-utils@^1.2.0 +import base64 +import dataclasses +import decimal +import typing +from abc import ABC, abstractmethod + +import algokit_utils +import algosdk +from algosdk.v2client import models +from algosdk.atomic_transaction_composer import ( + AtomicTransactionComposer, + AtomicTransactionResponse, + SimulateAtomicTransactionResponse, + TransactionSigner, + TransactionWithSigner +) + +_APP_SPEC_JSON = r"""{ + "hints": { + "arc4_static_array()void": { + "call_config": { + "no_op": "CALL" + } + } + }, + "source": { + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RhdGljQXJyYXkuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRTdGF0aWNBcnJheS5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANQogICAgbWV0aG9kICJhcmM0X3N0YXRpY19hcnJheSgpdm9pZCIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfc3RhdGljX2FycmF5X3JvdXRlQDIKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfc3RhdGljX2FycmF5X3JvdXRlQDI6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICBjYWxsc3ViIGFyYzRfc3RhdGljX2FycmF5CiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANToKICAgIHR4biBPbkNvbXBsZXRpb24KICAgIGJueiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDkKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICAhCiAgICBhc3NlcnQgLy8gaXMgY3JlYXRpbmcKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAOToKICAgIGludCAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RhdGljQXJyYXkuYXJjNF9zdGF0aWNfYXJyYXkoKSAtPiB2b2lkOgphcmM0X3N0YXRpY19hcnJheToKICAgIHByb3RvIDAgMAogICAgaW50IDAKICAgIGR1cAoKYXJjNF9zdGF0aWNfYXJyYXlfZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDEKICAgIGludCA0CiAgICA8CiAgICBieiBhcmM0X3N0YXRpY19hcnJheV9hZnRlcl9mb3JANAogICAgZnJhbWVfZGlnIDEKICAgIGR1cAogICAgaW50IDQKICAgICoKICAgIGJ5dGUgMHgwMDAwMDAwMTAwMDAwMDBhMDAwMDAwZmYwMDAwMDA4MAogICAgc3dhcAogICAgaW50IDQKICAgIGV4dHJhY3QzIC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgYnRvaQogICAgZnJhbWVfZGlnIDAKICAgICsKICAgIGZyYW1lX2J1cnkgMAogICAgaW50IDEKICAgICsKICAgIGZyYW1lX2J1cnkgMQogICAgYiBhcmM0X3N0YXRpY19hcnJheV9mb3JfaGVhZGVyQDEKCmFyYzRfc3RhdGljX2FycmF5X2FmdGVyX2ZvckA0OgogICAgZnJhbWVfZGlnIDAKICAgIGludCAzOTQKICAgID09CiAgICBhc3NlcnQKICAgIHJldHN1Ygo=", + "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RhdGljQXJyYXkuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" + }, + "state": { + "global": { + "num_byte_slices": 0, + "num_uints": 0 + }, + "local": { + "num_byte_slices": 0, + "num_uints": 0 + } + }, + "schema": { + "global": { + "declared": {}, + "reserved": {} + }, + "local": { + "declared": {}, + "reserved": {} + } + }, + "contract": { + "name": "Arc4StaticArray", + "methods": [ + { + "name": "arc4_static_array", + "args": [], + "returns": { + "type": "void" + }, + "desc": "You can create a static array directly from the contract." + } + ], + "networks": {} + }, + "bare_call_config": { + "no_op": "CREATE" + } +}""" +APP_SPEC = algokit_utils.ApplicationSpecification.from_json(_APP_SPEC_JSON) +_TReturn = typing.TypeVar("_TReturn") + + +class _ArgsBase(ABC, typing.Generic[_TReturn]): + @staticmethod + @abstractmethod + def method() -> str: + ... + + +_TArgs = typing.TypeVar("_TArgs", bound=_ArgsBase[typing.Any]) + + +@dataclasses.dataclass(kw_only=True) +class _TArgsHolder(typing.Generic[_TArgs]): + args: _TArgs + + +def _filter_none(value: dict | typing.Any) -> dict | typing.Any: + if isinstance(value, dict): + return {k: _filter_none(v) for k, v in value.items() if v is not None} + return value + + +def _as_dict(data: typing.Any, *, convert_all: bool = True) -> dict[str, typing.Any]: + if data is None: + return {} + if not dataclasses.is_dataclass(data): + raise TypeError(f"{data} must be a dataclass") + if convert_all: + result = dataclasses.asdict(data) # type: ignore[call-overload] + else: + result = {f.name: getattr(data, f.name) for f in dataclasses.fields(data)} + return _filter_none(result) + + +def _convert_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, +) -> algokit_utils.TransactionParametersDict: + return typing.cast(algokit_utils.TransactionParametersDict, _as_dict(transaction_parameters)) + + +def _convert_call_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, +) -> algokit_utils.OnCompleteCallParametersDict: + return typing.cast(algokit_utils.OnCompleteCallParametersDict, _as_dict(transaction_parameters)) + + +def _convert_create_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, + on_complete: algokit_utils.OnCompleteActionName, +) -> algokit_utils.CreateCallParametersDict: + result = typing.cast(algokit_utils.CreateCallParametersDict, _as_dict(transaction_parameters)) + on_complete_enum = on_complete.replace("_", " ").title().replace(" ", "") + "OC" + result["on_complete"] = getattr(algosdk.transaction.OnComplete, on_complete_enum) + return result + + +def _convert_deploy_args( + deploy_args: algokit_utils.DeployCallArgs | None, +) -> algokit_utils.ABICreateCallArgsDict | None: + if deploy_args is None: + return None + + deploy_args_dict = typing.cast(algokit_utils.ABICreateCallArgsDict, _as_dict(deploy_args)) + if isinstance(deploy_args, _TArgsHolder): + deploy_args_dict["args"] = _as_dict(deploy_args.args) + deploy_args_dict["method"] = deploy_args.args.method() + + return deploy_args_dict + + +@dataclasses.dataclass(kw_only=True) +class Arc4StaticArrayArgs(_ArgsBase[None]): + """You can create a static array directly from the contract.""" + + @staticmethod + def method() -> str: + return "arc4_static_array()void" + + +@dataclasses.dataclass(kw_only=True) +class SimulateOptions: + allow_more_logs: bool = dataclasses.field(default=False) + allow_empty_signatures: bool = dataclasses.field(default=False) + extra_opcode_budget: int = dataclasses.field(default=0) + exec_trace_config: models.SimulateTraceConfig | None = dataclasses.field(default=None) + + +class Composer: + + def __init__(self, app_client: algokit_utils.ApplicationClient, atc: AtomicTransactionComposer): + self.app_client = app_client + self.atc = atc + + def build(self) -> AtomicTransactionComposer: + return self.atc + + def simulate(self, options: SimulateOptions | None = None) -> SimulateAtomicTransactionResponse: + request = models.SimulateRequest( + allow_more_logs=options.allow_more_logs, + allow_empty_signatures=options.allow_empty_signatures, + extra_opcode_budget=options.extra_opcode_budget, + exec_trace_config=options.exec_trace_config, + txn_groups=[] + ) if options else None + result = self.atc.simulate(self.app_client.algod_client, request) + return result + + def execute(self) -> AtomicTransactionResponse: + return self.app_client.execute_atc(self.atc) + + def arc4_static_array( + self, + *, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> "Composer": + """You can create a static array directly from the contract. + + Adds a call to `arc4_static_array()void` ABI method + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + args = Arc4StaticArrayArgs() + self.app_client.compose_call( + self.atc, + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return self + + def create_bare( + self, + *, + on_complete: typing.Literal["no_op"] = "no_op", + transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, + ) -> "Composer": + """Adds a call to create an application using the no_op bare method + + :param typing.Literal[no_op] on_complete: On completion type to use + :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + self.app_client.compose_create( + self.atc, + call_abi_method=False, + transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), + ) + return self + + def clear_state( + self, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + app_args: list[bytes] | None = None, + ) -> "Composer": + """Adds a call to the application with on completion set to ClearState + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :param list[bytes] | None app_args: (optional) Application args to pass""" + + self.app_client.compose_clear_state(self.atc, _convert_transaction_parameters(transaction_parameters), app_args) + return self + + +class Arc4StaticArrayClient: + """A class for interacting with the Arc4StaticArray app providing high productivity and + strongly typed methods to deploy and call the app""" + + @typing.overload + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + app_id: int = 0, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + ... + + @typing.overload + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + creator: str | algokit_utils.Account, + indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, + existing_deployments: algokit_utils.AppLookup | None = None, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + ... + + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + creator: str | algokit_utils.Account | None = None, + indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, + existing_deployments: algokit_utils.AppLookup | None = None, + app_id: int = 0, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + """ + Arc4StaticArrayClient can be created with an app_id to interact with an existing application, alternatively + it can be created with a creator and indexer_client specified to find existing applications by name and creator. + + :param AlgodClient algod_client: AlgoSDK algod client + :param int app_id: The app_id of an existing application, to instead find the application by creator and name + use the creator and indexer_client parameters + :param str | Account creator: The address or Account of the app creator to resolve the app_id + :param IndexerClient indexer_client: AlgoSDK indexer client, only required if deploying or finding app_id by + creator and app name + :param AppLookup existing_deployments: + :param TransactionSigner | Account signer: Account or signer to use to sign transactions, if not specified and + creator was passed as an Account will use that. + :param str sender: Address to use as the sender for all transactions, will use the address associated with the + signer if not specified. + :param TemplateValueMapping template_values: Values to use for TMPL_* template variables, dictionary keys should + *NOT* include the TMPL_ prefix + :param str | None app_name: Name of application to use when deploying, defaults to name defined on the + Application Specification + """ + + self.app_spec = APP_SPEC + + # calling full __init__ signature, so ignoring mypy warning about overloads + self.app_client = algokit_utils.ApplicationClient( # type: ignore[call-overload, misc] + algod_client=algod_client, + app_spec=self.app_spec, + app_id=app_id, + creator=creator, + indexer_client=indexer_client, + existing_deployments=existing_deployments, + signer=signer, + sender=sender, + suggested_params=suggested_params, + template_values=template_values, + app_name=app_name, + ) + + @property + def algod_client(self) -> algosdk.v2client.algod.AlgodClient: + return self.app_client.algod_client + + @property + def app_id(self) -> int: + return self.app_client.app_id + + @app_id.setter + def app_id(self, value: int) -> None: + self.app_client.app_id = value + + @property + def app_address(self) -> str: + return self.app_client.app_address + + @property + def sender(self) -> str | None: + return self.app_client.sender + + @sender.setter + def sender(self, value: str) -> None: + self.app_client.sender = value + + @property + def signer(self) -> TransactionSigner | None: + return self.app_client.signer + + @signer.setter + def signer(self, value: TransactionSigner) -> None: + self.app_client.signer = value + + @property + def suggested_params(self) -> algosdk.transaction.SuggestedParams | None: + return self.app_client.suggested_params + + @suggested_params.setter + def suggested_params(self, value: algosdk.transaction.SuggestedParams | None) -> None: + self.app_client.suggested_params = value + + def arc4_static_array( + self, + *, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> algokit_utils.ABITransactionResponse[None]: + """You can create a static array directly from the contract. + + Calls `arc4_static_array()void` ABI method + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.ABITransactionResponse[None]: The result of the transaction""" + + args = Arc4StaticArrayArgs() + result = self.app_client.call( + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return result + + def create_bare( + self, + *, + on_complete: typing.Literal["no_op"] = "no_op", + transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, + ) -> algokit_utils.TransactionResponse: + """Creates an application using the no_op bare method + + :param typing.Literal[no_op] on_complete: On completion type to use + :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.TransactionResponse: The result of the transaction""" + + result = self.app_client.create( + call_abi_method=False, + transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), + ) + return result + + def clear_state( + self, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + app_args: list[bytes] | None = None, + ) -> algokit_utils.TransactionResponse: + """Calls the application with on completion set to ClearState + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :param list[bytes] | None app_args: (optional) Application args to pass + :returns algokit_utils.TransactionResponse: The result of the transaction""" + + return self.app_client.clear_state(_convert_transaction_parameters(transaction_parameters), app_args) + + def deploy( + self, + version: str | None = None, + *, + signer: TransactionSigner | None = None, + sender: str | None = None, + allow_update: bool | None = None, + allow_delete: bool | None = None, + on_update: algokit_utils.OnUpdate = algokit_utils.OnUpdate.Fail, + on_schema_break: algokit_utils.OnSchemaBreak = algokit_utils.OnSchemaBreak.Fail, + template_values: algokit_utils.TemplateValueMapping | None = None, + create_args: algokit_utils.DeployCallArgs | None = None, + update_args: algokit_utils.DeployCallArgs | None = None, + delete_args: algokit_utils.DeployCallArgs | None = None, + ) -> algokit_utils.DeployResponse: + """Deploy an application and update client to reference it. + + Idempotently deploy (create, update/delete if changed) an app against the given name via the given creator + account, including deploy-time template placeholder substitutions. + To understand the architecture decisions behind this functionality please see + + + ```{note} + If there is a breaking state schema change to an existing app (and `on_schema_break` is set to + 'ReplaceApp' the existing app will be deleted and re-created. + ``` + + ```{note} + If there is an update (different TEAL code) to an existing app (and `on_update` is set to 'ReplaceApp') + the existing app will be deleted and re-created. + ``` + + :param str version: version to use when creating or updating app, if None version will be auto incremented + :param algosdk.atomic_transaction_composer.TransactionSigner signer: signer to use when deploying app + , if None uses self.signer + :param str sender: sender address to use when deploying app, if None uses self.sender + :param bool allow_delete: Used to set the `TMPL_DELETABLE` template variable to conditionally control if an app + can be deleted + :param bool allow_update: Used to set the `TMPL_UPDATABLE` template variable to conditionally control if an app + can be updated + :param OnUpdate on_update: Determines what action to take if an application update is required + :param OnSchemaBreak on_schema_break: Determines what action to take if an application schema requirements + has increased beyond the current allocation + :param dict[str, int|str|bytes] template_values: Values to use for `TMPL_*` template variables, dictionary keys + should *NOT* include the TMPL_ prefix + :param algokit_utils.DeployCallArgs | None create_args: Arguments used when creating an application + :param algokit_utils.DeployCallArgs | None update_args: Arguments used when updating an application + :param algokit_utils.DeployCallArgs | None delete_args: Arguments used when deleting an application + :return DeployResponse: details action taken and relevant transactions + :raises DeploymentError: If the deployment failed""" + + return self.app_client.deploy( + version, + signer=signer, + sender=sender, + allow_update=allow_update, + allow_delete=allow_delete, + on_update=on_update, + on_schema_break=on_schema_break, + template_values=template_values, + create_args=_convert_deploy_args(create_args), + update_args=_convert_deploy_args(update_args), + delete_args=_convert_deploy_args(delete_args), + ) + + def compose(self, atc: AtomicTransactionComposer | None = None) -> Composer: + return Composer(self.app_client, atc or AtomicTransactionComposer()) diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_struct_client.py b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_struct_client.py new file mode 100644 index 0000000..36e879a --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_struct_client.py @@ -0,0 +1,695 @@ +# flake8: noqa +# fmt: off +# mypy: disable-error-code="no-any-return, no-untyped-call, misc, type-arg" +# This file was automatically generated by algokit-client-generator. +# DO NOT MODIFY IT BY HAND. +# requires: algokit-utils@^1.2.0 +import base64 +import dataclasses +import decimal +import typing +from abc import ABC, abstractmethod + +import algokit_utils +import algosdk +from algosdk.v2client import models +from algosdk.atomic_transaction_composer import ( + AtomicTransactionComposer, + AtomicTransactionResponse, + SimulateAtomicTransactionResponse, + TransactionSigner, + TransactionWithSigner +) + +_APP_SPEC_JSON = r"""{ + "hints": { + "add_todo(string)(string,bool)[]": { + "call_config": { + "no_op": "CALL" + } + }, + "complete_todo(string)void": { + "call_config": { + "no_op": "CALL" + } + }, + "return_todo(string)(string,bool)": { + "structs": { + "output": { + "name": "Todo", + "elements": [ + [ + "task", + "string" + ], + [ + "completed", + "bool" + ] + ] + } + }, + "call_config": { + "no_op": "CALL" + } + } + }, + "source": { + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RydWN0LmFwcHJvdmFsX3Byb2dyYW06CiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYm56IG1haW5fZW50cnlwb2ludEAyCiAgICBjYWxsc3ViIF9faW5pdF9fCgptYWluX2VudHJ5cG9pbnRAMjoKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRTdHJ1Y3QuX19wdXlhX2FyYzRfcm91dGVyX18oKSAtPiB1aW50NjQ6Cl9fcHV5YV9hcmM0X3JvdXRlcl9fOgogICAgcHJvdG8gMCAxCiAgICB0eG4gTnVtQXBwQXJncwogICAgYnogX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDcKICAgIG1ldGhvZCAiYWRkX3RvZG8oc3RyaW5nKShzdHJpbmcsYm9vbClbXSIKICAgIG1ldGhvZCAiY29tcGxldGVfdG9kbyhzdHJpbmcpdm9pZCIKICAgIG1ldGhvZCAicmV0dXJuX3RvZG8oc3RyaW5nKShzdHJpbmcsYm9vbCkiCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAwCiAgICBtYXRjaCBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZGRfdG9kb19yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2NvbXBsZXRlX3RvZG9fcm91dGVAMyBfX3B1eWFfYXJjNF9yb3V0ZXJfX19yZXR1cm5fdG9kb19yb3V0ZUA0CiAgICBpbnQgMAogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZGRfdG9kb19yb3V0ZUAyOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgY2FsbHN1YiBhZGRfdG9kbwogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fY29tcGxldGVfdG9kb19yb3V0ZUAzOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgY2FsbHN1YiBjb21wbGV0ZV90b2RvCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19yZXR1cm5fdG9kb19yb3V0ZUA0OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgY2FsbHN1YiByZXR1cm5fdG9kbwogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDc6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBibnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMQogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgICEKICAgIGFzc2VydCAvLyBpcyBjcmVhdGluZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMToKICAgIGludCAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RydWN0LmFkZF90b2RvKHRhc2s6IGJ5dGVzKSAtPiBieXRlczoKYWRkX3RvZG86CiAgICBwcm90byAxIDEKICAgIGJ5dGUgMHgwMDAzMDAKICAgIGZyYW1lX2RpZyAtMQogICAgY29uY2F0CiAgICBpbnQgMAogICAgYnl0ZSAidG9kb3MiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIHNlbGYudG9kb3MgZXhpc3RzCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGJueiBhZGRfdG9kb19lbHNlX2JvZHlAMgogICAgYnl0ZSAweDAwMDIKICAgIHN3YXAKICAgIGNvbmNhdAogICAgYnl0ZSAweDAwMDEKICAgIHN3YXAKICAgIGNvbmNhdAogICAgYnl0ZSAidG9kb3MiCiAgICBzd2FwCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgYiBhZGRfdG9kb19hZnRlcl9pZl9lbHNlQDMKCmFkZF90b2RvX2Vsc2VfYm9keUAyOgogICAgaW50IDAKICAgIGJ5dGUgInRvZG9zIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBzZWxmLnRvZG9zIGV4aXN0cwogICAgYnl0ZSAweDAwMDIKICAgIHVuY292ZXIgMgogICAgY29uY2F0CiAgICBzd2FwCiAgICBkdXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgc3dhcAogICAgZXh0cmFjdCAyIDAKICAgIGludCAxCiAgICB1bmNvdmVyIDMKICAgIGNhbGxzdWIgZHluYW1pY19hcnJheV9jb25jYXRfZHluYW1pY19lbGVtZW50CiAgICBieXRlICJ0b2RvcyIKICAgIHN3YXAKICAgIGFwcF9nbG9iYWxfcHV0CgphZGRfdG9kb19hZnRlcl9pZl9lbHNlQDM6CiAgICBpbnQgMAogICAgYnl0ZSAidG9kb3MiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIHNlbGYudG9kb3MgZXhpc3RzCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RydWN0LmNvbXBsZXRlX3RvZG8odGFzazogYnl0ZXMpIC0+IHZvaWQ6CmNvbXBsZXRlX3RvZG86CiAgICBwcm90byAxIDAKICAgIGJ5dGUgIiIKICAgIGR1cAogICAgaW50IDAKICAgIGJ5dGUgInRvZG9zIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBzZWxmLnRvZG9zIGV4aXN0cwogICAgaW50IDAKICAgIGV4dHJhY3RfdWludDE2CiAgICBpbnQgMAoKY29tcGxldGVfdG9kb19mb3JfaGVhZGVyQDE6CiAgICBmcmFtZV9kaWcgMwogICAgZnJhbWVfZGlnIDIKICAgIDwKICAgIGJ6IGNvbXBsZXRlX3RvZG9fYWZ0ZXJfZm9yQDYKICAgIGludCAwCiAgICBieXRlICJ0b2RvcyIKICAgIGFwcF9nbG9iYWxfZ2V0X2V4CiAgICBhc3NlcnQgLy8gY2hlY2sgc2VsZi50b2RvcyBleGlzdHMKICAgIGR1cAogICAgZXh0cmFjdCAyIDAKICAgIGZyYW1lX2RpZyAzCiAgICBkdXAKICAgIGNvdmVyIDMKICAgIGludCAyCiAgICAqCiAgICBkdXAKICAgIGZyYW1lX2J1cnkgMAogICAgZGlnIDEKICAgIHN3YXAKICAgIGV4dHJhY3RfdWludDE2CiAgICBjb3ZlciAzCiAgICBzd2FwCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIHVuY292ZXIgMgogICAgaW50IDEKICAgICsKICAgIGR1cAogICAgY292ZXIgNAogICAgZHVwCiAgICBjb3ZlciAyCiAgICAtIC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgc3dhcAogICAgZGlnIDIKICAgIGxlbgogICAgY292ZXIgMgogICAgaW50IDIKICAgICoKICAgIGR1cAogICAgZnJhbWVfYnVyeSAxCiAgICBkaWcgMwogICAgc3dhcAogICAgZXh0cmFjdF91aW50MTYKICAgIHN3YXAKICAgIHNlbGVjdAogICAgc3dhcAogICAgY292ZXIgMgogICAgc3Vic3RyaW5nMwogICAgZHVwCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIHN3YXAKICAgIGR1cAogICAgbGVuCiAgICBzd2FwCiAgICBjb3ZlciAyCiAgICBzdWJzdHJpbmczCiAgICBmcmFtZV9kaWcgLTEKICAgID09CiAgICBieiBjb21wbGV0ZV90b2RvX2FmdGVyX2lmX2Vsc2VANAogICAgaW50IDAKICAgIGJ5dGUgInRvZG9zIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBzZWxmLnRvZG9zIGV4aXN0cwogICAgZHVwCiAgICBleHRyYWN0IDIgMAogICAgZHVwCiAgICBmcmFtZV9kaWcgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGNvdmVyIDIKICAgIHN3YXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgdW5jb3ZlciAzCiAgICAtIC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgZGlnIDEKICAgIGxlbgogICAgc3dhcAogICAgZGlnIDIKICAgIGZyYW1lX2RpZyAxCiAgICBleHRyYWN0X3VpbnQxNgogICAgc3dhcAogICAgc2VsZWN0CiAgICBzd2FwCiAgICBjb3ZlciAyCiAgICBzdWJzdHJpbmczCiAgICBpbnQgMTYKICAgIGludCAxCiAgICBzZXRiaXQKICAgIGludCAwCiAgICBieXRlICJ0b2RvcyIKICAgIGFwcF9nbG9iYWxfZ2V0X2V4CiAgICBhc3NlcnQgLy8gY2hlY2sgc2VsZi50b2RvcyBleGlzdHMKICAgIHN3YXAKICAgIGZyYW1lX2RpZyAzCiAgICBjYWxsc3ViIGR5bmFtaWNfYXJyYXlfcmVwbGFjZV9keW5hbWljX2VsZW1lbnQKICAgIGJ5dGUgInRvZG9zIgogICAgc3dhcAogICAgYXBwX2dsb2JhbF9wdXQKICAgIGIgY29tcGxldGVfdG9kb19hZnRlcl9mb3JANgoKY29tcGxldGVfdG9kb19hZnRlcl9pZl9lbHNlQDQ6CiAgICBmcmFtZV9idXJ5IDMKICAgIGIgY29tcGxldGVfdG9kb19mb3JfaGVhZGVyQDEKCmNvbXBsZXRlX3RvZG9fYWZ0ZXJfZm9yQDY6CiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RydWN0LnJldHVybl90b2RvKHRhc2s6IGJ5dGVzKSAtPiBieXRlczoKcmV0dXJuX3RvZG86CiAgICBwcm90byAxIDEKICAgIGludCAwCiAgICBieXRlICIiCiAgICBkdXAKICAgIGludCAwCiAgICBkdXAKICAgIGJ5dGUgInRvZG9zIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBzZWxmLnRvZG9zIGV4aXN0cwogICAgaW50IDAKICAgIGV4dHJhY3RfdWludDE2CiAgICBpbnQgMAoKcmV0dXJuX3RvZG9fZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDUKICAgIGZyYW1lX2RpZyA0CiAgICA8CiAgICBieiByZXR1cm5fdG9kb19hZnRlcl9mb3JANgogICAgaW50IDAKICAgIGJ5dGUgInRvZG9zIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBzZWxmLnRvZG9zIGV4aXN0cwogICAgZHVwCiAgICBleHRyYWN0IDIgMAogICAgZnJhbWVfZGlnIDUKICAgIGR1cAogICAgY292ZXIgMwogICAgaW50IDIKICAgICoKICAgIGR1cAogICAgZnJhbWVfYnVyeSAxCiAgICBkaWcgMQogICAgc3dhcAogICAgZXh0cmFjdF91aW50MTYKICAgIGNvdmVyIDMKICAgIHN3YXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgdW5jb3ZlciAyCiAgICBpbnQgMQogICAgKwogICAgZHVwCiAgICBmcmFtZV9idXJ5IDUKICAgIGR1cAogICAgY292ZXIgMgogICAgLSAvLyBvbiBlcnJvcjogSW5kZXggYWNjZXNzIGlzIG91dCBvZiBib3VuZHMKICAgIHN3YXAKICAgIGRpZyAyCiAgICBsZW4KICAgIGNvdmVyIDIKICAgIGludCAyCiAgICAqCiAgICBkdXAKICAgIGZyYW1lX2J1cnkgMgogICAgZGlnIDMKICAgIHN3YXAKICAgIGV4dHJhY3RfdWludDE2CiAgICBzd2FwCiAgICBzZWxlY3QKICAgIHN3YXAKICAgIGNvdmVyIDIKICAgIHN1YnN0cmluZzMKICAgIGR1cAogICAgaW50IDAKICAgIGV4dHJhY3RfdWludDE2CiAgICBzd2FwCiAgICBkdXAKICAgIGxlbgogICAgc3dhcAogICAgY292ZXIgMgogICAgc3Vic3RyaW5nMwogICAgZnJhbWVfZGlnIC0xCiAgICA9PQogICAgYnogcmV0dXJuX3RvZG9fZm9yX2hlYWRlckAxCiAgICBpbnQgMAogICAgYnl0ZSAidG9kb3MiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIHNlbGYudG9kb3MgZXhpc3RzCiAgICBkdXAKICAgIGV4dHJhY3QgMiAwCiAgICBkdXAKICAgIGZyYW1lX2RpZyAxCiAgICBleHRyYWN0X3VpbnQxNgogICAgY292ZXIgMgogICAgc3dhcAogICAgaW50IDAKICAgIGV4dHJhY3RfdWludDE2CiAgICBmcmFtZV9kaWcgNQogICAgLSAvLyBvbiBlcnJvcjogSW5kZXggYWNjZXNzIGlzIG91dCBvZiBib3VuZHMKICAgIGRpZyAxCiAgICBsZW4KICAgIHN3YXAKICAgIGRpZyAyCiAgICBmcmFtZV9kaWcgMgogICAgZXh0cmFjdF91aW50MTYKICAgIHN3YXAKICAgIHNlbGVjdAogICAgc3dhcAogICAgY292ZXIgMgogICAgc3Vic3RyaW5nMwogICAgZnJhbWVfYnVyeSAwCiAgICBpbnQgMQogICAgZnJhbWVfYnVyeSAzCiAgICBiIHJldHVybl90b2RvX2Zvcl9oZWFkZXJAMQoKcmV0dXJuX3RvZG9fYWZ0ZXJfZm9yQDY6CiAgICBmcmFtZV9kaWcgMwogICAgYXNzZXJ0CiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RydWN0Ll9faW5pdF9fKCkgLT4gdm9pZDoKX19pbml0X186CiAgICBwcm90byAwIDAKICAgIGJ5dGUgInRvZG9zIgogICAgYnl0ZSAweDAwMDAKICAgIGFwcF9nbG9iYWxfcHV0CiAgICByZXRzdWIKCgovLyBfcHV5YV9saWIuYXJjNC5keW5hbWljX2FycmF5X2NvbmNhdF9keW5hbWljX2VsZW1lbnQoYXJyYXlfaXRlbXNfY291bnQ6IHVpbnQ2NCwgYXJyYXlfaGVhZF9hbmRfdGFpbDogYnl0ZXMsIG5ld19pdGVtc19jb3VudDogdWludDY0LCBuZXdfaGVhZF9hbmRfdGFpbDogYnl0ZXMpIC0+IGJ5dGVzOgpkeW5hbWljX2FycmF5X2NvbmNhdF9keW5hbWljX2VsZW1lbnQ6CiAgICBwcm90byA0IDEKICAgIGJ5dGUgIiIKICAgIGJ5dGUgMHgKICAgIGZyYW1lX2RpZyAtMgogICAgaW50IDIKICAgICoKICAgIGZyYW1lX2RpZyAtNAogICAgaW50IDIKICAgICoKICAgIGludCAwCgpkeW5hbWljX2FycmF5X2NvbmNhdF9keW5hbWljX2VsZW1lbnRfZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDQKICAgIGZyYW1lX2RpZyAzCiAgICA8CiAgICBieiBkeW5hbWljX2FycmF5X2NvbmNhdF9keW5hbWljX2VsZW1lbnRfYWZ0ZXJfZm9yQDQKICAgIGZyYW1lX2RpZyAtMwogICAgZnJhbWVfZGlnIDQKICAgIGR1cAogICAgY292ZXIgMgogICAgZXh0cmFjdF91aW50MTYKICAgIGZyYW1lX2RpZyAyCiAgICArCiAgICBpdG9iCiAgICBleHRyYWN0IDYgMgogICAgZnJhbWVfZGlnIDEKICAgIHN3YXAKICAgIGNvbmNhdAogICAgZnJhbWVfYnVyeSAxCiAgICBpbnQgMgogICAgKwogICAgZnJhbWVfYnVyeSA0CiAgICBiIGR5bmFtaWNfYXJyYXlfY29uY2F0X2R5bmFtaWNfZWxlbWVudF9mb3JfaGVhZGVyQDEKCmR5bmFtaWNfYXJyYXlfY29uY2F0X2R5bmFtaWNfZWxlbWVudF9hZnRlcl9mb3JANDoKICAgIGZyYW1lX2RpZyAtMwogICAgbGVuCiAgICBmcmFtZV9idXJ5IDAKICAgIGludCAwCiAgICBmcmFtZV9idXJ5IDQKCmR5bmFtaWNfYXJyYXlfY29uY2F0X2R5bmFtaWNfZWxlbWVudF9mb3JfaGVhZGVyQDU6CiAgICBmcmFtZV9kaWcgNAogICAgZnJhbWVfZGlnIDIKICAgIDwKICAgIGJ6IGR5bmFtaWNfYXJyYXlfY29uY2F0X2R5bmFtaWNfZWxlbWVudF9hZnRlcl9mb3JAOAogICAgZnJhbWVfZGlnIC0xCiAgICBmcmFtZV9kaWcgNAogICAgZHVwCiAgICBjb3ZlciAyCiAgICBleHRyYWN0X3VpbnQxNgogICAgZnJhbWVfZGlnIDAKICAgICsKICAgIGl0b2IKICAgIGV4dHJhY3QgNiAyCiAgICBmcmFtZV9kaWcgMQogICAgc3dhcAogICAgY29uY2F0CiAgICBmcmFtZV9idXJ5IDEKICAgIGludCAyCiAgICArCiAgICBmcmFtZV9idXJ5IDQKICAgIGIgZHluYW1pY19hcnJheV9jb25jYXRfZHluYW1pY19lbGVtZW50X2Zvcl9oZWFkZXJANQoKZHluYW1pY19hcnJheV9jb25jYXRfZHluYW1pY19lbGVtZW50X2FmdGVyX2ZvckA4OgogICAgZnJhbWVfZGlnIC00CiAgICBmcmFtZV9kaWcgLTIKICAgICsKICAgIGl0b2IKICAgIGV4dHJhY3QgNiAyCiAgICBmcmFtZV9kaWcgMQogICAgY29uY2F0CiAgICBmcmFtZV9kaWcgLTMKICAgIGZyYW1lX2RpZyAzCiAgICBmcmFtZV9kaWcgMAogICAgc3Vic3RyaW5nMwogICAgY29uY2F0CiAgICBmcmFtZV9kaWcgLTEKICAgIGxlbgogICAgZnJhbWVfZGlnIC0xCiAgICBmcmFtZV9kaWcgMgogICAgdW5jb3ZlciAyCiAgICBzdWJzdHJpbmczCiAgICBjb25jYXQKICAgIGZyYW1lX2J1cnkgMAogICAgcmV0c3ViCgoKLy8gX3B1eWFfbGliLmFyYzQuZHluYW1pY19hcnJheV9yZXBsYWNlX2R5bmFtaWNfZWxlbWVudChzb3VyY2U6IGJ5dGVzLCBuZXdfaXRlbTogYnl0ZXMsIGluZGV4OiB1aW50NjQpIC0+IGJ5dGVzOgpkeW5hbWljX2FycmF5X3JlcGxhY2VfZHluYW1pY19lbGVtZW50OgogICAgcHJvdG8gMyAxCiAgICBmcmFtZV9kaWcgLTMKICAgIHN1YnN0cmluZyAwIDIKICAgIGR1cAogICAgYnRvaQogICAgZnJhbWVfZGlnIC0zCiAgICBleHRyYWN0IDIgMAogICAgZnJhbWVfZGlnIC0yCiAgICBmcmFtZV9kaWcgLTEKICAgIHVuY292ZXIgMwogICAgY2FsbHN1YiBzdGF0aWNfYXJyYXlfcmVwbGFjZV9keW5hbWljX2VsZW1lbnQKICAgIGNvbmNhdAogICAgcmV0c3ViCgoKLy8gX3B1eWFfbGliLmFyYzQuc3RhdGljX2FycmF5X3JlcGxhY2VfZHluYW1pY19lbGVtZW50KGFycmF5X2hlYWRfYW5kX3RhaWw6IGJ5dGVzLCBuZXdfaXRlbTogYnl0ZXMsIGluZGV4OiB1aW50NjQsIGFycmF5X2xlbmd0aDogdWludDY0KSAtPiBieXRlczoKc3RhdGljX2FycmF5X3JlcGxhY2VfZHluYW1pY19lbGVtZW50OgogICAgcHJvdG8gNCAxCiAgICBmcmFtZV9kaWcgLTIKICAgIGludCAyCiAgICAqCiAgICBmcmFtZV9kaWcgLTQKICAgIHN3YXAKICAgIGV4dHJhY3RfdWludDE2CiAgICBmcmFtZV9kaWcgLTIKICAgIGludCAxCiAgICArCiAgICBpbnQgMgogICAgKgogICAgZHVwCiAgICBjb3ZlciAyCiAgICBmcmFtZV9kaWcgLTQKICAgIHN3YXAKICAgIGV4dHJhY3RfdWludDE2CiAgICBmcmFtZV9kaWcgLTQKICAgIGxlbgogICAgZnJhbWVfZGlnIC0xCiAgICBmcmFtZV9kaWcgLTIKICAgIC0KICAgIGludCAxCiAgICAtCiAgICBkaWcgMQogICAgdW5jb3ZlciAzCiAgICB1bmNvdmVyIDIKICAgIHNlbGVjdAogICAgZHVwCiAgICBkaWcgMwogICAgLQogICAgY292ZXIgMwogICAgZnJhbWVfZGlnIC0zCiAgICBsZW4KICAgIGNvdmVyIDMKICAgIGZyYW1lX2RpZyAtNAogICAgaW50IDAKICAgIHVuY292ZXIgNAogICAgc3Vic3RyaW5nMwogICAgZnJhbWVfZGlnIC0zCiAgICBjb25jYXQKICAgIGZyYW1lX2RpZyAtNAogICAgdW5jb3ZlciAyCiAgICB1bmNvdmVyIDMKICAgIHN1YnN0cmluZzMKICAgIGNvbmNhdAogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMgogICAgKgoKc3RhdGljX2FycmF5X3JlcGxhY2VfZHluYW1pY19lbGVtZW50X2Zvcl9oZWFkZXJAMToKICAgIGZyYW1lX2RpZyAwCiAgICBmcmFtZV9kaWcgNAogICAgPAogICAgYnogc3RhdGljX2FycmF5X3JlcGxhY2VfZHluYW1pY19lbGVtZW50X2FmdGVyX2ZvckA0CiAgICBmcmFtZV9kaWcgMwogICAgZHVwCiAgICBmcmFtZV9kaWcgMAogICAgZHVwCiAgICBjb3ZlciAzCiAgICBleHRyYWN0X3VpbnQxNgogICAgZnJhbWVfZGlnIDIKICAgICsKICAgIGZyYW1lX2RpZyAxCiAgICAtCiAgICBpdG9iCiAgICBleHRyYWN0IDYgMgogICAgZGlnIDIKICAgIHN3YXAKICAgIHJlcGxhY2UzCiAgICBmcmFtZV9idXJ5IDMKICAgIGludCAyCiAgICArCiAgICBmcmFtZV9idXJ5IDAKICAgIGIgc3RhdGljX2FycmF5X3JlcGxhY2VfZHluYW1pY19lbGVtZW50X2Zvcl9oZWFkZXJAMQoKc3RhdGljX2FycmF5X3JlcGxhY2VfZHluYW1pY19lbGVtZW50X2FmdGVyX2ZvckA0OgogICAgZnJhbWVfZGlnIDMKICAgIGZyYW1lX2J1cnkgMAogICAgcmV0c3ViCg==", + "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RydWN0LmNsZWFyX3N0YXRlX3Byb2dyYW06CiAgICBpbnQgMQogICAgcmV0dXJuCg==" + }, + "state": { + "global": { + "num_byte_slices": 1, + "num_uints": 0 + }, + "local": { + "num_byte_slices": 0, + "num_uints": 0 + } + }, + "schema": { + "global": { + "declared": { + "todos": { + "type": "bytes", + "key": "todos" + } + }, + "reserved": {} + }, + "local": { + "declared": {}, + "reserved": {} + } + }, + "contract": { + "name": "Arc4Struct", + "methods": [ + { + "name": "add_todo", + "args": [ + { + "type": "string", + "name": "task" + } + ], + "returns": { + "type": "(string,bool)[]" + } + }, + { + "name": "complete_todo", + "args": [ + { + "type": "string", + "name": "task" + } + ], + "returns": { + "type": "void" + } + }, + { + "name": "return_todo", + "args": [ + { + "type": "string", + "name": "task" + } + ], + "returns": { + "type": "(string,bool)" + } + } + ], + "networks": {} + }, + "bare_call_config": { + "no_op": "CREATE" + } +}""" +APP_SPEC = algokit_utils.ApplicationSpecification.from_json(_APP_SPEC_JSON) +_TReturn = typing.TypeVar("_TReturn") + + +class _ArgsBase(ABC, typing.Generic[_TReturn]): + @staticmethod + @abstractmethod + def method() -> str: + ... + + +_TArgs = typing.TypeVar("_TArgs", bound=_ArgsBase[typing.Any]) + + +@dataclasses.dataclass(kw_only=True) +class _TArgsHolder(typing.Generic[_TArgs]): + args: _TArgs + + +def _filter_none(value: dict | typing.Any) -> dict | typing.Any: + if isinstance(value, dict): + return {k: _filter_none(v) for k, v in value.items() if v is not None} + return value + + +def _as_dict(data: typing.Any, *, convert_all: bool = True) -> dict[str, typing.Any]: + if data is None: + return {} + if not dataclasses.is_dataclass(data): + raise TypeError(f"{data} must be a dataclass") + if convert_all: + result = dataclasses.asdict(data) # type: ignore[call-overload] + else: + result = {f.name: getattr(data, f.name) for f in dataclasses.fields(data)} + return _filter_none(result) + + +def _convert_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, +) -> algokit_utils.TransactionParametersDict: + return typing.cast(algokit_utils.TransactionParametersDict, _as_dict(transaction_parameters)) + + +def _convert_call_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, +) -> algokit_utils.OnCompleteCallParametersDict: + return typing.cast(algokit_utils.OnCompleteCallParametersDict, _as_dict(transaction_parameters)) + + +def _convert_create_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, + on_complete: algokit_utils.OnCompleteActionName, +) -> algokit_utils.CreateCallParametersDict: + result = typing.cast(algokit_utils.CreateCallParametersDict, _as_dict(transaction_parameters)) + on_complete_enum = on_complete.replace("_", " ").title().replace(" ", "") + "OC" + result["on_complete"] = getattr(algosdk.transaction.OnComplete, on_complete_enum) + return result + + +def _convert_deploy_args( + deploy_args: algokit_utils.DeployCallArgs | None, +) -> algokit_utils.ABICreateCallArgsDict | None: + if deploy_args is None: + return None + + deploy_args_dict = typing.cast(algokit_utils.ABICreateCallArgsDict, _as_dict(deploy_args)) + if isinstance(deploy_args, _TArgsHolder): + deploy_args_dict["args"] = _as_dict(deploy_args.args) + deploy_args_dict["method"] = deploy_args.args.method() + + return deploy_args_dict + + +@dataclasses.dataclass(kw_only=True) +class AddTodoArgs(_ArgsBase[list[tuple[str, bool]]]): + task: str + + @staticmethod + def method() -> str: + return "add_todo(string)(string,bool)[]" + + +@dataclasses.dataclass(kw_only=True) +class CompleteTodoArgs(_ArgsBase[None]): + task: str + + @staticmethod + def method() -> str: + return "complete_todo(string)void" + + +@dataclasses.dataclass(kw_only=True) +class Todo: + task: str + completed: bool + + +@dataclasses.dataclass(kw_only=True) +class ReturnTodoArgs(_ArgsBase[Todo]): + task: str + + @staticmethod + def method() -> str: + return "return_todo(string)(string,bool)" + + +class ByteReader: + def __init__(self, data: bytes): + self._data = data + + @property + def as_bytes(self) -> bytes: + return self._data + + @property + def as_str(self) -> str: + return self._data.decode("utf8") + + @property + def as_base64(self) -> str: + return base64.b64encode(self._data).decode("utf8") + + @property + def as_hex(self) -> str: + return self._data.hex() + + +class GlobalState: + def __init__(self, data: dict[bytes, bytes | int]): + self.todos = ByteReader(typing.cast(bytes, data.get(b"todos"))) + + +@dataclasses.dataclass(kw_only=True) +class SimulateOptions: + allow_more_logs: bool = dataclasses.field(default=False) + allow_empty_signatures: bool = dataclasses.field(default=False) + extra_opcode_budget: int = dataclasses.field(default=0) + exec_trace_config: models.SimulateTraceConfig | None = dataclasses.field(default=None) + + +class Composer: + + def __init__(self, app_client: algokit_utils.ApplicationClient, atc: AtomicTransactionComposer): + self.app_client = app_client + self.atc = atc + + def build(self) -> AtomicTransactionComposer: + return self.atc + + def simulate(self, options: SimulateOptions | None = None) -> SimulateAtomicTransactionResponse: + request = models.SimulateRequest( + allow_more_logs=options.allow_more_logs, + allow_empty_signatures=options.allow_empty_signatures, + extra_opcode_budget=options.extra_opcode_budget, + exec_trace_config=options.exec_trace_config, + txn_groups=[] + ) if options else None + result = self.atc.simulate(self.app_client.algod_client, request) + return result + + def execute(self) -> AtomicTransactionResponse: + return self.app_client.execute_atc(self.atc) + + def add_todo( + self, + *, + task: str, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> "Composer": + """Adds a call to `add_todo(string)(string,bool)[]` ABI method + + :param str task: The `task` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + args = AddTodoArgs( + task=task, + ) + self.app_client.compose_call( + self.atc, + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return self + + def complete_todo( + self, + *, + task: str, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> "Composer": + """Adds a call to `complete_todo(string)void` ABI method + + :param str task: The `task` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + args = CompleteTodoArgs( + task=task, + ) + self.app_client.compose_call( + self.atc, + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return self + + def return_todo( + self, + *, + task: str, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> "Composer": + """Adds a call to `return_todo(string)(string,bool)` ABI method + + :param str task: The `task` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + args = ReturnTodoArgs( + task=task, + ) + self.app_client.compose_call( + self.atc, + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return self + + def create_bare( + self, + *, + on_complete: typing.Literal["no_op"] = "no_op", + transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, + ) -> "Composer": + """Adds a call to create an application using the no_op bare method + + :param typing.Literal[no_op] on_complete: On completion type to use + :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + self.app_client.compose_create( + self.atc, + call_abi_method=False, + transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), + ) + return self + + def clear_state( + self, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + app_args: list[bytes] | None = None, + ) -> "Composer": + """Adds a call to the application with on completion set to ClearState + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :param list[bytes] | None app_args: (optional) Application args to pass""" + + self.app_client.compose_clear_state(self.atc, _convert_transaction_parameters(transaction_parameters), app_args) + return self + + +class Arc4StructClient: + """A class for interacting with the Arc4Struct app providing high productivity and + strongly typed methods to deploy and call the app""" + + @typing.overload + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + app_id: int = 0, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + ... + + @typing.overload + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + creator: str | algokit_utils.Account, + indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, + existing_deployments: algokit_utils.AppLookup | None = None, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + ... + + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + creator: str | algokit_utils.Account | None = None, + indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, + existing_deployments: algokit_utils.AppLookup | None = None, + app_id: int = 0, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + """ + Arc4StructClient can be created with an app_id to interact with an existing application, alternatively + it can be created with a creator and indexer_client specified to find existing applications by name and creator. + + :param AlgodClient algod_client: AlgoSDK algod client + :param int app_id: The app_id of an existing application, to instead find the application by creator and name + use the creator and indexer_client parameters + :param str | Account creator: The address or Account of the app creator to resolve the app_id + :param IndexerClient indexer_client: AlgoSDK indexer client, only required if deploying or finding app_id by + creator and app name + :param AppLookup existing_deployments: + :param TransactionSigner | Account signer: Account or signer to use to sign transactions, if not specified and + creator was passed as an Account will use that. + :param str sender: Address to use as the sender for all transactions, will use the address associated with the + signer if not specified. + :param TemplateValueMapping template_values: Values to use for TMPL_* template variables, dictionary keys should + *NOT* include the TMPL_ prefix + :param str | None app_name: Name of application to use when deploying, defaults to name defined on the + Application Specification + """ + + self.app_spec = APP_SPEC + + # calling full __init__ signature, so ignoring mypy warning about overloads + self.app_client = algokit_utils.ApplicationClient( # type: ignore[call-overload, misc] + algod_client=algod_client, + app_spec=self.app_spec, + app_id=app_id, + creator=creator, + indexer_client=indexer_client, + existing_deployments=existing_deployments, + signer=signer, + sender=sender, + suggested_params=suggested_params, + template_values=template_values, + app_name=app_name, + ) + + @property + def algod_client(self) -> algosdk.v2client.algod.AlgodClient: + return self.app_client.algod_client + + @property + def app_id(self) -> int: + return self.app_client.app_id + + @app_id.setter + def app_id(self, value: int) -> None: + self.app_client.app_id = value + + @property + def app_address(self) -> str: + return self.app_client.app_address + + @property + def sender(self) -> str | None: + return self.app_client.sender + + @sender.setter + def sender(self, value: str) -> None: + self.app_client.sender = value + + @property + def signer(self) -> TransactionSigner | None: + return self.app_client.signer + + @signer.setter + def signer(self, value: TransactionSigner) -> None: + self.app_client.signer = value + + @property + def suggested_params(self) -> algosdk.transaction.SuggestedParams | None: + return self.app_client.suggested_params + + @suggested_params.setter + def suggested_params(self, value: algosdk.transaction.SuggestedParams | None) -> None: + self.app_client.suggested_params = value + + def get_global_state(self) -> GlobalState: + """Returns the application's global state wrapped in a strongly typed class with options to format the stored value""" + + state = typing.cast(dict[bytes, bytes | int], self.app_client.get_global_state(raw=True)) + return GlobalState(state) + + def add_todo( + self, + *, + task: str, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> algokit_utils.ABITransactionResponse[list[tuple[str, bool]]]: + """Calls `add_todo(string)(string,bool)[]` ABI method + + :param str task: The `task` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.ABITransactionResponse[list[tuple[str, bool]]]: The result of the transaction""" + + args = AddTodoArgs( + task=task, + ) + result = self.app_client.call( + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return result + + def complete_todo( + self, + *, + task: str, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> algokit_utils.ABITransactionResponse[None]: + """Calls `complete_todo(string)void` ABI method + + :param str task: The `task` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.ABITransactionResponse[None]: The result of the transaction""" + + args = CompleteTodoArgs( + task=task, + ) + result = self.app_client.call( + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return result + + def return_todo( + self, + *, + task: str, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> algokit_utils.ABITransactionResponse[Todo]: + """Calls `return_todo(string)(string,bool)` ABI method + + :param str task: The `task` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.ABITransactionResponse[Todo]: The result of the transaction""" + + args = ReturnTodoArgs( + task=task, + ) + result = self.app_client.call( + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + elements = self.app_spec.hints[args.method()].structs["output"]["elements"] + result_dict = {element[0]: value for element, value in zip(elements, result.return_value)} + result.return_value = Todo(**result_dict) + return result + + def create_bare( + self, + *, + on_complete: typing.Literal["no_op"] = "no_op", + transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, + ) -> algokit_utils.TransactionResponse: + """Creates an application using the no_op bare method + + :param typing.Literal[no_op] on_complete: On completion type to use + :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.TransactionResponse: The result of the transaction""" + + result = self.app_client.create( + call_abi_method=False, + transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), + ) + return result + + def clear_state( + self, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + app_args: list[bytes] | None = None, + ) -> algokit_utils.TransactionResponse: + """Calls the application with on completion set to ClearState + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :param list[bytes] | None app_args: (optional) Application args to pass + :returns algokit_utils.TransactionResponse: The result of the transaction""" + + return self.app_client.clear_state(_convert_transaction_parameters(transaction_parameters), app_args) + + def deploy( + self, + version: str | None = None, + *, + signer: TransactionSigner | None = None, + sender: str | None = None, + allow_update: bool | None = None, + allow_delete: bool | None = None, + on_update: algokit_utils.OnUpdate = algokit_utils.OnUpdate.Fail, + on_schema_break: algokit_utils.OnSchemaBreak = algokit_utils.OnSchemaBreak.Fail, + template_values: algokit_utils.TemplateValueMapping | None = None, + create_args: algokit_utils.DeployCallArgs | None = None, + update_args: algokit_utils.DeployCallArgs | None = None, + delete_args: algokit_utils.DeployCallArgs | None = None, + ) -> algokit_utils.DeployResponse: + """Deploy an application and update client to reference it. + + Idempotently deploy (create, update/delete if changed) an app against the given name via the given creator + account, including deploy-time template placeholder substitutions. + To understand the architecture decisions behind this functionality please see + + + ```{note} + If there is a breaking state schema change to an existing app (and `on_schema_break` is set to + 'ReplaceApp' the existing app will be deleted and re-created. + ``` + + ```{note} + If there is an update (different TEAL code) to an existing app (and `on_update` is set to 'ReplaceApp') + the existing app will be deleted and re-created. + ``` + + :param str version: version to use when creating or updating app, if None version will be auto incremented + :param algosdk.atomic_transaction_composer.TransactionSigner signer: signer to use when deploying app + , if None uses self.signer + :param str sender: sender address to use when deploying app, if None uses self.sender + :param bool allow_delete: Used to set the `TMPL_DELETABLE` template variable to conditionally control if an app + can be deleted + :param bool allow_update: Used to set the `TMPL_UPDATABLE` template variable to conditionally control if an app + can be updated + :param OnUpdate on_update: Determines what action to take if an application update is required + :param OnSchemaBreak on_schema_break: Determines what action to take if an application schema requirements + has increased beyond the current allocation + :param dict[str, int|str|bytes] template_values: Values to use for `TMPL_*` template variables, dictionary keys + should *NOT* include the TMPL_ prefix + :param algokit_utils.DeployCallArgs | None create_args: Arguments used when creating an application + :param algokit_utils.DeployCallArgs | None update_args: Arguments used when updating an application + :param algokit_utils.DeployCallArgs | None delete_args: Arguments used when deleting an application + :return DeployResponse: details action taken and relevant transactions + :raises DeploymentError: If the deployment failed""" + + return self.app_client.deploy( + version, + signer=signer, + sender=sender, + allow_update=allow_update, + allow_delete=allow_delete, + on_update=on_update, + on_schema_break=on_schema_break, + template_values=template_values, + create_args=_convert_deploy_args(create_args), + update_args=_convert_deploy_args(update_args), + delete_args=_convert_deploy_args(delete_args), + ) + + def compose(self, atc: AtomicTransactionComposer | None = None) -> Composer: + return Composer(self.app_client, atc or AtomicTransactionComposer()) diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_types_client.py b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_types_client.py index f41074f..68a5283 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_types_client.py +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_types_client.py @@ -23,14 +23,19 @@ _APP_SPEC_JSON = r"""{ "hints": { - "hello(string)string": { + "arc4_uint64(uint64,uint64)uint64": { + "call_config": { + "no_op": "CALL" + } + }, + "arc4_address(address)address": { "call_config": { "no_op": "CALL" } } }, "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANQogICAgbWV0aG9kICJoZWxsbyhzdHJpbmcpc3RyaW5nIgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAogICAgbWF0Y2ggX19wdXlhX2FyYzRfcm91dGVyX19faGVsbG9fcm91dGVAMgogICAgaW50IDAKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19faGVsbG9fcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGV4dHJhY3QgMiAwCiAgICBjYWxsc3ViIGhlbGxvCiAgICBkdXAKICAgIGxlbgogICAgaXRvYgogICAgZXh0cmFjdCA2IDIKICAgIHN3YXAKICAgIGNvbmNhdAogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDU6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBibnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUA5CiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgIQogICAgYXNzZXJ0IC8vIGlzIGNyZWF0aW5nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDk6CiAgICBpbnQgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmhlbGxvKG5hbWU6IGJ5dGVzKSAtPiBieXRlczoKaGVsbG86CiAgICBwcm90byAxIDEKICAgIGJ5dGUgIkhlbGxvLCAiCiAgICBmcmFtZV9kaWcgLTEKICAgIGNvbmNhdAogICAgcmV0c3ViCg==", + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANgogICAgbWV0aG9kICJhcmM0X3VpbnQ2NCh1aW50NjQsdWludDY0KXVpbnQ2NCIKICAgIG1ldGhvZCAiYXJjNF9hZGRyZXNzKGFkZHJlc3MpYWRkcmVzcyIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdWludDY0X3JvdXRlQDIgX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9hZGRyZXNzX3JvdXRlQDMKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdWludDY0X3JvdXRlQDI6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAyCiAgICBjYWxsc3ViIGFyYzRfdWludDY0CiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2FkZHJlc3Nfcm91dGVAMzoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF9hZGRyZXNzCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgIGJueiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDEwCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgIQogICAgYXNzZXJ0IC8vIGlzIGNyZWF0aW5nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDEwOgogICAgaW50IDAKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X3VpbnQ2NChhOiBieXRlcywgYjogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X3VpbnQ2NDoKICAgIHByb3RvIDIgMQogICAgZnJhbWVfZGlnIC0yCiAgICBidG9pCiAgICBmcmFtZV9kaWcgLTEKICAgIGJ0b2kKICAgICsKICAgIGl0b2IKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X2FkZHJlc3MoYWRkcmVzczogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X2FkZHJlc3M6CiAgICBwcm90byAxIDEKICAgIGZyYW1lX2RpZyAtMQogICAgYWNjdF9wYXJhbXNfZ2V0IEFjY3RCYWxhbmNlCiAgICBidXJ5IDEKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgZnJhbWVfZGlnIC0xCiAgICBhY2N0X3BhcmFtc19nZXQgQWNjdFRvdGFsQXNzZXRzCiAgICBidXJ5IDEKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgZnJhbWVfZGlnIC0xCiAgICByZXRzdWIK", "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" }, "state": { @@ -57,15 +62,32 @@ "name": "Arc4Types", "methods": [ { - "name": "hello", + "name": "arc4_uint64", "args": [ { - "type": "string", - "name": "name" + "type": "uint64", + "name": "a" + }, + { + "type": "uint64", + "name": "b" } ], "returns": { - "type": "string" + "type": "uint64" + }, + "desc": "This won't compile because you can't do math operations on arc4.UInt64 type.\nAll arc4 types are backed by byte arrays on the AVM. c = a + b" + }, + { + "name": "arc4_address", + "args": [ + { + "type": "address", + "name": "address" + } + ], + "returns": { + "type": "address" } } ], @@ -149,12 +171,25 @@ def _convert_deploy_args( @dataclasses.dataclass(kw_only=True) -class HelloArgs(_ArgsBase[str]): - name: str +class Arc4Uint64Args(_ArgsBase[int]): + """This won't compile because you can't do math operations on arc4.UInt64 type. + All arc4 types are backed by byte arrays on the AVM. c = a + b""" + + a: int + b: int + + @staticmethod + def method() -> str: + return "arc4_uint64(uint64,uint64)uint64" + + +@dataclasses.dataclass(kw_only=True) +class Arc4AddressArgs(_ArgsBase[str]): + address: str @staticmethod def method() -> str: - return "hello(string)string" + return "arc4_address(address)address" @dataclasses.dataclass(kw_only=True) @@ -188,20 +223,49 @@ def simulate(self, options: SimulateOptions | None = None) -> SimulateAtomicTran def execute(self) -> AtomicTransactionResponse: return self.app_client.execute_atc(self.atc) - def hello( + def arc4_uint64( self, *, - name: str, + a: int, + b: int, transaction_parameters: algokit_utils.TransactionParameters | None = None, ) -> "Composer": - """Adds a call to `hello(string)string` ABI method + """This won't compile because you can't do math operations on arc4.UInt64 type. + All arc4 types are backed by byte arrays on the AVM. c = a + b + + Adds a call to `arc4_uint64(uint64,uint64)uint64` ABI method - :param str name: The `name` ABI parameter + :param int a: The `a` ABI parameter + :param int b: The `b` ABI parameter :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters :returns Composer: This Composer instance""" - args = HelloArgs( - name=name, + args = Arc4Uint64Args( + a=a, + b=b, + ) + self.app_client.compose_call( + self.atc, + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return self + + def arc4_address( + self, + *, + address: str, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> "Composer": + """Adds a call to `arc4_address(address)address` ABI method + + :param str address: The `address` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + args = Arc4AddressArgs( + address=address, ) self.app_client.compose_call( self.atc, @@ -370,20 +434,48 @@ def suggested_params(self) -> algosdk.transaction.SuggestedParams | None: def suggested_params(self, value: algosdk.transaction.SuggestedParams | None) -> None: self.app_client.suggested_params = value - def hello( + def arc4_uint64( + self, + *, + a: int, + b: int, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> algokit_utils.ABITransactionResponse[int]: + """This won't compile because you can't do math operations on arc4.UInt64 type. + All arc4 types are backed by byte arrays on the AVM. c = a + b + + Calls `arc4_uint64(uint64,uint64)uint64` ABI method + + :param int a: The `a` ABI parameter + :param int b: The `b` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.ABITransactionResponse[int]: The result of the transaction""" + + args = Arc4Uint64Args( + a=a, + b=b, + ) + result = self.app_client.call( + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return result + + def arc4_address( self, *, - name: str, + address: str, transaction_parameters: algokit_utils.TransactionParameters | None = None, ) -> algokit_utils.ABITransactionResponse[str]: - """Calls `hello(string)string` ABI method + """Calls `arc4_address(address)address` ABI method - :param str name: The `name` ABI parameter + :param str address: The `address` ABI parameter :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters :returns algokit_utils.ABITransactionResponse[str]: The result of the transaction""" - args = HelloArgs( - name=name, + args = Arc4AddressArgs( + address=address, ) result = self.app_client.call( call_abi_method=args.method(), diff --git a/projects/python-contract-examples/tests/arc4_types_integration_test.py b/projects/python-contract-examples/tests/arc4_types_integration_test.py new file mode 100644 index 0000000..29ba53e --- /dev/null +++ b/projects/python-contract-examples/tests/arc4_types_integration_test.py @@ -0,0 +1,188 @@ +import pytest +from algokit_utils import TransactionParameters +from algokit_utils.beta.account_manager import AddressAndSigner +from algokit_utils.beta.algorand_client import ( + AlgorandClient, + AssetCreateParams, + AssetOptInParams, + PayParams, +) +from algokit_utils.config import config +from algosdk.v2client.algod import AlgodClient + +from smart_contracts.artifacts.arc4_types.arc4_static_array_client import Arc4StaticArrayClient +from smart_contracts.artifacts.arc4_types.arc4_struct_client import Arc4StructClient +from smart_contracts.artifacts.arc4_types.arc4_types_client import Arc4TypesClient + + +@pytest.fixture(scope="session") +def algorand() -> AlgorandClient: + """Get an AlgorandClient to use throughout the tests""" + algorand = AlgorandClient.default_local_net() + algorand.set_default_validity_window(1000) + + return algorand + + +@pytest.fixture(scope="session") +def dispenser(algorand: AlgorandClient) -> AddressAndSigner: + """Get the dispenser to fund test addresses""" + return algorand.account.dispenser() + + +@pytest.fixture(scope="session") +def creator(algorand: AlgorandClient, dispenser: AddressAndSigner) -> AddressAndSigner: + """Get an account to use as the creator of the contract""" + acct = algorand.account.random() + + # Make sure the account has some ALGO + algorand.send.payment( + PayParams(sender=dispenser.address, receiver=acct.address, amount=10_000_000) + ) + + return acct + + +@pytest.fixture(scope="session") +def alice(algorand: AlgorandClient, dispenser: AddressAndSigner) -> AddressAndSigner: + """Get an account to use as Alice who will participate in the auction""" + acct = algorand.account.random() + + # Make sure the account has some ALGO + algorand.send.payment( + PayParams(sender=dispenser.address, receiver=acct.address, amount=10_000_000) + ) + + return acct + + +@pytest.fixture(scope="session") +def arc4_statc_array_app_client( + algod_client: AlgodClient, creator: AddressAndSigner, algorand: AlgorandClient +) -> Arc4StaticArrayClient: + """Deploy the arc4 static array App and create an app client the creator will use to interact with the contract""" + + config.configure( + debug=True, + # trace_all=True, + ) + + client = Arc4StaticArrayClient( + algod_client, + sender=creator.address, + signer=creator.signer, + ) + + client.create_bare() + + algorand.send.payment( + PayParams( + sender=creator.address, + receiver=client.app_address, + amount=1000000, # 1 Algo + ) + ) + + return client + +@pytest.fixture(scope="session") +def arc4_struct_app_client( + algod_client: AlgodClient, creator: AddressAndSigner, algorand: AlgorandClient +) -> Arc4StructClient: + """Deploy the arc4 struct App and create an app client the creator will use to interact with the contract""" + + config.configure( + debug=True, + # trace_all=True, + ) + + client = Arc4StructClient( + algod_client, + sender=creator.address, + signer=creator.signer, + ) + + client.create_bare() + + algorand.send.payment( + PayParams( + sender=creator.address, + receiver=client.app_address, + amount=1000000, # 1 Algo + ) + ) + + return client + +@pytest.fixture(scope="session") +def arc4_types_app_client( + algod_client: AlgodClient, creator: AddressAndSigner, algorand: AlgorandClient +) -> Arc4TypesClient: + """Deploy the arc4 types App and create an app client the creator will use to interact with the contract""" + + config.configure( + debug=True, + # trace_all=True, + ) + + client = Arc4TypesClient( + algod_client, + sender=creator.address, + signer=creator.signer, + ) + + client.create_bare() + + algorand.send.payment( + PayParams( + sender=creator.address, + receiver=client.app_address, + amount=1000000, # 1 Algo + ) + ) + + return client + +def test_arc4_uint64( + arc4_types_app_client: Arc4TypesClient, +) -> None: + """Test the arc4_uint64 method""" + + # Call the arc4_uint64 method + result = arc4_types_app_client.arc4_uint64(a=1, b=2) + + # Check the result + assert result.return_value == 3 + +def test_arc4_address( + arc4_types_app_client: Arc4TypesClient, + creator : AddressAndSigner +) -> None: + """Test the arc4_address method""" + + # Call the arc4_address method + result = arc4_types_app_client.arc4_address(address=creator.address) + + # Check the result + assert result.return_value == arc4_types_app_client.sender + +def test_arc4_static_array( + arc4_statc_array_app_client: Arc4StaticArrayClient +) -> None: + """Test the arc4_static_array method""" + + # Call the arc4_static_array method + arc4_statc_array_app_client.arc4_static_array() + +def test_arc4_struct_add_todo( + arc4_struct_app_client: Arc4StructClient +) -> None: + """Test the add_todo method""" + + # Call the add_todo method + result = arc4_struct_app_client.add_todo(task="task") + print(result.return_value) + + assert result.return_value[0][0] == "task" + assert result.return_value[0][1] == False + assert len(result.return_value) == 1 From a053ff0b56b35698c39fed53758b6c7377153c82 Mon Sep 17 00:00:00 2001 From: "Chris Kim (Hyunggun)" Date: Mon, 28 Oct 2024 16:08:40 -0700 Subject: [PATCH 03/23] finish integration test --- .../smart_contracts/arc4_types/contract.py | 42 ++++++++------ .../arc4_types/deploy_config.py | 6 +- .../tests/arc4_types_integration_test.py | 55 +++++++++++++------ 3 files changed, 68 insertions(+), 35 deletions(-) diff --git a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py index e309b54..b829e85 100644 --- a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py +++ b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py @@ -1,8 +1,8 @@ # pyright: reportMissingModuleSource=false -from algopy import * -from algopy.arc4 import abimethod import typing as t +from algopy import ARC4Contract, GlobalState, UInt64, arc4, urange +from algopy.arc4 import abimethod class Arc4Types(ARC4Contract): @@ -11,7 +11,7 @@ class Arc4Types(ARC4Contract): def arc4_uint64(self, a: arc4.UInt64, b: arc4.UInt64) -> arc4.UInt64: """ This won't compile because you can't do math operations on arc4.UInt64 type. - All arc4 types are backed by byte arrays on the AVM. + All arc4 types are backed by byte arrays on the AVM. c = a + b """ @@ -19,18 +19,22 @@ def arc4_uint64(self, a: arc4.UInt64, b: arc4.UInt64) -> arc4.UInt64: c = a.native + b.native return arc4.UInt64(c) - + @abimethod() def arc4_address(self, address: arc4.Address) -> arc4.Address: - underlying_bytes = address.bytes # This will return the underlying bytes of the address. + underlying_bytes = ( + address.bytes + ) # This will return the underlying bytes of the address. - account = address.native # This will return the account type of the given address. + account = ( + address.native + ) # This will return the account type of the given address. bal = account.balance num_asset_holding = account.total_assets """ You can't return an Account type because it is a reference type. - Convert the Account type to arc4.Address type and return it. + Convert the Account type to arc4.Address type and return it. """ converted_address = arc4.Address(account) @@ -38,8 +42,10 @@ def arc4_address(self, address: arc4.Address) -> arc4.Address: return converted_address + AliasedStaticArray: t.TypeAlias = arc4.StaticArray[arc4.UInt8, t.Literal[1]] + class Arc4StaticArray(ARC4Contract): @abimethod() @@ -47,7 +53,9 @@ def arc4_static_array(self) -> None: """ You can create a static array directly from the contract. """ - static_uint32_array = arc4.StaticArray(arc4.UInt32(1), arc4.UInt32(10), arc4.UInt32(255), arc4.UInt32(128)) + static_uint32_array = arc4.StaticArray( + arc4.UInt32(1), arc4.UInt32(10), arc4.UInt32(255), arc4.UInt32(128) + ) total = UInt64(0) for uint32_item in static_uint32_array: @@ -71,20 +79,23 @@ def arc4_static_array(self) -> None: aliased_static.pop() """ + class Todo(arc4.Struct): task: arc4.String completed: arc4.Bool + Todos: t.TypeAlias = arc4.DynamicArray[Todo] + class Arc4Struct(ARC4Contract): def __init__(self) -> None: self.todos = GlobalState(Todos()) - + @abimethod() def add_todo(self, task: arc4.String) -> Todos: - todo = Todo(task=task, completed=arc4.Bool(False)) + todo = Todo(task=task, completed=arc4.Bool(False)) # noqa: FBT003 if self.todos.value.length == 0: self.todos.value = Todos(todo.copy()) @@ -92,15 +103,15 @@ def add_todo(self, task: arc4.String) -> Todos: self.todos.value.append(todo.copy()) return self.todos.value - + @abimethod() def complete_todo(self, task: arc4.String) -> None: for index in urange(self.todos.value.length): if self.todos.value[index].task == task: - self.todos.value[index].completed = arc4.Bool(True) + self.todos.value[index].completed = arc4.Bool(True) # noqa: FBT003 break - + @abimethod() def return_todo(self, task: arc4.String) -> Todo: todo_to_return: Todo @@ -111,8 +122,7 @@ def return_todo(self, task: arc4.String) -> Todo: if self.todos.value[index].task == task: todo_to_return = self.todos.value[index].copy() exist = True - + assert exist - + return todo_to_return - diff --git a/projects/python-contract-examples/smart_contracts/arc4_types/deploy_config.py b/projects/python-contract-examples/smart_contracts/arc4_types/deploy_config.py index bc1a7db..d5f6bdf 100644 --- a/projects/python-contract-examples/smart_contracts/arc4_types/deploy_config.py +++ b/projects/python-contract-examples/smart_contracts/arc4_types/deploy_config.py @@ -3,9 +3,10 @@ import algokit_utils from algosdk.v2client.algod import AlgodClient from algosdk.v2client.indexer import IndexerClient + from smart_contracts.artifacts.arc4_types.arc4_types_client import ( - Arc4TypesClient, - ) + Arc4TypesClient, +) logger = logging.getLogger(__name__) @@ -18,7 +19,6 @@ def deploy( deployer: algokit_utils.Account, ) -> None: - app_client = Arc4TypesClient( algod_client, creator=deployer, diff --git a/projects/python-contract-examples/tests/arc4_types_integration_test.py b/projects/python-contract-examples/tests/arc4_types_integration_test.py index 29ba53e..56a5e60 100644 --- a/projects/python-contract-examples/tests/arc4_types_integration_test.py +++ b/projects/python-contract-examples/tests/arc4_types_integration_test.py @@ -1,16 +1,15 @@ import pytest -from algokit_utils import TransactionParameters from algokit_utils.beta.account_manager import AddressAndSigner from algokit_utils.beta.algorand_client import ( AlgorandClient, - AssetCreateParams, - AssetOptInParams, PayParams, ) from algokit_utils.config import config from algosdk.v2client.algod import AlgodClient -from smart_contracts.artifacts.arc4_types.arc4_static_array_client import Arc4StaticArrayClient +from smart_contracts.artifacts.arc4_types.arc4_static_array_client import ( + Arc4StaticArrayClient, +) from smart_contracts.artifacts.arc4_types.arc4_struct_client import Arc4StructClient from smart_contracts.artifacts.arc4_types.arc4_types_client import Arc4TypesClient @@ -85,6 +84,7 @@ def arc4_statc_array_app_client( return client + @pytest.fixture(scope="session") def arc4_struct_app_client( algod_client: AlgodClient, creator: AddressAndSigner, algorand: AlgorandClient @@ -114,6 +114,7 @@ def arc4_struct_app_client( return client + @pytest.fixture(scope="session") def arc4_types_app_client( algod_client: AlgodClient, creator: AddressAndSigner, algorand: AlgorandClient @@ -143,6 +144,7 @@ def arc4_types_app_client( return client + def test_arc4_uint64( arc4_types_app_client: Arc4TypesClient, ) -> None: @@ -154,9 +156,9 @@ def test_arc4_uint64( # Check the result assert result.return_value == 3 + def test_arc4_address( - arc4_types_app_client: Arc4TypesClient, - creator : AddressAndSigner + arc4_types_app_client: Arc4TypesClient, creator: AddressAndSigner ) -> None: """Test the arc4_address method""" @@ -166,23 +168,44 @@ def test_arc4_address( # Check the result assert result.return_value == arc4_types_app_client.sender -def test_arc4_static_array( - arc4_statc_array_app_client: Arc4StaticArrayClient -) -> None: + +def test_arc4_static_array(arc4_statc_array_app_client: Arc4StaticArrayClient) -> None: """Test the arc4_static_array method""" # Call the arc4_static_array method arc4_statc_array_app_client.arc4_static_array() -def test_arc4_struct_add_todo( - arc4_struct_app_client: Arc4StructClient -) -> None: + +def test_arc4_struct_add_todo(arc4_struct_app_client: Arc4StructClient) -> None: """Test the add_todo method""" # Call the add_todo method - result = arc4_struct_app_client.add_todo(task="task") - print(result.return_value) + result = arc4_struct_app_client.add_todo(task="wash the dishes") - assert result.return_value[0][0] == "task" - assert result.return_value[0][1] == False + assert result.return_value[0][0] == "wash the dishes" + assert result.return_value[0][1] is False assert len(result.return_value) == 1 + + +def test_arc4_struct_complete_and_return_todo( + arc4_struct_app_client: Arc4StructClient, +) -> None: + """Test the complete_todo method""" + + # Call the add_todo method + result = arc4_struct_app_client.add_todo(task="walk my dogs") + + result = arc4_struct_app_client.return_todo(task="walk my dogs") + + # Check the result + assert result.return_value.task == "walk my dogs" + assert result.return_value.completed is False + + # Call the complete_todo method + arc4_struct_app_client.complete_todo(task="walk my dogs") + + result = arc4_struct_app_client.return_todo(task="walk my dogs") + + # Check the result + assert result.return_value.task == "walk my dogs" + assert result.return_value.completed is True From fba0008da877a6fb2981fae265bfac48431e0e1d Mon Sep 17 00:00:00 2001 From: "Chris Kim (Hyunggun)" Date: Tue, 29 Oct 2024 17:42:20 -0700 Subject: [PATCH 04/23] chore: minor updates to arc4 examples --- .../smart_contracts/arc4_types/contract.py | 30 +++-- .../arc4_types/Arc4Types.approval.teal | 44 +++++-- .../artifacts/arc4_types/Arc4Types.arc32.json | 26 ++++- .../artifacts/arc4_types/arc4_types_client.py | 107 +++++++++++++++--- .../tests/arc4_types_integration_test.py | 23 +++- 5 files changed, 184 insertions(+), 46 deletions(-) diff --git a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py index b829e85..1cf5d46 100644 --- a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py +++ b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py @@ -10,18 +10,18 @@ class Arc4Types(ARC4Contract): @abimethod() def arc4_uint64(self, a: arc4.UInt64, b: arc4.UInt64) -> arc4.UInt64: """ - This won't compile because you can't do math operations on arc4.UInt64 type. - All arc4 types are backed by byte arrays on the AVM. - c = a + b + Math operations (like a + b) are not supported on arc4.UInt64 types + since they are internally represented as byte arrays in the AVM. + Use the .native property to perform arithmetic operations. """ - # This is how you can do math operations on arc4.UInt64 type. + # Use the native integers to perform arithmetic c = a.native + b.native return arc4.UInt64(c) @abimethod() - def arc4_address(self, address: arc4.Address) -> arc4.Address: + def arc4_address_properties(self, address: arc4.Address) -> UInt64: underlying_bytes = ( address.bytes ) # This will return the underlying bytes of the address. @@ -29,8 +29,20 @@ def arc4_address(self, address: arc4.Address) -> arc4.Address: account = ( address.native ) # This will return the account type of the given address. - bal = account.balance - num_asset_holding = account.total_assets + + bal = account.balance # returns the balance of the account + total_asset = ( + account.total_assets + ) # returns the total assets held in the account + + return bal + + @abimethod() + def arc4_address_return(self, address: arc4.Address) -> arc4.Address: + + account = ( + address.native + ) # This will return the account type of the given address. """ You can't return an Account type because it is a reference type. @@ -95,7 +107,7 @@ def __init__(self) -> None: @abimethod() def add_todo(self, task: arc4.String) -> Todos: - todo = Todo(task=task, completed=arc4.Bool(False)) # noqa: FBT003 + todo = Todo(task=task, completed=arc4.Bool(False)) # noqa: FBT003 if self.todos.value.length == 0: self.todos.value = Todos(todo.copy()) @@ -109,7 +121,7 @@ def complete_todo(self, task: arc4.String) -> None: for index in urange(self.todos.value.length): if self.todos.value[index].task == task: - self.todos.value[index].completed = arc4.Bool(True) # noqa: FBT003 + self.todos.value[index].completed = arc4.Bool(True) # noqa: FBT003 break @abimethod() diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.approval.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.approval.teal index 3190f48..a4dd885 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.approval.teal +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.approval.teal @@ -9,11 +9,12 @@ smart_contracts.arc4_types.contract.Arc4Types.approval_program: __puya_arc4_router__: proto 0 1 txn NumAppArgs - bz __puya_arc4_router___bare_routing@6 + bz __puya_arc4_router___bare_routing@7 method "arc4_uint64(uint64,uint64)uint64" - method "arc4_address(address)address" + method "arc4_address_properties(address)uint64" + method "arc4_address_return(address)address" txna ApplicationArgs 0 - match __puya_arc4_router___arc4_uint64_route@2 __puya_arc4_router___arc4_address_route@3 + match __puya_arc4_router___arc4_uint64_route@2 __puya_arc4_router___arc4_address_properties_route@3 __puya_arc4_router___arc4_address_return_route@4 int 0 retsub @@ -33,14 +34,15 @@ __puya_arc4_router___arc4_uint64_route@2: int 1 retsub -__puya_arc4_router___arc4_address_route@3: +__puya_arc4_router___arc4_address_properties_route@3: txn OnCompletion ! assert // OnCompletion is NoOp txn ApplicationID assert // is not creating txna ApplicationArgs 1 - callsub arc4_address + callsub arc4_address_properties + itob byte 0x151f7c75 swap concat @@ -48,16 +50,31 @@ __puya_arc4_router___arc4_address_route@3: int 1 retsub -__puya_arc4_router___bare_routing@6: +__puya_arc4_router___arc4_address_return_route@4: txn OnCompletion - bnz __puya_arc4_router___after_if_else@10 + ! + assert // OnCompletion is NoOp + txn ApplicationID + assert // is not creating + txna ApplicationArgs 1 + callsub arc4_address_return + byte 0x151f7c75 + swap + concat + log + int 1 + retsub + +__puya_arc4_router___bare_routing@7: + txn OnCompletion + bnz __puya_arc4_router___after_if_else@11 txn ApplicationID ! assert // is creating int 1 retsub -__puya_arc4_router___after_if_else@10: +__puya_arc4_router___after_if_else@11: int 0 retsub @@ -74,16 +91,21 @@ arc4_uint64: retsub -// smart_contracts.arc4_types.contract.Arc4Types.arc4_address(address: bytes) -> bytes: -arc4_address: +// smart_contracts.arc4_types.contract.Arc4Types.arc4_address_properties(address: bytes) -> uint64: +arc4_address_properties: proto 1 1 frame_dig -1 acct_params_get AcctBalance - bury 1 assert // account funded frame_dig -1 acct_params_get AcctTotalAssets bury 1 assert // account funded + retsub + + +// smart_contracts.arc4_types.contract.Arc4Types.arc4_address_return(address: bytes) -> bytes: +arc4_address_return: + proto 1 1 frame_dig -1 retsub diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.arc32.json b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.arc32.json index f87d165..8d4ac00 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.arc32.json +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.arc32.json @@ -5,14 +5,19 @@ "no_op": "CALL" } }, - "arc4_address(address)address": { + "arc4_address_properties(address)uint64": { + "call_config": { + "no_op": "CALL" + } + }, + "arc4_address_return(address)address": { "call_config": { "no_op": "CALL" } } }, "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANgogICAgbWV0aG9kICJhcmM0X3VpbnQ2NCh1aW50NjQsdWludDY0KXVpbnQ2NCIKICAgIG1ldGhvZCAiYXJjNF9hZGRyZXNzKGFkZHJlc3MpYWRkcmVzcyIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdWludDY0X3JvdXRlQDIgX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9hZGRyZXNzX3JvdXRlQDMKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdWludDY0X3JvdXRlQDI6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAyCiAgICBjYWxsc3ViIGFyYzRfdWludDY0CiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2FkZHJlc3Nfcm91dGVAMzoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF9hZGRyZXNzCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgIGJueiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDEwCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgIQogICAgYXNzZXJ0IC8vIGlzIGNyZWF0aW5nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDEwOgogICAgaW50IDAKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X3VpbnQ2NChhOiBieXRlcywgYjogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X3VpbnQ2NDoKICAgIHByb3RvIDIgMQogICAgZnJhbWVfZGlnIC0yCiAgICBidG9pCiAgICBmcmFtZV9kaWcgLTEKICAgIGJ0b2kKICAgICsKICAgIGl0b2IKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X2FkZHJlc3MoYWRkcmVzczogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X2FkZHJlc3M6CiAgICBwcm90byAxIDEKICAgIGZyYW1lX2RpZyAtMQogICAgYWNjdF9wYXJhbXNfZ2V0IEFjY3RCYWxhbmNlCiAgICBidXJ5IDEKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgZnJhbWVfZGlnIC0xCiAgICBhY2N0X3BhcmFtc19nZXQgQWNjdFRvdGFsQXNzZXRzCiAgICBidXJ5IDEKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgZnJhbWVfZGlnIC0xCiAgICByZXRzdWIK", + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANwogICAgbWV0aG9kICJhcmM0X3VpbnQ2NCh1aW50NjQsdWludDY0KXVpbnQ2NCIKICAgIG1ldGhvZCAiYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXMoYWRkcmVzcyl1aW50NjQiCiAgICBtZXRob2QgImFyYzRfYWRkcmVzc19yZXR1cm4oYWRkcmVzcylhZGRyZXNzIgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAogICAgbWF0Y2ggX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF91aW50NjRfcm91dGVAMiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2FkZHJlc3NfcHJvcGVydGllc19yb3V0ZUAzIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYWRkcmVzc19yZXR1cm5fcm91dGVANAogICAgaW50IDAKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF91aW50NjRfcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDIKICAgIGNhbGxzdWIgYXJjNF91aW50NjQKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYWRkcmVzc19wcm9wZXJ0aWVzX3JvdXRlQDM6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICBjYWxsc3ViIGFyYzRfYWRkcmVzc19wcm9wZXJ0aWVzCiAgICBpdG9iCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2FkZHJlc3NfcmV0dXJuX3JvdXRlQDQ6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICBjYWxsc3ViIGFyYzRfYWRkcmVzc19yZXR1cm4KICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A3OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgYm56IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTEKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICAhCiAgICBhc3NlcnQgLy8gaXMgY3JlYXRpbmcKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTE6CiAgICBpbnQgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFyYzRfdWludDY0KGE6IGJ5dGVzLCBiOiBieXRlcykgLT4gYnl0ZXM6CmFyYzRfdWludDY0OgogICAgcHJvdG8gMiAxCiAgICBmcmFtZV9kaWcgLTIKICAgIGJ0b2kKICAgIGZyYW1lX2RpZyAtMQogICAgYnRvaQogICAgKwogICAgaXRvYgogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFyYzRfYWRkcmVzc19wcm9wZXJ0aWVzKGFkZHJlc3M6IGJ5dGVzKSAtPiB1aW50NjQ6CmFyYzRfYWRkcmVzc19wcm9wZXJ0aWVzOgogICAgcHJvdG8gMSAxCiAgICBmcmFtZV9kaWcgLTEKICAgIGFjY3RfcGFyYW1zX2dldCBBY2N0QmFsYW5jZQogICAgYXNzZXJ0IC8vIGFjY291bnQgZnVuZGVkCiAgICBmcmFtZV9kaWcgLTEKICAgIGFjY3RfcGFyYW1zX2dldCBBY2N0VG90YWxBc3NldHMKICAgIGJ1cnkgMQogICAgYXNzZXJ0IC8vIGFjY291bnQgZnVuZGVkCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXJjNF9hZGRyZXNzX3JldHVybihhZGRyZXNzOiBieXRlcykgLT4gYnl0ZXM6CmFyYzRfYWRkcmVzc19yZXR1cm46CiAgICBwcm90byAxIDEKICAgIGZyYW1lX2RpZyAtMQogICAgcmV0c3ViCg==", "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" }, "state": { @@ -54,10 +59,23 @@ "returns": { "type": "uint64" }, - "desc": "This won't compile because you can't do math operations on arc4.UInt64 type.\nAll arc4 types are backed by byte arrays on the AVM. c = a + b" + "desc": "Math operations (like a + b) are not supported on arc4.UInt64 types\nsince they are internally represented as byte arrays in the AVM. Use the .native property to perform arithmetic operations." + }, + { + "name": "arc4_address_properties", + "args": [ + { + "type": "address", + "name": "address" + } + ], + "readonly": false, + "returns": { + "type": "uint64" + } }, { - "name": "arc4_address", + "name": "arc4_address_return", "args": [ { "type": "address", diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_types_client.py b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_types_client.py index 68a5283..6fb99bd 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_types_client.py +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_types_client.py @@ -28,14 +28,19 @@ "no_op": "CALL" } }, - "arc4_address(address)address": { + "arc4_address_properties(address)uint64": { + "call_config": { + "no_op": "CALL" + } + }, + "arc4_address_return(address)address": { "call_config": { "no_op": "CALL" } } }, "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANgogICAgbWV0aG9kICJhcmM0X3VpbnQ2NCh1aW50NjQsdWludDY0KXVpbnQ2NCIKICAgIG1ldGhvZCAiYXJjNF9hZGRyZXNzKGFkZHJlc3MpYWRkcmVzcyIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdWludDY0X3JvdXRlQDIgX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9hZGRyZXNzX3JvdXRlQDMKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdWludDY0X3JvdXRlQDI6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAyCiAgICBjYWxsc3ViIGFyYzRfdWludDY0CiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2FkZHJlc3Nfcm91dGVAMzoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF9hZGRyZXNzCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgIGJueiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDEwCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgIQogICAgYXNzZXJ0IC8vIGlzIGNyZWF0aW5nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDEwOgogICAgaW50IDAKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X3VpbnQ2NChhOiBieXRlcywgYjogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X3VpbnQ2NDoKICAgIHByb3RvIDIgMQogICAgZnJhbWVfZGlnIC0yCiAgICBidG9pCiAgICBmcmFtZV9kaWcgLTEKICAgIGJ0b2kKICAgICsKICAgIGl0b2IKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X2FkZHJlc3MoYWRkcmVzczogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X2FkZHJlc3M6CiAgICBwcm90byAxIDEKICAgIGZyYW1lX2RpZyAtMQogICAgYWNjdF9wYXJhbXNfZ2V0IEFjY3RCYWxhbmNlCiAgICBidXJ5IDEKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgZnJhbWVfZGlnIC0xCiAgICBhY2N0X3BhcmFtc19nZXQgQWNjdFRvdGFsQXNzZXRzCiAgICBidXJ5IDEKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgZnJhbWVfZGlnIC0xCiAgICByZXRzdWIK", + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANwogICAgbWV0aG9kICJhcmM0X3VpbnQ2NCh1aW50NjQsdWludDY0KXVpbnQ2NCIKICAgIG1ldGhvZCAiYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXMoYWRkcmVzcyl1aW50NjQiCiAgICBtZXRob2QgImFyYzRfYWRkcmVzc19yZXR1cm4oYWRkcmVzcylhZGRyZXNzIgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAogICAgbWF0Y2ggX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF91aW50NjRfcm91dGVAMiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2FkZHJlc3NfcHJvcGVydGllc19yb3V0ZUAzIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYWRkcmVzc19yZXR1cm5fcm91dGVANAogICAgaW50IDAKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF91aW50NjRfcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDIKICAgIGNhbGxzdWIgYXJjNF91aW50NjQKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYWRkcmVzc19wcm9wZXJ0aWVzX3JvdXRlQDM6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICBjYWxsc3ViIGFyYzRfYWRkcmVzc19wcm9wZXJ0aWVzCiAgICBpdG9iCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2FkZHJlc3NfcmV0dXJuX3JvdXRlQDQ6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICBjYWxsc3ViIGFyYzRfYWRkcmVzc19yZXR1cm4KICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A3OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgYm56IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTEKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICAhCiAgICBhc3NlcnQgLy8gaXMgY3JlYXRpbmcKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTE6CiAgICBpbnQgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFyYzRfdWludDY0KGE6IGJ5dGVzLCBiOiBieXRlcykgLT4gYnl0ZXM6CmFyYzRfdWludDY0OgogICAgcHJvdG8gMiAxCiAgICBmcmFtZV9kaWcgLTIKICAgIGJ0b2kKICAgIGZyYW1lX2RpZyAtMQogICAgYnRvaQogICAgKwogICAgaXRvYgogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFyYzRfYWRkcmVzc19wcm9wZXJ0aWVzKGFkZHJlc3M6IGJ5dGVzKSAtPiB1aW50NjQ6CmFyYzRfYWRkcmVzc19wcm9wZXJ0aWVzOgogICAgcHJvdG8gMSAxCiAgICBmcmFtZV9kaWcgLTEKICAgIGFjY3RfcGFyYW1zX2dldCBBY2N0QmFsYW5jZQogICAgYXNzZXJ0IC8vIGFjY291bnQgZnVuZGVkCiAgICBmcmFtZV9kaWcgLTEKICAgIGFjY3RfcGFyYW1zX2dldCBBY2N0VG90YWxBc3NldHMKICAgIGJ1cnkgMQogICAgYXNzZXJ0IC8vIGFjY291bnQgZnVuZGVkCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXJjNF9hZGRyZXNzX3JldHVybihhZGRyZXNzOiBieXRlcykgLT4gYnl0ZXM6CmFyYzRfYWRkcmVzc19yZXR1cm46CiAgICBwcm90byAxIDEKICAgIGZyYW1lX2RpZyAtMQogICAgcmV0c3ViCg==", "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" }, "state": { @@ -76,10 +81,22 @@ "returns": { "type": "uint64" }, - "desc": "This won't compile because you can't do math operations on arc4.UInt64 type.\nAll arc4 types are backed by byte arrays on the AVM. c = a + b" + "desc": "Math operations (like a + b) are not supported on arc4.UInt64 types\nsince they are internally represented as byte arrays in the AVM. Use the .native property to perform arithmetic operations." + }, + { + "name": "arc4_address_properties", + "args": [ + { + "type": "address", + "name": "address" + } + ], + "returns": { + "type": "uint64" + } }, { - "name": "arc4_address", + "name": "arc4_address_return", "args": [ { "type": "address", @@ -172,8 +189,8 @@ def _convert_deploy_args( @dataclasses.dataclass(kw_only=True) class Arc4Uint64Args(_ArgsBase[int]): - """This won't compile because you can't do math operations on arc4.UInt64 type. - All arc4 types are backed by byte arrays on the AVM. c = a + b""" + """Math operations (like a + b) are not supported on arc4.UInt64 types + since they are internally represented as byte arrays in the AVM. Use the .native property to perform arithmetic operations.""" a: int b: int @@ -184,12 +201,21 @@ def method() -> str: @dataclasses.dataclass(kw_only=True) -class Arc4AddressArgs(_ArgsBase[str]): +class Arc4AddressPropertiesArgs(_ArgsBase[int]): address: str @staticmethod def method() -> str: - return "arc4_address(address)address" + return "arc4_address_properties(address)uint64" + + +@dataclasses.dataclass(kw_only=True) +class Arc4AddressReturnArgs(_ArgsBase[str]): + address: str + + @staticmethod + def method() -> str: + return "arc4_address_return(address)address" @dataclasses.dataclass(kw_only=True) @@ -230,8 +256,8 @@ def arc4_uint64( b: int, transaction_parameters: algokit_utils.TransactionParameters | None = None, ) -> "Composer": - """This won't compile because you can't do math operations on arc4.UInt64 type. - All arc4 types are backed by byte arrays on the AVM. c = a + b + """Math operations (like a + b) are not supported on arc4.UInt64 types + since they are internally represented as byte arrays in the AVM. Use the .native property to perform arithmetic operations. Adds a call to `arc4_uint64(uint64,uint64)uint64` ABI method @@ -252,19 +278,42 @@ def arc4_uint64( ) return self - def arc4_address( + def arc4_address_properties( self, *, address: str, transaction_parameters: algokit_utils.TransactionParameters | None = None, ) -> "Composer": - """Adds a call to `arc4_address(address)address` ABI method + """Adds a call to `arc4_address_properties(address)uint64` ABI method :param str address: The `address` ABI parameter :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters :returns Composer: This Composer instance""" - args = Arc4AddressArgs( + args = Arc4AddressPropertiesArgs( + address=address, + ) + self.app_client.compose_call( + self.atc, + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return self + + def arc4_address_return( + self, + *, + address: str, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> "Composer": + """Adds a call to `arc4_address_return(address)address` ABI method + + :param str address: The `address` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + args = Arc4AddressReturnArgs( address=address, ) self.app_client.compose_call( @@ -441,8 +490,8 @@ def arc4_uint64( b: int, transaction_parameters: algokit_utils.TransactionParameters | None = None, ) -> algokit_utils.ABITransactionResponse[int]: - """This won't compile because you can't do math operations on arc4.UInt64 type. - All arc4 types are backed by byte arrays on the AVM. c = a + b + """Math operations (like a + b) are not supported on arc4.UInt64 types + since they are internally represented as byte arrays in the AVM. Use the .native property to perform arithmetic operations. Calls `arc4_uint64(uint64,uint64)uint64` ABI method @@ -462,19 +511,41 @@ def arc4_uint64( ) return result - def arc4_address( + def arc4_address_properties( + self, + *, + address: str, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> algokit_utils.ABITransactionResponse[int]: + """Calls `arc4_address_properties(address)uint64` ABI method + + :param str address: The `address` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.ABITransactionResponse[int]: The result of the transaction""" + + args = Arc4AddressPropertiesArgs( + address=address, + ) + result = self.app_client.call( + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return result + + def arc4_address_return( self, *, address: str, transaction_parameters: algokit_utils.TransactionParameters | None = None, ) -> algokit_utils.ABITransactionResponse[str]: - """Calls `arc4_address(address)address` ABI method + """Calls `arc4_address_return(address)address` ABI method :param str address: The `address` ABI parameter :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters :returns algokit_utils.ABITransactionResponse[str]: The result of the transaction""" - args = Arc4AddressArgs( + args = Arc4AddressReturnArgs( address=address, ) result = self.app_client.call( diff --git a/projects/python-contract-examples/tests/arc4_types_integration_test.py b/projects/python-contract-examples/tests/arc4_types_integration_test.py index 56a5e60..ece30bf 100644 --- a/projects/python-contract-examples/tests/arc4_types_integration_test.py +++ b/projects/python-contract-examples/tests/arc4_types_integration_test.py @@ -157,16 +157,31 @@ def test_arc4_uint64( assert result.return_value == 3 -def test_arc4_address( +def test_arc4_address_properties( + arc4_types_app_client: Arc4TypesClient, + creator: AddressAndSigner, + algorand: AlgorandClient, +) -> None: + """Test the arc4_address_properties method""" + + # Call the arc4_address method + result = arc4_types_app_client.arc4_address_properties(address=creator.address) + + creator_info = algorand.account.get_information(creator.address) + + assert result.return_value == creator_info["amount"] + + +def test_arc4_address_return( arc4_types_app_client: Arc4TypesClient, creator: AddressAndSigner ) -> None: - """Test the arc4_address method""" + """Test the arc4_address_return method""" # Call the arc4_address method - result = arc4_types_app_client.arc4_address(address=creator.address) + result = arc4_types_app_client.arc4_address_return(address=creator.address) # Check the result - assert result.return_value == arc4_types_app_client.sender + assert result.return_value == creator.address def test_arc4_static_array(arc4_statc_array_app_client: Arc4StaticArrayClient) -> None: From 1d7f847b72a4a5df4317357dfee50971befd5e6c Mon Sep 17 00:00:00 2001 From: CiottiGiorgio Date: Mon, 4 Nov 2024 16:48:10 +0100 Subject: [PATCH 05/23] added uintN example. --- .../smart_contracts/arc4_types/contract.py | 17 +++ .../arc4_types/Arc4Types.approval.teal | 71 +++++++++-- .../artifacts/arc4_types/Arc4Types.arc32.json | 33 ++++- .../artifacts/arc4_types/arc4_types_client.py | 116 +++++++++++++++++- .../tests/arc4_types_integration_test.py | 10 ++ 5 files changed, 238 insertions(+), 9 deletions(-) diff --git a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py index 1cf5d46..28b5505 100644 --- a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py +++ b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py @@ -20,6 +20,23 @@ def arc4_uint64(self, a: arc4.UInt64, b: arc4.UInt64) -> arc4.UInt64: return arc4.UInt64(c) + @abimethod() + def arc4_uint_n( + self, a: arc4.UInt8, b: arc4.UInt16, c: arc4.UInt32, d: arc4.UInt64 + ) -> arc4.UInt64: + """ + The encoding of arc4 integers will be smaller if it uses fewer bits. + Ultimately, they are all represented with native UInt64. + """ + assert a.bytes.length == 1 + assert b.bytes.length == 2 + assert c.bytes.length == 4 + assert d.bytes.length == 8 + + total = a.native + b.native + c.native + d.native + + return arc4.UInt64(total) + @abimethod() def arc4_address_properties(self, address: arc4.Address) -> UInt64: underlying_bytes = ( diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.approval.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.approval.teal index a4dd885..29f91fc 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.approval.teal +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.approval.teal @@ -9,12 +9,13 @@ smart_contracts.arc4_types.contract.Arc4Types.approval_program: __puya_arc4_router__: proto 0 1 txn NumAppArgs - bz __puya_arc4_router___bare_routing@7 + bz __puya_arc4_router___bare_routing@8 method "arc4_uint64(uint64,uint64)uint64" + method "arc4_uint_n(uint8,uint16,uint32,uint64)uint64" method "arc4_address_properties(address)uint64" method "arc4_address_return(address)address" txna ApplicationArgs 0 - match __puya_arc4_router___arc4_uint64_route@2 __puya_arc4_router___arc4_address_properties_route@3 __puya_arc4_router___arc4_address_return_route@4 + match __puya_arc4_router___arc4_uint64_route@2 __puya_arc4_router___arc4_uint_n_route@3 __puya_arc4_router___arc4_address_properties_route@4 __puya_arc4_router___arc4_address_return_route@5 int 0 retsub @@ -34,7 +35,25 @@ __puya_arc4_router___arc4_uint64_route@2: int 1 retsub -__puya_arc4_router___arc4_address_properties_route@3: +__puya_arc4_router___arc4_uint_n_route@3: + txn OnCompletion + ! + assert // OnCompletion is NoOp + txn ApplicationID + assert // is not creating + txna ApplicationArgs 1 + txna ApplicationArgs 2 + txna ApplicationArgs 3 + txna ApplicationArgs 4 + callsub arc4_uint_n + byte 0x151f7c75 + swap + concat + log + int 1 + retsub + +__puya_arc4_router___arc4_address_properties_route@4: txn OnCompletion ! assert // OnCompletion is NoOp @@ -50,7 +69,7 @@ __puya_arc4_router___arc4_address_properties_route@3: int 1 retsub -__puya_arc4_router___arc4_address_return_route@4: +__puya_arc4_router___arc4_address_return_route@5: txn OnCompletion ! assert // OnCompletion is NoOp @@ -65,16 +84,16 @@ __puya_arc4_router___arc4_address_return_route@4: int 1 retsub -__puya_arc4_router___bare_routing@7: +__puya_arc4_router___bare_routing@8: txn OnCompletion - bnz __puya_arc4_router___after_if_else@11 + bnz __puya_arc4_router___after_if_else@12 txn ApplicationID ! assert // is creating int 1 retsub -__puya_arc4_router___after_if_else@11: +__puya_arc4_router___after_if_else@12: int 0 retsub @@ -91,6 +110,44 @@ arc4_uint64: retsub +// smart_contracts.arc4_types.contract.Arc4Types.arc4_uint_n(a: bytes, b: bytes, c: bytes, d: bytes) -> bytes: +arc4_uint_n: + proto 4 1 + frame_dig -4 + len + int 1 + == + assert + frame_dig -3 + len + int 2 + == + assert + frame_dig -2 + len + int 4 + == + assert + frame_dig -1 + len + int 8 + == + assert + frame_dig -4 + btoi + frame_dig -3 + btoi + + + frame_dig -2 + btoi + + + frame_dig -1 + btoi + + + itob + retsub + + // smart_contracts.arc4_types.contract.Arc4Types.arc4_address_properties(address: bytes) -> uint64: arc4_address_properties: proto 1 1 diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.arc32.json b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.arc32.json index 8d4ac00..591eb5f 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.arc32.json +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.arc32.json @@ -5,6 +5,11 @@ "no_op": "CALL" } }, + "arc4_uint_n(uint8,uint16,uint32,uint64)uint64": { + "call_config": { + "no_op": "CALL" + } + }, "arc4_address_properties(address)uint64": { "call_config": { "no_op": "CALL" @@ -17,7 +22,7 @@ } }, "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANwogICAgbWV0aG9kICJhcmM0X3VpbnQ2NCh1aW50NjQsdWludDY0KXVpbnQ2NCIKICAgIG1ldGhvZCAiYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXMoYWRkcmVzcyl1aW50NjQiCiAgICBtZXRob2QgImFyYzRfYWRkcmVzc19yZXR1cm4oYWRkcmVzcylhZGRyZXNzIgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAogICAgbWF0Y2ggX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF91aW50NjRfcm91dGVAMiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2FkZHJlc3NfcHJvcGVydGllc19yb3V0ZUAzIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYWRkcmVzc19yZXR1cm5fcm91dGVANAogICAgaW50IDAKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF91aW50NjRfcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDIKICAgIGNhbGxzdWIgYXJjNF91aW50NjQKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYWRkcmVzc19wcm9wZXJ0aWVzX3JvdXRlQDM6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICBjYWxsc3ViIGFyYzRfYWRkcmVzc19wcm9wZXJ0aWVzCiAgICBpdG9iCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2FkZHJlc3NfcmV0dXJuX3JvdXRlQDQ6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICBjYWxsc3ViIGFyYzRfYWRkcmVzc19yZXR1cm4KICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A3OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgYm56IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTEKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICAhCiAgICBhc3NlcnQgLy8gaXMgY3JlYXRpbmcKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTE6CiAgICBpbnQgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFyYzRfdWludDY0KGE6IGJ5dGVzLCBiOiBieXRlcykgLT4gYnl0ZXM6CmFyYzRfdWludDY0OgogICAgcHJvdG8gMiAxCiAgICBmcmFtZV9kaWcgLTIKICAgIGJ0b2kKICAgIGZyYW1lX2RpZyAtMQogICAgYnRvaQogICAgKwogICAgaXRvYgogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFyYzRfYWRkcmVzc19wcm9wZXJ0aWVzKGFkZHJlc3M6IGJ5dGVzKSAtPiB1aW50NjQ6CmFyYzRfYWRkcmVzc19wcm9wZXJ0aWVzOgogICAgcHJvdG8gMSAxCiAgICBmcmFtZV9kaWcgLTEKICAgIGFjY3RfcGFyYW1zX2dldCBBY2N0QmFsYW5jZQogICAgYXNzZXJ0IC8vIGFjY291bnQgZnVuZGVkCiAgICBmcmFtZV9kaWcgLTEKICAgIGFjY3RfcGFyYW1zX2dldCBBY2N0VG90YWxBc3NldHMKICAgIGJ1cnkgMQogICAgYXNzZXJ0IC8vIGFjY291bnQgZnVuZGVkCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXJjNF9hZGRyZXNzX3JldHVybihhZGRyZXNzOiBieXRlcykgLT4gYnl0ZXM6CmFyYzRfYWRkcmVzc19yZXR1cm46CiAgICBwcm90byAxIDEKICAgIGZyYW1lX2RpZyAtMQogICAgcmV0c3ViCg==", + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdAOAogICAgbWV0aG9kICJhcmM0X3VpbnQ2NCh1aW50NjQsdWludDY0KXVpbnQ2NCIKICAgIG1ldGhvZCAiYXJjNF91aW50X24odWludDgsdWludDE2LHVpbnQzMix1aW50NjQpdWludDY0IgogICAgbWV0aG9kICJhcmM0X2FkZHJlc3NfcHJvcGVydGllcyhhZGRyZXNzKXVpbnQ2NCIKICAgIG1ldGhvZCAiYXJjNF9hZGRyZXNzX3JldHVybihhZGRyZXNzKWFkZHJlc3MiCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAwCiAgICBtYXRjaCBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X3VpbnQ2NF9yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdWludF9uX3JvdXRlQDMgX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXNfcm91dGVANCBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2FkZHJlc3NfcmV0dXJuX3JvdXRlQDUKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdWludDY0X3JvdXRlQDI6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAyCiAgICBjYWxsc3ViIGFyYzRfdWludDY0CiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X3VpbnRfbl9yb3V0ZUAzOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgNAogICAgY2FsbHN1YiBhcmM0X3VpbnRfbgogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXNfcm91dGVANDoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXMKICAgIGl0b2IKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYWRkcmVzc19yZXR1cm5fcm91dGVANToKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF9hZGRyZXNzX3JldHVybgogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDg6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBibnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMgogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgICEKICAgIGFzc2VydCAvLyBpcyBjcmVhdGluZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMjoKICAgIGludCAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXJjNF91aW50NjQoYTogYnl0ZXMsIGI6IGJ5dGVzKSAtPiBieXRlczoKYXJjNF91aW50NjQ6CiAgICBwcm90byAyIDEKICAgIGZyYW1lX2RpZyAtMgogICAgYnRvaQogICAgZnJhbWVfZGlnIC0xCiAgICBidG9pCiAgICArCiAgICBpdG9iCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXJjNF91aW50X24oYTogYnl0ZXMsIGI6IGJ5dGVzLCBjOiBieXRlcywgZDogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X3VpbnRfbjoKICAgIHByb3RvIDQgMQogICAgZnJhbWVfZGlnIC00CiAgICBsZW4KICAgIGludCAxCiAgICA9PQogICAgYXNzZXJ0CiAgICBmcmFtZV9kaWcgLTMKICAgIGxlbgogICAgaW50IDIKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMgogICAgbGVuCiAgICBpbnQgNAogICAgPT0KICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0xCiAgICBsZW4KICAgIGludCA4CiAgICA9PQogICAgYXNzZXJ0CiAgICBmcmFtZV9kaWcgLTQKICAgIGJ0b2kKICAgIGZyYW1lX2RpZyAtMwogICAgYnRvaQogICAgKwogICAgZnJhbWVfZGlnIC0yCiAgICBidG9pCiAgICArCiAgICBmcmFtZV9kaWcgLTEKICAgIGJ0b2kKICAgICsKICAgIGl0b2IKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X2FkZHJlc3NfcHJvcGVydGllcyhhZGRyZXNzOiBieXRlcykgLT4gdWludDY0OgphcmM0X2FkZHJlc3NfcHJvcGVydGllczoKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBhY2N0X3BhcmFtc19nZXQgQWNjdEJhbGFuY2UKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgZnJhbWVfZGlnIC0xCiAgICBhY2N0X3BhcmFtc19nZXQgQWNjdFRvdGFsQXNzZXRzCiAgICBidXJ5IDEKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFyYzRfYWRkcmVzc19yZXR1cm4oYWRkcmVzczogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X2FkZHJlc3NfcmV0dXJuOgogICAgcHJvdG8gMSAxCiAgICBmcmFtZV9kaWcgLTEKICAgIHJldHN1Ygo=", "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" }, "state": { @@ -61,6 +66,32 @@ }, "desc": "Math operations (like a + b) are not supported on arc4.UInt64 types\nsince they are internally represented as byte arrays in the AVM. Use the .native property to perform arithmetic operations." }, + { + "name": "arc4_uint_n", + "args": [ + { + "type": "uint8", + "name": "a" + }, + { + "type": "uint16", + "name": "b" + }, + { + "type": "uint32", + "name": "c" + }, + { + "type": "uint64", + "name": "d" + } + ], + "readonly": false, + "returns": { + "type": "uint64" + }, + "desc": "The encoding of arc4 integers will be smaller if it uses fewer bits.\nUltimately, they are all represented with native UInt64." + }, { "name": "arc4_address_properties", "args": [ diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_types_client.py b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_types_client.py index 6fb99bd..ae3314a 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_types_client.py +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_types_client.py @@ -28,6 +28,11 @@ "no_op": "CALL" } }, + "arc4_uint_n(uint8,uint16,uint32,uint64)uint64": { + "call_config": { + "no_op": "CALL" + } + }, "arc4_address_properties(address)uint64": { "call_config": { "no_op": "CALL" @@ -40,7 +45,7 @@ } }, "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANwogICAgbWV0aG9kICJhcmM0X3VpbnQ2NCh1aW50NjQsdWludDY0KXVpbnQ2NCIKICAgIG1ldGhvZCAiYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXMoYWRkcmVzcyl1aW50NjQiCiAgICBtZXRob2QgImFyYzRfYWRkcmVzc19yZXR1cm4oYWRkcmVzcylhZGRyZXNzIgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAogICAgbWF0Y2ggX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF91aW50NjRfcm91dGVAMiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2FkZHJlc3NfcHJvcGVydGllc19yb3V0ZUAzIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYWRkcmVzc19yZXR1cm5fcm91dGVANAogICAgaW50IDAKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF91aW50NjRfcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDIKICAgIGNhbGxzdWIgYXJjNF91aW50NjQKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYWRkcmVzc19wcm9wZXJ0aWVzX3JvdXRlQDM6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICBjYWxsc3ViIGFyYzRfYWRkcmVzc19wcm9wZXJ0aWVzCiAgICBpdG9iCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2FkZHJlc3NfcmV0dXJuX3JvdXRlQDQ6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICBjYWxsc3ViIGFyYzRfYWRkcmVzc19yZXR1cm4KICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A3OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgYm56IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTEKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICAhCiAgICBhc3NlcnQgLy8gaXMgY3JlYXRpbmcKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTE6CiAgICBpbnQgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFyYzRfdWludDY0KGE6IGJ5dGVzLCBiOiBieXRlcykgLT4gYnl0ZXM6CmFyYzRfdWludDY0OgogICAgcHJvdG8gMiAxCiAgICBmcmFtZV9kaWcgLTIKICAgIGJ0b2kKICAgIGZyYW1lX2RpZyAtMQogICAgYnRvaQogICAgKwogICAgaXRvYgogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFyYzRfYWRkcmVzc19wcm9wZXJ0aWVzKGFkZHJlc3M6IGJ5dGVzKSAtPiB1aW50NjQ6CmFyYzRfYWRkcmVzc19wcm9wZXJ0aWVzOgogICAgcHJvdG8gMSAxCiAgICBmcmFtZV9kaWcgLTEKICAgIGFjY3RfcGFyYW1zX2dldCBBY2N0QmFsYW5jZQogICAgYXNzZXJ0IC8vIGFjY291bnQgZnVuZGVkCiAgICBmcmFtZV9kaWcgLTEKICAgIGFjY3RfcGFyYW1zX2dldCBBY2N0VG90YWxBc3NldHMKICAgIGJ1cnkgMQogICAgYXNzZXJ0IC8vIGFjY291bnQgZnVuZGVkCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXJjNF9hZGRyZXNzX3JldHVybihhZGRyZXNzOiBieXRlcykgLT4gYnl0ZXM6CmFyYzRfYWRkcmVzc19yZXR1cm46CiAgICBwcm90byAxIDEKICAgIGZyYW1lX2RpZyAtMQogICAgcmV0c3ViCg==", + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdAOAogICAgbWV0aG9kICJhcmM0X3VpbnQ2NCh1aW50NjQsdWludDY0KXVpbnQ2NCIKICAgIG1ldGhvZCAiYXJjNF91aW50X24odWludDgsdWludDE2LHVpbnQzMix1aW50NjQpdWludDY0IgogICAgbWV0aG9kICJhcmM0X2FkZHJlc3NfcHJvcGVydGllcyhhZGRyZXNzKXVpbnQ2NCIKICAgIG1ldGhvZCAiYXJjNF9hZGRyZXNzX3JldHVybihhZGRyZXNzKWFkZHJlc3MiCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAwCiAgICBtYXRjaCBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X3VpbnQ2NF9yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdWludF9uX3JvdXRlQDMgX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXNfcm91dGVANCBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2FkZHJlc3NfcmV0dXJuX3JvdXRlQDUKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdWludDY0X3JvdXRlQDI6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAyCiAgICBjYWxsc3ViIGFyYzRfdWludDY0CiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X3VpbnRfbl9yb3V0ZUAzOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgNAogICAgY2FsbHN1YiBhcmM0X3VpbnRfbgogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXNfcm91dGVANDoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXMKICAgIGl0b2IKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYWRkcmVzc19yZXR1cm5fcm91dGVANToKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF9hZGRyZXNzX3JldHVybgogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDg6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBibnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMgogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgICEKICAgIGFzc2VydCAvLyBpcyBjcmVhdGluZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMjoKICAgIGludCAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXJjNF91aW50NjQoYTogYnl0ZXMsIGI6IGJ5dGVzKSAtPiBieXRlczoKYXJjNF91aW50NjQ6CiAgICBwcm90byAyIDEKICAgIGZyYW1lX2RpZyAtMgogICAgYnRvaQogICAgZnJhbWVfZGlnIC0xCiAgICBidG9pCiAgICArCiAgICBpdG9iCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXJjNF91aW50X24oYTogYnl0ZXMsIGI6IGJ5dGVzLCBjOiBieXRlcywgZDogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X3VpbnRfbjoKICAgIHByb3RvIDQgMQogICAgZnJhbWVfZGlnIC00CiAgICBsZW4KICAgIGludCAxCiAgICA9PQogICAgYXNzZXJ0CiAgICBmcmFtZV9kaWcgLTMKICAgIGxlbgogICAgaW50IDIKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMgogICAgbGVuCiAgICBpbnQgNAogICAgPT0KICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0xCiAgICBsZW4KICAgIGludCA4CiAgICA9PQogICAgYXNzZXJ0CiAgICBmcmFtZV9kaWcgLTQKICAgIGJ0b2kKICAgIGZyYW1lX2RpZyAtMwogICAgYnRvaQogICAgKwogICAgZnJhbWVfZGlnIC0yCiAgICBidG9pCiAgICArCiAgICBmcmFtZV9kaWcgLTEKICAgIGJ0b2kKICAgICsKICAgIGl0b2IKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X2FkZHJlc3NfcHJvcGVydGllcyhhZGRyZXNzOiBieXRlcykgLT4gdWludDY0OgphcmM0X2FkZHJlc3NfcHJvcGVydGllczoKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBhY2N0X3BhcmFtc19nZXQgQWNjdEJhbGFuY2UKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgZnJhbWVfZGlnIC0xCiAgICBhY2N0X3BhcmFtc19nZXQgQWNjdFRvdGFsQXNzZXRzCiAgICBidXJ5IDEKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFyYzRfYWRkcmVzc19yZXR1cm4oYWRkcmVzczogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X2FkZHJlc3NfcmV0dXJuOgogICAgcHJvdG8gMSAxCiAgICBmcmFtZV9kaWcgLTEKICAgIHJldHN1Ygo=", "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" }, "state": { @@ -83,6 +88,31 @@ }, "desc": "Math operations (like a + b) are not supported on arc4.UInt64 types\nsince they are internally represented as byte arrays in the AVM. Use the .native property to perform arithmetic operations." }, + { + "name": "arc4_uint_n", + "args": [ + { + "type": "uint8", + "name": "a" + }, + { + "type": "uint16", + "name": "b" + }, + { + "type": "uint32", + "name": "c" + }, + { + "type": "uint64", + "name": "d" + } + ], + "returns": { + "type": "uint64" + }, + "desc": "The encoding of arc4 integers will be smaller if it uses fewer bits.\nUltimately, they are all represented with native UInt64." + }, { "name": "arc4_address_properties", "args": [ @@ -200,6 +230,21 @@ def method() -> str: return "arc4_uint64(uint64,uint64)uint64" +@dataclasses.dataclass(kw_only=True) +class Arc4UintNArgs(_ArgsBase[int]): + """The encoding of arc4 integers will be smaller if it uses fewer bits. + Ultimately, they are all represented with native UInt64.""" + + a: int + b: int + c: int + d: int + + @staticmethod + def method() -> str: + return "arc4_uint_n(uint8,uint16,uint32,uint64)uint64" + + @dataclasses.dataclass(kw_only=True) class Arc4AddressPropertiesArgs(_ArgsBase[int]): address: str @@ -278,6 +323,41 @@ def arc4_uint64( ) return self + def arc4_uint_n( + self, + *, + a: int, + b: int, + c: int, + d: int, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> "Composer": + """The encoding of arc4 integers will be smaller if it uses fewer bits. + Ultimately, they are all represented with native UInt64. + + Adds a call to `arc4_uint_n(uint8,uint16,uint32,uint64)uint64` ABI method + + :param int a: The `a` ABI parameter + :param int b: The `b` ABI parameter + :param int c: The `c` ABI parameter + :param int d: The `d` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + args = Arc4UintNArgs( + a=a, + b=b, + c=c, + d=d, + ) + self.app_client.compose_call( + self.atc, + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return self + def arc4_address_properties( self, *, @@ -511,6 +591,40 @@ def arc4_uint64( ) return result + def arc4_uint_n( + self, + *, + a: int, + b: int, + c: int, + d: int, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> algokit_utils.ABITransactionResponse[int]: + """The encoding of arc4 integers will be smaller if it uses fewer bits. + Ultimately, they are all represented with native UInt64. + + Calls `arc4_uint_n(uint8,uint16,uint32,uint64)uint64` ABI method + + :param int a: The `a` ABI parameter + :param int b: The `b` ABI parameter + :param int c: The `c` ABI parameter + :param int d: The `d` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.ABITransactionResponse[int]: The result of the transaction""" + + args = Arc4UintNArgs( + a=a, + b=b, + c=c, + d=d, + ) + result = self.app_client.call( + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return result + def arc4_address_properties( self, *, diff --git a/projects/python-contract-examples/tests/arc4_types_integration_test.py b/projects/python-contract-examples/tests/arc4_types_integration_test.py index ece30bf..7bedabe 100644 --- a/projects/python-contract-examples/tests/arc4_types_integration_test.py +++ b/projects/python-contract-examples/tests/arc4_types_integration_test.py @@ -157,6 +157,16 @@ def test_arc4_uint64( assert result.return_value == 3 +def test_arc4_uint_n( + arc4_types_app_client: Arc4TypesClient, +) -> None: + """Test the arc4_uint_n method""" + + result = arc4_types_app_client.arc4_uint_n(a=100, b=1_000, c=100_000, d=100_000) + + assert result.return_value == 201_100 + + def test_arc4_address_properties( arc4_types_app_client: Arc4TypesClient, creator: AddressAndSigner, From 227a40620e2a401ab31a0b801968cf4c7561f43a Mon Sep 17 00:00:00 2001 From: CiottiGiorgio Date: Mon, 4 Nov 2024 16:55:26 +0100 Subject: [PATCH 06/23] added biguintN example. --- .../smart_contracts/arc4_types/contract.py | 14 +++ .../arc4_types/Arc4Types.approval.teal | 66 +++++++++-- .../artifacts/arc4_types/Arc4Types.arc32.json | 29 ++++- .../artifacts/arc4_types/arc4_types_client.py | 105 +++++++++++++++++- .../tests/arc4_types_integration_test.py | 10 ++ 5 files changed, 215 insertions(+), 9 deletions(-) diff --git a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py index 28b5505..9d0e886 100644 --- a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py +++ b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py @@ -37,6 +37,20 @@ def arc4_uint_n( return arc4.UInt64(total) + @abimethod() + def arc4_biguint_n(self, a: arc4.UInt128, b: arc4.UInt256, c: arc4.UInt512) -> arc4.UInt512: + """ + Integers with larger bit size are supported up to 512 bits. + Ultimately, they are all represented with native BigUInt. + """ + assert a.bytes.length == 16 + assert b.bytes.length == 32 + assert c.bytes.length == 64 + + total = a.native + b.native + c.native + + return arc4.UInt512(total) + @abimethod() def arc4_address_properties(self, address: arc4.Address) -> UInt64: underlying_bytes = ( diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.approval.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.approval.teal index 29f91fc..db20a79 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.approval.teal +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.approval.teal @@ -9,13 +9,14 @@ smart_contracts.arc4_types.contract.Arc4Types.approval_program: __puya_arc4_router__: proto 0 1 txn NumAppArgs - bz __puya_arc4_router___bare_routing@8 + bz __puya_arc4_router___bare_routing@9 method "arc4_uint64(uint64,uint64)uint64" method "arc4_uint_n(uint8,uint16,uint32,uint64)uint64" + method "arc4_biguint_n(uint128,uint256,uint512)uint512" method "arc4_address_properties(address)uint64" method "arc4_address_return(address)address" txna ApplicationArgs 0 - match __puya_arc4_router___arc4_uint64_route@2 __puya_arc4_router___arc4_uint_n_route@3 __puya_arc4_router___arc4_address_properties_route@4 __puya_arc4_router___arc4_address_return_route@5 + match __puya_arc4_router___arc4_uint64_route@2 __puya_arc4_router___arc4_uint_n_route@3 __puya_arc4_router___arc4_biguint_n_route@4 __puya_arc4_router___arc4_address_properties_route@5 __puya_arc4_router___arc4_address_return_route@6 int 0 retsub @@ -53,7 +54,24 @@ __puya_arc4_router___arc4_uint_n_route@3: int 1 retsub -__puya_arc4_router___arc4_address_properties_route@4: +__puya_arc4_router___arc4_biguint_n_route@4: + txn OnCompletion + ! + assert // OnCompletion is NoOp + txn ApplicationID + assert // is not creating + txna ApplicationArgs 1 + txna ApplicationArgs 2 + txna ApplicationArgs 3 + callsub arc4_biguint_n + byte 0x151f7c75 + swap + concat + log + int 1 + retsub + +__puya_arc4_router___arc4_address_properties_route@5: txn OnCompletion ! assert // OnCompletion is NoOp @@ -69,7 +87,7 @@ __puya_arc4_router___arc4_address_properties_route@4: int 1 retsub -__puya_arc4_router___arc4_address_return_route@5: +__puya_arc4_router___arc4_address_return_route@6: txn OnCompletion ! assert // OnCompletion is NoOp @@ -84,16 +102,16 @@ __puya_arc4_router___arc4_address_return_route@5: int 1 retsub -__puya_arc4_router___bare_routing@8: +__puya_arc4_router___bare_routing@9: txn OnCompletion - bnz __puya_arc4_router___after_if_else@12 + bnz __puya_arc4_router___after_if_else@13 txn ApplicationID ! assert // is creating int 1 retsub -__puya_arc4_router___after_if_else@12: +__puya_arc4_router___after_if_else@13: int 0 retsub @@ -148,6 +166,40 @@ arc4_uint_n: retsub +// smart_contracts.arc4_types.contract.Arc4Types.arc4_biguint_n(a: bytes, b: bytes, c: bytes) -> bytes: +arc4_biguint_n: + proto 3 1 + frame_dig -3 + len + int 16 + == + assert + frame_dig -2 + len + int 32 + == + assert + frame_dig -1 + len + int 64 + == + assert + frame_dig -3 + frame_dig -2 + b+ + frame_dig -1 + b+ + dup + len + int 64 + <= + assert // overflow + int 64 + bzero + b| + retsub + + // smart_contracts.arc4_types.contract.Arc4Types.arc4_address_properties(address: bytes) -> uint64: arc4_address_properties: proto 1 1 diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.arc32.json b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.arc32.json index 591eb5f..e3ed17b 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.arc32.json +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.arc32.json @@ -10,6 +10,11 @@ "no_op": "CALL" } }, + "arc4_biguint_n(uint128,uint256,uint512)uint512": { + "call_config": { + "no_op": "CALL" + } + }, "arc4_address_properties(address)uint64": { "call_config": { "no_op": "CALL" @@ -22,7 +27,7 @@ } }, "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdAOAogICAgbWV0aG9kICJhcmM0X3VpbnQ2NCh1aW50NjQsdWludDY0KXVpbnQ2NCIKICAgIG1ldGhvZCAiYXJjNF91aW50X24odWludDgsdWludDE2LHVpbnQzMix1aW50NjQpdWludDY0IgogICAgbWV0aG9kICJhcmM0X2FkZHJlc3NfcHJvcGVydGllcyhhZGRyZXNzKXVpbnQ2NCIKICAgIG1ldGhvZCAiYXJjNF9hZGRyZXNzX3JldHVybihhZGRyZXNzKWFkZHJlc3MiCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAwCiAgICBtYXRjaCBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X3VpbnQ2NF9yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdWludF9uX3JvdXRlQDMgX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXNfcm91dGVANCBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2FkZHJlc3NfcmV0dXJuX3JvdXRlQDUKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdWludDY0X3JvdXRlQDI6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAyCiAgICBjYWxsc3ViIGFyYzRfdWludDY0CiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X3VpbnRfbl9yb3V0ZUAzOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgNAogICAgY2FsbHN1YiBhcmM0X3VpbnRfbgogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXNfcm91dGVANDoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXMKICAgIGl0b2IKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYWRkcmVzc19yZXR1cm5fcm91dGVANToKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF9hZGRyZXNzX3JldHVybgogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDg6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBibnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMgogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgICEKICAgIGFzc2VydCAvLyBpcyBjcmVhdGluZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMjoKICAgIGludCAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXJjNF91aW50NjQoYTogYnl0ZXMsIGI6IGJ5dGVzKSAtPiBieXRlczoKYXJjNF91aW50NjQ6CiAgICBwcm90byAyIDEKICAgIGZyYW1lX2RpZyAtMgogICAgYnRvaQogICAgZnJhbWVfZGlnIC0xCiAgICBidG9pCiAgICArCiAgICBpdG9iCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXJjNF91aW50X24oYTogYnl0ZXMsIGI6IGJ5dGVzLCBjOiBieXRlcywgZDogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X3VpbnRfbjoKICAgIHByb3RvIDQgMQogICAgZnJhbWVfZGlnIC00CiAgICBsZW4KICAgIGludCAxCiAgICA9PQogICAgYXNzZXJ0CiAgICBmcmFtZV9kaWcgLTMKICAgIGxlbgogICAgaW50IDIKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMgogICAgbGVuCiAgICBpbnQgNAogICAgPT0KICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0xCiAgICBsZW4KICAgIGludCA4CiAgICA9PQogICAgYXNzZXJ0CiAgICBmcmFtZV9kaWcgLTQKICAgIGJ0b2kKICAgIGZyYW1lX2RpZyAtMwogICAgYnRvaQogICAgKwogICAgZnJhbWVfZGlnIC0yCiAgICBidG9pCiAgICArCiAgICBmcmFtZV9kaWcgLTEKICAgIGJ0b2kKICAgICsKICAgIGl0b2IKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X2FkZHJlc3NfcHJvcGVydGllcyhhZGRyZXNzOiBieXRlcykgLT4gdWludDY0OgphcmM0X2FkZHJlc3NfcHJvcGVydGllczoKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBhY2N0X3BhcmFtc19nZXQgQWNjdEJhbGFuY2UKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgZnJhbWVfZGlnIC0xCiAgICBhY2N0X3BhcmFtc19nZXQgQWNjdFRvdGFsQXNzZXRzCiAgICBidXJ5IDEKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFyYzRfYWRkcmVzc19yZXR1cm4oYWRkcmVzczogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X2FkZHJlc3NfcmV0dXJuOgogICAgcHJvdG8gMSAxCiAgICBmcmFtZV9kaWcgLTEKICAgIHJldHN1Ygo=", + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdAOQogICAgbWV0aG9kICJhcmM0X3VpbnQ2NCh1aW50NjQsdWludDY0KXVpbnQ2NCIKICAgIG1ldGhvZCAiYXJjNF91aW50X24odWludDgsdWludDE2LHVpbnQzMix1aW50NjQpdWludDY0IgogICAgbWV0aG9kICJhcmM0X2JpZ3VpbnRfbih1aW50MTI4LHVpbnQyNTYsdWludDUxMil1aW50NTEyIgogICAgbWV0aG9kICJhcmM0X2FkZHJlc3NfcHJvcGVydGllcyhhZGRyZXNzKXVpbnQ2NCIKICAgIG1ldGhvZCAiYXJjNF9hZGRyZXNzX3JldHVybihhZGRyZXNzKWFkZHJlc3MiCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAwCiAgICBtYXRjaCBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X3VpbnQ2NF9yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdWludF9uX3JvdXRlQDMgX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9iaWd1aW50X25fcm91dGVANCBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2FkZHJlc3NfcHJvcGVydGllc19yb3V0ZUA1IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYWRkcmVzc19yZXR1cm5fcm91dGVANgogICAgaW50IDAKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF91aW50NjRfcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDIKICAgIGNhbGxzdWIgYXJjNF91aW50NjQKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdWludF9uX3JvdXRlQDM6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAyCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAzCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyA0CiAgICBjYWxsc3ViIGFyYzRfdWludF9uCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2JpZ3VpbnRfbl9yb3V0ZUA0OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMwogICAgY2FsbHN1YiBhcmM0X2JpZ3VpbnRfbgogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXNfcm91dGVANToKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXMKICAgIGl0b2IKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYWRkcmVzc19yZXR1cm5fcm91dGVANjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF9hZGRyZXNzX3JldHVybgogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDk6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBibnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMwogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgICEKICAgIGFzc2VydCAvLyBpcyBjcmVhdGluZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMzoKICAgIGludCAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXJjNF91aW50NjQoYTogYnl0ZXMsIGI6IGJ5dGVzKSAtPiBieXRlczoKYXJjNF91aW50NjQ6CiAgICBwcm90byAyIDEKICAgIGZyYW1lX2RpZyAtMgogICAgYnRvaQogICAgZnJhbWVfZGlnIC0xCiAgICBidG9pCiAgICArCiAgICBpdG9iCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXJjNF91aW50X24oYTogYnl0ZXMsIGI6IGJ5dGVzLCBjOiBieXRlcywgZDogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X3VpbnRfbjoKICAgIHByb3RvIDQgMQogICAgZnJhbWVfZGlnIC00CiAgICBsZW4KICAgIGludCAxCiAgICA9PQogICAgYXNzZXJ0CiAgICBmcmFtZV9kaWcgLTMKICAgIGxlbgogICAgaW50IDIKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMgogICAgbGVuCiAgICBpbnQgNAogICAgPT0KICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0xCiAgICBsZW4KICAgIGludCA4CiAgICA9PQogICAgYXNzZXJ0CiAgICBmcmFtZV9kaWcgLTQKICAgIGJ0b2kKICAgIGZyYW1lX2RpZyAtMwogICAgYnRvaQogICAgKwogICAgZnJhbWVfZGlnIC0yCiAgICBidG9pCiAgICArCiAgICBmcmFtZV9kaWcgLTEKICAgIGJ0b2kKICAgICsKICAgIGl0b2IKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X2JpZ3VpbnRfbihhOiBieXRlcywgYjogYnl0ZXMsIGM6IGJ5dGVzKSAtPiBieXRlczoKYXJjNF9iaWd1aW50X246CiAgICBwcm90byAzIDEKICAgIGZyYW1lX2RpZyAtMwogICAgbGVuCiAgICBpbnQgMTYKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMgogICAgbGVuCiAgICBpbnQgMzIKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMQogICAgbGVuCiAgICBpbnQgNjQKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMwogICAgZnJhbWVfZGlnIC0yCiAgICBiKwogICAgZnJhbWVfZGlnIC0xCiAgICBiKwogICAgZHVwCiAgICBsZW4KICAgIGludCA2NAogICAgPD0KICAgIGFzc2VydCAvLyBvdmVyZmxvdwogICAgaW50IDY0CiAgICBiemVybwogICAgYnwKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X2FkZHJlc3NfcHJvcGVydGllcyhhZGRyZXNzOiBieXRlcykgLT4gdWludDY0OgphcmM0X2FkZHJlc3NfcHJvcGVydGllczoKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBhY2N0X3BhcmFtc19nZXQgQWNjdEJhbGFuY2UKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgZnJhbWVfZGlnIC0xCiAgICBhY2N0X3BhcmFtc19nZXQgQWNjdFRvdGFsQXNzZXRzCiAgICBidXJ5IDEKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFyYzRfYWRkcmVzc19yZXR1cm4oYWRkcmVzczogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X2FkZHJlc3NfcmV0dXJuOgogICAgcHJvdG8gMSAxCiAgICBmcmFtZV9kaWcgLTEKICAgIHJldHN1Ygo=", "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" }, "state": { @@ -92,6 +97,28 @@ }, "desc": "The encoding of arc4 integers will be smaller if it uses fewer bits.\nUltimately, they are all represented with native UInt64." }, + { + "name": "arc4_biguint_n", + "args": [ + { + "type": "uint128", + "name": "a" + }, + { + "type": "uint256", + "name": "b" + }, + { + "type": "uint512", + "name": "c" + } + ], + "readonly": false, + "returns": { + "type": "uint512" + }, + "desc": "Integers with larger bit size are supported up to 512 bits.\nUltimately, they are all represented with native BigUInt." + }, { "name": "arc4_address_properties", "args": [ diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_types_client.py b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_types_client.py index ae3314a..d092cd3 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_types_client.py +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_types_client.py @@ -33,6 +33,11 @@ "no_op": "CALL" } }, + "arc4_biguint_n(uint128,uint256,uint512)uint512": { + "call_config": { + "no_op": "CALL" + } + }, "arc4_address_properties(address)uint64": { "call_config": { "no_op": "CALL" @@ -45,7 +50,7 @@ } }, "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdAOAogICAgbWV0aG9kICJhcmM0X3VpbnQ2NCh1aW50NjQsdWludDY0KXVpbnQ2NCIKICAgIG1ldGhvZCAiYXJjNF91aW50X24odWludDgsdWludDE2LHVpbnQzMix1aW50NjQpdWludDY0IgogICAgbWV0aG9kICJhcmM0X2FkZHJlc3NfcHJvcGVydGllcyhhZGRyZXNzKXVpbnQ2NCIKICAgIG1ldGhvZCAiYXJjNF9hZGRyZXNzX3JldHVybihhZGRyZXNzKWFkZHJlc3MiCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAwCiAgICBtYXRjaCBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X3VpbnQ2NF9yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdWludF9uX3JvdXRlQDMgX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXNfcm91dGVANCBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2FkZHJlc3NfcmV0dXJuX3JvdXRlQDUKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdWludDY0X3JvdXRlQDI6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAyCiAgICBjYWxsc3ViIGFyYzRfdWludDY0CiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X3VpbnRfbl9yb3V0ZUAzOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgNAogICAgY2FsbHN1YiBhcmM0X3VpbnRfbgogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXNfcm91dGVANDoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXMKICAgIGl0b2IKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYWRkcmVzc19yZXR1cm5fcm91dGVANToKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF9hZGRyZXNzX3JldHVybgogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDg6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBibnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMgogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgICEKICAgIGFzc2VydCAvLyBpcyBjcmVhdGluZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMjoKICAgIGludCAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXJjNF91aW50NjQoYTogYnl0ZXMsIGI6IGJ5dGVzKSAtPiBieXRlczoKYXJjNF91aW50NjQ6CiAgICBwcm90byAyIDEKICAgIGZyYW1lX2RpZyAtMgogICAgYnRvaQogICAgZnJhbWVfZGlnIC0xCiAgICBidG9pCiAgICArCiAgICBpdG9iCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXJjNF91aW50X24oYTogYnl0ZXMsIGI6IGJ5dGVzLCBjOiBieXRlcywgZDogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X3VpbnRfbjoKICAgIHByb3RvIDQgMQogICAgZnJhbWVfZGlnIC00CiAgICBsZW4KICAgIGludCAxCiAgICA9PQogICAgYXNzZXJ0CiAgICBmcmFtZV9kaWcgLTMKICAgIGxlbgogICAgaW50IDIKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMgogICAgbGVuCiAgICBpbnQgNAogICAgPT0KICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0xCiAgICBsZW4KICAgIGludCA4CiAgICA9PQogICAgYXNzZXJ0CiAgICBmcmFtZV9kaWcgLTQKICAgIGJ0b2kKICAgIGZyYW1lX2RpZyAtMwogICAgYnRvaQogICAgKwogICAgZnJhbWVfZGlnIC0yCiAgICBidG9pCiAgICArCiAgICBmcmFtZV9kaWcgLTEKICAgIGJ0b2kKICAgICsKICAgIGl0b2IKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X2FkZHJlc3NfcHJvcGVydGllcyhhZGRyZXNzOiBieXRlcykgLT4gdWludDY0OgphcmM0X2FkZHJlc3NfcHJvcGVydGllczoKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBhY2N0X3BhcmFtc19nZXQgQWNjdEJhbGFuY2UKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgZnJhbWVfZGlnIC0xCiAgICBhY2N0X3BhcmFtc19nZXQgQWNjdFRvdGFsQXNzZXRzCiAgICBidXJ5IDEKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFyYzRfYWRkcmVzc19yZXR1cm4oYWRkcmVzczogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X2FkZHJlc3NfcmV0dXJuOgogICAgcHJvdG8gMSAxCiAgICBmcmFtZV9kaWcgLTEKICAgIHJldHN1Ygo=", + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdAOQogICAgbWV0aG9kICJhcmM0X3VpbnQ2NCh1aW50NjQsdWludDY0KXVpbnQ2NCIKICAgIG1ldGhvZCAiYXJjNF91aW50X24odWludDgsdWludDE2LHVpbnQzMix1aW50NjQpdWludDY0IgogICAgbWV0aG9kICJhcmM0X2JpZ3VpbnRfbih1aW50MTI4LHVpbnQyNTYsdWludDUxMil1aW50NTEyIgogICAgbWV0aG9kICJhcmM0X2FkZHJlc3NfcHJvcGVydGllcyhhZGRyZXNzKXVpbnQ2NCIKICAgIG1ldGhvZCAiYXJjNF9hZGRyZXNzX3JldHVybihhZGRyZXNzKWFkZHJlc3MiCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAwCiAgICBtYXRjaCBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X3VpbnQ2NF9yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdWludF9uX3JvdXRlQDMgX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9iaWd1aW50X25fcm91dGVANCBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2FkZHJlc3NfcHJvcGVydGllc19yb3V0ZUA1IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYWRkcmVzc19yZXR1cm5fcm91dGVANgogICAgaW50IDAKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF91aW50NjRfcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDIKICAgIGNhbGxzdWIgYXJjNF91aW50NjQKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdWludF9uX3JvdXRlQDM6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAyCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAzCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyA0CiAgICBjYWxsc3ViIGFyYzRfdWludF9uCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2JpZ3VpbnRfbl9yb3V0ZUA0OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMwogICAgY2FsbHN1YiBhcmM0X2JpZ3VpbnRfbgogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXNfcm91dGVANToKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXMKICAgIGl0b2IKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYWRkcmVzc19yZXR1cm5fcm91dGVANjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF9hZGRyZXNzX3JldHVybgogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDk6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBibnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMwogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgICEKICAgIGFzc2VydCAvLyBpcyBjcmVhdGluZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMzoKICAgIGludCAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXJjNF91aW50NjQoYTogYnl0ZXMsIGI6IGJ5dGVzKSAtPiBieXRlczoKYXJjNF91aW50NjQ6CiAgICBwcm90byAyIDEKICAgIGZyYW1lX2RpZyAtMgogICAgYnRvaQogICAgZnJhbWVfZGlnIC0xCiAgICBidG9pCiAgICArCiAgICBpdG9iCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXJjNF91aW50X24oYTogYnl0ZXMsIGI6IGJ5dGVzLCBjOiBieXRlcywgZDogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X3VpbnRfbjoKICAgIHByb3RvIDQgMQogICAgZnJhbWVfZGlnIC00CiAgICBsZW4KICAgIGludCAxCiAgICA9PQogICAgYXNzZXJ0CiAgICBmcmFtZV9kaWcgLTMKICAgIGxlbgogICAgaW50IDIKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMgogICAgbGVuCiAgICBpbnQgNAogICAgPT0KICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0xCiAgICBsZW4KICAgIGludCA4CiAgICA9PQogICAgYXNzZXJ0CiAgICBmcmFtZV9kaWcgLTQKICAgIGJ0b2kKICAgIGZyYW1lX2RpZyAtMwogICAgYnRvaQogICAgKwogICAgZnJhbWVfZGlnIC0yCiAgICBidG9pCiAgICArCiAgICBmcmFtZV9kaWcgLTEKICAgIGJ0b2kKICAgICsKICAgIGl0b2IKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X2JpZ3VpbnRfbihhOiBieXRlcywgYjogYnl0ZXMsIGM6IGJ5dGVzKSAtPiBieXRlczoKYXJjNF9iaWd1aW50X246CiAgICBwcm90byAzIDEKICAgIGZyYW1lX2RpZyAtMwogICAgbGVuCiAgICBpbnQgMTYKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMgogICAgbGVuCiAgICBpbnQgMzIKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMQogICAgbGVuCiAgICBpbnQgNjQKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMwogICAgZnJhbWVfZGlnIC0yCiAgICBiKwogICAgZnJhbWVfZGlnIC0xCiAgICBiKwogICAgZHVwCiAgICBsZW4KICAgIGludCA2NAogICAgPD0KICAgIGFzc2VydCAvLyBvdmVyZmxvdwogICAgaW50IDY0CiAgICBiemVybwogICAgYnwKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X2FkZHJlc3NfcHJvcGVydGllcyhhZGRyZXNzOiBieXRlcykgLT4gdWludDY0OgphcmM0X2FkZHJlc3NfcHJvcGVydGllczoKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBhY2N0X3BhcmFtc19nZXQgQWNjdEJhbGFuY2UKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgZnJhbWVfZGlnIC0xCiAgICBhY2N0X3BhcmFtc19nZXQgQWNjdFRvdGFsQXNzZXRzCiAgICBidXJ5IDEKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFyYzRfYWRkcmVzc19yZXR1cm4oYWRkcmVzczogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X2FkZHJlc3NfcmV0dXJuOgogICAgcHJvdG8gMSAxCiAgICBmcmFtZV9kaWcgLTEKICAgIHJldHN1Ygo=", "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" }, "state": { @@ -113,6 +118,27 @@ }, "desc": "The encoding of arc4 integers will be smaller if it uses fewer bits.\nUltimately, they are all represented with native UInt64." }, + { + "name": "arc4_biguint_n", + "args": [ + { + "type": "uint128", + "name": "a" + }, + { + "type": "uint256", + "name": "b" + }, + { + "type": "uint512", + "name": "c" + } + ], + "returns": { + "type": "uint512" + }, + "desc": "Integers with larger bit size are supported up to 512 bits.\nUltimately, they are all represented with native BigUInt." + }, { "name": "arc4_address_properties", "args": [ @@ -245,6 +271,20 @@ def method() -> str: return "arc4_uint_n(uint8,uint16,uint32,uint64)uint64" +@dataclasses.dataclass(kw_only=True) +class Arc4BiguintNArgs(_ArgsBase[int]): + """Integers with larger bit size are supported up to 512 bits. + Ultimately, they are all represented with native BigUInt.""" + + a: int + b: int + c: int + + @staticmethod + def method() -> str: + return "arc4_biguint_n(uint128,uint256,uint512)uint512" + + @dataclasses.dataclass(kw_only=True) class Arc4AddressPropertiesArgs(_ArgsBase[int]): address: str @@ -358,6 +398,38 @@ def arc4_uint_n( ) return self + def arc4_biguint_n( + self, + *, + a: int, + b: int, + c: int, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> "Composer": + """Integers with larger bit size are supported up to 512 bits. + Ultimately, they are all represented with native BigUInt. + + Adds a call to `arc4_biguint_n(uint128,uint256,uint512)uint512` ABI method + + :param int a: The `a` ABI parameter + :param int b: The `b` ABI parameter + :param int c: The `c` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + args = Arc4BiguintNArgs( + a=a, + b=b, + c=c, + ) + self.app_client.compose_call( + self.atc, + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return self + def arc4_address_properties( self, *, @@ -625,6 +697,37 @@ def arc4_uint_n( ) return result + def arc4_biguint_n( + self, + *, + a: int, + b: int, + c: int, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> algokit_utils.ABITransactionResponse[int]: + """Integers with larger bit size are supported up to 512 bits. + Ultimately, they are all represented with native BigUInt. + + Calls `arc4_biguint_n(uint128,uint256,uint512)uint512` ABI method + + :param int a: The `a` ABI parameter + :param int b: The `b` ABI parameter + :param int c: The `c` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.ABITransactionResponse[int]: The result of the transaction""" + + args = Arc4BiguintNArgs( + a=a, + b=b, + c=c, + ) + result = self.app_client.call( + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return result + def arc4_address_properties( self, *, diff --git a/projects/python-contract-examples/tests/arc4_types_integration_test.py b/projects/python-contract-examples/tests/arc4_types_integration_test.py index 7bedabe..3070a82 100644 --- a/projects/python-contract-examples/tests/arc4_types_integration_test.py +++ b/projects/python-contract-examples/tests/arc4_types_integration_test.py @@ -167,6 +167,16 @@ def test_arc4_uint_n( assert result.return_value == 201_100 +def test_arc4_biguint_n( + arc4_types_app_client: Arc4TypesClient, +) -> None: + """Test the arc4_uint_n method""" + + result = arc4_types_app_client.arc4_biguint_n(a=2**65, b=2**129, c=2**257) + + assert result.return_value == 2**65 + 2**129 + 2**257 + + def test_arc4_address_properties( arc4_types_app_client: Arc4TypesClient, creator: AddressAndSigner, From 6cbdb710e37c0aa8b9c09422b15e2eb4a6686fba Mon Sep 17 00:00:00 2001 From: CiottiGiorgio Date: Mon, 4 Nov 2024 17:46:56 +0100 Subject: [PATCH 07/23] added bytes examples. --- .../smart_contracts/arc4_types/contract.py | 42 +- .../arc4_types/Arc4DynamicArray.approval.teal | 277 +++++++++ .../arc4_types/Arc4DynamicArray.arc32.json | 70 +++ .../arc4_types/Arc4DynamicArray.clear.teal | 5 + .../arc4_types/Arc4Types.approval.teal | 42 +- .../artifacts/arc4_types/Arc4Types.arc32.json | 21 +- .../arc4_types/arc4_dynamic_array_client.py | 565 ++++++++++++++++++ .../artifacts/arc4_types/arc4_types_client.py | 80 ++- .../tests/arc4_types_integration_test.py | 59 ++ 9 files changed, 1151 insertions(+), 10 deletions(-) create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.approval.teal create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.arc32.json create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.clear.teal create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_dynamic_array_client.py diff --git a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py index 9d0e886..3d3e19b 100644 --- a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py +++ b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py @@ -1,7 +1,7 @@ # pyright: reportMissingModuleSource=false import typing as t -from algopy import ARC4Contract, GlobalState, UInt64, arc4, urange +from algopy import ARC4Contract, GlobalState, UInt64, arc4, urange, String, Bytes from algopy.arc4 import abimethod @@ -51,6 +51,13 @@ def arc4_biguint_n(self, a: arc4.UInt128, b: arc4.UInt256, c: arc4.UInt512) -> a return arc4.UInt512(total) + @abimethod() + def arc4_byte(self, a: arc4.Byte) -> arc4.Byte: + """ + An arc4.Byte is essentially an alias for an 8-bit integer. + """ + return arc4.Byte(a.native + 1) + @abimethod() def arc4_address_properties(self, address: arc4.Address) -> UInt64: underlying_bytes = ( @@ -123,6 +130,39 @@ def arc4_static_array(self) -> None: """ +class Arc4DynamicArray(ARC4Contract): + + @abimethod() + def arc4_dynamic_array(self, name: arc4.String) -> arc4.String: + """ + Dynamic Arrays have variable size and capacity. + They are similar to native Python lists because they can also append, extend, and pop. + """ + dynamic_string_array = arc4.DynamicArray[arc4.String](arc4.String("Hello")) + + extension = arc4.DynamicArray[arc4.String](arc4.String(" world"), arc4.String(", ")) + dynamic_string_array.extend(extension) + + dynamic_string_array.append(name) + dynamic_string_array.append(arc4.String("!")) + dynamic_string_array.pop() + + greeting = String() + for x in dynamic_string_array: + greeting += x.native + + return arc4.String(greeting) + + @abimethod() + def arc4_dynamic_bytes(self) -> arc4.DynamicBytes: + """arc4.DynamicBytes are essentially an arc4.DynamicArray[arc4.Bytes] and some convenience methods.""" + dynamic_bytes = arc4.DynamicBytes(b"\xFF\xFF\xFF") + + dynamic_bytes[0] = arc4.Byte(0) + + return dynamic_bytes + + class Todo(arc4.Struct): task: arc4.String completed: arc4.Bool diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.approval.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.approval.teal new file mode 100644 index 0000000..1557272 --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.approval.teal @@ -0,0 +1,277 @@ +#pragma version 10 + +smart_contracts.arc4_types.contract.Arc4DynamicArray.approval_program: + callsub __puya_arc4_router__ + return + + +// smart_contracts.arc4_types.contract.Arc4DynamicArray.__puya_arc4_router__() -> uint64: +__puya_arc4_router__: + proto 0 1 + txn NumAppArgs + bz __puya_arc4_router___bare_routing@6 + method "arc4_dynamic_array(string)string" + method "arc4_dynamic_bytes()byte[]" + txna ApplicationArgs 0 + match __puya_arc4_router___arc4_dynamic_array_route@2 __puya_arc4_router___arc4_dynamic_bytes_route@3 + int 0 + retsub + +__puya_arc4_router___arc4_dynamic_array_route@2: + txn OnCompletion + ! + assert // OnCompletion is NoOp + txn ApplicationID + assert // is not creating + txna ApplicationArgs 1 + callsub arc4_dynamic_array + byte 0x151f7c75 + swap + concat + log + int 1 + retsub + +__puya_arc4_router___arc4_dynamic_bytes_route@3: + txn OnCompletion + ! + assert // OnCompletion is NoOp + txn ApplicationID + assert // is not creating + callsub arc4_dynamic_bytes + byte 0x151f7c75 + swap + concat + log + int 1 + retsub + +__puya_arc4_router___bare_routing@6: + txn OnCompletion + bnz __puya_arc4_router___after_if_else@10 + txn ApplicationID + ! + assert // is creating + int 1 + retsub + +__puya_arc4_router___after_if_else@10: + int 0 + retsub + + +// smart_contracts.arc4_types.contract.Arc4DynamicArray.arc4_dynamic_array(name: bytes) -> bytes: +arc4_dynamic_array: + proto 1 1 + byte 0x00010002000548656c6c6f + byte 0x000620776f726c6400022c20 + int 2 + callsub dynamic_array_concat_byte_length_head + frame_dig -1 + int 1 + callsub dynamic_array_concat_byte_length_head + byte 0x000121 + int 1 + callsub dynamic_array_concat_byte_length_head + callsub dynamic_array_pop_byte_length_head + dup + uncover 2 + pop + byte "" + swap + int 0 + extract_uint16 + int 0 + +arc4_dynamic_array_for_header@1: + frame_dig 3 + frame_dig 2 + < + bz arc4_dynamic_array_after_for@4 + frame_dig 0 + extract 2 0 + frame_dig 3 + dup + cover 2 + int 2 + * + dig 1 + swap + extract_uint16 + dup2 + extract_uint16 + int 2 + + + extract3 + extract 2 0 + frame_dig 1 + swap + concat + frame_bury 1 + int 1 + + + frame_bury 3 + b arc4_dynamic_array_for_header@1 + +arc4_dynamic_array_after_for@4: + frame_dig 1 + dup + len + itob + extract 6 2 + swap + concat + frame_bury 0 + retsub + + +// smart_contracts.arc4_types.contract.Arc4DynamicArray.arc4_dynamic_bytes() -> bytes: +arc4_dynamic_bytes: + proto 0 1 + byte 0x0003ffffff + byte 0x00 + replace2 2 + retsub + + +// _puya_lib.arc4.dynamic_array_pop_byte_length_head(array: bytes) -> bytes, bytes: +dynamic_array_pop_byte_length_head: + proto 1 2 + frame_dig -1 + int 0 + extract_uint16 + int 1 + - + dup + int 2 + * + frame_dig -1 + extract 2 0 + dup + dig 2 + extract_uint16 + swap + dup + len + swap + dup + dig 3 + uncover 3 + substring3 + cover 3 + dup + int 0 + dig 4 + substring3 + cover 2 + uncover 3 + int 2 + + + uncover 2 + substring3 + concat + dig 2 + itob + extract 6 2 + swap + uncover 3 + int 0 + callsub recalculate_head_for_elements_with_byte_length_head + concat + retsub + + +// _puya_lib.arc4.dynamic_array_concat_byte_length_head(array: bytes, new_items_bytes: bytes, new_items_count: uint64) -> bytes: +dynamic_array_concat_byte_length_head: + proto 3 1 + frame_dig -3 + int 0 + extract_uint16 + dup + frame_dig -1 + + + swap + int 2 + * + int 2 + + + swap + dup + itob + extract 6 2 + swap + frame_dig -3 + int 2 + dig 4 + substring3 + frame_dig -1 + int 2 + * + bzero + concat + frame_dig -3 + len + frame_dig -3 + uncover 5 + uncover 2 + substring3 + concat + frame_dig -2 + concat + swap + int 0 + callsub recalculate_head_for_elements_with_byte_length_head + concat + retsub + + +// _puya_lib.arc4.recalculate_head_for_elements_with_byte_length_head(array_head_and_tail: bytes, length: uint64, start_at_index: uint64) -> bytes: +recalculate_head_for_elements_with_byte_length_head: + proto 3 1 + frame_dig -2 + int 2 + * + dup + frame_dig -1 + int 2 + * + dup + cover 2 + frame_dig -3 + swap + extract_uint16 + frame_dig -1 + select + +recalculate_head_for_elements_with_byte_length_head_for_header@1: + frame_dig 1 + frame_dig 0 + < + bz recalculate_head_for_elements_with_byte_length_head_after_for@4 + frame_dig 2 + dup + itob + extract 6 2 + frame_dig -3 + frame_dig 1 + dup + cover 4 + uncover 2 + replace3 + dup + frame_bury -3 + dig 1 + extract_uint16 + int 2 + + + + + frame_bury 2 + int 2 + + + frame_bury 1 + b recalculate_head_for_elements_with_byte_length_head_for_header@1 + +recalculate_head_for_elements_with_byte_length_head_after_for@4: + frame_dig -3 + frame_bury 0 + retsub diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.arc32.json b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.arc32.json new file mode 100644 index 0000000..41922ee --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.arc32.json @@ -0,0 +1,70 @@ +{ + "hints": { + "arc4_dynamic_array(string)string": { + "call_config": { + "no_op": "CALL" + } + }, + "arc4_dynamic_bytes()byte[]": { + "call_config": { + "no_op": "CALL" + } + } + }, + "source": { + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5LmFwcHJvdmFsX3Byb2dyYW06CiAgICBjYWxsc3ViIF9fcHV5YV9hcmM0X3JvdXRlcl9fCiAgICByZXR1cm4KCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5Ll9fcHV5YV9hcmM0X3JvdXRlcl9fKCkgLT4gdWludDY0OgpfX3B1eWFfYXJjNF9yb3V0ZXJfXzoKICAgIHByb3RvIDAgMQogICAgdHhuIE51bUFwcEFyZ3MKICAgIGJ6IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2CiAgICBtZXRob2QgImFyYzRfZHluYW1pY19hcnJheShzdHJpbmcpc3RyaW5nIgogICAgbWV0aG9kICJhcmM0X2R5bmFtaWNfYnl0ZXMoKWJ5dGVbXSIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfZHluYW1pY19hcnJheV9yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfZHluYW1pY19ieXRlc19yb3V0ZUAzCiAgICBpbnQgMAogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2R5bmFtaWNfYXJyYXlfcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF9keW5hbWljX2FycmF5CiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2R5bmFtaWNfYnl0ZXNfcm91dGVAMzoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIGNhbGxzdWIgYXJjNF9keW5hbWljX2J5dGVzCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgIGJueiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDEwCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgIQogICAgYXNzZXJ0IC8vIGlzIGNyZWF0aW5nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDEwOgogICAgaW50IDAKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzREeW5hbWljQXJyYXkuYXJjNF9keW5hbWljX2FycmF5KG5hbWU6IGJ5dGVzKSAtPiBieXRlczoKYXJjNF9keW5hbWljX2FycmF5OgogICAgcHJvdG8gMSAxCiAgICBieXRlIDB4MDAwMTAwMDIwMDA1NDg2NTZjNmM2ZgogICAgYnl0ZSAweDAwMDYyMDc3NmY3MjZjNjQwMDAyMmMyMAogICAgaW50IDIKICAgIGNhbGxzdWIgZHluYW1pY19hcnJheV9jb25jYXRfYnl0ZV9sZW5ndGhfaGVhZAogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMQogICAgY2FsbHN1YiBkeW5hbWljX2FycmF5X2NvbmNhdF9ieXRlX2xlbmd0aF9oZWFkCiAgICBieXRlIDB4MDAwMTIxCiAgICBpbnQgMQogICAgY2FsbHN1YiBkeW5hbWljX2FycmF5X2NvbmNhdF9ieXRlX2xlbmd0aF9oZWFkCiAgICBjYWxsc3ViIGR5bmFtaWNfYXJyYXlfcG9wX2J5dGVfbGVuZ3RoX2hlYWQKICAgIGR1cAogICAgdW5jb3ZlciAyCiAgICBwb3AKICAgIGJ5dGUgIiIKICAgIHN3YXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50IDAKCmFyYzRfZHluYW1pY19hcnJheV9mb3JfaGVhZGVyQDE6CiAgICBmcmFtZV9kaWcgMwogICAgZnJhbWVfZGlnIDIKICAgIDwKICAgIGJ6IGFyYzRfZHluYW1pY19hcnJheV9hZnRlcl9mb3JANAogICAgZnJhbWVfZGlnIDAKICAgIGV4dHJhY3QgMiAwCiAgICBmcmFtZV9kaWcgMwogICAgZHVwCiAgICBjb3ZlciAyCiAgICBpbnQgMgogICAgKgogICAgZGlnIDEKICAgIHN3YXAKICAgIGV4dHJhY3RfdWludDE2CiAgICBkdXAyCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50IDIKICAgICsKICAgIGV4dHJhY3QzCiAgICBleHRyYWN0IDIgMAogICAgZnJhbWVfZGlnIDEKICAgIHN3YXAKICAgIGNvbmNhdAogICAgZnJhbWVfYnVyeSAxCiAgICBpbnQgMQogICAgKwogICAgZnJhbWVfYnVyeSAzCiAgICBiIGFyYzRfZHluYW1pY19hcnJheV9mb3JfaGVhZGVyQDEKCmFyYzRfZHluYW1pY19hcnJheV9hZnRlcl9mb3JANDoKICAgIGZyYW1lX2RpZyAxCiAgICBkdXAKICAgIGxlbgogICAgaXRvYgogICAgZXh0cmFjdCA2IDIKICAgIHN3YXAKICAgIGNvbmNhdAogICAgZnJhbWVfYnVyeSAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5LmFyYzRfZHluYW1pY19ieXRlcygpIC0+IGJ5dGVzOgphcmM0X2R5bmFtaWNfYnl0ZXM6CiAgICBwcm90byAwIDEKICAgIGJ5dGUgMHgwMDAzZmZmZmZmCiAgICBieXRlIDB4MDAKICAgIHJlcGxhY2UyIDIKICAgIHJldHN1YgoKCi8vIF9wdXlhX2xpYi5hcmM0LmR5bmFtaWNfYXJyYXlfcG9wX2J5dGVfbGVuZ3RoX2hlYWQoYXJyYXk6IGJ5dGVzKSAtPiBieXRlcywgYnl0ZXM6CmR5bmFtaWNfYXJyYXlfcG9wX2J5dGVfbGVuZ3RoX2hlYWQ6CiAgICBwcm90byAxIDIKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDAKICAgIGV4dHJhY3RfdWludDE2CiAgICBpbnQgMQogICAgLQogICAgZHVwCiAgICBpbnQgMgogICAgKgogICAgZnJhbWVfZGlnIC0xCiAgICBleHRyYWN0IDIgMAogICAgZHVwCiAgICBkaWcgMgogICAgZXh0cmFjdF91aW50MTYKICAgIHN3YXAKICAgIGR1cAogICAgbGVuCiAgICBzd2FwCiAgICBkdXAKICAgIGRpZyAzCiAgICB1bmNvdmVyIDMKICAgIHN1YnN0cmluZzMKICAgIGNvdmVyIDMKICAgIGR1cAogICAgaW50IDAKICAgIGRpZyA0CiAgICBzdWJzdHJpbmczCiAgICBjb3ZlciAyCiAgICB1bmNvdmVyIDMKICAgIGludCAyCiAgICArCiAgICB1bmNvdmVyIDIKICAgIHN1YnN0cmluZzMKICAgIGNvbmNhdAogICAgZGlnIDIKICAgIGl0b2IKICAgIGV4dHJhY3QgNiAyCiAgICBzd2FwCiAgICB1bmNvdmVyIDMKICAgIGludCAwCiAgICBjYWxsc3ViIHJlY2FsY3VsYXRlX2hlYWRfZm9yX2VsZW1lbnRzX3dpdGhfYnl0ZV9sZW5ndGhfaGVhZAogICAgY29uY2F0CiAgICByZXRzdWIKCgovLyBfcHV5YV9saWIuYXJjNC5keW5hbWljX2FycmF5X2NvbmNhdF9ieXRlX2xlbmd0aF9oZWFkKGFycmF5OiBieXRlcywgbmV3X2l0ZW1zX2J5dGVzOiBieXRlcywgbmV3X2l0ZW1zX2NvdW50OiB1aW50NjQpIC0+IGJ5dGVzOgpkeW5hbWljX2FycmF5X2NvbmNhdF9ieXRlX2xlbmd0aF9oZWFkOgogICAgcHJvdG8gMyAxCiAgICBmcmFtZV9kaWcgLTMKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgZHVwCiAgICBmcmFtZV9kaWcgLTEKICAgICsKICAgIHN3YXAKICAgIGludCAyCiAgICAqCiAgICBpbnQgMgogICAgKwogICAgc3dhcAogICAgZHVwCiAgICBpdG9iCiAgICBleHRyYWN0IDYgMgogICAgc3dhcAogICAgZnJhbWVfZGlnIC0zCiAgICBpbnQgMgogICAgZGlnIDQKICAgIHN1YnN0cmluZzMKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDIKICAgICoKICAgIGJ6ZXJvCiAgICBjb25jYXQKICAgIGZyYW1lX2RpZyAtMwogICAgbGVuCiAgICBmcmFtZV9kaWcgLTMKICAgIHVuY292ZXIgNQogICAgdW5jb3ZlciAyCiAgICBzdWJzdHJpbmczCiAgICBjb25jYXQKICAgIGZyYW1lX2RpZyAtMgogICAgY29uY2F0CiAgICBzd2FwCiAgICBpbnQgMAogICAgY2FsbHN1YiByZWNhbGN1bGF0ZV9oZWFkX2Zvcl9lbGVtZW50c193aXRoX2J5dGVfbGVuZ3RoX2hlYWQKICAgIGNvbmNhdAogICAgcmV0c3ViCgoKLy8gX3B1eWFfbGliLmFyYzQucmVjYWxjdWxhdGVfaGVhZF9mb3JfZWxlbWVudHNfd2l0aF9ieXRlX2xlbmd0aF9oZWFkKGFycmF5X2hlYWRfYW5kX3RhaWw6IGJ5dGVzLCBsZW5ndGg6IHVpbnQ2NCwgc3RhcnRfYXRfaW5kZXg6IHVpbnQ2NCkgLT4gYnl0ZXM6CnJlY2FsY3VsYXRlX2hlYWRfZm9yX2VsZW1lbnRzX3dpdGhfYnl0ZV9sZW5ndGhfaGVhZDoKICAgIHByb3RvIDMgMQogICAgZnJhbWVfZGlnIC0yCiAgICBpbnQgMgogICAgKgogICAgZHVwCiAgICBmcmFtZV9kaWcgLTEKICAgIGludCAyCiAgICAqCiAgICBkdXAKICAgIGNvdmVyIDIKICAgIGZyYW1lX2RpZyAtMwogICAgc3dhcAogICAgZXh0cmFjdF91aW50MTYKICAgIGZyYW1lX2RpZyAtMQogICAgc2VsZWN0CgpyZWNhbGN1bGF0ZV9oZWFkX2Zvcl9lbGVtZW50c193aXRoX2J5dGVfbGVuZ3RoX2hlYWRfZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDEKICAgIGZyYW1lX2RpZyAwCiAgICA8CiAgICBieiByZWNhbGN1bGF0ZV9oZWFkX2Zvcl9lbGVtZW50c193aXRoX2J5dGVfbGVuZ3RoX2hlYWRfYWZ0ZXJfZm9yQDQKICAgIGZyYW1lX2RpZyAyCiAgICBkdXAKICAgIGl0b2IKICAgIGV4dHJhY3QgNiAyCiAgICBmcmFtZV9kaWcgLTMKICAgIGZyYW1lX2RpZyAxCiAgICBkdXAKICAgIGNvdmVyIDQKICAgIHVuY292ZXIgMgogICAgcmVwbGFjZTMKICAgIGR1cAogICAgZnJhbWVfYnVyeSAtMwogICAgZGlnIDEKICAgIGV4dHJhY3RfdWludDE2CiAgICBpbnQgMgogICAgKwogICAgKwogICAgZnJhbWVfYnVyeSAyCiAgICBpbnQgMgogICAgKwogICAgZnJhbWVfYnVyeSAxCiAgICBiIHJlY2FsY3VsYXRlX2hlYWRfZm9yX2VsZW1lbnRzX3dpdGhfYnl0ZV9sZW5ndGhfaGVhZF9mb3JfaGVhZGVyQDEKCnJlY2FsY3VsYXRlX2hlYWRfZm9yX2VsZW1lbnRzX3dpdGhfYnl0ZV9sZW5ndGhfaGVhZF9hZnRlcl9mb3JANDoKICAgIGZyYW1lX2RpZyAtMwogICAgZnJhbWVfYnVyeSAwCiAgICByZXRzdWIK", + "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5LmNsZWFyX3N0YXRlX3Byb2dyYW06CiAgICBpbnQgMQogICAgcmV0dXJuCg==" + }, + "state": { + "global": { + "num_byte_slices": 0, + "num_uints": 0 + }, + "local": { + "num_byte_slices": 0, + "num_uints": 0 + } + }, + "schema": { + "global": { + "declared": {}, + "reserved": {} + }, + "local": { + "declared": {}, + "reserved": {} + } + }, + "contract": { + "name": "Arc4DynamicArray", + "methods": [ + { + "name": "arc4_dynamic_array", + "args": [ + { + "type": "string", + "name": "name" + } + ], + "readonly": false, + "returns": { + "type": "string" + }, + "desc": "Dynamic Arrays have variable size and capacity.\nThey are similar to native Python lists because they can also append, extend, and pop." + }, + { + "name": "arc4_dynamic_bytes", + "args": [], + "readonly": false, + "returns": { + "type": "byte[]" + }, + "desc": "arc4.DynamicBytes are essentially an arc4.DynamicArray[arc4.Bytes] and some convenience methods." + } + ], + "networks": {} + }, + "bare_call_config": { + "no_op": "CREATE" + } +} \ No newline at end of file diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.clear.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.clear.teal new file mode 100644 index 0000000..ac284db --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.clear.teal @@ -0,0 +1,5 @@ +#pragma version 10 + +smart_contracts.arc4_types.contract.Arc4DynamicArray.clear_state_program: + int 1 + return diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.approval.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.approval.teal index db20a79..cf1936c 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.approval.teal +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.approval.teal @@ -9,14 +9,15 @@ smart_contracts.arc4_types.contract.Arc4Types.approval_program: __puya_arc4_router__: proto 0 1 txn NumAppArgs - bz __puya_arc4_router___bare_routing@9 + bz __puya_arc4_router___bare_routing@10 method "arc4_uint64(uint64,uint64)uint64" method "arc4_uint_n(uint8,uint16,uint32,uint64)uint64" method "arc4_biguint_n(uint128,uint256,uint512)uint512" + method "arc4_byte(byte)byte" method "arc4_address_properties(address)uint64" method "arc4_address_return(address)address" txna ApplicationArgs 0 - match __puya_arc4_router___arc4_uint64_route@2 __puya_arc4_router___arc4_uint_n_route@3 __puya_arc4_router___arc4_biguint_n_route@4 __puya_arc4_router___arc4_address_properties_route@5 __puya_arc4_router___arc4_address_return_route@6 + match __puya_arc4_router___arc4_uint64_route@2 __puya_arc4_router___arc4_uint_n_route@3 __puya_arc4_router___arc4_biguint_n_route@4 __puya_arc4_router___arc4_byte_route@5 __puya_arc4_router___arc4_address_properties_route@6 __puya_arc4_router___arc4_address_return_route@7 int 0 retsub @@ -71,7 +72,22 @@ __puya_arc4_router___arc4_biguint_n_route@4: int 1 retsub -__puya_arc4_router___arc4_address_properties_route@5: +__puya_arc4_router___arc4_byte_route@5: + txn OnCompletion + ! + assert // OnCompletion is NoOp + txn ApplicationID + assert // is not creating + txna ApplicationArgs 1 + callsub arc4_byte + byte 0x151f7c75 + swap + concat + log + int 1 + retsub + +__puya_arc4_router___arc4_address_properties_route@6: txn OnCompletion ! assert // OnCompletion is NoOp @@ -87,7 +103,7 @@ __puya_arc4_router___arc4_address_properties_route@5: int 1 retsub -__puya_arc4_router___arc4_address_return_route@6: +__puya_arc4_router___arc4_address_return_route@7: txn OnCompletion ! assert // OnCompletion is NoOp @@ -102,16 +118,16 @@ __puya_arc4_router___arc4_address_return_route@6: int 1 retsub -__puya_arc4_router___bare_routing@9: +__puya_arc4_router___bare_routing@10: txn OnCompletion - bnz __puya_arc4_router___after_if_else@13 + bnz __puya_arc4_router___after_if_else@14 txn ApplicationID ! assert // is creating int 1 retsub -__puya_arc4_router___after_if_else@13: +__puya_arc4_router___after_if_else@14: int 0 retsub @@ -200,6 +216,18 @@ arc4_biguint_n: retsub +// smart_contracts.arc4_types.contract.Arc4Types.arc4_byte(a: bytes) -> bytes: +arc4_byte: + proto 1 1 + frame_dig -1 + btoi + int 1 + + + itob + extract 7 1 + retsub + + // smart_contracts.arc4_types.contract.Arc4Types.arc4_address_properties(address: bytes) -> uint64: arc4_address_properties: proto 1 1 diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.arc32.json b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.arc32.json index e3ed17b..8fda8ad 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.arc32.json +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.arc32.json @@ -15,6 +15,11 @@ "no_op": "CALL" } }, + "arc4_byte(byte)byte": { + "call_config": { + "no_op": "CALL" + } + }, "arc4_address_properties(address)uint64": { "call_config": { "no_op": "CALL" @@ -27,7 +32,7 @@ } }, "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdAOQogICAgbWV0aG9kICJhcmM0X3VpbnQ2NCh1aW50NjQsdWludDY0KXVpbnQ2NCIKICAgIG1ldGhvZCAiYXJjNF91aW50X24odWludDgsdWludDE2LHVpbnQzMix1aW50NjQpdWludDY0IgogICAgbWV0aG9kICJhcmM0X2JpZ3VpbnRfbih1aW50MTI4LHVpbnQyNTYsdWludDUxMil1aW50NTEyIgogICAgbWV0aG9kICJhcmM0X2FkZHJlc3NfcHJvcGVydGllcyhhZGRyZXNzKXVpbnQ2NCIKICAgIG1ldGhvZCAiYXJjNF9hZGRyZXNzX3JldHVybihhZGRyZXNzKWFkZHJlc3MiCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAwCiAgICBtYXRjaCBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X3VpbnQ2NF9yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdWludF9uX3JvdXRlQDMgX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9iaWd1aW50X25fcm91dGVANCBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2FkZHJlc3NfcHJvcGVydGllc19yb3V0ZUA1IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYWRkcmVzc19yZXR1cm5fcm91dGVANgogICAgaW50IDAKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF91aW50NjRfcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDIKICAgIGNhbGxzdWIgYXJjNF91aW50NjQKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdWludF9uX3JvdXRlQDM6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAyCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAzCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyA0CiAgICBjYWxsc3ViIGFyYzRfdWludF9uCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2JpZ3VpbnRfbl9yb3V0ZUA0OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMwogICAgY2FsbHN1YiBhcmM0X2JpZ3VpbnRfbgogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXNfcm91dGVANToKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXMKICAgIGl0b2IKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYWRkcmVzc19yZXR1cm5fcm91dGVANjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF9hZGRyZXNzX3JldHVybgogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDk6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBibnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMwogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgICEKICAgIGFzc2VydCAvLyBpcyBjcmVhdGluZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMzoKICAgIGludCAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXJjNF91aW50NjQoYTogYnl0ZXMsIGI6IGJ5dGVzKSAtPiBieXRlczoKYXJjNF91aW50NjQ6CiAgICBwcm90byAyIDEKICAgIGZyYW1lX2RpZyAtMgogICAgYnRvaQogICAgZnJhbWVfZGlnIC0xCiAgICBidG9pCiAgICArCiAgICBpdG9iCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXJjNF91aW50X24oYTogYnl0ZXMsIGI6IGJ5dGVzLCBjOiBieXRlcywgZDogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X3VpbnRfbjoKICAgIHByb3RvIDQgMQogICAgZnJhbWVfZGlnIC00CiAgICBsZW4KICAgIGludCAxCiAgICA9PQogICAgYXNzZXJ0CiAgICBmcmFtZV9kaWcgLTMKICAgIGxlbgogICAgaW50IDIKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMgogICAgbGVuCiAgICBpbnQgNAogICAgPT0KICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0xCiAgICBsZW4KICAgIGludCA4CiAgICA9PQogICAgYXNzZXJ0CiAgICBmcmFtZV9kaWcgLTQKICAgIGJ0b2kKICAgIGZyYW1lX2RpZyAtMwogICAgYnRvaQogICAgKwogICAgZnJhbWVfZGlnIC0yCiAgICBidG9pCiAgICArCiAgICBmcmFtZV9kaWcgLTEKICAgIGJ0b2kKICAgICsKICAgIGl0b2IKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X2JpZ3VpbnRfbihhOiBieXRlcywgYjogYnl0ZXMsIGM6IGJ5dGVzKSAtPiBieXRlczoKYXJjNF9iaWd1aW50X246CiAgICBwcm90byAzIDEKICAgIGZyYW1lX2RpZyAtMwogICAgbGVuCiAgICBpbnQgMTYKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMgogICAgbGVuCiAgICBpbnQgMzIKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMQogICAgbGVuCiAgICBpbnQgNjQKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMwogICAgZnJhbWVfZGlnIC0yCiAgICBiKwogICAgZnJhbWVfZGlnIC0xCiAgICBiKwogICAgZHVwCiAgICBsZW4KICAgIGludCA2NAogICAgPD0KICAgIGFzc2VydCAvLyBvdmVyZmxvdwogICAgaW50IDY0CiAgICBiemVybwogICAgYnwKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X2FkZHJlc3NfcHJvcGVydGllcyhhZGRyZXNzOiBieXRlcykgLT4gdWludDY0OgphcmM0X2FkZHJlc3NfcHJvcGVydGllczoKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBhY2N0X3BhcmFtc19nZXQgQWNjdEJhbGFuY2UKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgZnJhbWVfZGlnIC0xCiAgICBhY2N0X3BhcmFtc19nZXQgQWNjdFRvdGFsQXNzZXRzCiAgICBidXJ5IDEKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFyYzRfYWRkcmVzc19yZXR1cm4oYWRkcmVzczogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X2FkZHJlc3NfcmV0dXJuOgogICAgcHJvdG8gMSAxCiAgICBmcmFtZV9kaWcgLTEKICAgIHJldHN1Ygo=", + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdAMTAKICAgIG1ldGhvZCAiYXJjNF91aW50NjQodWludDY0LHVpbnQ2NCl1aW50NjQiCiAgICBtZXRob2QgImFyYzRfdWludF9uKHVpbnQ4LHVpbnQxNix1aW50MzIsdWludDY0KXVpbnQ2NCIKICAgIG1ldGhvZCAiYXJjNF9iaWd1aW50X24odWludDEyOCx1aW50MjU2LHVpbnQ1MTIpdWludDUxMiIKICAgIG1ldGhvZCAiYXJjNF9ieXRlKGJ5dGUpYnl0ZSIKICAgIG1ldGhvZCAiYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXMoYWRkcmVzcyl1aW50NjQiCiAgICBtZXRob2QgImFyYzRfYWRkcmVzc19yZXR1cm4oYWRkcmVzcylhZGRyZXNzIgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAogICAgbWF0Y2ggX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF91aW50NjRfcm91dGVAMiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X3VpbnRfbl9yb3V0ZUAzIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYmlndWludF9uX3JvdXRlQDQgX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9ieXRlX3JvdXRlQDUgX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXNfcm91dGVANiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2FkZHJlc3NfcmV0dXJuX3JvdXRlQDcKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdWludDY0X3JvdXRlQDI6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAyCiAgICBjYWxsc3ViIGFyYzRfdWludDY0CiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X3VpbnRfbl9yb3V0ZUAzOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgNAogICAgY2FsbHN1YiBhcmM0X3VpbnRfbgogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9iaWd1aW50X25fcm91dGVANDoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDMKICAgIGNhbGxzdWIgYXJjNF9iaWd1aW50X24KICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYnl0ZV9yb3V0ZUA1OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgY2FsbHN1YiBhcmM0X2J5dGUKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYWRkcmVzc19wcm9wZXJ0aWVzX3JvdXRlQDY6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICBjYWxsc3ViIGFyYzRfYWRkcmVzc19wcm9wZXJ0aWVzCiAgICBpdG9iCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2FkZHJlc3NfcmV0dXJuX3JvdXRlQDc6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICBjYWxsc3ViIGFyYzRfYWRkcmVzc19yZXR1cm4KICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0AxMDoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgIGJueiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDE0CiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgIQogICAgYXNzZXJ0IC8vIGlzIGNyZWF0aW5nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDE0OgogICAgaW50IDAKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X3VpbnQ2NChhOiBieXRlcywgYjogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X3VpbnQ2NDoKICAgIHByb3RvIDIgMQogICAgZnJhbWVfZGlnIC0yCiAgICBidG9pCiAgICBmcmFtZV9kaWcgLTEKICAgIGJ0b2kKICAgICsKICAgIGl0b2IKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X3VpbnRfbihhOiBieXRlcywgYjogYnl0ZXMsIGM6IGJ5dGVzLCBkOiBieXRlcykgLT4gYnl0ZXM6CmFyYzRfdWludF9uOgogICAgcHJvdG8gNCAxCiAgICBmcmFtZV9kaWcgLTQKICAgIGxlbgogICAgaW50IDEKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMwogICAgbGVuCiAgICBpbnQgMgogICAgPT0KICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0yCiAgICBsZW4KICAgIGludCA0CiAgICA9PQogICAgYXNzZXJ0CiAgICBmcmFtZV9kaWcgLTEKICAgIGxlbgogICAgaW50IDgKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtNAogICAgYnRvaQogICAgZnJhbWVfZGlnIC0zCiAgICBidG9pCiAgICArCiAgICBmcmFtZV9kaWcgLTIKICAgIGJ0b2kKICAgICsKICAgIGZyYW1lX2RpZyAtMQogICAgYnRvaQogICAgKwogICAgaXRvYgogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFyYzRfYmlndWludF9uKGE6IGJ5dGVzLCBiOiBieXRlcywgYzogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X2JpZ3VpbnRfbjoKICAgIHByb3RvIDMgMQogICAgZnJhbWVfZGlnIC0zCiAgICBsZW4KICAgIGludCAxNgogICAgPT0KICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0yCiAgICBsZW4KICAgIGludCAzMgogICAgPT0KICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0xCiAgICBsZW4KICAgIGludCA2NAogICAgPT0KICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0zCiAgICBmcmFtZV9kaWcgLTIKICAgIGIrCiAgICBmcmFtZV9kaWcgLTEKICAgIGIrCiAgICBkdXAKICAgIGxlbgogICAgaW50IDY0CiAgICA8PQogICAgYXNzZXJ0IC8vIG92ZXJmbG93CiAgICBpbnQgNjQKICAgIGJ6ZXJvCiAgICBifAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFyYzRfYnl0ZShhOiBieXRlcykgLT4gYnl0ZXM6CmFyYzRfYnl0ZToKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBidG9pCiAgICBpbnQgMQogICAgKwogICAgaXRvYgogICAgZXh0cmFjdCA3IDEKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X2FkZHJlc3NfcHJvcGVydGllcyhhZGRyZXNzOiBieXRlcykgLT4gdWludDY0OgphcmM0X2FkZHJlc3NfcHJvcGVydGllczoKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBhY2N0X3BhcmFtc19nZXQgQWNjdEJhbGFuY2UKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgZnJhbWVfZGlnIC0xCiAgICBhY2N0X3BhcmFtc19nZXQgQWNjdFRvdGFsQXNzZXRzCiAgICBidXJ5IDEKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFyYzRfYWRkcmVzc19yZXR1cm4oYWRkcmVzczogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X2FkZHJlc3NfcmV0dXJuOgogICAgcHJvdG8gMSAxCiAgICBmcmFtZV9kaWcgLTEKICAgIHJldHN1Ygo=", "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" }, "state": { @@ -119,6 +124,20 @@ }, "desc": "Integers with larger bit size are supported up to 512 bits.\nUltimately, they are all represented with native BigUInt." }, + { + "name": "arc4_byte", + "args": [ + { + "type": "byte", + "name": "a" + } + ], + "readonly": false, + "returns": { + "type": "byte" + }, + "desc": "An arc4.Byte is essentially an alias for an 8-bit integer." + }, { "name": "arc4_address_properties", "args": [ diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_dynamic_array_client.py b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_dynamic_array_client.py new file mode 100644 index 0000000..4bf7295 --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_dynamic_array_client.py @@ -0,0 +1,565 @@ +# flake8: noqa +# fmt: off +# mypy: disable-error-code="no-any-return, no-untyped-call, misc, type-arg" +# This file was automatically generated by algokit-client-generator. +# DO NOT MODIFY IT BY HAND. +# requires: algokit-utils@^1.2.0 +import base64 +import dataclasses +import decimal +import typing +from abc import ABC, abstractmethod + +import algokit_utils +import algosdk +from algosdk.v2client import models +from algosdk.atomic_transaction_composer import ( + AtomicTransactionComposer, + AtomicTransactionResponse, + SimulateAtomicTransactionResponse, + TransactionSigner, + TransactionWithSigner +) + +_APP_SPEC_JSON = r"""{ + "hints": { + "arc4_dynamic_array(string)string": { + "call_config": { + "no_op": "CALL" + } + }, + "arc4_dynamic_bytes()byte[]": { + "call_config": { + "no_op": "CALL" + } + } + }, + "source": { + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5LmFwcHJvdmFsX3Byb2dyYW06CiAgICBjYWxsc3ViIF9fcHV5YV9hcmM0X3JvdXRlcl9fCiAgICByZXR1cm4KCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5Ll9fcHV5YV9hcmM0X3JvdXRlcl9fKCkgLT4gdWludDY0OgpfX3B1eWFfYXJjNF9yb3V0ZXJfXzoKICAgIHByb3RvIDAgMQogICAgdHhuIE51bUFwcEFyZ3MKICAgIGJ6IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2CiAgICBtZXRob2QgImFyYzRfZHluYW1pY19hcnJheShzdHJpbmcpc3RyaW5nIgogICAgbWV0aG9kICJhcmM0X2R5bmFtaWNfYnl0ZXMoKWJ5dGVbXSIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfZHluYW1pY19hcnJheV9yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfZHluYW1pY19ieXRlc19yb3V0ZUAzCiAgICBpbnQgMAogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2R5bmFtaWNfYXJyYXlfcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF9keW5hbWljX2FycmF5CiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2R5bmFtaWNfYnl0ZXNfcm91dGVAMzoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIGNhbGxzdWIgYXJjNF9keW5hbWljX2J5dGVzCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgIGJueiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDEwCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgIQogICAgYXNzZXJ0IC8vIGlzIGNyZWF0aW5nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDEwOgogICAgaW50IDAKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzREeW5hbWljQXJyYXkuYXJjNF9keW5hbWljX2FycmF5KG5hbWU6IGJ5dGVzKSAtPiBieXRlczoKYXJjNF9keW5hbWljX2FycmF5OgogICAgcHJvdG8gMSAxCiAgICBieXRlIDB4MDAwMTAwMDIwMDA1NDg2NTZjNmM2ZgogICAgYnl0ZSAweDAwMDYyMDc3NmY3MjZjNjQwMDAyMmMyMAogICAgaW50IDIKICAgIGNhbGxzdWIgZHluYW1pY19hcnJheV9jb25jYXRfYnl0ZV9sZW5ndGhfaGVhZAogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMQogICAgY2FsbHN1YiBkeW5hbWljX2FycmF5X2NvbmNhdF9ieXRlX2xlbmd0aF9oZWFkCiAgICBieXRlIDB4MDAwMTIxCiAgICBpbnQgMQogICAgY2FsbHN1YiBkeW5hbWljX2FycmF5X2NvbmNhdF9ieXRlX2xlbmd0aF9oZWFkCiAgICBjYWxsc3ViIGR5bmFtaWNfYXJyYXlfcG9wX2J5dGVfbGVuZ3RoX2hlYWQKICAgIGR1cAogICAgdW5jb3ZlciAyCiAgICBwb3AKICAgIGJ5dGUgIiIKICAgIHN3YXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50IDAKCmFyYzRfZHluYW1pY19hcnJheV9mb3JfaGVhZGVyQDE6CiAgICBmcmFtZV9kaWcgMwogICAgZnJhbWVfZGlnIDIKICAgIDwKICAgIGJ6IGFyYzRfZHluYW1pY19hcnJheV9hZnRlcl9mb3JANAogICAgZnJhbWVfZGlnIDAKICAgIGV4dHJhY3QgMiAwCiAgICBmcmFtZV9kaWcgMwogICAgZHVwCiAgICBjb3ZlciAyCiAgICBpbnQgMgogICAgKgogICAgZGlnIDEKICAgIHN3YXAKICAgIGV4dHJhY3RfdWludDE2CiAgICBkdXAyCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50IDIKICAgICsKICAgIGV4dHJhY3QzCiAgICBleHRyYWN0IDIgMAogICAgZnJhbWVfZGlnIDEKICAgIHN3YXAKICAgIGNvbmNhdAogICAgZnJhbWVfYnVyeSAxCiAgICBpbnQgMQogICAgKwogICAgZnJhbWVfYnVyeSAzCiAgICBiIGFyYzRfZHluYW1pY19hcnJheV9mb3JfaGVhZGVyQDEKCmFyYzRfZHluYW1pY19hcnJheV9hZnRlcl9mb3JANDoKICAgIGZyYW1lX2RpZyAxCiAgICBkdXAKICAgIGxlbgogICAgaXRvYgogICAgZXh0cmFjdCA2IDIKICAgIHN3YXAKICAgIGNvbmNhdAogICAgZnJhbWVfYnVyeSAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5LmFyYzRfZHluYW1pY19ieXRlcygpIC0+IGJ5dGVzOgphcmM0X2R5bmFtaWNfYnl0ZXM6CiAgICBwcm90byAwIDEKICAgIGJ5dGUgMHgwMDAzZmZmZmZmCiAgICBieXRlIDB4MDAKICAgIHJlcGxhY2UyIDIKICAgIHJldHN1YgoKCi8vIF9wdXlhX2xpYi5hcmM0LmR5bmFtaWNfYXJyYXlfcG9wX2J5dGVfbGVuZ3RoX2hlYWQoYXJyYXk6IGJ5dGVzKSAtPiBieXRlcywgYnl0ZXM6CmR5bmFtaWNfYXJyYXlfcG9wX2J5dGVfbGVuZ3RoX2hlYWQ6CiAgICBwcm90byAxIDIKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDAKICAgIGV4dHJhY3RfdWludDE2CiAgICBpbnQgMQogICAgLQogICAgZHVwCiAgICBpbnQgMgogICAgKgogICAgZnJhbWVfZGlnIC0xCiAgICBleHRyYWN0IDIgMAogICAgZHVwCiAgICBkaWcgMgogICAgZXh0cmFjdF91aW50MTYKICAgIHN3YXAKICAgIGR1cAogICAgbGVuCiAgICBzd2FwCiAgICBkdXAKICAgIGRpZyAzCiAgICB1bmNvdmVyIDMKICAgIHN1YnN0cmluZzMKICAgIGNvdmVyIDMKICAgIGR1cAogICAgaW50IDAKICAgIGRpZyA0CiAgICBzdWJzdHJpbmczCiAgICBjb3ZlciAyCiAgICB1bmNvdmVyIDMKICAgIGludCAyCiAgICArCiAgICB1bmNvdmVyIDIKICAgIHN1YnN0cmluZzMKICAgIGNvbmNhdAogICAgZGlnIDIKICAgIGl0b2IKICAgIGV4dHJhY3QgNiAyCiAgICBzd2FwCiAgICB1bmNvdmVyIDMKICAgIGludCAwCiAgICBjYWxsc3ViIHJlY2FsY3VsYXRlX2hlYWRfZm9yX2VsZW1lbnRzX3dpdGhfYnl0ZV9sZW5ndGhfaGVhZAogICAgY29uY2F0CiAgICByZXRzdWIKCgovLyBfcHV5YV9saWIuYXJjNC5keW5hbWljX2FycmF5X2NvbmNhdF9ieXRlX2xlbmd0aF9oZWFkKGFycmF5OiBieXRlcywgbmV3X2l0ZW1zX2J5dGVzOiBieXRlcywgbmV3X2l0ZW1zX2NvdW50OiB1aW50NjQpIC0+IGJ5dGVzOgpkeW5hbWljX2FycmF5X2NvbmNhdF9ieXRlX2xlbmd0aF9oZWFkOgogICAgcHJvdG8gMyAxCiAgICBmcmFtZV9kaWcgLTMKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgZHVwCiAgICBmcmFtZV9kaWcgLTEKICAgICsKICAgIHN3YXAKICAgIGludCAyCiAgICAqCiAgICBpbnQgMgogICAgKwogICAgc3dhcAogICAgZHVwCiAgICBpdG9iCiAgICBleHRyYWN0IDYgMgogICAgc3dhcAogICAgZnJhbWVfZGlnIC0zCiAgICBpbnQgMgogICAgZGlnIDQKICAgIHN1YnN0cmluZzMKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDIKICAgICoKICAgIGJ6ZXJvCiAgICBjb25jYXQKICAgIGZyYW1lX2RpZyAtMwogICAgbGVuCiAgICBmcmFtZV9kaWcgLTMKICAgIHVuY292ZXIgNQogICAgdW5jb3ZlciAyCiAgICBzdWJzdHJpbmczCiAgICBjb25jYXQKICAgIGZyYW1lX2RpZyAtMgogICAgY29uY2F0CiAgICBzd2FwCiAgICBpbnQgMAogICAgY2FsbHN1YiByZWNhbGN1bGF0ZV9oZWFkX2Zvcl9lbGVtZW50c193aXRoX2J5dGVfbGVuZ3RoX2hlYWQKICAgIGNvbmNhdAogICAgcmV0c3ViCgoKLy8gX3B1eWFfbGliLmFyYzQucmVjYWxjdWxhdGVfaGVhZF9mb3JfZWxlbWVudHNfd2l0aF9ieXRlX2xlbmd0aF9oZWFkKGFycmF5X2hlYWRfYW5kX3RhaWw6IGJ5dGVzLCBsZW5ndGg6IHVpbnQ2NCwgc3RhcnRfYXRfaW5kZXg6IHVpbnQ2NCkgLT4gYnl0ZXM6CnJlY2FsY3VsYXRlX2hlYWRfZm9yX2VsZW1lbnRzX3dpdGhfYnl0ZV9sZW5ndGhfaGVhZDoKICAgIHByb3RvIDMgMQogICAgZnJhbWVfZGlnIC0yCiAgICBpbnQgMgogICAgKgogICAgZHVwCiAgICBmcmFtZV9kaWcgLTEKICAgIGludCAyCiAgICAqCiAgICBkdXAKICAgIGNvdmVyIDIKICAgIGZyYW1lX2RpZyAtMwogICAgc3dhcAogICAgZXh0cmFjdF91aW50MTYKICAgIGZyYW1lX2RpZyAtMQogICAgc2VsZWN0CgpyZWNhbGN1bGF0ZV9oZWFkX2Zvcl9lbGVtZW50c193aXRoX2J5dGVfbGVuZ3RoX2hlYWRfZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDEKICAgIGZyYW1lX2RpZyAwCiAgICA8CiAgICBieiByZWNhbGN1bGF0ZV9oZWFkX2Zvcl9lbGVtZW50c193aXRoX2J5dGVfbGVuZ3RoX2hlYWRfYWZ0ZXJfZm9yQDQKICAgIGZyYW1lX2RpZyAyCiAgICBkdXAKICAgIGl0b2IKICAgIGV4dHJhY3QgNiAyCiAgICBmcmFtZV9kaWcgLTMKICAgIGZyYW1lX2RpZyAxCiAgICBkdXAKICAgIGNvdmVyIDQKICAgIHVuY292ZXIgMgogICAgcmVwbGFjZTMKICAgIGR1cAogICAgZnJhbWVfYnVyeSAtMwogICAgZGlnIDEKICAgIGV4dHJhY3RfdWludDE2CiAgICBpbnQgMgogICAgKwogICAgKwogICAgZnJhbWVfYnVyeSAyCiAgICBpbnQgMgogICAgKwogICAgZnJhbWVfYnVyeSAxCiAgICBiIHJlY2FsY3VsYXRlX2hlYWRfZm9yX2VsZW1lbnRzX3dpdGhfYnl0ZV9sZW5ndGhfaGVhZF9mb3JfaGVhZGVyQDEKCnJlY2FsY3VsYXRlX2hlYWRfZm9yX2VsZW1lbnRzX3dpdGhfYnl0ZV9sZW5ndGhfaGVhZF9hZnRlcl9mb3JANDoKICAgIGZyYW1lX2RpZyAtMwogICAgZnJhbWVfYnVyeSAwCiAgICByZXRzdWIK", + "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5LmNsZWFyX3N0YXRlX3Byb2dyYW06CiAgICBpbnQgMQogICAgcmV0dXJuCg==" + }, + "state": { + "global": { + "num_byte_slices": 0, + "num_uints": 0 + }, + "local": { + "num_byte_slices": 0, + "num_uints": 0 + } + }, + "schema": { + "global": { + "declared": {}, + "reserved": {} + }, + "local": { + "declared": {}, + "reserved": {} + } + }, + "contract": { + "name": "Arc4DynamicArray", + "methods": [ + { + "name": "arc4_dynamic_array", + "args": [ + { + "type": "string", + "name": "name" + } + ], + "returns": { + "type": "string" + }, + "desc": "Dynamic Arrays have variable size and capacity.\nThey are similar to native Python lists because they can also append, extend, and pop." + }, + { + "name": "arc4_dynamic_bytes", + "args": [], + "returns": { + "type": "byte[]" + }, + "desc": "arc4.DynamicBytes are essentially an arc4.DynamicArray[arc4.Bytes] and some convenience methods." + } + ], + "networks": {} + }, + "bare_call_config": { + "no_op": "CREATE" + } +}""" +APP_SPEC = algokit_utils.ApplicationSpecification.from_json(_APP_SPEC_JSON) +_TReturn = typing.TypeVar("_TReturn") + + +class _ArgsBase(ABC, typing.Generic[_TReturn]): + @staticmethod + @abstractmethod + def method() -> str: + ... + + +_TArgs = typing.TypeVar("_TArgs", bound=_ArgsBase[typing.Any]) + + +@dataclasses.dataclass(kw_only=True) +class _TArgsHolder(typing.Generic[_TArgs]): + args: _TArgs + + +def _filter_none(value: dict | typing.Any) -> dict | typing.Any: + if isinstance(value, dict): + return {k: _filter_none(v) for k, v in value.items() if v is not None} + return value + + +def _as_dict(data: typing.Any, *, convert_all: bool = True) -> dict[str, typing.Any]: + if data is None: + return {} + if not dataclasses.is_dataclass(data): + raise TypeError(f"{data} must be a dataclass") + if convert_all: + result = dataclasses.asdict(data) # type: ignore[call-overload] + else: + result = {f.name: getattr(data, f.name) for f in dataclasses.fields(data)} + return _filter_none(result) + + +def _convert_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, +) -> algokit_utils.TransactionParametersDict: + return typing.cast(algokit_utils.TransactionParametersDict, _as_dict(transaction_parameters)) + + +def _convert_call_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, +) -> algokit_utils.OnCompleteCallParametersDict: + return typing.cast(algokit_utils.OnCompleteCallParametersDict, _as_dict(transaction_parameters)) + + +def _convert_create_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, + on_complete: algokit_utils.OnCompleteActionName, +) -> algokit_utils.CreateCallParametersDict: + result = typing.cast(algokit_utils.CreateCallParametersDict, _as_dict(transaction_parameters)) + on_complete_enum = on_complete.replace("_", " ").title().replace(" ", "") + "OC" + result["on_complete"] = getattr(algosdk.transaction.OnComplete, on_complete_enum) + return result + + +def _convert_deploy_args( + deploy_args: algokit_utils.DeployCallArgs | None, +) -> algokit_utils.ABICreateCallArgsDict | None: + if deploy_args is None: + return None + + deploy_args_dict = typing.cast(algokit_utils.ABICreateCallArgsDict, _as_dict(deploy_args)) + if isinstance(deploy_args, _TArgsHolder): + deploy_args_dict["args"] = _as_dict(deploy_args.args) + deploy_args_dict["method"] = deploy_args.args.method() + + return deploy_args_dict + + +@dataclasses.dataclass(kw_only=True) +class Arc4DynamicArrayArgs(_ArgsBase[str]): + """Dynamic Arrays have variable size and capacity. + They are similar to native Python lists because they can also append, extend, and pop.""" + + name: str + + @staticmethod + def method() -> str: + return "arc4_dynamic_array(string)string" + + +@dataclasses.dataclass(kw_only=True) +class Arc4DynamicBytesArgs(_ArgsBase[bytes | bytearray]): + """arc4.DynamicBytes are essentially an arc4.DynamicArray[arc4.Bytes] and some convenience methods.""" + + @staticmethod + def method() -> str: + return "arc4_dynamic_bytes()byte[]" + + +@dataclasses.dataclass(kw_only=True) +class SimulateOptions: + allow_more_logs: bool = dataclasses.field(default=False) + allow_empty_signatures: bool = dataclasses.field(default=False) + extra_opcode_budget: int = dataclasses.field(default=0) + exec_trace_config: models.SimulateTraceConfig | None = dataclasses.field(default=None) + + +class Composer: + + def __init__(self, app_client: algokit_utils.ApplicationClient, atc: AtomicTransactionComposer): + self.app_client = app_client + self.atc = atc + + def build(self) -> AtomicTransactionComposer: + return self.atc + + def simulate(self, options: SimulateOptions | None = None) -> SimulateAtomicTransactionResponse: + request = models.SimulateRequest( + allow_more_logs=options.allow_more_logs, + allow_empty_signatures=options.allow_empty_signatures, + extra_opcode_budget=options.extra_opcode_budget, + exec_trace_config=options.exec_trace_config, + txn_groups=[] + ) if options else None + result = self.atc.simulate(self.app_client.algod_client, request) + return result + + def execute(self) -> AtomicTransactionResponse: + return self.app_client.execute_atc(self.atc) + + def arc4_dynamic_array( + self, + *, + name: str, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> "Composer": + """Dynamic Arrays have variable size and capacity. + They are similar to native Python lists because they can also append, extend, and pop. + + Adds a call to `arc4_dynamic_array(string)string` ABI method + + :param str name: The `name` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + args = Arc4DynamicArrayArgs( + name=name, + ) + self.app_client.compose_call( + self.atc, + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return self + + def arc4_dynamic_bytes( + self, + *, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> "Composer": + """arc4.DynamicBytes are essentially an arc4.DynamicArray[arc4.Bytes] and some convenience methods. + + Adds a call to `arc4_dynamic_bytes()byte[]` ABI method + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + args = Arc4DynamicBytesArgs() + self.app_client.compose_call( + self.atc, + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return self + + def create_bare( + self, + *, + on_complete: typing.Literal["no_op"] = "no_op", + transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, + ) -> "Composer": + """Adds a call to create an application using the no_op bare method + + :param typing.Literal[no_op] on_complete: On completion type to use + :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + self.app_client.compose_create( + self.atc, + call_abi_method=False, + transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), + ) + return self + + def clear_state( + self, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + app_args: list[bytes] | None = None, + ) -> "Composer": + """Adds a call to the application with on completion set to ClearState + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :param list[bytes] | None app_args: (optional) Application args to pass""" + + self.app_client.compose_clear_state(self.atc, _convert_transaction_parameters(transaction_parameters), app_args) + return self + + +class Arc4DynamicArrayClient: + """A class for interacting with the Arc4DynamicArray app providing high productivity and + strongly typed methods to deploy and call the app""" + + @typing.overload + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + app_id: int = 0, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + ... + + @typing.overload + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + creator: str | algokit_utils.Account, + indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, + existing_deployments: algokit_utils.AppLookup | None = None, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + ... + + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + creator: str | algokit_utils.Account | None = None, + indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, + existing_deployments: algokit_utils.AppLookup | None = None, + app_id: int = 0, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + """ + Arc4DynamicArrayClient can be created with an app_id to interact with an existing application, alternatively + it can be created with a creator and indexer_client specified to find existing applications by name and creator. + + :param AlgodClient algod_client: AlgoSDK algod client + :param int app_id: The app_id of an existing application, to instead find the application by creator and name + use the creator and indexer_client parameters + :param str | Account creator: The address or Account of the app creator to resolve the app_id + :param IndexerClient indexer_client: AlgoSDK indexer client, only required if deploying or finding app_id by + creator and app name + :param AppLookup existing_deployments: + :param TransactionSigner | Account signer: Account or signer to use to sign transactions, if not specified and + creator was passed as an Account will use that. + :param str sender: Address to use as the sender for all transactions, will use the address associated with the + signer if not specified. + :param TemplateValueMapping template_values: Values to use for TMPL_* template variables, dictionary keys should + *NOT* include the TMPL_ prefix + :param str | None app_name: Name of application to use when deploying, defaults to name defined on the + Application Specification + """ + + self.app_spec = APP_SPEC + + # calling full __init__ signature, so ignoring mypy warning about overloads + self.app_client = algokit_utils.ApplicationClient( # type: ignore[call-overload, misc] + algod_client=algod_client, + app_spec=self.app_spec, + app_id=app_id, + creator=creator, + indexer_client=indexer_client, + existing_deployments=existing_deployments, + signer=signer, + sender=sender, + suggested_params=suggested_params, + template_values=template_values, + app_name=app_name, + ) + + @property + def algod_client(self) -> algosdk.v2client.algod.AlgodClient: + return self.app_client.algod_client + + @property + def app_id(self) -> int: + return self.app_client.app_id + + @app_id.setter + def app_id(self, value: int) -> None: + self.app_client.app_id = value + + @property + def app_address(self) -> str: + return self.app_client.app_address + + @property + def sender(self) -> str | None: + return self.app_client.sender + + @sender.setter + def sender(self, value: str) -> None: + self.app_client.sender = value + + @property + def signer(self) -> TransactionSigner | None: + return self.app_client.signer + + @signer.setter + def signer(self, value: TransactionSigner) -> None: + self.app_client.signer = value + + @property + def suggested_params(self) -> algosdk.transaction.SuggestedParams | None: + return self.app_client.suggested_params + + @suggested_params.setter + def suggested_params(self, value: algosdk.transaction.SuggestedParams | None) -> None: + self.app_client.suggested_params = value + + def arc4_dynamic_array( + self, + *, + name: str, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> algokit_utils.ABITransactionResponse[str]: + """Dynamic Arrays have variable size and capacity. + They are similar to native Python lists because they can also append, extend, and pop. + + Calls `arc4_dynamic_array(string)string` ABI method + + :param str name: The `name` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.ABITransactionResponse[str]: The result of the transaction""" + + args = Arc4DynamicArrayArgs( + name=name, + ) + result = self.app_client.call( + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return result + + def arc4_dynamic_bytes( + self, + *, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> algokit_utils.ABITransactionResponse[bytes | bytearray]: + """arc4.DynamicBytes are essentially an arc4.DynamicArray[arc4.Bytes] and some convenience methods. + + Calls `arc4_dynamic_bytes()byte[]` ABI method + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.ABITransactionResponse[bytes | bytearray]: The result of the transaction""" + + args = Arc4DynamicBytesArgs() + result = self.app_client.call( + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return result + + def create_bare( + self, + *, + on_complete: typing.Literal["no_op"] = "no_op", + transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, + ) -> algokit_utils.TransactionResponse: + """Creates an application using the no_op bare method + + :param typing.Literal[no_op] on_complete: On completion type to use + :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.TransactionResponse: The result of the transaction""" + + result = self.app_client.create( + call_abi_method=False, + transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), + ) + return result + + def clear_state( + self, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + app_args: list[bytes] | None = None, + ) -> algokit_utils.TransactionResponse: + """Calls the application with on completion set to ClearState + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :param list[bytes] | None app_args: (optional) Application args to pass + :returns algokit_utils.TransactionResponse: The result of the transaction""" + + return self.app_client.clear_state(_convert_transaction_parameters(transaction_parameters), app_args) + + def deploy( + self, + version: str | None = None, + *, + signer: TransactionSigner | None = None, + sender: str | None = None, + allow_update: bool | None = None, + allow_delete: bool | None = None, + on_update: algokit_utils.OnUpdate = algokit_utils.OnUpdate.Fail, + on_schema_break: algokit_utils.OnSchemaBreak = algokit_utils.OnSchemaBreak.Fail, + template_values: algokit_utils.TemplateValueMapping | None = None, + create_args: algokit_utils.DeployCallArgs | None = None, + update_args: algokit_utils.DeployCallArgs | None = None, + delete_args: algokit_utils.DeployCallArgs | None = None, + ) -> algokit_utils.DeployResponse: + """Deploy an application and update client to reference it. + + Idempotently deploy (create, update/delete if changed) an app against the given name via the given creator + account, including deploy-time template placeholder substitutions. + To understand the architecture decisions behind this functionality please see + + + ```{note} + If there is a breaking state schema change to an existing app (and `on_schema_break` is set to + 'ReplaceApp' the existing app will be deleted and re-created. + ``` + + ```{note} + If there is an update (different TEAL code) to an existing app (and `on_update` is set to 'ReplaceApp') + the existing app will be deleted and re-created. + ``` + + :param str version: version to use when creating or updating app, if None version will be auto incremented + :param algosdk.atomic_transaction_composer.TransactionSigner signer: signer to use when deploying app + , if None uses self.signer + :param str sender: sender address to use when deploying app, if None uses self.sender + :param bool allow_delete: Used to set the `TMPL_DELETABLE` template variable to conditionally control if an app + can be deleted + :param bool allow_update: Used to set the `TMPL_UPDATABLE` template variable to conditionally control if an app + can be updated + :param OnUpdate on_update: Determines what action to take if an application update is required + :param OnSchemaBreak on_schema_break: Determines what action to take if an application schema requirements + has increased beyond the current allocation + :param dict[str, int|str|bytes] template_values: Values to use for `TMPL_*` template variables, dictionary keys + should *NOT* include the TMPL_ prefix + :param algokit_utils.DeployCallArgs | None create_args: Arguments used when creating an application + :param algokit_utils.DeployCallArgs | None update_args: Arguments used when updating an application + :param algokit_utils.DeployCallArgs | None delete_args: Arguments used when deleting an application + :return DeployResponse: details action taken and relevant transactions + :raises DeploymentError: If the deployment failed""" + + return self.app_client.deploy( + version, + signer=signer, + sender=sender, + allow_update=allow_update, + allow_delete=allow_delete, + on_update=on_update, + on_schema_break=on_schema_break, + template_values=template_values, + create_args=_convert_deploy_args(create_args), + update_args=_convert_deploy_args(update_args), + delete_args=_convert_deploy_args(delete_args), + ) + + def compose(self, atc: AtomicTransactionComposer | None = None) -> Composer: + return Composer(self.app_client, atc or AtomicTransactionComposer()) diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_types_client.py b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_types_client.py index d092cd3..fa693aa 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_types_client.py +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_types_client.py @@ -38,6 +38,11 @@ "no_op": "CALL" } }, + "arc4_byte(byte)byte": { + "call_config": { + "no_op": "CALL" + } + }, "arc4_address_properties(address)uint64": { "call_config": { "no_op": "CALL" @@ -50,7 +55,7 @@ } }, "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdAOQogICAgbWV0aG9kICJhcmM0X3VpbnQ2NCh1aW50NjQsdWludDY0KXVpbnQ2NCIKICAgIG1ldGhvZCAiYXJjNF91aW50X24odWludDgsdWludDE2LHVpbnQzMix1aW50NjQpdWludDY0IgogICAgbWV0aG9kICJhcmM0X2JpZ3VpbnRfbih1aW50MTI4LHVpbnQyNTYsdWludDUxMil1aW50NTEyIgogICAgbWV0aG9kICJhcmM0X2FkZHJlc3NfcHJvcGVydGllcyhhZGRyZXNzKXVpbnQ2NCIKICAgIG1ldGhvZCAiYXJjNF9hZGRyZXNzX3JldHVybihhZGRyZXNzKWFkZHJlc3MiCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAwCiAgICBtYXRjaCBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X3VpbnQ2NF9yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdWludF9uX3JvdXRlQDMgX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9iaWd1aW50X25fcm91dGVANCBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2FkZHJlc3NfcHJvcGVydGllc19yb3V0ZUA1IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYWRkcmVzc19yZXR1cm5fcm91dGVANgogICAgaW50IDAKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF91aW50NjRfcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDIKICAgIGNhbGxzdWIgYXJjNF91aW50NjQKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdWludF9uX3JvdXRlQDM6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAyCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAzCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyA0CiAgICBjYWxsc3ViIGFyYzRfdWludF9uCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2JpZ3VpbnRfbl9yb3V0ZUA0OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMwogICAgY2FsbHN1YiBhcmM0X2JpZ3VpbnRfbgogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXNfcm91dGVANToKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXMKICAgIGl0b2IKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYWRkcmVzc19yZXR1cm5fcm91dGVANjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF9hZGRyZXNzX3JldHVybgogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDk6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBibnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMwogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgICEKICAgIGFzc2VydCAvLyBpcyBjcmVhdGluZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMzoKICAgIGludCAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXJjNF91aW50NjQoYTogYnl0ZXMsIGI6IGJ5dGVzKSAtPiBieXRlczoKYXJjNF91aW50NjQ6CiAgICBwcm90byAyIDEKICAgIGZyYW1lX2RpZyAtMgogICAgYnRvaQogICAgZnJhbWVfZGlnIC0xCiAgICBidG9pCiAgICArCiAgICBpdG9iCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXJjNF91aW50X24oYTogYnl0ZXMsIGI6IGJ5dGVzLCBjOiBieXRlcywgZDogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X3VpbnRfbjoKICAgIHByb3RvIDQgMQogICAgZnJhbWVfZGlnIC00CiAgICBsZW4KICAgIGludCAxCiAgICA9PQogICAgYXNzZXJ0CiAgICBmcmFtZV9kaWcgLTMKICAgIGxlbgogICAgaW50IDIKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMgogICAgbGVuCiAgICBpbnQgNAogICAgPT0KICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0xCiAgICBsZW4KICAgIGludCA4CiAgICA9PQogICAgYXNzZXJ0CiAgICBmcmFtZV9kaWcgLTQKICAgIGJ0b2kKICAgIGZyYW1lX2RpZyAtMwogICAgYnRvaQogICAgKwogICAgZnJhbWVfZGlnIC0yCiAgICBidG9pCiAgICArCiAgICBmcmFtZV9kaWcgLTEKICAgIGJ0b2kKICAgICsKICAgIGl0b2IKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X2JpZ3VpbnRfbihhOiBieXRlcywgYjogYnl0ZXMsIGM6IGJ5dGVzKSAtPiBieXRlczoKYXJjNF9iaWd1aW50X246CiAgICBwcm90byAzIDEKICAgIGZyYW1lX2RpZyAtMwogICAgbGVuCiAgICBpbnQgMTYKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMgogICAgbGVuCiAgICBpbnQgMzIKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMQogICAgbGVuCiAgICBpbnQgNjQKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMwogICAgZnJhbWVfZGlnIC0yCiAgICBiKwogICAgZnJhbWVfZGlnIC0xCiAgICBiKwogICAgZHVwCiAgICBsZW4KICAgIGludCA2NAogICAgPD0KICAgIGFzc2VydCAvLyBvdmVyZmxvdwogICAgaW50IDY0CiAgICBiemVybwogICAgYnwKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X2FkZHJlc3NfcHJvcGVydGllcyhhZGRyZXNzOiBieXRlcykgLT4gdWludDY0OgphcmM0X2FkZHJlc3NfcHJvcGVydGllczoKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBhY2N0X3BhcmFtc19nZXQgQWNjdEJhbGFuY2UKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgZnJhbWVfZGlnIC0xCiAgICBhY2N0X3BhcmFtc19nZXQgQWNjdFRvdGFsQXNzZXRzCiAgICBidXJ5IDEKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFyYzRfYWRkcmVzc19yZXR1cm4oYWRkcmVzczogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X2FkZHJlc3NfcmV0dXJuOgogICAgcHJvdG8gMSAxCiAgICBmcmFtZV9kaWcgLTEKICAgIHJldHN1Ygo=", + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdAMTAKICAgIG1ldGhvZCAiYXJjNF91aW50NjQodWludDY0LHVpbnQ2NCl1aW50NjQiCiAgICBtZXRob2QgImFyYzRfdWludF9uKHVpbnQ4LHVpbnQxNix1aW50MzIsdWludDY0KXVpbnQ2NCIKICAgIG1ldGhvZCAiYXJjNF9iaWd1aW50X24odWludDEyOCx1aW50MjU2LHVpbnQ1MTIpdWludDUxMiIKICAgIG1ldGhvZCAiYXJjNF9ieXRlKGJ5dGUpYnl0ZSIKICAgIG1ldGhvZCAiYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXMoYWRkcmVzcyl1aW50NjQiCiAgICBtZXRob2QgImFyYzRfYWRkcmVzc19yZXR1cm4oYWRkcmVzcylhZGRyZXNzIgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAogICAgbWF0Y2ggX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF91aW50NjRfcm91dGVAMiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X3VpbnRfbl9yb3V0ZUAzIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYmlndWludF9uX3JvdXRlQDQgX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9ieXRlX3JvdXRlQDUgX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXNfcm91dGVANiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2FkZHJlc3NfcmV0dXJuX3JvdXRlQDcKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdWludDY0X3JvdXRlQDI6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAyCiAgICBjYWxsc3ViIGFyYzRfdWludDY0CiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X3VpbnRfbl9yb3V0ZUAzOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgNAogICAgY2FsbHN1YiBhcmM0X3VpbnRfbgogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9iaWd1aW50X25fcm91dGVANDoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDMKICAgIGNhbGxzdWIgYXJjNF9iaWd1aW50X24KICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYnl0ZV9yb3V0ZUA1OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgY2FsbHN1YiBhcmM0X2J5dGUKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYWRkcmVzc19wcm9wZXJ0aWVzX3JvdXRlQDY6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICBjYWxsc3ViIGFyYzRfYWRkcmVzc19wcm9wZXJ0aWVzCiAgICBpdG9iCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2FkZHJlc3NfcmV0dXJuX3JvdXRlQDc6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICBjYWxsc3ViIGFyYzRfYWRkcmVzc19yZXR1cm4KICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0AxMDoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgIGJueiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDE0CiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgIQogICAgYXNzZXJ0IC8vIGlzIGNyZWF0aW5nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDE0OgogICAgaW50IDAKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X3VpbnQ2NChhOiBieXRlcywgYjogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X3VpbnQ2NDoKICAgIHByb3RvIDIgMQogICAgZnJhbWVfZGlnIC0yCiAgICBidG9pCiAgICBmcmFtZV9kaWcgLTEKICAgIGJ0b2kKICAgICsKICAgIGl0b2IKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X3VpbnRfbihhOiBieXRlcywgYjogYnl0ZXMsIGM6IGJ5dGVzLCBkOiBieXRlcykgLT4gYnl0ZXM6CmFyYzRfdWludF9uOgogICAgcHJvdG8gNCAxCiAgICBmcmFtZV9kaWcgLTQKICAgIGxlbgogICAgaW50IDEKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMwogICAgbGVuCiAgICBpbnQgMgogICAgPT0KICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0yCiAgICBsZW4KICAgIGludCA0CiAgICA9PQogICAgYXNzZXJ0CiAgICBmcmFtZV9kaWcgLTEKICAgIGxlbgogICAgaW50IDgKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtNAogICAgYnRvaQogICAgZnJhbWVfZGlnIC0zCiAgICBidG9pCiAgICArCiAgICBmcmFtZV9kaWcgLTIKICAgIGJ0b2kKICAgICsKICAgIGZyYW1lX2RpZyAtMQogICAgYnRvaQogICAgKwogICAgaXRvYgogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFyYzRfYmlndWludF9uKGE6IGJ5dGVzLCBiOiBieXRlcywgYzogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X2JpZ3VpbnRfbjoKICAgIHByb3RvIDMgMQogICAgZnJhbWVfZGlnIC0zCiAgICBsZW4KICAgIGludCAxNgogICAgPT0KICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0yCiAgICBsZW4KICAgIGludCAzMgogICAgPT0KICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0xCiAgICBsZW4KICAgIGludCA2NAogICAgPT0KICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0zCiAgICBmcmFtZV9kaWcgLTIKICAgIGIrCiAgICBmcmFtZV9kaWcgLTEKICAgIGIrCiAgICBkdXAKICAgIGxlbgogICAgaW50IDY0CiAgICA8PQogICAgYXNzZXJ0IC8vIG92ZXJmbG93CiAgICBpbnQgNjQKICAgIGJ6ZXJvCiAgICBifAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFyYzRfYnl0ZShhOiBieXRlcykgLT4gYnl0ZXM6CmFyYzRfYnl0ZToKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBidG9pCiAgICBpbnQgMQogICAgKwogICAgaXRvYgogICAgZXh0cmFjdCA3IDEKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X2FkZHJlc3NfcHJvcGVydGllcyhhZGRyZXNzOiBieXRlcykgLT4gdWludDY0OgphcmM0X2FkZHJlc3NfcHJvcGVydGllczoKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBhY2N0X3BhcmFtc19nZXQgQWNjdEJhbGFuY2UKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgZnJhbWVfZGlnIC0xCiAgICBhY2N0X3BhcmFtc19nZXQgQWNjdFRvdGFsQXNzZXRzCiAgICBidXJ5IDEKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFyYzRfYWRkcmVzc19yZXR1cm4oYWRkcmVzczogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X2FkZHJlc3NfcmV0dXJuOgogICAgcHJvdG8gMSAxCiAgICBmcmFtZV9kaWcgLTEKICAgIHJldHN1Ygo=", "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" }, "state": { @@ -139,6 +144,19 @@ }, "desc": "Integers with larger bit size are supported up to 512 bits.\nUltimately, they are all represented with native BigUInt." }, + { + "name": "arc4_byte", + "args": [ + { + "type": "byte", + "name": "a" + } + ], + "returns": { + "type": "byte" + }, + "desc": "An arc4.Byte is essentially an alias for an 8-bit integer." + }, { "name": "arc4_address_properties", "args": [ @@ -285,6 +303,17 @@ def method() -> str: return "arc4_biguint_n(uint128,uint256,uint512)uint512" +@dataclasses.dataclass(kw_only=True) +class Arc4ByteArgs(_ArgsBase[int]): + """An arc4.Byte is essentially an alias for an 8-bit integer.""" + + a: int + + @staticmethod + def method() -> str: + return "arc4_byte(byte)byte" + + @dataclasses.dataclass(kw_only=True) class Arc4AddressPropertiesArgs(_ArgsBase[int]): address: str @@ -430,6 +459,31 @@ def arc4_biguint_n( ) return self + def arc4_byte( + self, + *, + a: int, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> "Composer": + """An arc4.Byte is essentially an alias for an 8-bit integer. + + Adds a call to `arc4_byte(byte)byte` ABI method + + :param int a: The `a` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + args = Arc4ByteArgs( + a=a, + ) + self.app_client.compose_call( + self.atc, + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return self + def arc4_address_properties( self, *, @@ -728,6 +782,30 @@ def arc4_biguint_n( ) return result + def arc4_byte( + self, + *, + a: int, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> algokit_utils.ABITransactionResponse[int]: + """An arc4.Byte is essentially an alias for an 8-bit integer. + + Calls `arc4_byte(byte)byte` ABI method + + :param int a: The `a` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.ABITransactionResponse[int]: The result of the transaction""" + + args = Arc4ByteArgs( + a=a, + ) + result = self.app_client.call( + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return result + def arc4_address_properties( self, *, diff --git a/projects/python-contract-examples/tests/arc4_types_integration_test.py b/projects/python-contract-examples/tests/arc4_types_integration_test.py index 3070a82..ab972a2 100644 --- a/projects/python-contract-examples/tests/arc4_types_integration_test.py +++ b/projects/python-contract-examples/tests/arc4_types_integration_test.py @@ -7,6 +7,7 @@ from algokit_utils.config import config from algosdk.v2client.algod import AlgodClient +from smart_contracts.artifacts.arc4_types.arc4_dynamic_array_client import Arc4DynamicArrayClient, SimulateOptions from smart_contracts.artifacts.arc4_types.arc4_static_array_client import ( Arc4StaticArrayClient, ) @@ -85,6 +86,36 @@ def arc4_statc_array_app_client( return client +@pytest.fixture(scope="session") +def arc4_dynamic_array_app_client( + algod_client: AlgodClient, creator: AddressAndSigner, algorand: AlgorandClient +) -> Arc4DynamicArrayClient: + """Deploy the arc4 static array App and create an app client the creator will use to interact with the contract""" + + config.configure( + debug=True, + # trace_all=True, + ) + + client = Arc4DynamicArrayClient( + algod_client, + sender=creator.address, + signer=creator.signer, + ) + + client.create_bare() + + algorand.send.payment( + PayParams( + sender=creator.address, + receiver=client.app_address, + amount=1000000, # 1 Algo + ) + ) + + return client + + @pytest.fixture(scope="session") def arc4_struct_app_client( algod_client: AlgodClient, creator: AddressAndSigner, algorand: AlgorandClient @@ -177,6 +208,16 @@ def test_arc4_biguint_n( assert result.return_value == 2**65 + 2**129 + 2**257 +def test_arc4_byte( + arc4_types_app_client: Arc4TypesClient, +) -> None: + """Test the arc4_byte method""" + + result = arc4_types_app_client.arc4_byte(a=5) + + assert result.return_value == 6 + + def test_arc4_address_properties( arc4_types_app_client: Arc4TypesClient, creator: AddressAndSigner, @@ -211,6 +252,24 @@ def test_arc4_static_array(arc4_statc_array_app_client: Arc4StaticArrayClient) - arc4_statc_array_app_client.arc4_static_array() +def test_arc4_dynamic_array(arc4_dynamic_array_app_client: Arc4DynamicArrayClient) -> None: + """Test the arc4_dynamic_array method""" + + # Call the arc4_static_array method with simulate to avoid opcode budget constraints. + result = arc4_dynamic_array_app_client.compose().arc4_dynamic_array(name="John").simulate(SimulateOptions(extra_opcode_budget=700)) + + assert result.abi_results[0].return_value == "Hello world, John" + + +def test_arc4_dynamic_bytes(arc4_dynamic_array_app_client: Arc4DynamicArrayClient) -> None: + """Test the arc4_dynamic_bytes method""" + + # Call the arc4_static_array method. + result = arc4_dynamic_array_app_client.arc4_dynamic_bytes() + + assert result.return_value == [0, 255, 255] + + def test_arc4_struct_add_todo(arc4_struct_app_client: Arc4StructClient) -> None: """Test the add_todo method""" From e6a8885ba1472bbd88d41728a3e7ba3322f1aa46 Mon Sep 17 00:00:00 2001 From: CiottiGiorgio Date: Mon, 4 Nov 2024 17:56:14 +0100 Subject: [PATCH 08/23] added tuples examples. --- .../smart_contracts/arc4_types/contract.py | 14 + .../arc4_types/Arc4Tuple.approval.teal | 104 ++++ .../artifacts/arc4_types/Arc4Tuple.arc32.json | 56 ++ .../artifacts/arc4_types/Arc4Tuple.clear.teal | 5 + .../artifacts/arc4_types/arc4_tuple_client.py | 499 ++++++++++++++++++ .../tests/arc4_types_integration_test.py | 41 ++ 6 files changed, 719 insertions(+) create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.approval.teal create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.arc32.json create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.clear.teal create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_tuple_client.py diff --git a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py index 3d3e19b..a0cd972 100644 --- a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py +++ b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py @@ -209,3 +209,17 @@ def return_todo(self, task: arc4.String) -> Todo: assert exist return todo_to_return + + +class Arc4Tuple(ARC4Contract): + + @abimethod() + def arc4_tuple(self, a: arc4.Tuple[arc4.UInt8, arc4.String, arc4.UInt64, arc4.DynamicArray[arc4.UInt32]]) -> arc4.String: + """An arc4.Tuple is a heterogeneous collection of arc4 types.""" + + total = a[0].native + a[2].native + + for x in a[3]: + total += x.native + + return a[1] diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.approval.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.approval.teal new file mode 100644 index 0000000..025d4bd --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.approval.teal @@ -0,0 +1,104 @@ +#pragma version 10 + +smart_contracts.arc4_types.contract.Arc4Tuple.approval_program: + callsub __puya_arc4_router__ + return + + +// smart_contracts.arc4_types.contract.Arc4Tuple.__puya_arc4_router__() -> uint64: +__puya_arc4_router__: + proto 0 1 + txn NumAppArgs + bz __puya_arc4_router___bare_routing@5 + method "arc4_tuple((uint8,string,uint64,uint32[]))string" + txna ApplicationArgs 0 + match __puya_arc4_router___arc4_tuple_route@2 + int 0 + retsub + +__puya_arc4_router___arc4_tuple_route@2: + txn OnCompletion + ! + assert // OnCompletion is NoOp + txn ApplicationID + assert // is not creating + txna ApplicationArgs 1 + callsub arc4_tuple + byte 0x151f7c75 + swap + concat + log + int 1 + retsub + +__puya_arc4_router___bare_routing@5: + txn OnCompletion + bnz __puya_arc4_router___after_if_else@9 + txn ApplicationID + ! + assert // is creating + int 1 + retsub + +__puya_arc4_router___after_if_else@9: + int 0 + retsub + + +// smart_contracts.arc4_types.contract.Arc4Tuple.arc4_tuple(a: bytes) -> bytes: +arc4_tuple: + proto 1 1 + frame_dig -1 + extract 0 1 // on error: Index access is out of bounds + btoi + frame_dig -1 + extract 3 8 // on error: Index access is out of bounds + btoi + + + frame_dig -1 + int 11 + extract_uint16 + dup + frame_dig -1 + len + frame_dig -1 + cover 2 + substring3 + dup + int 0 + extract_uint16 + int 0 + +arc4_tuple_for_header@1: + frame_dig 4 + frame_dig 3 + < + bz arc4_tuple_after_for@4 + frame_dig 2 + extract 2 0 + frame_dig 4 + dup + cover 2 + int 4 + * + int 4 + extract3 // on error: Index access is out of bounds + btoi + frame_dig 0 + + + frame_bury 0 + int 1 + + + frame_bury 4 + b arc4_tuple_for_header@1 + +arc4_tuple_after_for@4: + frame_dig -1 + int 1 + extract_uint16 + frame_dig -1 + swap + frame_dig 1 + substring3 + frame_bury 0 + retsub diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.arc32.json b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.arc32.json new file mode 100644 index 0000000..c8e910f --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.arc32.json @@ -0,0 +1,56 @@ +{ + "hints": { + "arc4_tuple((uint8,string,uint64,uint32[]))string": { + "call_config": { + "no_op": "CALL" + } + } + }, + "source": { + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHVwbGUuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUdXBsZS5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANQogICAgbWV0aG9kICJhcmM0X3R1cGxlKCh1aW50OCxzdHJpbmcsdWludDY0LHVpbnQzMltdKSlzdHJpbmciCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAwCiAgICBtYXRjaCBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X3R1cGxlX3JvdXRlQDIKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdHVwbGVfcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF90dXBsZQogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDU6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBibnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUA5CiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgIQogICAgYXNzZXJ0IC8vIGlzIGNyZWF0aW5nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDk6CiAgICBpbnQgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLmFyYzRfdHVwbGUoYTogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X3R1cGxlOgogICAgcHJvdG8gMSAxCiAgICBmcmFtZV9kaWcgLTEKICAgIGV4dHJhY3QgMCAxIC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgYnRvaQogICAgZnJhbWVfZGlnIC0xCiAgICBleHRyYWN0IDMgOCAvLyBvbiBlcnJvcjogSW5kZXggYWNjZXNzIGlzIG91dCBvZiBib3VuZHMKICAgIGJ0b2kKICAgICsKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDExCiAgICBleHRyYWN0X3VpbnQxNgogICAgZHVwCiAgICBmcmFtZV9kaWcgLTEKICAgIGxlbgogICAgZnJhbWVfZGlnIC0xCiAgICBjb3ZlciAyCiAgICBzdWJzdHJpbmczCiAgICBkdXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50IDAKCmFyYzRfdHVwbGVfZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDQKICAgIGZyYW1lX2RpZyAzCiAgICA8CiAgICBieiBhcmM0X3R1cGxlX2FmdGVyX2ZvckA0CiAgICBmcmFtZV9kaWcgMgogICAgZXh0cmFjdCAyIDAKICAgIGZyYW1lX2RpZyA0CiAgICBkdXAKICAgIGNvdmVyIDIKICAgIGludCA0CiAgICAqCiAgICBpbnQgNAogICAgZXh0cmFjdDMgLy8gb24gZXJyb3I6IEluZGV4IGFjY2VzcyBpcyBvdXQgb2YgYm91bmRzCiAgICBidG9pCiAgICBmcmFtZV9kaWcgMAogICAgKwogICAgZnJhbWVfYnVyeSAwCiAgICBpbnQgMQogICAgKwogICAgZnJhbWVfYnVyeSA0CiAgICBiIGFyYzRfdHVwbGVfZm9yX2hlYWRlckAxCgphcmM0X3R1cGxlX2FmdGVyX2ZvckA0OgogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMQogICAgZXh0cmFjdF91aW50MTYKICAgIGZyYW1lX2RpZyAtMQogICAgc3dhcAogICAgZnJhbWVfZGlnIDEKICAgIHN1YnN0cmluZzMKICAgIGZyYW1lX2J1cnkgMAogICAgcmV0c3ViCg==", + "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHVwbGUuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" + }, + "state": { + "global": { + "num_byte_slices": 0, + "num_uints": 0 + }, + "local": { + "num_byte_slices": 0, + "num_uints": 0 + } + }, + "schema": { + "global": { + "declared": {}, + "reserved": {} + }, + "local": { + "declared": {}, + "reserved": {} + } + }, + "contract": { + "name": "Arc4Tuple", + "methods": [ + { + "name": "arc4_tuple", + "args": [ + { + "type": "(uint8,string,uint64,uint32[])", + "name": "a" + } + ], + "readonly": false, + "returns": { + "type": "string" + }, + "desc": "An arc4.Tuple is a heterogeneous collection of arc4 types." + } + ], + "networks": {} + }, + "bare_call_config": { + "no_op": "CREATE" + } +} \ No newline at end of file diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.clear.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.clear.teal new file mode 100644 index 0000000..3150069 --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.clear.teal @@ -0,0 +1,5 @@ +#pragma version 10 + +smart_contracts.arc4_types.contract.Arc4Tuple.clear_state_program: + int 1 + return diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_tuple_client.py b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_tuple_client.py new file mode 100644 index 0000000..e78a989 --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_tuple_client.py @@ -0,0 +1,499 @@ +# flake8: noqa +# fmt: off +# mypy: disable-error-code="no-any-return, no-untyped-call, misc, type-arg" +# This file was automatically generated by algokit-client-generator. +# DO NOT MODIFY IT BY HAND. +# requires: algokit-utils@^1.2.0 +import base64 +import dataclasses +import decimal +import typing +from abc import ABC, abstractmethod + +import algokit_utils +import algosdk +from algosdk.v2client import models +from algosdk.atomic_transaction_composer import ( + AtomicTransactionComposer, + AtomicTransactionResponse, + SimulateAtomicTransactionResponse, + TransactionSigner, + TransactionWithSigner +) + +_APP_SPEC_JSON = r"""{ + "hints": { + "arc4_tuple((uint8,string,uint64,uint32[]))string": { + "call_config": { + "no_op": "CALL" + } + } + }, + "source": { + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHVwbGUuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUdXBsZS5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANQogICAgbWV0aG9kICJhcmM0X3R1cGxlKCh1aW50OCxzdHJpbmcsdWludDY0LHVpbnQzMltdKSlzdHJpbmciCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAwCiAgICBtYXRjaCBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X3R1cGxlX3JvdXRlQDIKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdHVwbGVfcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF90dXBsZQogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDU6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBibnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUA5CiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgIQogICAgYXNzZXJ0IC8vIGlzIGNyZWF0aW5nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDk6CiAgICBpbnQgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLmFyYzRfdHVwbGUoYTogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X3R1cGxlOgogICAgcHJvdG8gMSAxCiAgICBmcmFtZV9kaWcgLTEKICAgIGV4dHJhY3QgMCAxIC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgYnRvaQogICAgZnJhbWVfZGlnIC0xCiAgICBleHRyYWN0IDMgOCAvLyBvbiBlcnJvcjogSW5kZXggYWNjZXNzIGlzIG91dCBvZiBib3VuZHMKICAgIGJ0b2kKICAgICsKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDExCiAgICBleHRyYWN0X3VpbnQxNgogICAgZHVwCiAgICBmcmFtZV9kaWcgLTEKICAgIGxlbgogICAgZnJhbWVfZGlnIC0xCiAgICBjb3ZlciAyCiAgICBzdWJzdHJpbmczCiAgICBkdXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50IDAKCmFyYzRfdHVwbGVfZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDQKICAgIGZyYW1lX2RpZyAzCiAgICA8CiAgICBieiBhcmM0X3R1cGxlX2FmdGVyX2ZvckA0CiAgICBmcmFtZV9kaWcgMgogICAgZXh0cmFjdCAyIDAKICAgIGZyYW1lX2RpZyA0CiAgICBkdXAKICAgIGNvdmVyIDIKICAgIGludCA0CiAgICAqCiAgICBpbnQgNAogICAgZXh0cmFjdDMgLy8gb24gZXJyb3I6IEluZGV4IGFjY2VzcyBpcyBvdXQgb2YgYm91bmRzCiAgICBidG9pCiAgICBmcmFtZV9kaWcgMAogICAgKwogICAgZnJhbWVfYnVyeSAwCiAgICBpbnQgMQogICAgKwogICAgZnJhbWVfYnVyeSA0CiAgICBiIGFyYzRfdHVwbGVfZm9yX2hlYWRlckAxCgphcmM0X3R1cGxlX2FmdGVyX2ZvckA0OgogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMQogICAgZXh0cmFjdF91aW50MTYKICAgIGZyYW1lX2RpZyAtMQogICAgc3dhcAogICAgZnJhbWVfZGlnIDEKICAgIHN1YnN0cmluZzMKICAgIGZyYW1lX2J1cnkgMAogICAgcmV0c3ViCg==", + "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHVwbGUuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" + }, + "state": { + "global": { + "num_byte_slices": 0, + "num_uints": 0 + }, + "local": { + "num_byte_slices": 0, + "num_uints": 0 + } + }, + "schema": { + "global": { + "declared": {}, + "reserved": {} + }, + "local": { + "declared": {}, + "reserved": {} + } + }, + "contract": { + "name": "Arc4Tuple", + "methods": [ + { + "name": "arc4_tuple", + "args": [ + { + "type": "(uint8,string,uint64,uint32[])", + "name": "a" + } + ], + "returns": { + "type": "string" + }, + "desc": "An arc4.Tuple is a heterogeneous collection of arc4 types." + } + ], + "networks": {} + }, + "bare_call_config": { + "no_op": "CREATE" + } +}""" +APP_SPEC = algokit_utils.ApplicationSpecification.from_json(_APP_SPEC_JSON) +_TReturn = typing.TypeVar("_TReturn") + + +class _ArgsBase(ABC, typing.Generic[_TReturn]): + @staticmethod + @abstractmethod + def method() -> str: + ... + + +_TArgs = typing.TypeVar("_TArgs", bound=_ArgsBase[typing.Any]) + + +@dataclasses.dataclass(kw_only=True) +class _TArgsHolder(typing.Generic[_TArgs]): + args: _TArgs + + +def _filter_none(value: dict | typing.Any) -> dict | typing.Any: + if isinstance(value, dict): + return {k: _filter_none(v) for k, v in value.items() if v is not None} + return value + + +def _as_dict(data: typing.Any, *, convert_all: bool = True) -> dict[str, typing.Any]: + if data is None: + return {} + if not dataclasses.is_dataclass(data): + raise TypeError(f"{data} must be a dataclass") + if convert_all: + result = dataclasses.asdict(data) # type: ignore[call-overload] + else: + result = {f.name: getattr(data, f.name) for f in dataclasses.fields(data)} + return _filter_none(result) + + +def _convert_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, +) -> algokit_utils.TransactionParametersDict: + return typing.cast(algokit_utils.TransactionParametersDict, _as_dict(transaction_parameters)) + + +def _convert_call_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, +) -> algokit_utils.OnCompleteCallParametersDict: + return typing.cast(algokit_utils.OnCompleteCallParametersDict, _as_dict(transaction_parameters)) + + +def _convert_create_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, + on_complete: algokit_utils.OnCompleteActionName, +) -> algokit_utils.CreateCallParametersDict: + result = typing.cast(algokit_utils.CreateCallParametersDict, _as_dict(transaction_parameters)) + on_complete_enum = on_complete.replace("_", " ").title().replace(" ", "") + "OC" + result["on_complete"] = getattr(algosdk.transaction.OnComplete, on_complete_enum) + return result + + +def _convert_deploy_args( + deploy_args: algokit_utils.DeployCallArgs | None, +) -> algokit_utils.ABICreateCallArgsDict | None: + if deploy_args is None: + return None + + deploy_args_dict = typing.cast(algokit_utils.ABICreateCallArgsDict, _as_dict(deploy_args)) + if isinstance(deploy_args, _TArgsHolder): + deploy_args_dict["args"] = _as_dict(deploy_args.args) + deploy_args_dict["method"] = deploy_args.args.method() + + return deploy_args_dict + + +@dataclasses.dataclass(kw_only=True) +class Arc4TupleArgs(_ArgsBase[str]): + """An arc4.Tuple is a heterogeneous collection of arc4 types.""" + + a: tuple[int, str, int, list[int]] + + @staticmethod + def method() -> str: + return "arc4_tuple((uint8,string,uint64,uint32[]))string" + + +@dataclasses.dataclass(kw_only=True) +class SimulateOptions: + allow_more_logs: bool = dataclasses.field(default=False) + allow_empty_signatures: bool = dataclasses.field(default=False) + extra_opcode_budget: int = dataclasses.field(default=0) + exec_trace_config: models.SimulateTraceConfig | None = dataclasses.field(default=None) + + +class Composer: + + def __init__(self, app_client: algokit_utils.ApplicationClient, atc: AtomicTransactionComposer): + self.app_client = app_client + self.atc = atc + + def build(self) -> AtomicTransactionComposer: + return self.atc + + def simulate(self, options: SimulateOptions | None = None) -> SimulateAtomicTransactionResponse: + request = models.SimulateRequest( + allow_more_logs=options.allow_more_logs, + allow_empty_signatures=options.allow_empty_signatures, + extra_opcode_budget=options.extra_opcode_budget, + exec_trace_config=options.exec_trace_config, + txn_groups=[] + ) if options else None + result = self.atc.simulate(self.app_client.algod_client, request) + return result + + def execute(self) -> AtomicTransactionResponse: + return self.app_client.execute_atc(self.atc) + + def arc4_tuple( + self, + *, + a: tuple[int, str, int, list[int]], + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> "Composer": + """An arc4.Tuple is a heterogeneous collection of arc4 types. + + Adds a call to `arc4_tuple((uint8,string,uint64,uint32[]))string` ABI method + + :param tuple[int, str, int, list[int]] a: The `a` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + args = Arc4TupleArgs( + a=a, + ) + self.app_client.compose_call( + self.atc, + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return self + + def create_bare( + self, + *, + on_complete: typing.Literal["no_op"] = "no_op", + transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, + ) -> "Composer": + """Adds a call to create an application using the no_op bare method + + :param typing.Literal[no_op] on_complete: On completion type to use + :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + self.app_client.compose_create( + self.atc, + call_abi_method=False, + transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), + ) + return self + + def clear_state( + self, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + app_args: list[bytes] | None = None, + ) -> "Composer": + """Adds a call to the application with on completion set to ClearState + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :param list[bytes] | None app_args: (optional) Application args to pass""" + + self.app_client.compose_clear_state(self.atc, _convert_transaction_parameters(transaction_parameters), app_args) + return self + + +class Arc4TupleClient: + """A class for interacting with the Arc4Tuple app providing high productivity and + strongly typed methods to deploy and call the app""" + + @typing.overload + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + app_id: int = 0, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + ... + + @typing.overload + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + creator: str | algokit_utils.Account, + indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, + existing_deployments: algokit_utils.AppLookup | None = None, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + ... + + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + creator: str | algokit_utils.Account | None = None, + indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, + existing_deployments: algokit_utils.AppLookup | None = None, + app_id: int = 0, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + """ + Arc4TupleClient can be created with an app_id to interact with an existing application, alternatively + it can be created with a creator and indexer_client specified to find existing applications by name and creator. + + :param AlgodClient algod_client: AlgoSDK algod client + :param int app_id: The app_id of an existing application, to instead find the application by creator and name + use the creator and indexer_client parameters + :param str | Account creator: The address or Account of the app creator to resolve the app_id + :param IndexerClient indexer_client: AlgoSDK indexer client, only required if deploying or finding app_id by + creator and app name + :param AppLookup existing_deployments: + :param TransactionSigner | Account signer: Account or signer to use to sign transactions, if not specified and + creator was passed as an Account will use that. + :param str sender: Address to use as the sender for all transactions, will use the address associated with the + signer if not specified. + :param TemplateValueMapping template_values: Values to use for TMPL_* template variables, dictionary keys should + *NOT* include the TMPL_ prefix + :param str | None app_name: Name of application to use when deploying, defaults to name defined on the + Application Specification + """ + + self.app_spec = APP_SPEC + + # calling full __init__ signature, so ignoring mypy warning about overloads + self.app_client = algokit_utils.ApplicationClient( # type: ignore[call-overload, misc] + algod_client=algod_client, + app_spec=self.app_spec, + app_id=app_id, + creator=creator, + indexer_client=indexer_client, + existing_deployments=existing_deployments, + signer=signer, + sender=sender, + suggested_params=suggested_params, + template_values=template_values, + app_name=app_name, + ) + + @property + def algod_client(self) -> algosdk.v2client.algod.AlgodClient: + return self.app_client.algod_client + + @property + def app_id(self) -> int: + return self.app_client.app_id + + @app_id.setter + def app_id(self, value: int) -> None: + self.app_client.app_id = value + + @property + def app_address(self) -> str: + return self.app_client.app_address + + @property + def sender(self) -> str | None: + return self.app_client.sender + + @sender.setter + def sender(self, value: str) -> None: + self.app_client.sender = value + + @property + def signer(self) -> TransactionSigner | None: + return self.app_client.signer + + @signer.setter + def signer(self, value: TransactionSigner) -> None: + self.app_client.signer = value + + @property + def suggested_params(self) -> algosdk.transaction.SuggestedParams | None: + return self.app_client.suggested_params + + @suggested_params.setter + def suggested_params(self, value: algosdk.transaction.SuggestedParams | None) -> None: + self.app_client.suggested_params = value + + def arc4_tuple( + self, + *, + a: tuple[int, str, int, list[int]], + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> algokit_utils.ABITransactionResponse[str]: + """An arc4.Tuple is a heterogeneous collection of arc4 types. + + Calls `arc4_tuple((uint8,string,uint64,uint32[]))string` ABI method + + :param tuple[int, str, int, list[int]] a: The `a` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.ABITransactionResponse[str]: The result of the transaction""" + + args = Arc4TupleArgs( + a=a, + ) + result = self.app_client.call( + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return result + + def create_bare( + self, + *, + on_complete: typing.Literal["no_op"] = "no_op", + transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, + ) -> algokit_utils.TransactionResponse: + """Creates an application using the no_op bare method + + :param typing.Literal[no_op] on_complete: On completion type to use + :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.TransactionResponse: The result of the transaction""" + + result = self.app_client.create( + call_abi_method=False, + transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), + ) + return result + + def clear_state( + self, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + app_args: list[bytes] | None = None, + ) -> algokit_utils.TransactionResponse: + """Calls the application with on completion set to ClearState + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :param list[bytes] | None app_args: (optional) Application args to pass + :returns algokit_utils.TransactionResponse: The result of the transaction""" + + return self.app_client.clear_state(_convert_transaction_parameters(transaction_parameters), app_args) + + def deploy( + self, + version: str | None = None, + *, + signer: TransactionSigner | None = None, + sender: str | None = None, + allow_update: bool | None = None, + allow_delete: bool | None = None, + on_update: algokit_utils.OnUpdate = algokit_utils.OnUpdate.Fail, + on_schema_break: algokit_utils.OnSchemaBreak = algokit_utils.OnSchemaBreak.Fail, + template_values: algokit_utils.TemplateValueMapping | None = None, + create_args: algokit_utils.DeployCallArgs | None = None, + update_args: algokit_utils.DeployCallArgs | None = None, + delete_args: algokit_utils.DeployCallArgs | None = None, + ) -> algokit_utils.DeployResponse: + """Deploy an application and update client to reference it. + + Idempotently deploy (create, update/delete if changed) an app against the given name via the given creator + account, including deploy-time template placeholder substitutions. + To understand the architecture decisions behind this functionality please see + + + ```{note} + If there is a breaking state schema change to an existing app (and `on_schema_break` is set to + 'ReplaceApp' the existing app will be deleted and re-created. + ``` + + ```{note} + If there is an update (different TEAL code) to an existing app (and `on_update` is set to 'ReplaceApp') + the existing app will be deleted and re-created. + ``` + + :param str version: version to use when creating or updating app, if None version will be auto incremented + :param algosdk.atomic_transaction_composer.TransactionSigner signer: signer to use when deploying app + , if None uses self.signer + :param str sender: sender address to use when deploying app, if None uses self.sender + :param bool allow_delete: Used to set the `TMPL_DELETABLE` template variable to conditionally control if an app + can be deleted + :param bool allow_update: Used to set the `TMPL_UPDATABLE` template variable to conditionally control if an app + can be updated + :param OnUpdate on_update: Determines what action to take if an application update is required + :param OnSchemaBreak on_schema_break: Determines what action to take if an application schema requirements + has increased beyond the current allocation + :param dict[str, int|str|bytes] template_values: Values to use for `TMPL_*` template variables, dictionary keys + should *NOT* include the TMPL_ prefix + :param algokit_utils.DeployCallArgs | None create_args: Arguments used when creating an application + :param algokit_utils.DeployCallArgs | None update_args: Arguments used when updating an application + :param algokit_utils.DeployCallArgs | None delete_args: Arguments used when deleting an application + :return DeployResponse: details action taken and relevant transactions + :raises DeploymentError: If the deployment failed""" + + return self.app_client.deploy( + version, + signer=signer, + sender=sender, + allow_update=allow_update, + allow_delete=allow_delete, + on_update=on_update, + on_schema_break=on_schema_break, + template_values=template_values, + create_args=_convert_deploy_args(create_args), + update_args=_convert_deploy_args(update_args), + delete_args=_convert_deploy_args(delete_args), + ) + + def compose(self, atc: AtomicTransactionComposer | None = None) -> Composer: + return Composer(self.app_client, atc or AtomicTransactionComposer()) diff --git a/projects/python-contract-examples/tests/arc4_types_integration_test.py b/projects/python-contract-examples/tests/arc4_types_integration_test.py index ab972a2..1e5681a 100644 --- a/projects/python-contract-examples/tests/arc4_types_integration_test.py +++ b/projects/python-contract-examples/tests/arc4_types_integration_test.py @@ -12,6 +12,7 @@ Arc4StaticArrayClient, ) from smart_contracts.artifacts.arc4_types.arc4_struct_client import Arc4StructClient +from smart_contracts.artifacts.arc4_types.arc4_tuple_client import Arc4TupleClient from smart_contracts.artifacts.arc4_types.arc4_types_client import Arc4TypesClient @@ -116,6 +117,36 @@ def arc4_dynamic_array_app_client( return client +@pytest.fixture(scope="session") +def arc4_tuple_app_client( + algod_client: AlgodClient, creator: AddressAndSigner, algorand: AlgorandClient +) -> Arc4TupleClient: + """Deploy the arc4 static array App and create an app client the creator will use to interact with the contract""" + + config.configure( + debug=True, + # trace_all=True, + ) + + client = Arc4TupleClient( + algod_client, + sender=creator.address, + signer=creator.signer, + ) + + client.create_bare() + + algorand.send.payment( + PayParams( + sender=creator.address, + receiver=client.app_address, + amount=1000000, # 1 Algo + ) + ) + + return client + + @pytest.fixture(scope="session") def arc4_struct_app_client( algod_client: AlgodClient, creator: AddressAndSigner, algorand: AlgorandClient @@ -303,3 +334,13 @@ def test_arc4_struct_complete_and_return_todo( # Check the result assert result.return_value.task == "walk my dogs" assert result.return_value.completed is True + + +def test_arc4_tuple( + arc4_tuple_app_client: Arc4TupleClient, +) -> None: + """Test the arc4_tuple method""" + + result = arc4_tuple_app_client.arc4_tuple(a=(4, "This is a good string.", 100, [1, 2, 3])) + + assert result.return_value == "This is a good string." From d71c8fff727f9b7d59bd74732f8afb32aef76df3 Mon Sep 17 00:00:00 2001 From: CiottiGiorgio Date: Tue, 5 Nov 2024 10:21:31 +0100 Subject: [PATCH 09/23] fix linting. --- .../smart_contracts/arc4_types/contract.py | 21 ++++++++++++----- .../arc4_types/deploy_config.py | 6 ----- .../tests/arc4_types_integration_test.py | 23 +++++++++++++++---- 3 files changed, 33 insertions(+), 17 deletions(-) diff --git a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py index a0cd972..8b049ca 100644 --- a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py +++ b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py @@ -1,7 +1,7 @@ # pyright: reportMissingModuleSource=false import typing as t -from algopy import ARC4Contract, GlobalState, UInt64, arc4, urange, String, Bytes +from algopy import ARC4Contract, GlobalState, String, UInt64, arc4, urange from algopy.arc4 import abimethod @@ -38,7 +38,9 @@ def arc4_uint_n( return arc4.UInt64(total) @abimethod() - def arc4_biguint_n(self, a: arc4.UInt128, b: arc4.UInt256, c: arc4.UInt512) -> arc4.UInt512: + def arc4_biguint_n( + self, a: arc4.UInt128, b: arc4.UInt256, c: arc4.UInt512 + ) -> arc4.UInt512: """ Integers with larger bit size are supported up to 512 bits. Ultimately, they are all represented with native BigUInt. @@ -60,7 +62,7 @@ def arc4_byte(self, a: arc4.Byte) -> arc4.Byte: @abimethod() def arc4_address_properties(self, address: arc4.Address) -> UInt64: - underlying_bytes = ( + underlying_bytes = ( # noqa: F841 address.bytes ) # This will return the underlying bytes of the address. @@ -69,7 +71,7 @@ def arc4_address_properties(self, address: arc4.Address) -> UInt64: ) # This will return the account type of the given address. bal = account.balance # returns the balance of the account - total_asset = ( + total_asset = ( # noqa: F841 account.total_assets ) # returns the total assets held in the account @@ -140,7 +142,9 @@ def arc4_dynamic_array(self, name: arc4.String) -> arc4.String: """ dynamic_string_array = arc4.DynamicArray[arc4.String](arc4.String("Hello")) - extension = arc4.DynamicArray[arc4.String](arc4.String(" world"), arc4.String(", ")) + extension = arc4.DynamicArray[arc4.String]( + arc4.String(" world"), arc4.String(", ") + ) dynamic_string_array.extend(extension) dynamic_string_array.append(name) @@ -214,7 +218,12 @@ def return_todo(self, task: arc4.String) -> Todo: class Arc4Tuple(ARC4Contract): @abimethod() - def arc4_tuple(self, a: arc4.Tuple[arc4.UInt8, arc4.String, arc4.UInt64, arc4.DynamicArray[arc4.UInt32]]) -> arc4.String: + def arc4_tuple( + self, + a: arc4.Tuple[ + arc4.UInt8, arc4.String, arc4.UInt64, arc4.DynamicArray[arc4.UInt32] + ], + ) -> arc4.String: """An arc4.Tuple is a heterogeneous collection of arc4 types.""" total = a[0].native + a[2].native diff --git a/projects/python-contract-examples/smart_contracts/arc4_types/deploy_config.py b/projects/python-contract-examples/smart_contracts/arc4_types/deploy_config.py index d5f6bdf..14805d6 100644 --- a/projects/python-contract-examples/smart_contracts/arc4_types/deploy_config.py +++ b/projects/python-contract-examples/smart_contracts/arc4_types/deploy_config.py @@ -28,9 +28,3 @@ def deploy( on_schema_break=algokit_utils.OnSchemaBreak.AppendApp, on_update=algokit_utils.OnUpdate.AppendApp, ) - name = "world" - response = app_client.hello(name=name) - logger.info( - f"Called hello on {app_spec.contract.name} ({app_client.app_id}) " - f"with name={name}, received: {response.return_value}" - ) diff --git a/projects/python-contract-examples/tests/arc4_types_integration_test.py b/projects/python-contract-examples/tests/arc4_types_integration_test.py index 1e5681a..4d4f03f 100644 --- a/projects/python-contract-examples/tests/arc4_types_integration_test.py +++ b/projects/python-contract-examples/tests/arc4_types_integration_test.py @@ -7,7 +7,10 @@ from algokit_utils.config import config from algosdk.v2client.algod import AlgodClient -from smart_contracts.artifacts.arc4_types.arc4_dynamic_array_client import Arc4DynamicArrayClient, SimulateOptions +from smart_contracts.artifacts.arc4_types.arc4_dynamic_array_client import ( + Arc4DynamicArrayClient, + SimulateOptions, +) from smart_contracts.artifacts.arc4_types.arc4_static_array_client import ( Arc4StaticArrayClient, ) @@ -283,16 +286,24 @@ def test_arc4_static_array(arc4_statc_array_app_client: Arc4StaticArrayClient) - arc4_statc_array_app_client.arc4_static_array() -def test_arc4_dynamic_array(arc4_dynamic_array_app_client: Arc4DynamicArrayClient) -> None: +def test_arc4_dynamic_array( + arc4_dynamic_array_app_client: Arc4DynamicArrayClient, +) -> None: """Test the arc4_dynamic_array method""" # Call the arc4_static_array method with simulate to avoid opcode budget constraints. - result = arc4_dynamic_array_app_client.compose().arc4_dynamic_array(name="John").simulate(SimulateOptions(extra_opcode_budget=700)) + result = ( + arc4_dynamic_array_app_client.compose() + .arc4_dynamic_array(name="John") + .simulate(SimulateOptions(extra_opcode_budget=700)) + ) assert result.abi_results[0].return_value == "Hello world, John" -def test_arc4_dynamic_bytes(arc4_dynamic_array_app_client: Arc4DynamicArrayClient) -> None: +def test_arc4_dynamic_bytes( + arc4_dynamic_array_app_client: Arc4DynamicArrayClient, +) -> None: """Test the arc4_dynamic_bytes method""" # Call the arc4_static_array method. @@ -341,6 +352,8 @@ def test_arc4_tuple( ) -> None: """Test the arc4_tuple method""" - result = arc4_tuple_app_client.arc4_tuple(a=(4, "This is a good string.", 100, [1, 2, 3])) + result = arc4_tuple_app_client.arc4_tuple( + a=(4, "This is a good string.", 100, [1, 2, 3]) + ) assert result.return_value == "This is a good string." From 16a068015aa12d2b9331e6e268298d2606a210a6 Mon Sep 17 00:00:00 2001 From: CiottiGiorgio Date: Wed, 6 Nov 2024 10:11:54 +0100 Subject: [PATCH 10/23] add return tuple example. --- .../smart_contracts/arc4_types/contract.py | 9 +- .../arc4_types/Arc4Tuple.approval.teal | 50 ++++++++--- .../artifacts/arc4_types/Arc4Tuple.arc32.json | 20 ++++- .../artifacts/arc4_types/arc4_tuple_client.py | 85 ++++++++++++++++--- .../tests/arc4_types_integration_test.py | 16 +++- 5 files changed, 148 insertions(+), 32 deletions(-) diff --git a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py index 8b049ca..216af58 100644 --- a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py +++ b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py @@ -218,7 +218,7 @@ def return_todo(self, task: arc4.String) -> Todo: class Arc4Tuple(ARC4Contract): @abimethod() - def arc4_tuple( + def arc4_tuple_argument( self, a: arc4.Tuple[ arc4.UInt8, arc4.String, arc4.UInt64, arc4.DynamicArray[arc4.UInt32] @@ -232,3 +232,10 @@ def arc4_tuple( total += x.native return a[1] + + @abimethod() + def arc4_tuple_return(self) -> arc4.Tuple[arc4.UInt128, arc4.String]: + """An arc4.Tuple can be returned when more than one return value is needed.""" + arc4_tuple = arc4.Tuple((arc4.UInt128(42), arc4.String("hello, world!"))) + + return arc4_tuple diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.approval.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.approval.teal index 025d4bd..4c5fbc2 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.approval.teal +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.approval.teal @@ -9,21 +9,22 @@ smart_contracts.arc4_types.contract.Arc4Tuple.approval_program: __puya_arc4_router__: proto 0 1 txn NumAppArgs - bz __puya_arc4_router___bare_routing@5 - method "arc4_tuple((uint8,string,uint64,uint32[]))string" + bz __puya_arc4_router___bare_routing@6 + method "arc4_tuple_argument((uint8,string,uint64,uint32[]))string" + method "arc4_tuple_return()(uint128,string)" txna ApplicationArgs 0 - match __puya_arc4_router___arc4_tuple_route@2 + match __puya_arc4_router___arc4_tuple_argument_route@2 __puya_arc4_router___arc4_tuple_return_route@3 int 0 retsub -__puya_arc4_router___arc4_tuple_route@2: +__puya_arc4_router___arc4_tuple_argument_route@2: txn OnCompletion ! assert // OnCompletion is NoOp txn ApplicationID assert // is not creating txna ApplicationArgs 1 - callsub arc4_tuple + callsub arc4_tuple_argument byte 0x151f7c75 swap concat @@ -31,22 +32,36 @@ __puya_arc4_router___arc4_tuple_route@2: int 1 retsub -__puya_arc4_router___bare_routing@5: +__puya_arc4_router___arc4_tuple_return_route@3: txn OnCompletion - bnz __puya_arc4_router___after_if_else@9 + ! + assert // OnCompletion is NoOp + txn ApplicationID + assert // is not creating + callsub arc4_tuple_return + byte 0x151f7c75 + swap + concat + log + int 1 + retsub + +__puya_arc4_router___bare_routing@6: + txn OnCompletion + bnz __puya_arc4_router___after_if_else@10 txn ApplicationID ! assert // is creating int 1 retsub -__puya_arc4_router___after_if_else@9: +__puya_arc4_router___after_if_else@10: int 0 retsub -// smart_contracts.arc4_types.contract.Arc4Tuple.arc4_tuple(a: bytes) -> bytes: -arc4_tuple: +// smart_contracts.arc4_types.contract.Arc4Tuple.arc4_tuple_argument(a: bytes) -> bytes: +arc4_tuple_argument: proto 1 1 frame_dig -1 extract 0 1 // on error: Index access is out of bounds @@ -69,11 +84,11 @@ arc4_tuple: extract_uint16 int 0 -arc4_tuple_for_header@1: +arc4_tuple_argument_for_header@1: frame_dig 4 frame_dig 3 < - bz arc4_tuple_after_for@4 + bz arc4_tuple_argument_after_for@4 frame_dig 2 extract 2 0 frame_dig 4 @@ -90,9 +105,9 @@ arc4_tuple_for_header@1: int 1 + frame_bury 4 - b arc4_tuple_for_header@1 + b arc4_tuple_argument_for_header@1 -arc4_tuple_after_for@4: +arc4_tuple_argument_after_for@4: frame_dig -1 int 1 extract_uint16 @@ -102,3 +117,10 @@ arc4_tuple_after_for@4: substring3 frame_bury 0 retsub + + +// smart_contracts.arc4_types.contract.Arc4Tuple.arc4_tuple_return() -> bytes: +arc4_tuple_return: + proto 0 1 + byte 0x0000000000000000000000000000002a0012000d68656c6c6f2c20776f726c6421 + retsub diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.arc32.json b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.arc32.json index c8e910f..9f7f02a 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.arc32.json +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.arc32.json @@ -1,13 +1,18 @@ { "hints": { - "arc4_tuple((uint8,string,uint64,uint32[]))string": { + "arc4_tuple_argument((uint8,string,uint64,uint32[]))string": { + "call_config": { + "no_op": "CALL" + } + }, + "arc4_tuple_return()(uint128,string)": { "call_config": { "no_op": "CALL" } } }, "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHVwbGUuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUdXBsZS5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANQogICAgbWV0aG9kICJhcmM0X3R1cGxlKCh1aW50OCxzdHJpbmcsdWludDY0LHVpbnQzMltdKSlzdHJpbmciCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAwCiAgICBtYXRjaCBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X3R1cGxlX3JvdXRlQDIKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdHVwbGVfcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF90dXBsZQogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDU6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBibnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUA5CiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgIQogICAgYXNzZXJ0IC8vIGlzIGNyZWF0aW5nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDk6CiAgICBpbnQgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLmFyYzRfdHVwbGUoYTogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X3R1cGxlOgogICAgcHJvdG8gMSAxCiAgICBmcmFtZV9kaWcgLTEKICAgIGV4dHJhY3QgMCAxIC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgYnRvaQogICAgZnJhbWVfZGlnIC0xCiAgICBleHRyYWN0IDMgOCAvLyBvbiBlcnJvcjogSW5kZXggYWNjZXNzIGlzIG91dCBvZiBib3VuZHMKICAgIGJ0b2kKICAgICsKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDExCiAgICBleHRyYWN0X3VpbnQxNgogICAgZHVwCiAgICBmcmFtZV9kaWcgLTEKICAgIGxlbgogICAgZnJhbWVfZGlnIC0xCiAgICBjb3ZlciAyCiAgICBzdWJzdHJpbmczCiAgICBkdXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50IDAKCmFyYzRfdHVwbGVfZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDQKICAgIGZyYW1lX2RpZyAzCiAgICA8CiAgICBieiBhcmM0X3R1cGxlX2FmdGVyX2ZvckA0CiAgICBmcmFtZV9kaWcgMgogICAgZXh0cmFjdCAyIDAKICAgIGZyYW1lX2RpZyA0CiAgICBkdXAKICAgIGNvdmVyIDIKICAgIGludCA0CiAgICAqCiAgICBpbnQgNAogICAgZXh0cmFjdDMgLy8gb24gZXJyb3I6IEluZGV4IGFjY2VzcyBpcyBvdXQgb2YgYm91bmRzCiAgICBidG9pCiAgICBmcmFtZV9kaWcgMAogICAgKwogICAgZnJhbWVfYnVyeSAwCiAgICBpbnQgMQogICAgKwogICAgZnJhbWVfYnVyeSA0CiAgICBiIGFyYzRfdHVwbGVfZm9yX2hlYWRlckAxCgphcmM0X3R1cGxlX2FmdGVyX2ZvckA0OgogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMQogICAgZXh0cmFjdF91aW50MTYKICAgIGZyYW1lX2RpZyAtMQogICAgc3dhcAogICAgZnJhbWVfZGlnIDEKICAgIHN1YnN0cmluZzMKICAgIGZyYW1lX2J1cnkgMAogICAgcmV0c3ViCg==", + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHVwbGUuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUdXBsZS5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANgogICAgbWV0aG9kICJhcmM0X3R1cGxlX2FyZ3VtZW50KCh1aW50OCxzdHJpbmcsdWludDY0LHVpbnQzMltdKSlzdHJpbmciCiAgICBtZXRob2QgImFyYzRfdHVwbGVfcmV0dXJuKCkodWludDEyOCxzdHJpbmcpIgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAogICAgbWF0Y2ggX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF90dXBsZV9hcmd1bWVudF9yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdHVwbGVfcmV0dXJuX3JvdXRlQDMKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdHVwbGVfYXJndW1lbnRfcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF90dXBsZV9hcmd1bWVudAogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF90dXBsZV9yZXR1cm5fcm91dGVAMzoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIGNhbGxzdWIgYXJjNF90dXBsZV9yZXR1cm4KICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgYm56IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTAKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICAhCiAgICBhc3NlcnQgLy8gaXMgY3JlYXRpbmcKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTA6CiAgICBpbnQgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLmFyYzRfdHVwbGVfYXJndW1lbnQoYTogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X3R1cGxlX2FyZ3VtZW50OgogICAgcHJvdG8gMSAxCiAgICBmcmFtZV9kaWcgLTEKICAgIGV4dHJhY3QgMCAxIC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgYnRvaQogICAgZnJhbWVfZGlnIC0xCiAgICBleHRyYWN0IDMgOCAvLyBvbiBlcnJvcjogSW5kZXggYWNjZXNzIGlzIG91dCBvZiBib3VuZHMKICAgIGJ0b2kKICAgICsKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDExCiAgICBleHRyYWN0X3VpbnQxNgogICAgZHVwCiAgICBmcmFtZV9kaWcgLTEKICAgIGxlbgogICAgZnJhbWVfZGlnIC0xCiAgICBjb3ZlciAyCiAgICBzdWJzdHJpbmczCiAgICBkdXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50IDAKCmFyYzRfdHVwbGVfYXJndW1lbnRfZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDQKICAgIGZyYW1lX2RpZyAzCiAgICA8CiAgICBieiBhcmM0X3R1cGxlX2FyZ3VtZW50X2FmdGVyX2ZvckA0CiAgICBmcmFtZV9kaWcgMgogICAgZXh0cmFjdCAyIDAKICAgIGZyYW1lX2RpZyA0CiAgICBkdXAKICAgIGNvdmVyIDIKICAgIGludCA0CiAgICAqCiAgICBpbnQgNAogICAgZXh0cmFjdDMgLy8gb24gZXJyb3I6IEluZGV4IGFjY2VzcyBpcyBvdXQgb2YgYm91bmRzCiAgICBidG9pCiAgICBmcmFtZV9kaWcgMAogICAgKwogICAgZnJhbWVfYnVyeSAwCiAgICBpbnQgMQogICAgKwogICAgZnJhbWVfYnVyeSA0CiAgICBiIGFyYzRfdHVwbGVfYXJndW1lbnRfZm9yX2hlYWRlckAxCgphcmM0X3R1cGxlX2FyZ3VtZW50X2FmdGVyX2ZvckA0OgogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMQogICAgZXh0cmFjdF91aW50MTYKICAgIGZyYW1lX2RpZyAtMQogICAgc3dhcAogICAgZnJhbWVfZGlnIDEKICAgIHN1YnN0cmluZzMKICAgIGZyYW1lX2J1cnkgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLmFyYzRfdHVwbGVfcmV0dXJuKCkgLT4gYnl0ZXM6CmFyYzRfdHVwbGVfcmV0dXJuOgogICAgcHJvdG8gMCAxCiAgICBieXRlIDB4MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMmEwMDEyMDAwZDY4NjU2YzZjNmYyYzIwNzc2ZjcyNmM2NDIxCiAgICByZXRzdWIK", "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHVwbGUuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" }, "state": { @@ -34,7 +39,7 @@ "name": "Arc4Tuple", "methods": [ { - "name": "arc4_tuple", + "name": "arc4_tuple_argument", "args": [ { "type": "(uint8,string,uint64,uint32[])", @@ -46,6 +51,15 @@ "type": "string" }, "desc": "An arc4.Tuple is a heterogeneous collection of arc4 types." + }, + { + "name": "arc4_tuple_return", + "args": [], + "readonly": false, + "returns": { + "type": "(uint128,string)" + }, + "desc": "An arc4.Tuple can be returned when more than one return value is needed." } ], "networks": {} diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_tuple_client.py b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_tuple_client.py index e78a989..3bfc750 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_tuple_client.py +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_tuple_client.py @@ -23,14 +23,19 @@ _APP_SPEC_JSON = r"""{ "hints": { - "arc4_tuple((uint8,string,uint64,uint32[]))string": { + "arc4_tuple_argument((uint8,string,uint64,uint32[]))string": { + "call_config": { + "no_op": "CALL" + } + }, + "arc4_tuple_return()(uint128,string)": { "call_config": { "no_op": "CALL" } } }, "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHVwbGUuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUdXBsZS5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANQogICAgbWV0aG9kICJhcmM0X3R1cGxlKCh1aW50OCxzdHJpbmcsdWludDY0LHVpbnQzMltdKSlzdHJpbmciCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAwCiAgICBtYXRjaCBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X3R1cGxlX3JvdXRlQDIKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdHVwbGVfcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF90dXBsZQogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDU6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBibnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUA5CiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgIQogICAgYXNzZXJ0IC8vIGlzIGNyZWF0aW5nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDk6CiAgICBpbnQgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLmFyYzRfdHVwbGUoYTogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X3R1cGxlOgogICAgcHJvdG8gMSAxCiAgICBmcmFtZV9kaWcgLTEKICAgIGV4dHJhY3QgMCAxIC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgYnRvaQogICAgZnJhbWVfZGlnIC0xCiAgICBleHRyYWN0IDMgOCAvLyBvbiBlcnJvcjogSW5kZXggYWNjZXNzIGlzIG91dCBvZiBib3VuZHMKICAgIGJ0b2kKICAgICsKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDExCiAgICBleHRyYWN0X3VpbnQxNgogICAgZHVwCiAgICBmcmFtZV9kaWcgLTEKICAgIGxlbgogICAgZnJhbWVfZGlnIC0xCiAgICBjb3ZlciAyCiAgICBzdWJzdHJpbmczCiAgICBkdXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50IDAKCmFyYzRfdHVwbGVfZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDQKICAgIGZyYW1lX2RpZyAzCiAgICA8CiAgICBieiBhcmM0X3R1cGxlX2FmdGVyX2ZvckA0CiAgICBmcmFtZV9kaWcgMgogICAgZXh0cmFjdCAyIDAKICAgIGZyYW1lX2RpZyA0CiAgICBkdXAKICAgIGNvdmVyIDIKICAgIGludCA0CiAgICAqCiAgICBpbnQgNAogICAgZXh0cmFjdDMgLy8gb24gZXJyb3I6IEluZGV4IGFjY2VzcyBpcyBvdXQgb2YgYm91bmRzCiAgICBidG9pCiAgICBmcmFtZV9kaWcgMAogICAgKwogICAgZnJhbWVfYnVyeSAwCiAgICBpbnQgMQogICAgKwogICAgZnJhbWVfYnVyeSA0CiAgICBiIGFyYzRfdHVwbGVfZm9yX2hlYWRlckAxCgphcmM0X3R1cGxlX2FmdGVyX2ZvckA0OgogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMQogICAgZXh0cmFjdF91aW50MTYKICAgIGZyYW1lX2RpZyAtMQogICAgc3dhcAogICAgZnJhbWVfZGlnIDEKICAgIHN1YnN0cmluZzMKICAgIGZyYW1lX2J1cnkgMAogICAgcmV0c3ViCg==", + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHVwbGUuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUdXBsZS5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANgogICAgbWV0aG9kICJhcmM0X3R1cGxlX2FyZ3VtZW50KCh1aW50OCxzdHJpbmcsdWludDY0LHVpbnQzMltdKSlzdHJpbmciCiAgICBtZXRob2QgImFyYzRfdHVwbGVfcmV0dXJuKCkodWludDEyOCxzdHJpbmcpIgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAogICAgbWF0Y2ggX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF90dXBsZV9hcmd1bWVudF9yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdHVwbGVfcmV0dXJuX3JvdXRlQDMKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdHVwbGVfYXJndW1lbnRfcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF90dXBsZV9hcmd1bWVudAogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF90dXBsZV9yZXR1cm5fcm91dGVAMzoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIGNhbGxzdWIgYXJjNF90dXBsZV9yZXR1cm4KICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgYm56IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTAKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICAhCiAgICBhc3NlcnQgLy8gaXMgY3JlYXRpbmcKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTA6CiAgICBpbnQgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLmFyYzRfdHVwbGVfYXJndW1lbnQoYTogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X3R1cGxlX2FyZ3VtZW50OgogICAgcHJvdG8gMSAxCiAgICBmcmFtZV9kaWcgLTEKICAgIGV4dHJhY3QgMCAxIC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgYnRvaQogICAgZnJhbWVfZGlnIC0xCiAgICBleHRyYWN0IDMgOCAvLyBvbiBlcnJvcjogSW5kZXggYWNjZXNzIGlzIG91dCBvZiBib3VuZHMKICAgIGJ0b2kKICAgICsKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDExCiAgICBleHRyYWN0X3VpbnQxNgogICAgZHVwCiAgICBmcmFtZV9kaWcgLTEKICAgIGxlbgogICAgZnJhbWVfZGlnIC0xCiAgICBjb3ZlciAyCiAgICBzdWJzdHJpbmczCiAgICBkdXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50IDAKCmFyYzRfdHVwbGVfYXJndW1lbnRfZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDQKICAgIGZyYW1lX2RpZyAzCiAgICA8CiAgICBieiBhcmM0X3R1cGxlX2FyZ3VtZW50X2FmdGVyX2ZvckA0CiAgICBmcmFtZV9kaWcgMgogICAgZXh0cmFjdCAyIDAKICAgIGZyYW1lX2RpZyA0CiAgICBkdXAKICAgIGNvdmVyIDIKICAgIGludCA0CiAgICAqCiAgICBpbnQgNAogICAgZXh0cmFjdDMgLy8gb24gZXJyb3I6IEluZGV4IGFjY2VzcyBpcyBvdXQgb2YgYm91bmRzCiAgICBidG9pCiAgICBmcmFtZV9kaWcgMAogICAgKwogICAgZnJhbWVfYnVyeSAwCiAgICBpbnQgMQogICAgKwogICAgZnJhbWVfYnVyeSA0CiAgICBiIGFyYzRfdHVwbGVfYXJndW1lbnRfZm9yX2hlYWRlckAxCgphcmM0X3R1cGxlX2FyZ3VtZW50X2FmdGVyX2ZvckA0OgogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMQogICAgZXh0cmFjdF91aW50MTYKICAgIGZyYW1lX2RpZyAtMQogICAgc3dhcAogICAgZnJhbWVfZGlnIDEKICAgIHN1YnN0cmluZzMKICAgIGZyYW1lX2J1cnkgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLmFyYzRfdHVwbGVfcmV0dXJuKCkgLT4gYnl0ZXM6CmFyYzRfdHVwbGVfcmV0dXJuOgogICAgcHJvdG8gMCAxCiAgICBieXRlIDB4MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMmEwMDEyMDAwZDY4NjU2YzZjNmYyYzIwNzc2ZjcyNmM2NDIxCiAgICByZXRzdWIK", "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHVwbGUuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" }, "state": { @@ -57,7 +62,7 @@ "name": "Arc4Tuple", "methods": [ { - "name": "arc4_tuple", + "name": "arc4_tuple_argument", "args": [ { "type": "(uint8,string,uint64,uint32[])", @@ -68,6 +73,14 @@ "type": "string" }, "desc": "An arc4.Tuple is a heterogeneous collection of arc4 types." + }, + { + "name": "arc4_tuple_return", + "args": [], + "returns": { + "type": "(uint128,string)" + }, + "desc": "An arc4.Tuple can be returned when more than one return value is needed." } ], "networks": {} @@ -150,14 +163,23 @@ def _convert_deploy_args( @dataclasses.dataclass(kw_only=True) -class Arc4TupleArgs(_ArgsBase[str]): +class Arc4TupleArgumentArgs(_ArgsBase[str]): """An arc4.Tuple is a heterogeneous collection of arc4 types.""" a: tuple[int, str, int, list[int]] @staticmethod def method() -> str: - return "arc4_tuple((uint8,string,uint64,uint32[]))string" + return "arc4_tuple_argument((uint8,string,uint64,uint32[]))string" + + +@dataclasses.dataclass(kw_only=True) +class Arc4TupleReturnArgs(_ArgsBase[tuple[int, str]]): + """An arc4.Tuple can be returned when more than one return value is needed.""" + + @staticmethod + def method() -> str: + return "arc4_tuple_return()(uint128,string)" @dataclasses.dataclass(kw_only=True) @@ -191,7 +213,7 @@ def simulate(self, options: SimulateOptions | None = None) -> SimulateAtomicTran def execute(self) -> AtomicTransactionResponse: return self.app_client.execute_atc(self.atc) - def arc4_tuple( + def arc4_tuple_argument( self, *, a: tuple[int, str, int, list[int]], @@ -199,13 +221,13 @@ def arc4_tuple( ) -> "Composer": """An arc4.Tuple is a heterogeneous collection of arc4 types. - Adds a call to `arc4_tuple((uint8,string,uint64,uint32[]))string` ABI method + Adds a call to `arc4_tuple_argument((uint8,string,uint64,uint32[]))string` ABI method :param tuple[int, str, int, list[int]] a: The `a` ABI parameter :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters :returns Composer: This Composer instance""" - args = Arc4TupleArgs( + args = Arc4TupleArgumentArgs( a=a, ) self.app_client.compose_call( @@ -216,6 +238,27 @@ def arc4_tuple( ) return self + def arc4_tuple_return( + self, + *, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> "Composer": + """An arc4.Tuple can be returned when more than one return value is needed. + + Adds a call to `arc4_tuple_return()(uint128,string)` ABI method + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + args = Arc4TupleReturnArgs() + self.app_client.compose_call( + self.atc, + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return self + def create_bare( self, *, @@ -375,7 +418,7 @@ def suggested_params(self) -> algosdk.transaction.SuggestedParams | None: def suggested_params(self, value: algosdk.transaction.SuggestedParams | None) -> None: self.app_client.suggested_params = value - def arc4_tuple( + def arc4_tuple_argument( self, *, a: tuple[int, str, int, list[int]], @@ -383,13 +426,13 @@ def arc4_tuple( ) -> algokit_utils.ABITransactionResponse[str]: """An arc4.Tuple is a heterogeneous collection of arc4 types. - Calls `arc4_tuple((uint8,string,uint64,uint32[]))string` ABI method + Calls `arc4_tuple_argument((uint8,string,uint64,uint32[]))string` ABI method :param tuple[int, str, int, list[int]] a: The `a` ABI parameter :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters :returns algokit_utils.ABITransactionResponse[str]: The result of the transaction""" - args = Arc4TupleArgs( + args = Arc4TupleArgumentArgs( a=a, ) result = self.app_client.call( @@ -399,6 +442,26 @@ def arc4_tuple( ) return result + def arc4_tuple_return( + self, + *, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> algokit_utils.ABITransactionResponse[tuple[int, str]]: + """An arc4.Tuple can be returned when more than one return value is needed. + + Calls `arc4_tuple_return()(uint128,string)` ABI method + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.ABITransactionResponse[tuple[int, str]]: The result of the transaction""" + + args = Arc4TupleReturnArgs() + result = self.app_client.call( + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return result + def create_bare( self, *, diff --git a/projects/python-contract-examples/tests/arc4_types_integration_test.py b/projects/python-contract-examples/tests/arc4_types_integration_test.py index 4d4f03f..f1d4c8f 100644 --- a/projects/python-contract-examples/tests/arc4_types_integration_test.py +++ b/projects/python-contract-examples/tests/arc4_types_integration_test.py @@ -347,13 +347,23 @@ def test_arc4_struct_complete_and_return_todo( assert result.return_value.completed is True -def test_arc4_tuple( +def test_arc4_tuple_argument( arc4_tuple_app_client: Arc4TupleClient, ) -> None: - """Test the arc4_tuple method""" + """Test the arc4_tuple_argument method""" - result = arc4_tuple_app_client.arc4_tuple( + result = arc4_tuple_app_client.arc4_tuple_argument( a=(4, "This is a good string.", 100, [1, 2, 3]) ) assert result.return_value == "This is a good string." + + +def test_arc4_tuple_return( + arc4_tuple_app_client: Arc4TupleClient, +) -> None: + """Test the arc4_tuple_return method""" + + result = arc4_tuple_app_client.arc4_tuple_return() + + assert result.return_value == [42, "hello, world!"] From b937f915b90dd44fead60e209683b42a974bd205 Mon Sep 17 00:00:00 2001 From: "Chris Kim (Hyunggun)" Date: Thu, 7 Nov 2024 09:33:00 -0800 Subject: [PATCH 11/23] update dynamicArray, tuple --- .../smart_contracts/arc4_types/contract.py | 51 ++++++---- .../arc4_types/Arc4DynamicArray.approval.teal | 60 +++++++++--- .../arc4_types/Arc4DynamicArray.arc32.json | 2 +- .../arc4_types/Arc4StaticArray.approval.teal | 8 ++ .../arc4_types/Arc4StaticArray.arc32.json | 2 +- .../arc4_types/Arc4Tuple.approval.teal | 95 +++++++++++-------- .../artifacts/arc4_types/Arc4Tuple.arc32.json | 18 ++-- .../arc4_types/arc4_dynamic_array_client.py | 2 +- .../arc4_types/arc4_static_array_client.py | 2 +- .../artifacts/arc4_types/arc4_tuple_client.py | 72 +++++++------- 10 files changed, 189 insertions(+), 123 deletions(-) diff --git a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py index 216af58..29bb90e 100644 --- a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py +++ b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py @@ -124,10 +124,13 @@ def arc4_static_array(self) -> None: assert (aliased_static[0].native + aliased_static[index].native) == 202 + aliased_static[0] = arc4.UInt8(202) + + assert aliased_static[0].native == 202 + """ - You can't modify the elements of a static array. + You can't add or pop values from a static array because it has a fixed size. so this won't compile: - aliased_static[0] = arc4.UInt8(100) aliased_static.pop() """ @@ -135,27 +138,28 @@ def arc4_static_array(self) -> None: class Arc4DynamicArray(ARC4Contract): @abimethod() - def arc4_dynamic_array(self, name: arc4.String) -> arc4.String: + def arc4_dynamic_array(self, name: arc4.String) -> String: """ Dynamic Arrays have variable size and capacity. They are similar to native Python lists because they can also append, extend, and pop. """ - dynamic_string_array = arc4.DynamicArray[arc4.String](arc4.String("Hello")) + dynamic_string_array = arc4.DynamicArray[arc4.String](arc4.String("Hello ")) extension = arc4.DynamicArray[arc4.String]( - arc4.String(" world"), arc4.String(", ") + name, arc4.String("!") ) dynamic_string_array.extend(extension) - dynamic_string_array.append(name) - dynamic_string_array.append(arc4.String("!")) - dynamic_string_array.pop() - + copied_dynamic_string_array = dynamic_string_array.copy() + copied_dynamic_string_array.pop() + copied_dynamic_string_array.pop() + copied_dynamic_string_array.append(arc4.String("world!")) + greeting = String() for x in dynamic_string_array: greeting += x.native - return arc4.String(greeting) + return greeting @abimethod() def arc4_dynamic_bytes(self) -> arc4.DynamicBytes: @@ -215,27 +219,32 @@ def return_todo(self, task: arc4.String) -> Todo: return todo_to_return +contact_info_tuple = arc4.Tuple[arc4.String, arc4.String, arc4.UInt64, arc4.DynamicArray[arc4.UInt8]] # name, email, phone + class Arc4Tuple(ARC4Contract): @abimethod() - def arc4_tuple_argument( + def add_contact_info( self, - a: arc4.Tuple[ - arc4.UInt8, arc4.String, arc4.UInt64, arc4.DynamicArray[arc4.UInt32] - ], - ) -> arc4.String: + contact: contact_info_tuple + ) -> UInt64: """An arc4.Tuple is a heterogeneous collection of arc4 types.""" + name, email, phone, donate_history = contact.native + + assert name.native == "John Woods" + assert email.native == "john@something.com" + assert phone == arc4.UInt64(555_555_555) - total = a[0].native + a[2].native + total_donation = UInt64(0) - for x in a[3]: - total += x.native + for x in donate_history: + total_donation += x.native - return a[1] + return total_donation @abimethod() - def arc4_tuple_return(self) -> arc4.Tuple[arc4.UInt128, arc4.String]: + def return_contact(self) -> arc4.Tuple[arc4.String, arc4.String, arc4.UInt64]: """An arc4.Tuple can be returned when more than one return value is needed.""" - arc4_tuple = arc4.Tuple((arc4.UInt128(42), arc4.String("hello, world!"))) + arc4_tuple = arc4.Tuple((arc4.String("Alice"), arc4.String("alice@something.com"), arc4.UInt64(555_555_555))) return arc4_tuple diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.approval.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.approval.teal index 1557272..60f1eeb 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.approval.teal +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.approval.teal @@ -25,6 +25,12 @@ __puya_arc4_router___arc4_dynamic_array_route@2: assert // is not creating txna ApplicationArgs 1 callsub arc4_dynamic_array + dup + len + itob + extract 6 2 + swap + concat byte 0x151f7c75 swap concat @@ -63,19 +69,49 @@ __puya_arc4_router___after_if_else@10: // smart_contracts.arc4_types.contract.Arc4DynamicArray.arc4_dynamic_array(name: bytes) -> bytes: arc4_dynamic_array: proto 1 1 - byte 0x00010002000548656c6c6f - byte 0x000620776f726c6400022c20 - int 2 - callsub dynamic_array_concat_byte_length_head frame_dig -1 - int 1 - callsub dynamic_array_concat_byte_length_head + len + int 4 + + + itob + extract 6 2 + byte 0x0004 + swap + concat + frame_dig -1 + concat byte 0x000121 - int 1 - callsub dynamic_array_concat_byte_length_head - callsub dynamic_array_pop_byte_length_head + concat + byte 0x0002 + swap + concat + dup + int 0 + extract_uint16 + swap + extract 2 0 + swap dup + int 2 + * + swap + dig 2 + len + swap + cover 3 + substring3 + byte 0x00010002000648656c6c6f20 + swap uncover 2 + callsub dynamic_array_concat_byte_length_head + dupn 2 + callsub dynamic_array_pop_byte_length_head + bury 1 + callsub dynamic_array_pop_byte_length_head + bury 1 + byte 0x0006776f726c6421 + int 1 + callsub dynamic_array_concat_byte_length_head pop byte "" swap @@ -115,12 +151,6 @@ arc4_dynamic_array_for_header@1: arc4_dynamic_array_after_for@4: frame_dig 1 - dup - len - itob - extract 6 2 - swap - concat frame_bury 0 retsub diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.arc32.json b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.arc32.json index 41922ee..d18e906 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.arc32.json +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.arc32.json @@ -12,7 +12,7 @@ } }, "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5LmFwcHJvdmFsX3Byb2dyYW06CiAgICBjYWxsc3ViIF9fcHV5YV9hcmM0X3JvdXRlcl9fCiAgICByZXR1cm4KCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5Ll9fcHV5YV9hcmM0X3JvdXRlcl9fKCkgLT4gdWludDY0OgpfX3B1eWFfYXJjNF9yb3V0ZXJfXzoKICAgIHByb3RvIDAgMQogICAgdHhuIE51bUFwcEFyZ3MKICAgIGJ6IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2CiAgICBtZXRob2QgImFyYzRfZHluYW1pY19hcnJheShzdHJpbmcpc3RyaW5nIgogICAgbWV0aG9kICJhcmM0X2R5bmFtaWNfYnl0ZXMoKWJ5dGVbXSIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfZHluYW1pY19hcnJheV9yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfZHluYW1pY19ieXRlc19yb3V0ZUAzCiAgICBpbnQgMAogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2R5bmFtaWNfYXJyYXlfcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF9keW5hbWljX2FycmF5CiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2R5bmFtaWNfYnl0ZXNfcm91dGVAMzoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIGNhbGxzdWIgYXJjNF9keW5hbWljX2J5dGVzCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgIGJueiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDEwCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgIQogICAgYXNzZXJ0IC8vIGlzIGNyZWF0aW5nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDEwOgogICAgaW50IDAKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzREeW5hbWljQXJyYXkuYXJjNF9keW5hbWljX2FycmF5KG5hbWU6IGJ5dGVzKSAtPiBieXRlczoKYXJjNF9keW5hbWljX2FycmF5OgogICAgcHJvdG8gMSAxCiAgICBieXRlIDB4MDAwMTAwMDIwMDA1NDg2NTZjNmM2ZgogICAgYnl0ZSAweDAwMDYyMDc3NmY3MjZjNjQwMDAyMmMyMAogICAgaW50IDIKICAgIGNhbGxzdWIgZHluYW1pY19hcnJheV9jb25jYXRfYnl0ZV9sZW5ndGhfaGVhZAogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMQogICAgY2FsbHN1YiBkeW5hbWljX2FycmF5X2NvbmNhdF9ieXRlX2xlbmd0aF9oZWFkCiAgICBieXRlIDB4MDAwMTIxCiAgICBpbnQgMQogICAgY2FsbHN1YiBkeW5hbWljX2FycmF5X2NvbmNhdF9ieXRlX2xlbmd0aF9oZWFkCiAgICBjYWxsc3ViIGR5bmFtaWNfYXJyYXlfcG9wX2J5dGVfbGVuZ3RoX2hlYWQKICAgIGR1cAogICAgdW5jb3ZlciAyCiAgICBwb3AKICAgIGJ5dGUgIiIKICAgIHN3YXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50IDAKCmFyYzRfZHluYW1pY19hcnJheV9mb3JfaGVhZGVyQDE6CiAgICBmcmFtZV9kaWcgMwogICAgZnJhbWVfZGlnIDIKICAgIDwKICAgIGJ6IGFyYzRfZHluYW1pY19hcnJheV9hZnRlcl9mb3JANAogICAgZnJhbWVfZGlnIDAKICAgIGV4dHJhY3QgMiAwCiAgICBmcmFtZV9kaWcgMwogICAgZHVwCiAgICBjb3ZlciAyCiAgICBpbnQgMgogICAgKgogICAgZGlnIDEKICAgIHN3YXAKICAgIGV4dHJhY3RfdWludDE2CiAgICBkdXAyCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50IDIKICAgICsKICAgIGV4dHJhY3QzCiAgICBleHRyYWN0IDIgMAogICAgZnJhbWVfZGlnIDEKICAgIHN3YXAKICAgIGNvbmNhdAogICAgZnJhbWVfYnVyeSAxCiAgICBpbnQgMQogICAgKwogICAgZnJhbWVfYnVyeSAzCiAgICBiIGFyYzRfZHluYW1pY19hcnJheV9mb3JfaGVhZGVyQDEKCmFyYzRfZHluYW1pY19hcnJheV9hZnRlcl9mb3JANDoKICAgIGZyYW1lX2RpZyAxCiAgICBkdXAKICAgIGxlbgogICAgaXRvYgogICAgZXh0cmFjdCA2IDIKICAgIHN3YXAKICAgIGNvbmNhdAogICAgZnJhbWVfYnVyeSAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5LmFyYzRfZHluYW1pY19ieXRlcygpIC0+IGJ5dGVzOgphcmM0X2R5bmFtaWNfYnl0ZXM6CiAgICBwcm90byAwIDEKICAgIGJ5dGUgMHgwMDAzZmZmZmZmCiAgICBieXRlIDB4MDAKICAgIHJlcGxhY2UyIDIKICAgIHJldHN1YgoKCi8vIF9wdXlhX2xpYi5hcmM0LmR5bmFtaWNfYXJyYXlfcG9wX2J5dGVfbGVuZ3RoX2hlYWQoYXJyYXk6IGJ5dGVzKSAtPiBieXRlcywgYnl0ZXM6CmR5bmFtaWNfYXJyYXlfcG9wX2J5dGVfbGVuZ3RoX2hlYWQ6CiAgICBwcm90byAxIDIKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDAKICAgIGV4dHJhY3RfdWludDE2CiAgICBpbnQgMQogICAgLQogICAgZHVwCiAgICBpbnQgMgogICAgKgogICAgZnJhbWVfZGlnIC0xCiAgICBleHRyYWN0IDIgMAogICAgZHVwCiAgICBkaWcgMgogICAgZXh0cmFjdF91aW50MTYKICAgIHN3YXAKICAgIGR1cAogICAgbGVuCiAgICBzd2FwCiAgICBkdXAKICAgIGRpZyAzCiAgICB1bmNvdmVyIDMKICAgIHN1YnN0cmluZzMKICAgIGNvdmVyIDMKICAgIGR1cAogICAgaW50IDAKICAgIGRpZyA0CiAgICBzdWJzdHJpbmczCiAgICBjb3ZlciAyCiAgICB1bmNvdmVyIDMKICAgIGludCAyCiAgICArCiAgICB1bmNvdmVyIDIKICAgIHN1YnN0cmluZzMKICAgIGNvbmNhdAogICAgZGlnIDIKICAgIGl0b2IKICAgIGV4dHJhY3QgNiAyCiAgICBzd2FwCiAgICB1bmNvdmVyIDMKICAgIGludCAwCiAgICBjYWxsc3ViIHJlY2FsY3VsYXRlX2hlYWRfZm9yX2VsZW1lbnRzX3dpdGhfYnl0ZV9sZW5ndGhfaGVhZAogICAgY29uY2F0CiAgICByZXRzdWIKCgovLyBfcHV5YV9saWIuYXJjNC5keW5hbWljX2FycmF5X2NvbmNhdF9ieXRlX2xlbmd0aF9oZWFkKGFycmF5OiBieXRlcywgbmV3X2l0ZW1zX2J5dGVzOiBieXRlcywgbmV3X2l0ZW1zX2NvdW50OiB1aW50NjQpIC0+IGJ5dGVzOgpkeW5hbWljX2FycmF5X2NvbmNhdF9ieXRlX2xlbmd0aF9oZWFkOgogICAgcHJvdG8gMyAxCiAgICBmcmFtZV9kaWcgLTMKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgZHVwCiAgICBmcmFtZV9kaWcgLTEKICAgICsKICAgIHN3YXAKICAgIGludCAyCiAgICAqCiAgICBpbnQgMgogICAgKwogICAgc3dhcAogICAgZHVwCiAgICBpdG9iCiAgICBleHRyYWN0IDYgMgogICAgc3dhcAogICAgZnJhbWVfZGlnIC0zCiAgICBpbnQgMgogICAgZGlnIDQKICAgIHN1YnN0cmluZzMKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDIKICAgICoKICAgIGJ6ZXJvCiAgICBjb25jYXQKICAgIGZyYW1lX2RpZyAtMwogICAgbGVuCiAgICBmcmFtZV9kaWcgLTMKICAgIHVuY292ZXIgNQogICAgdW5jb3ZlciAyCiAgICBzdWJzdHJpbmczCiAgICBjb25jYXQKICAgIGZyYW1lX2RpZyAtMgogICAgY29uY2F0CiAgICBzd2FwCiAgICBpbnQgMAogICAgY2FsbHN1YiByZWNhbGN1bGF0ZV9oZWFkX2Zvcl9lbGVtZW50c193aXRoX2J5dGVfbGVuZ3RoX2hlYWQKICAgIGNvbmNhdAogICAgcmV0c3ViCgoKLy8gX3B1eWFfbGliLmFyYzQucmVjYWxjdWxhdGVfaGVhZF9mb3JfZWxlbWVudHNfd2l0aF9ieXRlX2xlbmd0aF9oZWFkKGFycmF5X2hlYWRfYW5kX3RhaWw6IGJ5dGVzLCBsZW5ndGg6IHVpbnQ2NCwgc3RhcnRfYXRfaW5kZXg6IHVpbnQ2NCkgLT4gYnl0ZXM6CnJlY2FsY3VsYXRlX2hlYWRfZm9yX2VsZW1lbnRzX3dpdGhfYnl0ZV9sZW5ndGhfaGVhZDoKICAgIHByb3RvIDMgMQogICAgZnJhbWVfZGlnIC0yCiAgICBpbnQgMgogICAgKgogICAgZHVwCiAgICBmcmFtZV9kaWcgLTEKICAgIGludCAyCiAgICAqCiAgICBkdXAKICAgIGNvdmVyIDIKICAgIGZyYW1lX2RpZyAtMwogICAgc3dhcAogICAgZXh0cmFjdF91aW50MTYKICAgIGZyYW1lX2RpZyAtMQogICAgc2VsZWN0CgpyZWNhbGN1bGF0ZV9oZWFkX2Zvcl9lbGVtZW50c193aXRoX2J5dGVfbGVuZ3RoX2hlYWRfZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDEKICAgIGZyYW1lX2RpZyAwCiAgICA8CiAgICBieiByZWNhbGN1bGF0ZV9oZWFkX2Zvcl9lbGVtZW50c193aXRoX2J5dGVfbGVuZ3RoX2hlYWRfYWZ0ZXJfZm9yQDQKICAgIGZyYW1lX2RpZyAyCiAgICBkdXAKICAgIGl0b2IKICAgIGV4dHJhY3QgNiAyCiAgICBmcmFtZV9kaWcgLTMKICAgIGZyYW1lX2RpZyAxCiAgICBkdXAKICAgIGNvdmVyIDQKICAgIHVuY292ZXIgMgogICAgcmVwbGFjZTMKICAgIGR1cAogICAgZnJhbWVfYnVyeSAtMwogICAgZGlnIDEKICAgIGV4dHJhY3RfdWludDE2CiAgICBpbnQgMgogICAgKwogICAgKwogICAgZnJhbWVfYnVyeSAyCiAgICBpbnQgMgogICAgKwogICAgZnJhbWVfYnVyeSAxCiAgICBiIHJlY2FsY3VsYXRlX2hlYWRfZm9yX2VsZW1lbnRzX3dpdGhfYnl0ZV9sZW5ndGhfaGVhZF9mb3JfaGVhZGVyQDEKCnJlY2FsY3VsYXRlX2hlYWRfZm9yX2VsZW1lbnRzX3dpdGhfYnl0ZV9sZW5ndGhfaGVhZF9hZnRlcl9mb3JANDoKICAgIGZyYW1lX2RpZyAtMwogICAgZnJhbWVfYnVyeSAwCiAgICByZXRzdWIK", + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5LmFwcHJvdmFsX3Byb2dyYW06CiAgICBjYWxsc3ViIF9fcHV5YV9hcmM0X3JvdXRlcl9fCiAgICByZXR1cm4KCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5Ll9fcHV5YV9hcmM0X3JvdXRlcl9fKCkgLT4gdWludDY0OgpfX3B1eWFfYXJjNF9yb3V0ZXJfXzoKICAgIHByb3RvIDAgMQogICAgdHhuIE51bUFwcEFyZ3MKICAgIGJ6IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2CiAgICBtZXRob2QgImFyYzRfZHluYW1pY19hcnJheShzdHJpbmcpc3RyaW5nIgogICAgbWV0aG9kICJhcmM0X2R5bmFtaWNfYnl0ZXMoKWJ5dGVbXSIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfZHluYW1pY19hcnJheV9yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfZHluYW1pY19ieXRlc19yb3V0ZUAzCiAgICBpbnQgMAogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2R5bmFtaWNfYXJyYXlfcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF9keW5hbWljX2FycmF5CiAgICBkdXAKICAgIGxlbgogICAgaXRvYgogICAgZXh0cmFjdCA2IDIKICAgIHN3YXAKICAgIGNvbmNhdAogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9keW5hbWljX2J5dGVzX3JvdXRlQDM6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICBjYWxsc3ViIGFyYzRfZHluYW1pY19ieXRlcwogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDY6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBibnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgICEKICAgIGFzc2VydCAvLyBpcyBjcmVhdGluZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMDoKICAgIGludCAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5LmFyYzRfZHluYW1pY19hcnJheShuYW1lOiBieXRlcykgLT4gYnl0ZXM6CmFyYzRfZHluYW1pY19hcnJheToKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBsZW4KICAgIGludCA0CiAgICArCiAgICBpdG9iCiAgICBleHRyYWN0IDYgMgogICAgYnl0ZSAweDAwMDQKICAgIHN3YXAKICAgIGNvbmNhdAogICAgZnJhbWVfZGlnIC0xCiAgICBjb25jYXQKICAgIGJ5dGUgMHgwMDAxMjEKICAgIGNvbmNhdAogICAgYnl0ZSAweDAwMDIKICAgIHN3YXAKICAgIGNvbmNhdAogICAgZHVwCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIHN3YXAKICAgIGV4dHJhY3QgMiAwCiAgICBzd2FwCiAgICBkdXAKICAgIGludCAyCiAgICAqCiAgICBzd2FwCiAgICBkaWcgMgogICAgbGVuCiAgICBzd2FwCiAgICBjb3ZlciAzCiAgICBzdWJzdHJpbmczCiAgICBieXRlIDB4MDAwMTAwMDIwMDA2NDg2NTZjNmM2ZjIwCiAgICBzd2FwCiAgICB1bmNvdmVyIDIKICAgIGNhbGxzdWIgZHluYW1pY19hcnJheV9jb25jYXRfYnl0ZV9sZW5ndGhfaGVhZAogICAgZHVwbiAyCiAgICBjYWxsc3ViIGR5bmFtaWNfYXJyYXlfcG9wX2J5dGVfbGVuZ3RoX2hlYWQKICAgIGJ1cnkgMQogICAgY2FsbHN1YiBkeW5hbWljX2FycmF5X3BvcF9ieXRlX2xlbmd0aF9oZWFkCiAgICBidXJ5IDEKICAgIGJ5dGUgMHgwMDA2Nzc2ZjcyNmM2NDIxCiAgICBpbnQgMQogICAgY2FsbHN1YiBkeW5hbWljX2FycmF5X2NvbmNhdF9ieXRlX2xlbmd0aF9oZWFkCiAgICBwb3AKICAgIGJ5dGUgIiIKICAgIHN3YXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50IDAKCmFyYzRfZHluYW1pY19hcnJheV9mb3JfaGVhZGVyQDE6CiAgICBmcmFtZV9kaWcgMwogICAgZnJhbWVfZGlnIDIKICAgIDwKICAgIGJ6IGFyYzRfZHluYW1pY19hcnJheV9hZnRlcl9mb3JANAogICAgZnJhbWVfZGlnIDAKICAgIGV4dHJhY3QgMiAwCiAgICBmcmFtZV9kaWcgMwogICAgZHVwCiAgICBjb3ZlciAyCiAgICBpbnQgMgogICAgKgogICAgZGlnIDEKICAgIHN3YXAKICAgIGV4dHJhY3RfdWludDE2CiAgICBkdXAyCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50IDIKICAgICsKICAgIGV4dHJhY3QzCiAgICBleHRyYWN0IDIgMAogICAgZnJhbWVfZGlnIDEKICAgIHN3YXAKICAgIGNvbmNhdAogICAgZnJhbWVfYnVyeSAxCiAgICBpbnQgMQogICAgKwogICAgZnJhbWVfYnVyeSAzCiAgICBiIGFyYzRfZHluYW1pY19hcnJheV9mb3JfaGVhZGVyQDEKCmFyYzRfZHluYW1pY19hcnJheV9hZnRlcl9mb3JANDoKICAgIGZyYW1lX2RpZyAxCiAgICBmcmFtZV9idXJ5IDAKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzREeW5hbWljQXJyYXkuYXJjNF9keW5hbWljX2J5dGVzKCkgLT4gYnl0ZXM6CmFyYzRfZHluYW1pY19ieXRlczoKICAgIHByb3RvIDAgMQogICAgYnl0ZSAweDAwMDNmZmZmZmYKICAgIGJ5dGUgMHgwMAogICAgcmVwbGFjZTIgMgogICAgcmV0c3ViCgoKLy8gX3B1eWFfbGliLmFyYzQuZHluYW1pY19hcnJheV9wb3BfYnl0ZV9sZW5ndGhfaGVhZChhcnJheTogYnl0ZXMpIC0+IGJ5dGVzLCBieXRlczoKZHluYW1pY19hcnJheV9wb3BfYnl0ZV9sZW5ndGhfaGVhZDoKICAgIHByb3RvIDEgMgogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGludCAxCiAgICAtCiAgICBkdXAKICAgIGludCAyCiAgICAqCiAgICBmcmFtZV9kaWcgLTEKICAgIGV4dHJhY3QgMiAwCiAgICBkdXAKICAgIGRpZyAyCiAgICBleHRyYWN0X3VpbnQxNgogICAgc3dhcAogICAgZHVwCiAgICBsZW4KICAgIHN3YXAKICAgIGR1cAogICAgZGlnIDMKICAgIHVuY292ZXIgMwogICAgc3Vic3RyaW5nMwogICAgY292ZXIgMwogICAgZHVwCiAgICBpbnQgMAogICAgZGlnIDQKICAgIHN1YnN0cmluZzMKICAgIGNvdmVyIDIKICAgIHVuY292ZXIgMwogICAgaW50IDIKICAgICsKICAgIHVuY292ZXIgMgogICAgc3Vic3RyaW5nMwogICAgY29uY2F0CiAgICBkaWcgMgogICAgaXRvYgogICAgZXh0cmFjdCA2IDIKICAgIHN3YXAKICAgIHVuY292ZXIgMwogICAgaW50IDAKICAgIGNhbGxzdWIgcmVjYWxjdWxhdGVfaGVhZF9mb3JfZWxlbWVudHNfd2l0aF9ieXRlX2xlbmd0aF9oZWFkCiAgICBjb25jYXQKICAgIHJldHN1YgoKCi8vIF9wdXlhX2xpYi5hcmM0LmR5bmFtaWNfYXJyYXlfY29uY2F0X2J5dGVfbGVuZ3RoX2hlYWQoYXJyYXk6IGJ5dGVzLCBuZXdfaXRlbXNfYnl0ZXM6IGJ5dGVzLCBuZXdfaXRlbXNfY291bnQ6IHVpbnQ2NCkgLT4gYnl0ZXM6CmR5bmFtaWNfYXJyYXlfY29uY2F0X2J5dGVfbGVuZ3RoX2hlYWQ6CiAgICBwcm90byAzIDEKICAgIGZyYW1lX2RpZyAtMwogICAgaW50IDAKICAgIGV4dHJhY3RfdWludDE2CiAgICBkdXAKICAgIGZyYW1lX2RpZyAtMQogICAgKwogICAgc3dhcAogICAgaW50IDIKICAgICoKICAgIGludCAyCiAgICArCiAgICBzd2FwCiAgICBkdXAKICAgIGl0b2IKICAgIGV4dHJhY3QgNiAyCiAgICBzd2FwCiAgICBmcmFtZV9kaWcgLTMKICAgIGludCAyCiAgICBkaWcgNAogICAgc3Vic3RyaW5nMwogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMgogICAgKgogICAgYnplcm8KICAgIGNvbmNhdAogICAgZnJhbWVfZGlnIC0zCiAgICBsZW4KICAgIGZyYW1lX2RpZyAtMwogICAgdW5jb3ZlciA1CiAgICB1bmNvdmVyIDIKICAgIHN1YnN0cmluZzMKICAgIGNvbmNhdAogICAgZnJhbWVfZGlnIC0yCiAgICBjb25jYXQKICAgIHN3YXAKICAgIGludCAwCiAgICBjYWxsc3ViIHJlY2FsY3VsYXRlX2hlYWRfZm9yX2VsZW1lbnRzX3dpdGhfYnl0ZV9sZW5ndGhfaGVhZAogICAgY29uY2F0CiAgICByZXRzdWIKCgovLyBfcHV5YV9saWIuYXJjNC5yZWNhbGN1bGF0ZV9oZWFkX2Zvcl9lbGVtZW50c193aXRoX2J5dGVfbGVuZ3RoX2hlYWQoYXJyYXlfaGVhZF9hbmRfdGFpbDogYnl0ZXMsIGxlbmd0aDogdWludDY0LCBzdGFydF9hdF9pbmRleDogdWludDY0KSAtPiBieXRlczoKcmVjYWxjdWxhdGVfaGVhZF9mb3JfZWxlbWVudHNfd2l0aF9ieXRlX2xlbmd0aF9oZWFkOgogICAgcHJvdG8gMyAxCiAgICBmcmFtZV9kaWcgLTIKICAgIGludCAyCiAgICAqCiAgICBkdXAKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDIKICAgICoKICAgIGR1cAogICAgY292ZXIgMgogICAgZnJhbWVfZGlnIC0zCiAgICBzd2FwCiAgICBleHRyYWN0X3VpbnQxNgogICAgZnJhbWVfZGlnIC0xCiAgICBzZWxlY3QKCnJlY2FsY3VsYXRlX2hlYWRfZm9yX2VsZW1lbnRzX3dpdGhfYnl0ZV9sZW5ndGhfaGVhZF9mb3JfaGVhZGVyQDE6CiAgICBmcmFtZV9kaWcgMQogICAgZnJhbWVfZGlnIDAKICAgIDwKICAgIGJ6IHJlY2FsY3VsYXRlX2hlYWRfZm9yX2VsZW1lbnRzX3dpdGhfYnl0ZV9sZW5ndGhfaGVhZF9hZnRlcl9mb3JANAogICAgZnJhbWVfZGlnIDIKICAgIGR1cAogICAgaXRvYgogICAgZXh0cmFjdCA2IDIKICAgIGZyYW1lX2RpZyAtMwogICAgZnJhbWVfZGlnIDEKICAgIGR1cAogICAgY292ZXIgNAogICAgdW5jb3ZlciAyCiAgICByZXBsYWNlMwogICAgZHVwCiAgICBmcmFtZV9idXJ5IC0zCiAgICBkaWcgMQogICAgZXh0cmFjdF91aW50MTYKICAgIGludCAyCiAgICArCiAgICArCiAgICBmcmFtZV9idXJ5IDIKICAgIGludCAyCiAgICArCiAgICBmcmFtZV9idXJ5IDEKICAgIGIgcmVjYWxjdWxhdGVfaGVhZF9mb3JfZWxlbWVudHNfd2l0aF9ieXRlX2xlbmd0aF9oZWFkX2Zvcl9oZWFkZXJAMQoKcmVjYWxjdWxhdGVfaGVhZF9mb3JfZWxlbWVudHNfd2l0aF9ieXRlX2xlbmd0aF9oZWFkX2FmdGVyX2ZvckA0OgogICAgZnJhbWVfZGlnIC0zCiAgICBmcmFtZV9idXJ5IDAKICAgIHJldHN1Ygo=", "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5LmNsZWFyX3N0YXRlX3Byb2dyYW06CiAgICBpbnQgMQogICAgcmV0dXJuCg==" }, "state": { diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.approval.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.approval.teal index 34832b9..1521f1e 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.approval.teal +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.approval.teal @@ -73,4 +73,12 @@ arc4_static_array_after_for@4: int 394 == assert + byte 0x65 + byte 0xca + replace2 0 + extract 0 1 // on error: Index access is out of bounds + btoi + int 202 + == + assert retsub diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.arc32.json b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.arc32.json index e3c51ca..1148733 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.arc32.json +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.arc32.json @@ -7,7 +7,7 @@ } }, "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RhdGljQXJyYXkuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRTdGF0aWNBcnJheS5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANQogICAgbWV0aG9kICJhcmM0X3N0YXRpY19hcnJheSgpdm9pZCIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfc3RhdGljX2FycmF5X3JvdXRlQDIKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfc3RhdGljX2FycmF5X3JvdXRlQDI6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICBjYWxsc3ViIGFyYzRfc3RhdGljX2FycmF5CiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANToKICAgIHR4biBPbkNvbXBsZXRpb24KICAgIGJueiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDkKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICAhCiAgICBhc3NlcnQgLy8gaXMgY3JlYXRpbmcKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAOToKICAgIGludCAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RhdGljQXJyYXkuYXJjNF9zdGF0aWNfYXJyYXkoKSAtPiB2b2lkOgphcmM0X3N0YXRpY19hcnJheToKICAgIHByb3RvIDAgMAogICAgaW50IDAKICAgIGR1cAoKYXJjNF9zdGF0aWNfYXJyYXlfZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDEKICAgIGludCA0CiAgICA8CiAgICBieiBhcmM0X3N0YXRpY19hcnJheV9hZnRlcl9mb3JANAogICAgZnJhbWVfZGlnIDEKICAgIGR1cAogICAgaW50IDQKICAgICoKICAgIGJ5dGUgMHgwMDAwMDAwMTAwMDAwMDBhMDAwMDAwZmYwMDAwMDA4MAogICAgc3dhcAogICAgaW50IDQKICAgIGV4dHJhY3QzIC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgYnRvaQogICAgZnJhbWVfZGlnIDAKICAgICsKICAgIGZyYW1lX2J1cnkgMAogICAgaW50IDEKICAgICsKICAgIGZyYW1lX2J1cnkgMQogICAgYiBhcmM0X3N0YXRpY19hcnJheV9mb3JfaGVhZGVyQDEKCmFyYzRfc3RhdGljX2FycmF5X2FmdGVyX2ZvckA0OgogICAgZnJhbWVfZGlnIDAKICAgIGludCAzOTQKICAgID09CiAgICBhc3NlcnQKICAgIHJldHN1Ygo=", + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RhdGljQXJyYXkuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRTdGF0aWNBcnJheS5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANQogICAgbWV0aG9kICJhcmM0X3N0YXRpY19hcnJheSgpdm9pZCIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfc3RhdGljX2FycmF5X3JvdXRlQDIKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfc3RhdGljX2FycmF5X3JvdXRlQDI6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICBjYWxsc3ViIGFyYzRfc3RhdGljX2FycmF5CiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANToKICAgIHR4biBPbkNvbXBsZXRpb24KICAgIGJueiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDkKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICAhCiAgICBhc3NlcnQgLy8gaXMgY3JlYXRpbmcKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAOToKICAgIGludCAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RhdGljQXJyYXkuYXJjNF9zdGF0aWNfYXJyYXkoKSAtPiB2b2lkOgphcmM0X3N0YXRpY19hcnJheToKICAgIHByb3RvIDAgMAogICAgaW50IDAKICAgIGR1cAoKYXJjNF9zdGF0aWNfYXJyYXlfZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDEKICAgIGludCA0CiAgICA8CiAgICBieiBhcmM0X3N0YXRpY19hcnJheV9hZnRlcl9mb3JANAogICAgZnJhbWVfZGlnIDEKICAgIGR1cAogICAgaW50IDQKICAgICoKICAgIGJ5dGUgMHgwMDAwMDAwMTAwMDAwMDBhMDAwMDAwZmYwMDAwMDA4MAogICAgc3dhcAogICAgaW50IDQKICAgIGV4dHJhY3QzIC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgYnRvaQogICAgZnJhbWVfZGlnIDAKICAgICsKICAgIGZyYW1lX2J1cnkgMAogICAgaW50IDEKICAgICsKICAgIGZyYW1lX2J1cnkgMQogICAgYiBhcmM0X3N0YXRpY19hcnJheV9mb3JfaGVhZGVyQDEKCmFyYzRfc3RhdGljX2FycmF5X2FmdGVyX2ZvckA0OgogICAgZnJhbWVfZGlnIDAKICAgIGludCAzOTQKICAgID09CiAgICBhc3NlcnQKICAgIGJ5dGUgMHg2NQogICAgYnl0ZSAweGNhCiAgICByZXBsYWNlMiAwCiAgICBleHRyYWN0IDAgMSAvLyBvbiBlcnJvcjogSW5kZXggYWNjZXNzIGlzIG91dCBvZiBib3VuZHMKICAgIGJ0b2kKICAgIGludCAyMDIKICAgID09CiAgICBhc3NlcnQKICAgIHJldHN1Ygo=", "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RhdGljQXJyYXkuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" }, "state": { diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.approval.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.approval.teal index 4c5fbc2..4de542f 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.approval.teal +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.approval.teal @@ -10,21 +10,22 @@ __puya_arc4_router__: proto 0 1 txn NumAppArgs bz __puya_arc4_router___bare_routing@6 - method "arc4_tuple_argument((uint8,string,uint64,uint32[]))string" - method "arc4_tuple_return()(uint128,string)" + method "add_contact_info((string,string,uint64,uint8[]))uint64" + method "return_contact()(string,string,uint64)" txna ApplicationArgs 0 - match __puya_arc4_router___arc4_tuple_argument_route@2 __puya_arc4_router___arc4_tuple_return_route@3 + match __puya_arc4_router___add_contact_info_route@2 __puya_arc4_router___return_contact_route@3 int 0 retsub -__puya_arc4_router___arc4_tuple_argument_route@2: +__puya_arc4_router___add_contact_info_route@2: txn OnCompletion ! assert // OnCompletion is NoOp txn ApplicationID assert // is not creating txna ApplicationArgs 1 - callsub arc4_tuple_argument + callsub add_contact_info + itob byte 0x151f7c75 swap concat @@ -32,13 +33,13 @@ __puya_arc4_router___arc4_tuple_argument_route@2: int 1 retsub -__puya_arc4_router___arc4_tuple_return_route@3: +__puya_arc4_router___return_contact_route@3: txn OnCompletion ! assert // OnCompletion is NoOp txn ApplicationID assert // is not creating - callsub arc4_tuple_return + callsub return_contact byte 0x151f7c75 swap concat @@ -60,67 +61,85 @@ __puya_arc4_router___after_if_else@10: retsub -// smart_contracts.arc4_types.contract.Arc4Tuple.arc4_tuple_argument(a: bytes) -> bytes: -arc4_tuple_argument: +// smart_contracts.arc4_types.contract.Arc4Tuple.add_contact_info(contact: bytes) -> uint64: +add_contact_info: proto 1 1 frame_dig -1 - extract 0 1 // on error: Index access is out of bounds - btoi + int 0 + extract_uint16 frame_dig -1 - extract 3 8 // on error: Index access is out of bounds - btoi - + + int 2 + extract_uint16 + frame_dig -1 + uncover 2 + dig 2 + substring3 + swap frame_dig -1 - int 11 + int 12 extract_uint16 - dup + frame_dig -1 + uncover 2 + dig 2 + substring3 + cover 2 + frame_dig -1 + extract 4 8 // on error: Index access is out of bounds + cover 3 frame_dig -1 len frame_dig -1 cover 2 substring3 dup + cover 4 + cover 4 + extract 2 0 + byte "John Woods" + == + assert + extract 2 0 + byte "john@something.com" + == + assert + byte 0x00000000211d1ae3 + b== + assert + int 0 + swap int 0 extract_uint16 int 0 -arc4_tuple_argument_for_header@1: - frame_dig 4 +add_contact_info_for_header@1: frame_dig 3 - < - bz arc4_tuple_argument_after_for@4 frame_dig 2 + < + bz add_contact_info_after_for@4 + frame_dig 0 extract 2 0 - frame_dig 4 + frame_dig 3 dup cover 2 - int 4 - * - int 4 + int 1 extract3 // on error: Index access is out of bounds btoi - frame_dig 0 + frame_dig 1 + - frame_bury 0 + frame_bury 1 int 1 + - frame_bury 4 - b arc4_tuple_argument_for_header@1 + frame_bury 3 + b add_contact_info_for_header@1 -arc4_tuple_argument_after_for@4: - frame_dig -1 - int 1 - extract_uint16 - frame_dig -1 - swap +add_contact_info_after_for@4: frame_dig 1 - substring3 frame_bury 0 retsub -// smart_contracts.arc4_types.contract.Arc4Tuple.arc4_tuple_return() -> bytes: -arc4_tuple_return: +// smart_contracts.arc4_types.contract.Arc4Tuple.return_contact() -> bytes: +return_contact: proto 0 1 - byte 0x0000000000000000000000000000002a0012000d68656c6c6f2c20776f726c6421 + byte 0x000c001300000000211d1ae30005416c6963650013616c69636540736f6d657468696e672e636f6d retsub diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.arc32.json b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.arc32.json index 9f7f02a..f60bdd6 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.arc32.json +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.arc32.json @@ -1,18 +1,18 @@ { "hints": { - "arc4_tuple_argument((uint8,string,uint64,uint32[]))string": { + "add_contact_info((string,string,uint64,uint8[]))uint64": { "call_config": { "no_op": "CALL" } }, - "arc4_tuple_return()(uint128,string)": { + "return_contact()(string,string,uint64)": { "call_config": { "no_op": "CALL" } } }, "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHVwbGUuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUdXBsZS5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANgogICAgbWV0aG9kICJhcmM0X3R1cGxlX2FyZ3VtZW50KCh1aW50OCxzdHJpbmcsdWludDY0LHVpbnQzMltdKSlzdHJpbmciCiAgICBtZXRob2QgImFyYzRfdHVwbGVfcmV0dXJuKCkodWludDEyOCxzdHJpbmcpIgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAogICAgbWF0Y2ggX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF90dXBsZV9hcmd1bWVudF9yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdHVwbGVfcmV0dXJuX3JvdXRlQDMKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdHVwbGVfYXJndW1lbnRfcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF90dXBsZV9hcmd1bWVudAogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF90dXBsZV9yZXR1cm5fcm91dGVAMzoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIGNhbGxzdWIgYXJjNF90dXBsZV9yZXR1cm4KICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgYm56IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTAKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICAhCiAgICBhc3NlcnQgLy8gaXMgY3JlYXRpbmcKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTA6CiAgICBpbnQgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLmFyYzRfdHVwbGVfYXJndW1lbnQoYTogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X3R1cGxlX2FyZ3VtZW50OgogICAgcHJvdG8gMSAxCiAgICBmcmFtZV9kaWcgLTEKICAgIGV4dHJhY3QgMCAxIC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgYnRvaQogICAgZnJhbWVfZGlnIC0xCiAgICBleHRyYWN0IDMgOCAvLyBvbiBlcnJvcjogSW5kZXggYWNjZXNzIGlzIG91dCBvZiBib3VuZHMKICAgIGJ0b2kKICAgICsKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDExCiAgICBleHRyYWN0X3VpbnQxNgogICAgZHVwCiAgICBmcmFtZV9kaWcgLTEKICAgIGxlbgogICAgZnJhbWVfZGlnIC0xCiAgICBjb3ZlciAyCiAgICBzdWJzdHJpbmczCiAgICBkdXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50IDAKCmFyYzRfdHVwbGVfYXJndW1lbnRfZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDQKICAgIGZyYW1lX2RpZyAzCiAgICA8CiAgICBieiBhcmM0X3R1cGxlX2FyZ3VtZW50X2FmdGVyX2ZvckA0CiAgICBmcmFtZV9kaWcgMgogICAgZXh0cmFjdCAyIDAKICAgIGZyYW1lX2RpZyA0CiAgICBkdXAKICAgIGNvdmVyIDIKICAgIGludCA0CiAgICAqCiAgICBpbnQgNAogICAgZXh0cmFjdDMgLy8gb24gZXJyb3I6IEluZGV4IGFjY2VzcyBpcyBvdXQgb2YgYm91bmRzCiAgICBidG9pCiAgICBmcmFtZV9kaWcgMAogICAgKwogICAgZnJhbWVfYnVyeSAwCiAgICBpbnQgMQogICAgKwogICAgZnJhbWVfYnVyeSA0CiAgICBiIGFyYzRfdHVwbGVfYXJndW1lbnRfZm9yX2hlYWRlckAxCgphcmM0X3R1cGxlX2FyZ3VtZW50X2FmdGVyX2ZvckA0OgogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMQogICAgZXh0cmFjdF91aW50MTYKICAgIGZyYW1lX2RpZyAtMQogICAgc3dhcAogICAgZnJhbWVfZGlnIDEKICAgIHN1YnN0cmluZzMKICAgIGZyYW1lX2J1cnkgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLmFyYzRfdHVwbGVfcmV0dXJuKCkgLT4gYnl0ZXM6CmFyYzRfdHVwbGVfcmV0dXJuOgogICAgcHJvdG8gMCAxCiAgICBieXRlIDB4MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMmEwMDEyMDAwZDY4NjU2YzZjNmYyYzIwNzc2ZjcyNmM2NDIxCiAgICByZXRzdWIK", + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHVwbGUuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUdXBsZS5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANgogICAgbWV0aG9kICJhZGRfY29udGFjdF9pbmZvKChzdHJpbmcsc3RyaW5nLHVpbnQ2NCx1aW50OFtdKSl1aW50NjQiCiAgICBtZXRob2QgInJldHVybl9jb250YWN0KCkoc3RyaW5nLHN0cmluZyx1aW50NjQpIgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAogICAgbWF0Y2ggX19wdXlhX2FyYzRfcm91dGVyX19fYWRkX2NvbnRhY3RfaW5mb19yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX3JldHVybl9jb250YWN0X3JvdXRlQDMKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FkZF9jb250YWN0X2luZm9fcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYWRkX2NvbnRhY3RfaW5mbwogICAgaXRvYgogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fcmV0dXJuX2NvbnRhY3Rfcm91dGVAMzoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIGNhbGxzdWIgcmV0dXJuX2NvbnRhY3QKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgYm56IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTAKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICAhCiAgICBhc3NlcnQgLy8gaXMgY3JlYXRpbmcKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTA6CiAgICBpbnQgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLmFkZF9jb250YWN0X2luZm8oY29udGFjdDogYnl0ZXMpIC0+IHVpbnQ2NDoKYWRkX2NvbnRhY3RfaW5mbzoKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDIKICAgIGV4dHJhY3RfdWludDE2CiAgICBmcmFtZV9kaWcgLTEKICAgIHVuY292ZXIgMgogICAgZGlnIDIKICAgIHN1YnN0cmluZzMKICAgIHN3YXAKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDEyCiAgICBleHRyYWN0X3VpbnQxNgogICAgZnJhbWVfZGlnIC0xCiAgICB1bmNvdmVyIDIKICAgIGRpZyAyCiAgICBzdWJzdHJpbmczCiAgICBjb3ZlciAyCiAgICBmcmFtZV9kaWcgLTEKICAgIGV4dHJhY3QgNCA4IC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgY292ZXIgMwogICAgZnJhbWVfZGlnIC0xCiAgICBsZW4KICAgIGZyYW1lX2RpZyAtMQogICAgY292ZXIgMgogICAgc3Vic3RyaW5nMwogICAgZHVwCiAgICBjb3ZlciA0CiAgICBjb3ZlciA0CiAgICBleHRyYWN0IDIgMAogICAgYnl0ZSAiSm9obiBXb29kcyIKICAgID09CiAgICBhc3NlcnQKICAgIGV4dHJhY3QgMiAwCiAgICBieXRlICJqb2huQHNvbWV0aGluZy5jb20iCiAgICA9PQogICAgYXNzZXJ0CiAgICBieXRlIDB4MDAwMDAwMDAyMTFkMWFlMwogICAgYj09CiAgICBhc3NlcnQKICAgIGludCAwCiAgICBzd2FwCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGludCAwCgphZGRfY29udGFjdF9pbmZvX2Zvcl9oZWFkZXJAMToKICAgIGZyYW1lX2RpZyAzCiAgICBmcmFtZV9kaWcgMgogICAgPAogICAgYnogYWRkX2NvbnRhY3RfaW5mb19hZnRlcl9mb3JANAogICAgZnJhbWVfZGlnIDAKICAgIGV4dHJhY3QgMiAwCiAgICBmcmFtZV9kaWcgMwogICAgZHVwCiAgICBjb3ZlciAyCiAgICBpbnQgMQogICAgZXh0cmFjdDMgLy8gb24gZXJyb3I6IEluZGV4IGFjY2VzcyBpcyBvdXQgb2YgYm91bmRzCiAgICBidG9pCiAgICBmcmFtZV9kaWcgMQogICAgKwogICAgZnJhbWVfYnVyeSAxCiAgICBpbnQgMQogICAgKwogICAgZnJhbWVfYnVyeSAzCiAgICBiIGFkZF9jb250YWN0X2luZm9fZm9yX2hlYWRlckAxCgphZGRfY29udGFjdF9pbmZvX2FmdGVyX2ZvckA0OgogICAgZnJhbWVfZGlnIDEKICAgIGZyYW1lX2J1cnkgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLnJldHVybl9jb250YWN0KCkgLT4gYnl0ZXM6CnJldHVybl9jb250YWN0OgogICAgcHJvdG8gMCAxCiAgICBieXRlIDB4MDAwYzAwMTMwMDAwMDAwMDIxMWQxYWUzMDAwNTQxNmM2OTYzNjUwMDEzNjE2YzY5NjM2NTQwNzM2ZjZkNjU3NDY4Njk2ZTY3MmU2MzZmNmQKICAgIHJldHN1Ygo=", "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHVwbGUuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" }, "state": { @@ -39,25 +39,25 @@ "name": "Arc4Tuple", "methods": [ { - "name": "arc4_tuple_argument", + "name": "add_contact_info", "args": [ { - "type": "(uint8,string,uint64,uint32[])", - "name": "a" + "type": "(string,string,uint64,uint8[])", + "name": "contact" } ], "readonly": false, "returns": { - "type": "string" + "type": "uint64" }, "desc": "An arc4.Tuple is a heterogeneous collection of arc4 types." }, { - "name": "arc4_tuple_return", + "name": "return_contact", "args": [], "readonly": false, "returns": { - "type": "(uint128,string)" + "type": "(string,string,uint64)" }, "desc": "An arc4.Tuple can be returned when more than one return value is needed." } diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_dynamic_array_client.py b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_dynamic_array_client.py index 4bf7295..63e6c90 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_dynamic_array_client.py +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_dynamic_array_client.py @@ -35,7 +35,7 @@ } }, "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5LmFwcHJvdmFsX3Byb2dyYW06CiAgICBjYWxsc3ViIF9fcHV5YV9hcmM0X3JvdXRlcl9fCiAgICByZXR1cm4KCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5Ll9fcHV5YV9hcmM0X3JvdXRlcl9fKCkgLT4gdWludDY0OgpfX3B1eWFfYXJjNF9yb3V0ZXJfXzoKICAgIHByb3RvIDAgMQogICAgdHhuIE51bUFwcEFyZ3MKICAgIGJ6IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2CiAgICBtZXRob2QgImFyYzRfZHluYW1pY19hcnJheShzdHJpbmcpc3RyaW5nIgogICAgbWV0aG9kICJhcmM0X2R5bmFtaWNfYnl0ZXMoKWJ5dGVbXSIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfZHluYW1pY19hcnJheV9yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfZHluYW1pY19ieXRlc19yb3V0ZUAzCiAgICBpbnQgMAogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2R5bmFtaWNfYXJyYXlfcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF9keW5hbWljX2FycmF5CiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2R5bmFtaWNfYnl0ZXNfcm91dGVAMzoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIGNhbGxzdWIgYXJjNF9keW5hbWljX2J5dGVzCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgIGJueiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDEwCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgIQogICAgYXNzZXJ0IC8vIGlzIGNyZWF0aW5nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDEwOgogICAgaW50IDAKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzREeW5hbWljQXJyYXkuYXJjNF9keW5hbWljX2FycmF5KG5hbWU6IGJ5dGVzKSAtPiBieXRlczoKYXJjNF9keW5hbWljX2FycmF5OgogICAgcHJvdG8gMSAxCiAgICBieXRlIDB4MDAwMTAwMDIwMDA1NDg2NTZjNmM2ZgogICAgYnl0ZSAweDAwMDYyMDc3NmY3MjZjNjQwMDAyMmMyMAogICAgaW50IDIKICAgIGNhbGxzdWIgZHluYW1pY19hcnJheV9jb25jYXRfYnl0ZV9sZW5ndGhfaGVhZAogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMQogICAgY2FsbHN1YiBkeW5hbWljX2FycmF5X2NvbmNhdF9ieXRlX2xlbmd0aF9oZWFkCiAgICBieXRlIDB4MDAwMTIxCiAgICBpbnQgMQogICAgY2FsbHN1YiBkeW5hbWljX2FycmF5X2NvbmNhdF9ieXRlX2xlbmd0aF9oZWFkCiAgICBjYWxsc3ViIGR5bmFtaWNfYXJyYXlfcG9wX2J5dGVfbGVuZ3RoX2hlYWQKICAgIGR1cAogICAgdW5jb3ZlciAyCiAgICBwb3AKICAgIGJ5dGUgIiIKICAgIHN3YXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50IDAKCmFyYzRfZHluYW1pY19hcnJheV9mb3JfaGVhZGVyQDE6CiAgICBmcmFtZV9kaWcgMwogICAgZnJhbWVfZGlnIDIKICAgIDwKICAgIGJ6IGFyYzRfZHluYW1pY19hcnJheV9hZnRlcl9mb3JANAogICAgZnJhbWVfZGlnIDAKICAgIGV4dHJhY3QgMiAwCiAgICBmcmFtZV9kaWcgMwogICAgZHVwCiAgICBjb3ZlciAyCiAgICBpbnQgMgogICAgKgogICAgZGlnIDEKICAgIHN3YXAKICAgIGV4dHJhY3RfdWludDE2CiAgICBkdXAyCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50IDIKICAgICsKICAgIGV4dHJhY3QzCiAgICBleHRyYWN0IDIgMAogICAgZnJhbWVfZGlnIDEKICAgIHN3YXAKICAgIGNvbmNhdAogICAgZnJhbWVfYnVyeSAxCiAgICBpbnQgMQogICAgKwogICAgZnJhbWVfYnVyeSAzCiAgICBiIGFyYzRfZHluYW1pY19hcnJheV9mb3JfaGVhZGVyQDEKCmFyYzRfZHluYW1pY19hcnJheV9hZnRlcl9mb3JANDoKICAgIGZyYW1lX2RpZyAxCiAgICBkdXAKICAgIGxlbgogICAgaXRvYgogICAgZXh0cmFjdCA2IDIKICAgIHN3YXAKICAgIGNvbmNhdAogICAgZnJhbWVfYnVyeSAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5LmFyYzRfZHluYW1pY19ieXRlcygpIC0+IGJ5dGVzOgphcmM0X2R5bmFtaWNfYnl0ZXM6CiAgICBwcm90byAwIDEKICAgIGJ5dGUgMHgwMDAzZmZmZmZmCiAgICBieXRlIDB4MDAKICAgIHJlcGxhY2UyIDIKICAgIHJldHN1YgoKCi8vIF9wdXlhX2xpYi5hcmM0LmR5bmFtaWNfYXJyYXlfcG9wX2J5dGVfbGVuZ3RoX2hlYWQoYXJyYXk6IGJ5dGVzKSAtPiBieXRlcywgYnl0ZXM6CmR5bmFtaWNfYXJyYXlfcG9wX2J5dGVfbGVuZ3RoX2hlYWQ6CiAgICBwcm90byAxIDIKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDAKICAgIGV4dHJhY3RfdWludDE2CiAgICBpbnQgMQogICAgLQogICAgZHVwCiAgICBpbnQgMgogICAgKgogICAgZnJhbWVfZGlnIC0xCiAgICBleHRyYWN0IDIgMAogICAgZHVwCiAgICBkaWcgMgogICAgZXh0cmFjdF91aW50MTYKICAgIHN3YXAKICAgIGR1cAogICAgbGVuCiAgICBzd2FwCiAgICBkdXAKICAgIGRpZyAzCiAgICB1bmNvdmVyIDMKICAgIHN1YnN0cmluZzMKICAgIGNvdmVyIDMKICAgIGR1cAogICAgaW50IDAKICAgIGRpZyA0CiAgICBzdWJzdHJpbmczCiAgICBjb3ZlciAyCiAgICB1bmNvdmVyIDMKICAgIGludCAyCiAgICArCiAgICB1bmNvdmVyIDIKICAgIHN1YnN0cmluZzMKICAgIGNvbmNhdAogICAgZGlnIDIKICAgIGl0b2IKICAgIGV4dHJhY3QgNiAyCiAgICBzd2FwCiAgICB1bmNvdmVyIDMKICAgIGludCAwCiAgICBjYWxsc3ViIHJlY2FsY3VsYXRlX2hlYWRfZm9yX2VsZW1lbnRzX3dpdGhfYnl0ZV9sZW5ndGhfaGVhZAogICAgY29uY2F0CiAgICByZXRzdWIKCgovLyBfcHV5YV9saWIuYXJjNC5keW5hbWljX2FycmF5X2NvbmNhdF9ieXRlX2xlbmd0aF9oZWFkKGFycmF5OiBieXRlcywgbmV3X2l0ZW1zX2J5dGVzOiBieXRlcywgbmV3X2l0ZW1zX2NvdW50OiB1aW50NjQpIC0+IGJ5dGVzOgpkeW5hbWljX2FycmF5X2NvbmNhdF9ieXRlX2xlbmd0aF9oZWFkOgogICAgcHJvdG8gMyAxCiAgICBmcmFtZV9kaWcgLTMKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgZHVwCiAgICBmcmFtZV9kaWcgLTEKICAgICsKICAgIHN3YXAKICAgIGludCAyCiAgICAqCiAgICBpbnQgMgogICAgKwogICAgc3dhcAogICAgZHVwCiAgICBpdG9iCiAgICBleHRyYWN0IDYgMgogICAgc3dhcAogICAgZnJhbWVfZGlnIC0zCiAgICBpbnQgMgogICAgZGlnIDQKICAgIHN1YnN0cmluZzMKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDIKICAgICoKICAgIGJ6ZXJvCiAgICBjb25jYXQKICAgIGZyYW1lX2RpZyAtMwogICAgbGVuCiAgICBmcmFtZV9kaWcgLTMKICAgIHVuY292ZXIgNQogICAgdW5jb3ZlciAyCiAgICBzdWJzdHJpbmczCiAgICBjb25jYXQKICAgIGZyYW1lX2RpZyAtMgogICAgY29uY2F0CiAgICBzd2FwCiAgICBpbnQgMAogICAgY2FsbHN1YiByZWNhbGN1bGF0ZV9oZWFkX2Zvcl9lbGVtZW50c193aXRoX2J5dGVfbGVuZ3RoX2hlYWQKICAgIGNvbmNhdAogICAgcmV0c3ViCgoKLy8gX3B1eWFfbGliLmFyYzQucmVjYWxjdWxhdGVfaGVhZF9mb3JfZWxlbWVudHNfd2l0aF9ieXRlX2xlbmd0aF9oZWFkKGFycmF5X2hlYWRfYW5kX3RhaWw6IGJ5dGVzLCBsZW5ndGg6IHVpbnQ2NCwgc3RhcnRfYXRfaW5kZXg6IHVpbnQ2NCkgLT4gYnl0ZXM6CnJlY2FsY3VsYXRlX2hlYWRfZm9yX2VsZW1lbnRzX3dpdGhfYnl0ZV9sZW5ndGhfaGVhZDoKICAgIHByb3RvIDMgMQogICAgZnJhbWVfZGlnIC0yCiAgICBpbnQgMgogICAgKgogICAgZHVwCiAgICBmcmFtZV9kaWcgLTEKICAgIGludCAyCiAgICAqCiAgICBkdXAKICAgIGNvdmVyIDIKICAgIGZyYW1lX2RpZyAtMwogICAgc3dhcAogICAgZXh0cmFjdF91aW50MTYKICAgIGZyYW1lX2RpZyAtMQogICAgc2VsZWN0CgpyZWNhbGN1bGF0ZV9oZWFkX2Zvcl9lbGVtZW50c193aXRoX2J5dGVfbGVuZ3RoX2hlYWRfZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDEKICAgIGZyYW1lX2RpZyAwCiAgICA8CiAgICBieiByZWNhbGN1bGF0ZV9oZWFkX2Zvcl9lbGVtZW50c193aXRoX2J5dGVfbGVuZ3RoX2hlYWRfYWZ0ZXJfZm9yQDQKICAgIGZyYW1lX2RpZyAyCiAgICBkdXAKICAgIGl0b2IKICAgIGV4dHJhY3QgNiAyCiAgICBmcmFtZV9kaWcgLTMKICAgIGZyYW1lX2RpZyAxCiAgICBkdXAKICAgIGNvdmVyIDQKICAgIHVuY292ZXIgMgogICAgcmVwbGFjZTMKICAgIGR1cAogICAgZnJhbWVfYnVyeSAtMwogICAgZGlnIDEKICAgIGV4dHJhY3RfdWludDE2CiAgICBpbnQgMgogICAgKwogICAgKwogICAgZnJhbWVfYnVyeSAyCiAgICBpbnQgMgogICAgKwogICAgZnJhbWVfYnVyeSAxCiAgICBiIHJlY2FsY3VsYXRlX2hlYWRfZm9yX2VsZW1lbnRzX3dpdGhfYnl0ZV9sZW5ndGhfaGVhZF9mb3JfaGVhZGVyQDEKCnJlY2FsY3VsYXRlX2hlYWRfZm9yX2VsZW1lbnRzX3dpdGhfYnl0ZV9sZW5ndGhfaGVhZF9hZnRlcl9mb3JANDoKICAgIGZyYW1lX2RpZyAtMwogICAgZnJhbWVfYnVyeSAwCiAgICByZXRzdWIK", + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5LmFwcHJvdmFsX3Byb2dyYW06CiAgICBjYWxsc3ViIF9fcHV5YV9hcmM0X3JvdXRlcl9fCiAgICByZXR1cm4KCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5Ll9fcHV5YV9hcmM0X3JvdXRlcl9fKCkgLT4gdWludDY0OgpfX3B1eWFfYXJjNF9yb3V0ZXJfXzoKICAgIHByb3RvIDAgMQogICAgdHhuIE51bUFwcEFyZ3MKICAgIGJ6IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2CiAgICBtZXRob2QgImFyYzRfZHluYW1pY19hcnJheShzdHJpbmcpc3RyaW5nIgogICAgbWV0aG9kICJhcmM0X2R5bmFtaWNfYnl0ZXMoKWJ5dGVbXSIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfZHluYW1pY19hcnJheV9yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfZHluYW1pY19ieXRlc19yb3V0ZUAzCiAgICBpbnQgMAogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2R5bmFtaWNfYXJyYXlfcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF9keW5hbWljX2FycmF5CiAgICBkdXAKICAgIGxlbgogICAgaXRvYgogICAgZXh0cmFjdCA2IDIKICAgIHN3YXAKICAgIGNvbmNhdAogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9keW5hbWljX2J5dGVzX3JvdXRlQDM6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICBjYWxsc3ViIGFyYzRfZHluYW1pY19ieXRlcwogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDY6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBibnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgICEKICAgIGFzc2VydCAvLyBpcyBjcmVhdGluZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMDoKICAgIGludCAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5LmFyYzRfZHluYW1pY19hcnJheShuYW1lOiBieXRlcykgLT4gYnl0ZXM6CmFyYzRfZHluYW1pY19hcnJheToKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBsZW4KICAgIGludCA0CiAgICArCiAgICBpdG9iCiAgICBleHRyYWN0IDYgMgogICAgYnl0ZSAweDAwMDQKICAgIHN3YXAKICAgIGNvbmNhdAogICAgZnJhbWVfZGlnIC0xCiAgICBjb25jYXQKICAgIGJ5dGUgMHgwMDAxMjEKICAgIGNvbmNhdAogICAgYnl0ZSAweDAwMDIKICAgIHN3YXAKICAgIGNvbmNhdAogICAgZHVwCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIHN3YXAKICAgIGV4dHJhY3QgMiAwCiAgICBzd2FwCiAgICBkdXAKICAgIGludCAyCiAgICAqCiAgICBzd2FwCiAgICBkaWcgMgogICAgbGVuCiAgICBzd2FwCiAgICBjb3ZlciAzCiAgICBzdWJzdHJpbmczCiAgICBieXRlIDB4MDAwMTAwMDIwMDA2NDg2NTZjNmM2ZjIwCiAgICBzd2FwCiAgICB1bmNvdmVyIDIKICAgIGNhbGxzdWIgZHluYW1pY19hcnJheV9jb25jYXRfYnl0ZV9sZW5ndGhfaGVhZAogICAgZHVwbiAyCiAgICBjYWxsc3ViIGR5bmFtaWNfYXJyYXlfcG9wX2J5dGVfbGVuZ3RoX2hlYWQKICAgIGJ1cnkgMQogICAgY2FsbHN1YiBkeW5hbWljX2FycmF5X3BvcF9ieXRlX2xlbmd0aF9oZWFkCiAgICBidXJ5IDEKICAgIGJ5dGUgMHgwMDA2Nzc2ZjcyNmM2NDIxCiAgICBpbnQgMQogICAgY2FsbHN1YiBkeW5hbWljX2FycmF5X2NvbmNhdF9ieXRlX2xlbmd0aF9oZWFkCiAgICBwb3AKICAgIGJ5dGUgIiIKICAgIHN3YXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50IDAKCmFyYzRfZHluYW1pY19hcnJheV9mb3JfaGVhZGVyQDE6CiAgICBmcmFtZV9kaWcgMwogICAgZnJhbWVfZGlnIDIKICAgIDwKICAgIGJ6IGFyYzRfZHluYW1pY19hcnJheV9hZnRlcl9mb3JANAogICAgZnJhbWVfZGlnIDAKICAgIGV4dHJhY3QgMiAwCiAgICBmcmFtZV9kaWcgMwogICAgZHVwCiAgICBjb3ZlciAyCiAgICBpbnQgMgogICAgKgogICAgZGlnIDEKICAgIHN3YXAKICAgIGV4dHJhY3RfdWludDE2CiAgICBkdXAyCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50IDIKICAgICsKICAgIGV4dHJhY3QzCiAgICBleHRyYWN0IDIgMAogICAgZnJhbWVfZGlnIDEKICAgIHN3YXAKICAgIGNvbmNhdAogICAgZnJhbWVfYnVyeSAxCiAgICBpbnQgMQogICAgKwogICAgZnJhbWVfYnVyeSAzCiAgICBiIGFyYzRfZHluYW1pY19hcnJheV9mb3JfaGVhZGVyQDEKCmFyYzRfZHluYW1pY19hcnJheV9hZnRlcl9mb3JANDoKICAgIGZyYW1lX2RpZyAxCiAgICBmcmFtZV9idXJ5IDAKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzREeW5hbWljQXJyYXkuYXJjNF9keW5hbWljX2J5dGVzKCkgLT4gYnl0ZXM6CmFyYzRfZHluYW1pY19ieXRlczoKICAgIHByb3RvIDAgMQogICAgYnl0ZSAweDAwMDNmZmZmZmYKICAgIGJ5dGUgMHgwMAogICAgcmVwbGFjZTIgMgogICAgcmV0c3ViCgoKLy8gX3B1eWFfbGliLmFyYzQuZHluYW1pY19hcnJheV9wb3BfYnl0ZV9sZW5ndGhfaGVhZChhcnJheTogYnl0ZXMpIC0+IGJ5dGVzLCBieXRlczoKZHluYW1pY19hcnJheV9wb3BfYnl0ZV9sZW5ndGhfaGVhZDoKICAgIHByb3RvIDEgMgogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGludCAxCiAgICAtCiAgICBkdXAKICAgIGludCAyCiAgICAqCiAgICBmcmFtZV9kaWcgLTEKICAgIGV4dHJhY3QgMiAwCiAgICBkdXAKICAgIGRpZyAyCiAgICBleHRyYWN0X3VpbnQxNgogICAgc3dhcAogICAgZHVwCiAgICBsZW4KICAgIHN3YXAKICAgIGR1cAogICAgZGlnIDMKICAgIHVuY292ZXIgMwogICAgc3Vic3RyaW5nMwogICAgY292ZXIgMwogICAgZHVwCiAgICBpbnQgMAogICAgZGlnIDQKICAgIHN1YnN0cmluZzMKICAgIGNvdmVyIDIKICAgIHVuY292ZXIgMwogICAgaW50IDIKICAgICsKICAgIHVuY292ZXIgMgogICAgc3Vic3RyaW5nMwogICAgY29uY2F0CiAgICBkaWcgMgogICAgaXRvYgogICAgZXh0cmFjdCA2IDIKICAgIHN3YXAKICAgIHVuY292ZXIgMwogICAgaW50IDAKICAgIGNhbGxzdWIgcmVjYWxjdWxhdGVfaGVhZF9mb3JfZWxlbWVudHNfd2l0aF9ieXRlX2xlbmd0aF9oZWFkCiAgICBjb25jYXQKICAgIHJldHN1YgoKCi8vIF9wdXlhX2xpYi5hcmM0LmR5bmFtaWNfYXJyYXlfY29uY2F0X2J5dGVfbGVuZ3RoX2hlYWQoYXJyYXk6IGJ5dGVzLCBuZXdfaXRlbXNfYnl0ZXM6IGJ5dGVzLCBuZXdfaXRlbXNfY291bnQ6IHVpbnQ2NCkgLT4gYnl0ZXM6CmR5bmFtaWNfYXJyYXlfY29uY2F0X2J5dGVfbGVuZ3RoX2hlYWQ6CiAgICBwcm90byAzIDEKICAgIGZyYW1lX2RpZyAtMwogICAgaW50IDAKICAgIGV4dHJhY3RfdWludDE2CiAgICBkdXAKICAgIGZyYW1lX2RpZyAtMQogICAgKwogICAgc3dhcAogICAgaW50IDIKICAgICoKICAgIGludCAyCiAgICArCiAgICBzd2FwCiAgICBkdXAKICAgIGl0b2IKICAgIGV4dHJhY3QgNiAyCiAgICBzd2FwCiAgICBmcmFtZV9kaWcgLTMKICAgIGludCAyCiAgICBkaWcgNAogICAgc3Vic3RyaW5nMwogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMgogICAgKgogICAgYnplcm8KICAgIGNvbmNhdAogICAgZnJhbWVfZGlnIC0zCiAgICBsZW4KICAgIGZyYW1lX2RpZyAtMwogICAgdW5jb3ZlciA1CiAgICB1bmNvdmVyIDIKICAgIHN1YnN0cmluZzMKICAgIGNvbmNhdAogICAgZnJhbWVfZGlnIC0yCiAgICBjb25jYXQKICAgIHN3YXAKICAgIGludCAwCiAgICBjYWxsc3ViIHJlY2FsY3VsYXRlX2hlYWRfZm9yX2VsZW1lbnRzX3dpdGhfYnl0ZV9sZW5ndGhfaGVhZAogICAgY29uY2F0CiAgICByZXRzdWIKCgovLyBfcHV5YV9saWIuYXJjNC5yZWNhbGN1bGF0ZV9oZWFkX2Zvcl9lbGVtZW50c193aXRoX2J5dGVfbGVuZ3RoX2hlYWQoYXJyYXlfaGVhZF9hbmRfdGFpbDogYnl0ZXMsIGxlbmd0aDogdWludDY0LCBzdGFydF9hdF9pbmRleDogdWludDY0KSAtPiBieXRlczoKcmVjYWxjdWxhdGVfaGVhZF9mb3JfZWxlbWVudHNfd2l0aF9ieXRlX2xlbmd0aF9oZWFkOgogICAgcHJvdG8gMyAxCiAgICBmcmFtZV9kaWcgLTIKICAgIGludCAyCiAgICAqCiAgICBkdXAKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDIKICAgICoKICAgIGR1cAogICAgY292ZXIgMgogICAgZnJhbWVfZGlnIC0zCiAgICBzd2FwCiAgICBleHRyYWN0X3VpbnQxNgogICAgZnJhbWVfZGlnIC0xCiAgICBzZWxlY3QKCnJlY2FsY3VsYXRlX2hlYWRfZm9yX2VsZW1lbnRzX3dpdGhfYnl0ZV9sZW5ndGhfaGVhZF9mb3JfaGVhZGVyQDE6CiAgICBmcmFtZV9kaWcgMQogICAgZnJhbWVfZGlnIDAKICAgIDwKICAgIGJ6IHJlY2FsY3VsYXRlX2hlYWRfZm9yX2VsZW1lbnRzX3dpdGhfYnl0ZV9sZW5ndGhfaGVhZF9hZnRlcl9mb3JANAogICAgZnJhbWVfZGlnIDIKICAgIGR1cAogICAgaXRvYgogICAgZXh0cmFjdCA2IDIKICAgIGZyYW1lX2RpZyAtMwogICAgZnJhbWVfZGlnIDEKICAgIGR1cAogICAgY292ZXIgNAogICAgdW5jb3ZlciAyCiAgICByZXBsYWNlMwogICAgZHVwCiAgICBmcmFtZV9idXJ5IC0zCiAgICBkaWcgMQogICAgZXh0cmFjdF91aW50MTYKICAgIGludCAyCiAgICArCiAgICArCiAgICBmcmFtZV9idXJ5IDIKICAgIGludCAyCiAgICArCiAgICBmcmFtZV9idXJ5IDEKICAgIGIgcmVjYWxjdWxhdGVfaGVhZF9mb3JfZWxlbWVudHNfd2l0aF9ieXRlX2xlbmd0aF9oZWFkX2Zvcl9oZWFkZXJAMQoKcmVjYWxjdWxhdGVfaGVhZF9mb3JfZWxlbWVudHNfd2l0aF9ieXRlX2xlbmd0aF9oZWFkX2FmdGVyX2ZvckA0OgogICAgZnJhbWVfZGlnIC0zCiAgICBmcmFtZV9idXJ5IDAKICAgIHJldHN1Ygo=", "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5LmNsZWFyX3N0YXRlX3Byb2dyYW06CiAgICBpbnQgMQogICAgcmV0dXJuCg==" }, "state": { diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_static_array_client.py b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_static_array_client.py index 69fa2b4..363c953 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_static_array_client.py +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_static_array_client.py @@ -30,7 +30,7 @@ } }, "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RhdGljQXJyYXkuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRTdGF0aWNBcnJheS5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANQogICAgbWV0aG9kICJhcmM0X3N0YXRpY19hcnJheSgpdm9pZCIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfc3RhdGljX2FycmF5X3JvdXRlQDIKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfc3RhdGljX2FycmF5X3JvdXRlQDI6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICBjYWxsc3ViIGFyYzRfc3RhdGljX2FycmF5CiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANToKICAgIHR4biBPbkNvbXBsZXRpb24KICAgIGJueiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDkKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICAhCiAgICBhc3NlcnQgLy8gaXMgY3JlYXRpbmcKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAOToKICAgIGludCAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RhdGljQXJyYXkuYXJjNF9zdGF0aWNfYXJyYXkoKSAtPiB2b2lkOgphcmM0X3N0YXRpY19hcnJheToKICAgIHByb3RvIDAgMAogICAgaW50IDAKICAgIGR1cAoKYXJjNF9zdGF0aWNfYXJyYXlfZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDEKICAgIGludCA0CiAgICA8CiAgICBieiBhcmM0X3N0YXRpY19hcnJheV9hZnRlcl9mb3JANAogICAgZnJhbWVfZGlnIDEKICAgIGR1cAogICAgaW50IDQKICAgICoKICAgIGJ5dGUgMHgwMDAwMDAwMTAwMDAwMDBhMDAwMDAwZmYwMDAwMDA4MAogICAgc3dhcAogICAgaW50IDQKICAgIGV4dHJhY3QzIC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgYnRvaQogICAgZnJhbWVfZGlnIDAKICAgICsKICAgIGZyYW1lX2J1cnkgMAogICAgaW50IDEKICAgICsKICAgIGZyYW1lX2J1cnkgMQogICAgYiBhcmM0X3N0YXRpY19hcnJheV9mb3JfaGVhZGVyQDEKCmFyYzRfc3RhdGljX2FycmF5X2FmdGVyX2ZvckA0OgogICAgZnJhbWVfZGlnIDAKICAgIGludCAzOTQKICAgID09CiAgICBhc3NlcnQKICAgIHJldHN1Ygo=", + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RhdGljQXJyYXkuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRTdGF0aWNBcnJheS5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANQogICAgbWV0aG9kICJhcmM0X3N0YXRpY19hcnJheSgpdm9pZCIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfc3RhdGljX2FycmF5X3JvdXRlQDIKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfc3RhdGljX2FycmF5X3JvdXRlQDI6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICBjYWxsc3ViIGFyYzRfc3RhdGljX2FycmF5CiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANToKICAgIHR4biBPbkNvbXBsZXRpb24KICAgIGJueiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDkKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICAhCiAgICBhc3NlcnQgLy8gaXMgY3JlYXRpbmcKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAOToKICAgIGludCAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RhdGljQXJyYXkuYXJjNF9zdGF0aWNfYXJyYXkoKSAtPiB2b2lkOgphcmM0X3N0YXRpY19hcnJheToKICAgIHByb3RvIDAgMAogICAgaW50IDAKICAgIGR1cAoKYXJjNF9zdGF0aWNfYXJyYXlfZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDEKICAgIGludCA0CiAgICA8CiAgICBieiBhcmM0X3N0YXRpY19hcnJheV9hZnRlcl9mb3JANAogICAgZnJhbWVfZGlnIDEKICAgIGR1cAogICAgaW50IDQKICAgICoKICAgIGJ5dGUgMHgwMDAwMDAwMTAwMDAwMDBhMDAwMDAwZmYwMDAwMDA4MAogICAgc3dhcAogICAgaW50IDQKICAgIGV4dHJhY3QzIC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgYnRvaQogICAgZnJhbWVfZGlnIDAKICAgICsKICAgIGZyYW1lX2J1cnkgMAogICAgaW50IDEKICAgICsKICAgIGZyYW1lX2J1cnkgMQogICAgYiBhcmM0X3N0YXRpY19hcnJheV9mb3JfaGVhZGVyQDEKCmFyYzRfc3RhdGljX2FycmF5X2FmdGVyX2ZvckA0OgogICAgZnJhbWVfZGlnIDAKICAgIGludCAzOTQKICAgID09CiAgICBhc3NlcnQKICAgIGJ5dGUgMHg2NQogICAgYnl0ZSAweGNhCiAgICByZXBsYWNlMiAwCiAgICBleHRyYWN0IDAgMSAvLyBvbiBlcnJvcjogSW5kZXggYWNjZXNzIGlzIG91dCBvZiBib3VuZHMKICAgIGJ0b2kKICAgIGludCAyMDIKICAgID09CiAgICBhc3NlcnQKICAgIHJldHN1Ygo=", "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RhdGljQXJyYXkuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" }, "state": { diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_tuple_client.py b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_tuple_client.py index 3bfc750..b7555e3 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_tuple_client.py +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_tuple_client.py @@ -23,19 +23,19 @@ _APP_SPEC_JSON = r"""{ "hints": { - "arc4_tuple_argument((uint8,string,uint64,uint32[]))string": { + "add_contact_info((string,string,uint64,uint8[]))uint64": { "call_config": { "no_op": "CALL" } }, - "arc4_tuple_return()(uint128,string)": { + "return_contact()(string,string,uint64)": { "call_config": { "no_op": "CALL" } } }, "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHVwbGUuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUdXBsZS5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANgogICAgbWV0aG9kICJhcmM0X3R1cGxlX2FyZ3VtZW50KCh1aW50OCxzdHJpbmcsdWludDY0LHVpbnQzMltdKSlzdHJpbmciCiAgICBtZXRob2QgImFyYzRfdHVwbGVfcmV0dXJuKCkodWludDEyOCxzdHJpbmcpIgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAogICAgbWF0Y2ggX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF90dXBsZV9hcmd1bWVudF9yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdHVwbGVfcmV0dXJuX3JvdXRlQDMKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdHVwbGVfYXJndW1lbnRfcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF90dXBsZV9hcmd1bWVudAogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF90dXBsZV9yZXR1cm5fcm91dGVAMzoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIGNhbGxzdWIgYXJjNF90dXBsZV9yZXR1cm4KICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgYm56IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTAKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICAhCiAgICBhc3NlcnQgLy8gaXMgY3JlYXRpbmcKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTA6CiAgICBpbnQgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLmFyYzRfdHVwbGVfYXJndW1lbnQoYTogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X3R1cGxlX2FyZ3VtZW50OgogICAgcHJvdG8gMSAxCiAgICBmcmFtZV9kaWcgLTEKICAgIGV4dHJhY3QgMCAxIC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgYnRvaQogICAgZnJhbWVfZGlnIC0xCiAgICBleHRyYWN0IDMgOCAvLyBvbiBlcnJvcjogSW5kZXggYWNjZXNzIGlzIG91dCBvZiBib3VuZHMKICAgIGJ0b2kKICAgICsKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDExCiAgICBleHRyYWN0X3VpbnQxNgogICAgZHVwCiAgICBmcmFtZV9kaWcgLTEKICAgIGxlbgogICAgZnJhbWVfZGlnIC0xCiAgICBjb3ZlciAyCiAgICBzdWJzdHJpbmczCiAgICBkdXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50IDAKCmFyYzRfdHVwbGVfYXJndW1lbnRfZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDQKICAgIGZyYW1lX2RpZyAzCiAgICA8CiAgICBieiBhcmM0X3R1cGxlX2FyZ3VtZW50X2FmdGVyX2ZvckA0CiAgICBmcmFtZV9kaWcgMgogICAgZXh0cmFjdCAyIDAKICAgIGZyYW1lX2RpZyA0CiAgICBkdXAKICAgIGNvdmVyIDIKICAgIGludCA0CiAgICAqCiAgICBpbnQgNAogICAgZXh0cmFjdDMgLy8gb24gZXJyb3I6IEluZGV4IGFjY2VzcyBpcyBvdXQgb2YgYm91bmRzCiAgICBidG9pCiAgICBmcmFtZV9kaWcgMAogICAgKwogICAgZnJhbWVfYnVyeSAwCiAgICBpbnQgMQogICAgKwogICAgZnJhbWVfYnVyeSA0CiAgICBiIGFyYzRfdHVwbGVfYXJndW1lbnRfZm9yX2hlYWRlckAxCgphcmM0X3R1cGxlX2FyZ3VtZW50X2FmdGVyX2ZvckA0OgogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMQogICAgZXh0cmFjdF91aW50MTYKICAgIGZyYW1lX2RpZyAtMQogICAgc3dhcAogICAgZnJhbWVfZGlnIDEKICAgIHN1YnN0cmluZzMKICAgIGZyYW1lX2J1cnkgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLmFyYzRfdHVwbGVfcmV0dXJuKCkgLT4gYnl0ZXM6CmFyYzRfdHVwbGVfcmV0dXJuOgogICAgcHJvdG8gMCAxCiAgICBieXRlIDB4MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMmEwMDEyMDAwZDY4NjU2YzZjNmYyYzIwNzc2ZjcyNmM2NDIxCiAgICByZXRzdWIK", + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHVwbGUuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUdXBsZS5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANgogICAgbWV0aG9kICJhZGRfY29udGFjdF9pbmZvKChzdHJpbmcsc3RyaW5nLHVpbnQ2NCx1aW50OFtdKSl1aW50NjQiCiAgICBtZXRob2QgInJldHVybl9jb250YWN0KCkoc3RyaW5nLHN0cmluZyx1aW50NjQpIgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAogICAgbWF0Y2ggX19wdXlhX2FyYzRfcm91dGVyX19fYWRkX2NvbnRhY3RfaW5mb19yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX3JldHVybl9jb250YWN0X3JvdXRlQDMKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FkZF9jb250YWN0X2luZm9fcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYWRkX2NvbnRhY3RfaW5mbwogICAgaXRvYgogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fcmV0dXJuX2NvbnRhY3Rfcm91dGVAMzoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIGNhbGxzdWIgcmV0dXJuX2NvbnRhY3QKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgYm56IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTAKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICAhCiAgICBhc3NlcnQgLy8gaXMgY3JlYXRpbmcKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTA6CiAgICBpbnQgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLmFkZF9jb250YWN0X2luZm8oY29udGFjdDogYnl0ZXMpIC0+IHVpbnQ2NDoKYWRkX2NvbnRhY3RfaW5mbzoKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDIKICAgIGV4dHJhY3RfdWludDE2CiAgICBmcmFtZV9kaWcgLTEKICAgIHVuY292ZXIgMgogICAgZGlnIDIKICAgIHN1YnN0cmluZzMKICAgIHN3YXAKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDEyCiAgICBleHRyYWN0X3VpbnQxNgogICAgZnJhbWVfZGlnIC0xCiAgICB1bmNvdmVyIDIKICAgIGRpZyAyCiAgICBzdWJzdHJpbmczCiAgICBjb3ZlciAyCiAgICBmcmFtZV9kaWcgLTEKICAgIGV4dHJhY3QgNCA4IC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgY292ZXIgMwogICAgZnJhbWVfZGlnIC0xCiAgICBsZW4KICAgIGZyYW1lX2RpZyAtMQogICAgY292ZXIgMgogICAgc3Vic3RyaW5nMwogICAgZHVwCiAgICBjb3ZlciA0CiAgICBjb3ZlciA0CiAgICBleHRyYWN0IDIgMAogICAgYnl0ZSAiSm9obiBXb29kcyIKICAgID09CiAgICBhc3NlcnQKICAgIGV4dHJhY3QgMiAwCiAgICBieXRlICJqb2huQHNvbWV0aGluZy5jb20iCiAgICA9PQogICAgYXNzZXJ0CiAgICBieXRlIDB4MDAwMDAwMDAyMTFkMWFlMwogICAgYj09CiAgICBhc3NlcnQKICAgIGludCAwCiAgICBzd2FwCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGludCAwCgphZGRfY29udGFjdF9pbmZvX2Zvcl9oZWFkZXJAMToKICAgIGZyYW1lX2RpZyAzCiAgICBmcmFtZV9kaWcgMgogICAgPAogICAgYnogYWRkX2NvbnRhY3RfaW5mb19hZnRlcl9mb3JANAogICAgZnJhbWVfZGlnIDAKICAgIGV4dHJhY3QgMiAwCiAgICBmcmFtZV9kaWcgMwogICAgZHVwCiAgICBjb3ZlciAyCiAgICBpbnQgMQogICAgZXh0cmFjdDMgLy8gb24gZXJyb3I6IEluZGV4IGFjY2VzcyBpcyBvdXQgb2YgYm91bmRzCiAgICBidG9pCiAgICBmcmFtZV9kaWcgMQogICAgKwogICAgZnJhbWVfYnVyeSAxCiAgICBpbnQgMQogICAgKwogICAgZnJhbWVfYnVyeSAzCiAgICBiIGFkZF9jb250YWN0X2luZm9fZm9yX2hlYWRlckAxCgphZGRfY29udGFjdF9pbmZvX2FmdGVyX2ZvckA0OgogICAgZnJhbWVfZGlnIDEKICAgIGZyYW1lX2J1cnkgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLnJldHVybl9jb250YWN0KCkgLT4gYnl0ZXM6CnJldHVybl9jb250YWN0OgogICAgcHJvdG8gMCAxCiAgICBieXRlIDB4MDAwYzAwMTMwMDAwMDAwMDIxMWQxYWUzMDAwNTQxNmM2OTYzNjUwMDEzNjE2YzY5NjM2NTQwNzM2ZjZkNjU3NDY4Njk2ZTY3MmU2MzZmNmQKICAgIHJldHN1Ygo=", "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHVwbGUuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" }, "state": { @@ -62,23 +62,23 @@ "name": "Arc4Tuple", "methods": [ { - "name": "arc4_tuple_argument", + "name": "add_contact_info", "args": [ { - "type": "(uint8,string,uint64,uint32[])", - "name": "a" + "type": "(string,string,uint64,uint8[])", + "name": "contact" } ], "returns": { - "type": "string" + "type": "uint64" }, "desc": "An arc4.Tuple is a heterogeneous collection of arc4 types." }, { - "name": "arc4_tuple_return", + "name": "return_contact", "args": [], "returns": { - "type": "(uint128,string)" + "type": "(string,string,uint64)" }, "desc": "An arc4.Tuple can be returned when more than one return value is needed." } @@ -163,23 +163,23 @@ def _convert_deploy_args( @dataclasses.dataclass(kw_only=True) -class Arc4TupleArgumentArgs(_ArgsBase[str]): +class AddContactInfoArgs(_ArgsBase[int]): """An arc4.Tuple is a heterogeneous collection of arc4 types.""" - a: tuple[int, str, int, list[int]] + contact: tuple[str, str, int, list[int]] @staticmethod def method() -> str: - return "arc4_tuple_argument((uint8,string,uint64,uint32[]))string" + return "add_contact_info((string,string,uint64,uint8[]))uint64" @dataclasses.dataclass(kw_only=True) -class Arc4TupleReturnArgs(_ArgsBase[tuple[int, str]]): +class ReturnContactArgs(_ArgsBase[tuple[str, str, int]]): """An arc4.Tuple can be returned when more than one return value is needed.""" @staticmethod def method() -> str: - return "arc4_tuple_return()(uint128,string)" + return "return_contact()(string,string,uint64)" @dataclasses.dataclass(kw_only=True) @@ -213,22 +213,22 @@ def simulate(self, options: SimulateOptions | None = None) -> SimulateAtomicTran def execute(self) -> AtomicTransactionResponse: return self.app_client.execute_atc(self.atc) - def arc4_tuple_argument( + def add_contact_info( self, *, - a: tuple[int, str, int, list[int]], + contact: tuple[str, str, int, list[int]], transaction_parameters: algokit_utils.TransactionParameters | None = None, ) -> "Composer": """An arc4.Tuple is a heterogeneous collection of arc4 types. - Adds a call to `arc4_tuple_argument((uint8,string,uint64,uint32[]))string` ABI method + Adds a call to `add_contact_info((string,string,uint64,uint8[]))uint64` ABI method - :param tuple[int, str, int, list[int]] a: The `a` ABI parameter + :param tuple[str, str, int, list[int]] contact: The `contact` ABI parameter :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters :returns Composer: This Composer instance""" - args = Arc4TupleArgumentArgs( - a=a, + args = AddContactInfoArgs( + contact=contact, ) self.app_client.compose_call( self.atc, @@ -238,19 +238,19 @@ def arc4_tuple_argument( ) return self - def arc4_tuple_return( + def return_contact( self, *, transaction_parameters: algokit_utils.TransactionParameters | None = None, ) -> "Composer": """An arc4.Tuple can be returned when more than one return value is needed. - Adds a call to `arc4_tuple_return()(uint128,string)` ABI method + Adds a call to `return_contact()(string,string,uint64)` ABI method :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters :returns Composer: This Composer instance""" - args = Arc4TupleReturnArgs() + args = ReturnContactArgs() self.app_client.compose_call( self.atc, call_abi_method=args.method(), @@ -418,22 +418,22 @@ def suggested_params(self) -> algosdk.transaction.SuggestedParams | None: def suggested_params(self, value: algosdk.transaction.SuggestedParams | None) -> None: self.app_client.suggested_params = value - def arc4_tuple_argument( + def add_contact_info( self, *, - a: tuple[int, str, int, list[int]], + contact: tuple[str, str, int, list[int]], transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> algokit_utils.ABITransactionResponse[str]: + ) -> algokit_utils.ABITransactionResponse[int]: """An arc4.Tuple is a heterogeneous collection of arc4 types. - Calls `arc4_tuple_argument((uint8,string,uint64,uint32[]))string` ABI method + Calls `add_contact_info((string,string,uint64,uint8[]))uint64` ABI method - :param tuple[int, str, int, list[int]] a: The `a` ABI parameter + :param tuple[str, str, int, list[int]] contact: The `contact` ABI parameter :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns algokit_utils.ABITransactionResponse[str]: The result of the transaction""" + :returns algokit_utils.ABITransactionResponse[int]: The result of the transaction""" - args = Arc4TupleArgumentArgs( - a=a, + args = AddContactInfoArgs( + contact=contact, ) result = self.app_client.call( call_abi_method=args.method(), @@ -442,19 +442,19 @@ def arc4_tuple_argument( ) return result - def arc4_tuple_return( + def return_contact( self, *, transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> algokit_utils.ABITransactionResponse[tuple[int, str]]: + ) -> algokit_utils.ABITransactionResponse[tuple[str, str, int]]: """An arc4.Tuple can be returned when more than one return value is needed. - Calls `arc4_tuple_return()(uint128,string)` ABI method + Calls `return_contact()(string,string,uint64)` ABI method :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns algokit_utils.ABITransactionResponse[tuple[int, str]]: The result of the transaction""" + :returns algokit_utils.ABITransactionResponse[tuple[str, str, int]]: The result of the transaction""" - args = Arc4TupleReturnArgs() + args = ReturnContactArgs() result = self.app_client.call( call_abi_method=args.method(), transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), From 644dcf2ff5f1d705246816ae68241083cd47c53e Mon Sep 17 00:00:00 2001 From: CiottiGiorgio Date: Thu, 7 Nov 2024 17:34:36 +0100 Subject: [PATCH 12/23] add native dynamic bytes example. --- .../smart_contracts/arc4_types/contract.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py index 29bb90e..db8ba26 100644 --- a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py +++ b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py @@ -166,6 +166,11 @@ def arc4_dynamic_bytes(self) -> arc4.DynamicBytes: """arc4.DynamicBytes are essentially an arc4.DynamicArray[arc4.Bytes] and some convenience methods.""" dynamic_bytes = arc4.DynamicBytes(b"\xFF\xFF\xFF") + # arc4.DynamicBytes can return the native bytearray instead of accessing every single index of the array. + # This is only true for arc4.DynamicBytes because, as an example, an arc4.DynamicArray[arc4.UInt64] + # doesn't have a native equivalent. + native_dynamic_bytes = dynamic_bytes.native # noqa: F841 + dynamic_bytes[0] = arc4.Byte(0) return dynamic_bytes From c485a4facd2fa6564ae39bb42725e63055c44090 Mon Sep 17 00:00:00 2001 From: CiottiGiorgio Date: Thu, 7 Nov 2024 18:02:42 +0100 Subject: [PATCH 13/23] add more dynamic bytes examples. --- .../smart_contracts/arc4_types/contract.py | 4 ++ .../arc4_types/Arc4DynamicArray.approval.teal | 48 +++++++++++++++++++ .../arc4_types/Arc4DynamicArray.arc32.json | 2 +- .../tests/arc4_types_integration_test.py | 2 +- 4 files changed, 54 insertions(+), 2 deletions(-) diff --git a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py index db8ba26..9973d89 100644 --- a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py +++ b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py @@ -173,6 +173,10 @@ def arc4_dynamic_bytes(self) -> arc4.DynamicBytes: dynamic_bytes[0] = arc4.Byte(0) + dynamic_bytes.extend(arc4.DynamicBytes(b"\xAA\xBB\xCC")) + dynamic_bytes.pop() + dynamic_bytes.append(arc4.Byte(255)) + return dynamic_bytes diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.approval.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.approval.teal index 60f1eeb..478b77c 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.approval.teal +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.approval.teal @@ -161,6 +161,54 @@ arc4_dynamic_bytes: byte 0x0003ffffff byte 0x00 replace2 2 + extract 2 0 + byte 0xaabbcc + concat + dup + len + itob + extract 6 2 + swap + concat + int 1 + callsub dynamic_array_pop_fixed_size + bury 1 + extract 2 0 + byte 0xff + concat + dup + len + itob + extract 6 2 + swap + concat + retsub + + +// _puya_lib.arc4.dynamic_array_pop_fixed_size(array: bytes, fixed_byte_size: uint64) -> bytes, bytes: +dynamic_array_pop_fixed_size: + proto 2 2 + frame_dig -2 + int 0 + extract_uint16 + int 1 + - + itob + extract 6 0 + frame_dig -2 + swap + replace2 0 + dup + len + frame_dig -1 + - + dup2 + frame_dig -1 + extract3 + cover 2 + int 0 + swap + substring3 retsub diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.arc32.json b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.arc32.json index d18e906..823e96d 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.arc32.json +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.arc32.json @@ -67,4 +67,4 @@ "bare_call_config": { "no_op": "CREATE" } -} \ No newline at end of file +} diff --git a/projects/python-contract-examples/tests/arc4_types_integration_test.py b/projects/python-contract-examples/tests/arc4_types_integration_test.py index f1d4c8f..475f865 100644 --- a/projects/python-contract-examples/tests/arc4_types_integration_test.py +++ b/projects/python-contract-examples/tests/arc4_types_integration_test.py @@ -309,7 +309,7 @@ def test_arc4_dynamic_bytes( # Call the arc4_static_array method. result = arc4_dynamic_array_app_client.arc4_dynamic_bytes() - assert result.return_value == [0, 255, 255] + assert result.return_value == [0, 255, 255, 170, 187, 255] def test_arc4_struct_add_todo(arc4_struct_app_client: Arc4StructClient) -> None: From c93a7f9a9c7ab993fafa94b109254e29c746be61 Mon Sep 17 00:00:00 2001 From: "Chris Kim (Hyunggun)" Date: Thu, 7 Nov 2024 09:37:34 -0800 Subject: [PATCH 14/23] update todo --- .../smart_contracts/arc4_types/contract.py | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py index 9973d89..9c85d01 100644 --- a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py +++ b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py @@ -191,25 +191,25 @@ class Todo(arc4.Struct): class Arc4Struct(ARC4Contract): def __init__(self) -> None: - self.todos = GlobalState(Todos()) + self.todos = Todos() @abimethod() def add_todo(self, task: arc4.String) -> Todos: todo = Todo(task=task, completed=arc4.Bool(False)) # noqa: FBT003 - if self.todos.value.length == 0: - self.todos.value = Todos(todo.copy()) + if not self.todos: + self.todos = Todos(todo.copy()) else: - self.todos.value.append(todo.copy()) + self.todos.append(todo.copy()) - return self.todos.value + return self.todos @abimethod() def complete_todo(self, task: arc4.String) -> None: - for index in urange(self.todos.value.length): - if self.todos.value[index].task == task: - self.todos.value[index].completed = arc4.Bool(True) # noqa: FBT003 + for index in urange(self.todos.length): + if self.todos[index].task == task: + self.todos[index].completed = arc4.Bool(True) # noqa: FBT003 break @abimethod() @@ -217,10 +217,10 @@ def return_todo(self, task: arc4.String) -> Todo: todo_to_return: Todo exist = False - for index in urange(self.todos.value.length): + for index in urange(self.todos.length): - if self.todos.value[index].task == task: - todo_to_return = self.todos.value[index].copy() + if self.todos[index].task == task: + todo_to_return = self.todos[index].copy() exist = True assert exist From dd8a3619c6bd35d6c6fcb038baee0420853baeb4 Mon Sep 17 00:00:00 2001 From: "Chris Kim (Hyunggun)" Date: Thu, 7 Nov 2024 11:03:57 -0800 Subject: [PATCH 15/23] added transaction type examples --- .../smart_contracts/arc4_types/contract.py | 37 +- .../arc4_types/Arc4DynamicArray.approval.teal | 355 ------- .../arc4_types/Arc4DynamicArray.arc32.json | 70 -- .../arc4_types/Arc4DynamicArray.clear.teal | 5 - .../arc4_types/Arc4StaticArray.approval.teal | 84 -- .../arc4_types/Arc4StaticArray.arc32.json | 51 - .../arc4_types/Arc4StaticArray.clear.teal | 5 - .../arc4_types/Arc4Struct.approval.teal | 567 ----------- .../arc4_types/Arc4Struct.arc32.json | 111 -- .../arc4_types/Arc4Struct.clear.teal | 5 - .../arc4_types/Arc4Tuple.approval.teal | 145 --- .../artifacts/arc4_types/Arc4Tuple.arc32.json | 70 -- .../artifacts/arc4_types/Arc4Tuple.clear.teal | 5 - .../arc4_types/Arc4Types.approval.teal | 248 ----- .../artifacts/arc4_types/Arc4Types.arc32.json | 173 ---- .../artifacts/arc4_types/Arc4Types.clear.teal | 5 - .../arc4_types/arc4_dynamic_array_client.py | 565 ----------- .../arc4_types/arc4_static_array_client.py | 484 --------- .../arc4_types/arc4_struct_client.py | 695 ------------- .../artifacts/arc4_types/arc4_tuple_client.py | 562 ----------- .../artifacts/arc4_types/arc4_types_client.py | 950 ------------------ 21 files changed, 33 insertions(+), 5159 deletions(-) delete mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.approval.teal delete mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.arc32.json delete mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.clear.teal delete mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.approval.teal delete mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.arc32.json delete mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.clear.teal delete mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.approval.teal delete mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.arc32.json delete mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.clear.teal delete mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.approval.teal delete mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.arc32.json delete mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.clear.teal delete mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.approval.teal delete mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.arc32.json delete mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.clear.teal delete mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_dynamic_array_client.py delete mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_static_array_client.py delete mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_struct_client.py delete mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_tuple_client.py delete mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_types_client.py diff --git a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py index 9c85d01..8be8277 100644 --- a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py +++ b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py @@ -1,7 +1,8 @@ # pyright: reportMissingModuleSource=false import typing as t -from algopy import ARC4Contract, GlobalState, String, UInt64, arc4, urange +# from algopy import ARC4Contract, GlobalState, String, UInt64, arc4, urange +from algopy import * from algopy.arc4 import abimethod @@ -232,6 +233,9 @@ def return_todo(self, task: arc4.String) -> Todo: class Arc4Tuple(ARC4Contract): + def __init__(self) -> None: + self.contact_info = GlobalState(contact_info_tuple((arc4.String(""), arc4.String(""), arc4.UInt64(0), arc4.DynamicArray[arc4.UInt8]()))) + @abimethod() def add_contact_info( self, @@ -249,11 +253,36 @@ def add_contact_info( for x in donate_history: total_donation += x.native + self.contact_info.value = contact + return total_donation @abimethod() - def return_contact(self) -> arc4.Tuple[arc4.String, arc4.String, arc4.UInt64]: + def return_contact(self) -> arc4.Tuple[arc4.String, arc4.String, arc4.UInt64, arc4.DynamicArray[arc4.UInt8]]: """An arc4.Tuple can be returned when more than one return value is needed.""" - arc4_tuple = arc4.Tuple((arc4.String("Alice"), arc4.String("alice@something.com"), arc4.UInt64(555_555_555))) + # arc4_tuple = arc4.Tuple((arc4.String("Alice"), arc4.String("alice@something.com"), arc4.UInt64(555_555_555))) + + + return self.contact_info.value + +class TransactionTypes(ARC4Contract): + + @abimethod + def paymentTxn(self, pay:gtxn.PaymentTransaction) -> UInt64: + assert pay.amount > 0 + assert pay.receiver == Global.current_application_address + assert pay.sender == Txn.sender + + return pay.amount + + @abimethod + def assetTransferTxn(self, asset_transfer: gtxn.AssetTransferTransaction) -> UInt64: + assert Global.current_application_address.is_opted_in(asset_transfer.xfer_asset), "Asset not opted in" + + assert asset_transfer.asset_amount > 0 + assert asset_transfer.asset_receiver == Global.current_application_address + assert asset_transfer.sender == Txn.sender + + return asset_transfer.asset_amount + - return arc4_tuple diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.approval.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.approval.teal deleted file mode 100644 index 478b77c..0000000 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.approval.teal +++ /dev/null @@ -1,355 +0,0 @@ -#pragma version 10 - -smart_contracts.arc4_types.contract.Arc4DynamicArray.approval_program: - callsub __puya_arc4_router__ - return - - -// smart_contracts.arc4_types.contract.Arc4DynamicArray.__puya_arc4_router__() -> uint64: -__puya_arc4_router__: - proto 0 1 - txn NumAppArgs - bz __puya_arc4_router___bare_routing@6 - method "arc4_dynamic_array(string)string" - method "arc4_dynamic_bytes()byte[]" - txna ApplicationArgs 0 - match __puya_arc4_router___arc4_dynamic_array_route@2 __puya_arc4_router___arc4_dynamic_bytes_route@3 - int 0 - retsub - -__puya_arc4_router___arc4_dynamic_array_route@2: - txn OnCompletion - ! - assert // OnCompletion is NoOp - txn ApplicationID - assert // is not creating - txna ApplicationArgs 1 - callsub arc4_dynamic_array - dup - len - itob - extract 6 2 - swap - concat - byte 0x151f7c75 - swap - concat - log - int 1 - retsub - -__puya_arc4_router___arc4_dynamic_bytes_route@3: - txn OnCompletion - ! - assert // OnCompletion is NoOp - txn ApplicationID - assert // is not creating - callsub arc4_dynamic_bytes - byte 0x151f7c75 - swap - concat - log - int 1 - retsub - -__puya_arc4_router___bare_routing@6: - txn OnCompletion - bnz __puya_arc4_router___after_if_else@10 - txn ApplicationID - ! - assert // is creating - int 1 - retsub - -__puya_arc4_router___after_if_else@10: - int 0 - retsub - - -// smart_contracts.arc4_types.contract.Arc4DynamicArray.arc4_dynamic_array(name: bytes) -> bytes: -arc4_dynamic_array: - proto 1 1 - frame_dig -1 - len - int 4 - + - itob - extract 6 2 - byte 0x0004 - swap - concat - frame_dig -1 - concat - byte 0x000121 - concat - byte 0x0002 - swap - concat - dup - int 0 - extract_uint16 - swap - extract 2 0 - swap - dup - int 2 - * - swap - dig 2 - len - swap - cover 3 - substring3 - byte 0x00010002000648656c6c6f20 - swap - uncover 2 - callsub dynamic_array_concat_byte_length_head - dupn 2 - callsub dynamic_array_pop_byte_length_head - bury 1 - callsub dynamic_array_pop_byte_length_head - bury 1 - byte 0x0006776f726c6421 - int 1 - callsub dynamic_array_concat_byte_length_head - pop - byte "" - swap - int 0 - extract_uint16 - int 0 - -arc4_dynamic_array_for_header@1: - frame_dig 3 - frame_dig 2 - < - bz arc4_dynamic_array_after_for@4 - frame_dig 0 - extract 2 0 - frame_dig 3 - dup - cover 2 - int 2 - * - dig 1 - swap - extract_uint16 - dup2 - extract_uint16 - int 2 - + - extract3 - extract 2 0 - frame_dig 1 - swap - concat - frame_bury 1 - int 1 - + - frame_bury 3 - b arc4_dynamic_array_for_header@1 - -arc4_dynamic_array_after_for@4: - frame_dig 1 - frame_bury 0 - retsub - - -// smart_contracts.arc4_types.contract.Arc4DynamicArray.arc4_dynamic_bytes() -> bytes: -arc4_dynamic_bytes: - proto 0 1 - byte 0x0003ffffff - byte 0x00 - replace2 2 - extract 2 0 - byte 0xaabbcc - concat - dup - len - itob - extract 6 2 - swap - concat - int 1 - callsub dynamic_array_pop_fixed_size - bury 1 - extract 2 0 - byte 0xff - concat - dup - len - itob - extract 6 2 - swap - concat - retsub - - -// _puya_lib.arc4.dynamic_array_pop_fixed_size(array: bytes, fixed_byte_size: uint64) -> bytes, bytes: -dynamic_array_pop_fixed_size: - proto 2 2 - frame_dig -2 - int 0 - extract_uint16 - int 1 - - - itob - extract 6 0 - frame_dig -2 - swap - replace2 0 - dup - len - frame_dig -1 - - - dup2 - frame_dig -1 - extract3 - cover 2 - int 0 - swap - substring3 - retsub - - -// _puya_lib.arc4.dynamic_array_pop_byte_length_head(array: bytes) -> bytes, bytes: -dynamic_array_pop_byte_length_head: - proto 1 2 - frame_dig -1 - int 0 - extract_uint16 - int 1 - - - dup - int 2 - * - frame_dig -1 - extract 2 0 - dup - dig 2 - extract_uint16 - swap - dup - len - swap - dup - dig 3 - uncover 3 - substring3 - cover 3 - dup - int 0 - dig 4 - substring3 - cover 2 - uncover 3 - int 2 - + - uncover 2 - substring3 - concat - dig 2 - itob - extract 6 2 - swap - uncover 3 - int 0 - callsub recalculate_head_for_elements_with_byte_length_head - concat - retsub - - -// _puya_lib.arc4.dynamic_array_concat_byte_length_head(array: bytes, new_items_bytes: bytes, new_items_count: uint64) -> bytes: -dynamic_array_concat_byte_length_head: - proto 3 1 - frame_dig -3 - int 0 - extract_uint16 - dup - frame_dig -1 - + - swap - int 2 - * - int 2 - + - swap - dup - itob - extract 6 2 - swap - frame_dig -3 - int 2 - dig 4 - substring3 - frame_dig -1 - int 2 - * - bzero - concat - frame_dig -3 - len - frame_dig -3 - uncover 5 - uncover 2 - substring3 - concat - frame_dig -2 - concat - swap - int 0 - callsub recalculate_head_for_elements_with_byte_length_head - concat - retsub - - -// _puya_lib.arc4.recalculate_head_for_elements_with_byte_length_head(array_head_and_tail: bytes, length: uint64, start_at_index: uint64) -> bytes: -recalculate_head_for_elements_with_byte_length_head: - proto 3 1 - frame_dig -2 - int 2 - * - dup - frame_dig -1 - int 2 - * - dup - cover 2 - frame_dig -3 - swap - extract_uint16 - frame_dig -1 - select - -recalculate_head_for_elements_with_byte_length_head_for_header@1: - frame_dig 1 - frame_dig 0 - < - bz recalculate_head_for_elements_with_byte_length_head_after_for@4 - frame_dig 2 - dup - itob - extract 6 2 - frame_dig -3 - frame_dig 1 - dup - cover 4 - uncover 2 - replace3 - dup - frame_bury -3 - dig 1 - extract_uint16 - int 2 - + - + - frame_bury 2 - int 2 - + - frame_bury 1 - b recalculate_head_for_elements_with_byte_length_head_for_header@1 - -recalculate_head_for_elements_with_byte_length_head_after_for@4: - frame_dig -3 - frame_bury 0 - retsub diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.arc32.json b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.arc32.json deleted file mode 100644 index 823e96d..0000000 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.arc32.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "hints": { - "arc4_dynamic_array(string)string": { - "call_config": { - "no_op": "CALL" - } - }, - "arc4_dynamic_bytes()byte[]": { - "call_config": { - "no_op": "CALL" - } - } - }, - "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5LmFwcHJvdmFsX3Byb2dyYW06CiAgICBjYWxsc3ViIF9fcHV5YV9hcmM0X3JvdXRlcl9fCiAgICByZXR1cm4KCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5Ll9fcHV5YV9hcmM0X3JvdXRlcl9fKCkgLT4gdWludDY0OgpfX3B1eWFfYXJjNF9yb3V0ZXJfXzoKICAgIHByb3RvIDAgMQogICAgdHhuIE51bUFwcEFyZ3MKICAgIGJ6IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2CiAgICBtZXRob2QgImFyYzRfZHluYW1pY19hcnJheShzdHJpbmcpc3RyaW5nIgogICAgbWV0aG9kICJhcmM0X2R5bmFtaWNfYnl0ZXMoKWJ5dGVbXSIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfZHluYW1pY19hcnJheV9yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfZHluYW1pY19ieXRlc19yb3V0ZUAzCiAgICBpbnQgMAogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2R5bmFtaWNfYXJyYXlfcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF9keW5hbWljX2FycmF5CiAgICBkdXAKICAgIGxlbgogICAgaXRvYgogICAgZXh0cmFjdCA2IDIKICAgIHN3YXAKICAgIGNvbmNhdAogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9keW5hbWljX2J5dGVzX3JvdXRlQDM6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICBjYWxsc3ViIGFyYzRfZHluYW1pY19ieXRlcwogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDY6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBibnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgICEKICAgIGFzc2VydCAvLyBpcyBjcmVhdGluZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMDoKICAgIGludCAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5LmFyYzRfZHluYW1pY19hcnJheShuYW1lOiBieXRlcykgLT4gYnl0ZXM6CmFyYzRfZHluYW1pY19hcnJheToKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBsZW4KICAgIGludCA0CiAgICArCiAgICBpdG9iCiAgICBleHRyYWN0IDYgMgogICAgYnl0ZSAweDAwMDQKICAgIHN3YXAKICAgIGNvbmNhdAogICAgZnJhbWVfZGlnIC0xCiAgICBjb25jYXQKICAgIGJ5dGUgMHgwMDAxMjEKICAgIGNvbmNhdAogICAgYnl0ZSAweDAwMDIKICAgIHN3YXAKICAgIGNvbmNhdAogICAgZHVwCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIHN3YXAKICAgIGV4dHJhY3QgMiAwCiAgICBzd2FwCiAgICBkdXAKICAgIGludCAyCiAgICAqCiAgICBzd2FwCiAgICBkaWcgMgogICAgbGVuCiAgICBzd2FwCiAgICBjb3ZlciAzCiAgICBzdWJzdHJpbmczCiAgICBieXRlIDB4MDAwMTAwMDIwMDA2NDg2NTZjNmM2ZjIwCiAgICBzd2FwCiAgICB1bmNvdmVyIDIKICAgIGNhbGxzdWIgZHluYW1pY19hcnJheV9jb25jYXRfYnl0ZV9sZW5ndGhfaGVhZAogICAgZHVwbiAyCiAgICBjYWxsc3ViIGR5bmFtaWNfYXJyYXlfcG9wX2J5dGVfbGVuZ3RoX2hlYWQKICAgIGJ1cnkgMQogICAgY2FsbHN1YiBkeW5hbWljX2FycmF5X3BvcF9ieXRlX2xlbmd0aF9oZWFkCiAgICBidXJ5IDEKICAgIGJ5dGUgMHgwMDA2Nzc2ZjcyNmM2NDIxCiAgICBpbnQgMQogICAgY2FsbHN1YiBkeW5hbWljX2FycmF5X2NvbmNhdF9ieXRlX2xlbmd0aF9oZWFkCiAgICBwb3AKICAgIGJ5dGUgIiIKICAgIHN3YXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50IDAKCmFyYzRfZHluYW1pY19hcnJheV9mb3JfaGVhZGVyQDE6CiAgICBmcmFtZV9kaWcgMwogICAgZnJhbWVfZGlnIDIKICAgIDwKICAgIGJ6IGFyYzRfZHluYW1pY19hcnJheV9hZnRlcl9mb3JANAogICAgZnJhbWVfZGlnIDAKICAgIGV4dHJhY3QgMiAwCiAgICBmcmFtZV9kaWcgMwogICAgZHVwCiAgICBjb3ZlciAyCiAgICBpbnQgMgogICAgKgogICAgZGlnIDEKICAgIHN3YXAKICAgIGV4dHJhY3RfdWludDE2CiAgICBkdXAyCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50IDIKICAgICsKICAgIGV4dHJhY3QzCiAgICBleHRyYWN0IDIgMAogICAgZnJhbWVfZGlnIDEKICAgIHN3YXAKICAgIGNvbmNhdAogICAgZnJhbWVfYnVyeSAxCiAgICBpbnQgMQogICAgKwogICAgZnJhbWVfYnVyeSAzCiAgICBiIGFyYzRfZHluYW1pY19hcnJheV9mb3JfaGVhZGVyQDEKCmFyYzRfZHluYW1pY19hcnJheV9hZnRlcl9mb3JANDoKICAgIGZyYW1lX2RpZyAxCiAgICBmcmFtZV9idXJ5IDAKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzREeW5hbWljQXJyYXkuYXJjNF9keW5hbWljX2J5dGVzKCkgLT4gYnl0ZXM6CmFyYzRfZHluYW1pY19ieXRlczoKICAgIHByb3RvIDAgMQogICAgYnl0ZSAweDAwMDNmZmZmZmYKICAgIGJ5dGUgMHgwMAogICAgcmVwbGFjZTIgMgogICAgcmV0c3ViCgoKLy8gX3B1eWFfbGliLmFyYzQuZHluYW1pY19hcnJheV9wb3BfYnl0ZV9sZW5ndGhfaGVhZChhcnJheTogYnl0ZXMpIC0+IGJ5dGVzLCBieXRlczoKZHluYW1pY19hcnJheV9wb3BfYnl0ZV9sZW5ndGhfaGVhZDoKICAgIHByb3RvIDEgMgogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGludCAxCiAgICAtCiAgICBkdXAKICAgIGludCAyCiAgICAqCiAgICBmcmFtZV9kaWcgLTEKICAgIGV4dHJhY3QgMiAwCiAgICBkdXAKICAgIGRpZyAyCiAgICBleHRyYWN0X3VpbnQxNgogICAgc3dhcAogICAgZHVwCiAgICBsZW4KICAgIHN3YXAKICAgIGR1cAogICAgZGlnIDMKICAgIHVuY292ZXIgMwogICAgc3Vic3RyaW5nMwogICAgY292ZXIgMwogICAgZHVwCiAgICBpbnQgMAogICAgZGlnIDQKICAgIHN1YnN0cmluZzMKICAgIGNvdmVyIDIKICAgIHVuY292ZXIgMwogICAgaW50IDIKICAgICsKICAgIHVuY292ZXIgMgogICAgc3Vic3RyaW5nMwogICAgY29uY2F0CiAgICBkaWcgMgogICAgaXRvYgogICAgZXh0cmFjdCA2IDIKICAgIHN3YXAKICAgIHVuY292ZXIgMwogICAgaW50IDAKICAgIGNhbGxzdWIgcmVjYWxjdWxhdGVfaGVhZF9mb3JfZWxlbWVudHNfd2l0aF9ieXRlX2xlbmd0aF9oZWFkCiAgICBjb25jYXQKICAgIHJldHN1YgoKCi8vIF9wdXlhX2xpYi5hcmM0LmR5bmFtaWNfYXJyYXlfY29uY2F0X2J5dGVfbGVuZ3RoX2hlYWQoYXJyYXk6IGJ5dGVzLCBuZXdfaXRlbXNfYnl0ZXM6IGJ5dGVzLCBuZXdfaXRlbXNfY291bnQ6IHVpbnQ2NCkgLT4gYnl0ZXM6CmR5bmFtaWNfYXJyYXlfY29uY2F0X2J5dGVfbGVuZ3RoX2hlYWQ6CiAgICBwcm90byAzIDEKICAgIGZyYW1lX2RpZyAtMwogICAgaW50IDAKICAgIGV4dHJhY3RfdWludDE2CiAgICBkdXAKICAgIGZyYW1lX2RpZyAtMQogICAgKwogICAgc3dhcAogICAgaW50IDIKICAgICoKICAgIGludCAyCiAgICArCiAgICBzd2FwCiAgICBkdXAKICAgIGl0b2IKICAgIGV4dHJhY3QgNiAyCiAgICBzd2FwCiAgICBmcmFtZV9kaWcgLTMKICAgIGludCAyCiAgICBkaWcgNAogICAgc3Vic3RyaW5nMwogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMgogICAgKgogICAgYnplcm8KICAgIGNvbmNhdAogICAgZnJhbWVfZGlnIC0zCiAgICBsZW4KICAgIGZyYW1lX2RpZyAtMwogICAgdW5jb3ZlciA1CiAgICB1bmNvdmVyIDIKICAgIHN1YnN0cmluZzMKICAgIGNvbmNhdAogICAgZnJhbWVfZGlnIC0yCiAgICBjb25jYXQKICAgIHN3YXAKICAgIGludCAwCiAgICBjYWxsc3ViIHJlY2FsY3VsYXRlX2hlYWRfZm9yX2VsZW1lbnRzX3dpdGhfYnl0ZV9sZW5ndGhfaGVhZAogICAgY29uY2F0CiAgICByZXRzdWIKCgovLyBfcHV5YV9saWIuYXJjNC5yZWNhbGN1bGF0ZV9oZWFkX2Zvcl9lbGVtZW50c193aXRoX2J5dGVfbGVuZ3RoX2hlYWQoYXJyYXlfaGVhZF9hbmRfdGFpbDogYnl0ZXMsIGxlbmd0aDogdWludDY0LCBzdGFydF9hdF9pbmRleDogdWludDY0KSAtPiBieXRlczoKcmVjYWxjdWxhdGVfaGVhZF9mb3JfZWxlbWVudHNfd2l0aF9ieXRlX2xlbmd0aF9oZWFkOgogICAgcHJvdG8gMyAxCiAgICBmcmFtZV9kaWcgLTIKICAgIGludCAyCiAgICAqCiAgICBkdXAKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDIKICAgICoKICAgIGR1cAogICAgY292ZXIgMgogICAgZnJhbWVfZGlnIC0zCiAgICBzd2FwCiAgICBleHRyYWN0X3VpbnQxNgogICAgZnJhbWVfZGlnIC0xCiAgICBzZWxlY3QKCnJlY2FsY3VsYXRlX2hlYWRfZm9yX2VsZW1lbnRzX3dpdGhfYnl0ZV9sZW5ndGhfaGVhZF9mb3JfaGVhZGVyQDE6CiAgICBmcmFtZV9kaWcgMQogICAgZnJhbWVfZGlnIDAKICAgIDwKICAgIGJ6IHJlY2FsY3VsYXRlX2hlYWRfZm9yX2VsZW1lbnRzX3dpdGhfYnl0ZV9sZW5ndGhfaGVhZF9hZnRlcl9mb3JANAogICAgZnJhbWVfZGlnIDIKICAgIGR1cAogICAgaXRvYgogICAgZXh0cmFjdCA2IDIKICAgIGZyYW1lX2RpZyAtMwogICAgZnJhbWVfZGlnIDEKICAgIGR1cAogICAgY292ZXIgNAogICAgdW5jb3ZlciAyCiAgICByZXBsYWNlMwogICAgZHVwCiAgICBmcmFtZV9idXJ5IC0zCiAgICBkaWcgMQogICAgZXh0cmFjdF91aW50MTYKICAgIGludCAyCiAgICArCiAgICArCiAgICBmcmFtZV9idXJ5IDIKICAgIGludCAyCiAgICArCiAgICBmcmFtZV9idXJ5IDEKICAgIGIgcmVjYWxjdWxhdGVfaGVhZF9mb3JfZWxlbWVudHNfd2l0aF9ieXRlX2xlbmd0aF9oZWFkX2Zvcl9oZWFkZXJAMQoKcmVjYWxjdWxhdGVfaGVhZF9mb3JfZWxlbWVudHNfd2l0aF9ieXRlX2xlbmd0aF9oZWFkX2FmdGVyX2ZvckA0OgogICAgZnJhbWVfZGlnIC0zCiAgICBmcmFtZV9idXJ5IDAKICAgIHJldHN1Ygo=", - "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5LmNsZWFyX3N0YXRlX3Byb2dyYW06CiAgICBpbnQgMQogICAgcmV0dXJuCg==" - }, - "state": { - "global": { - "num_byte_slices": 0, - "num_uints": 0 - }, - "local": { - "num_byte_slices": 0, - "num_uints": 0 - } - }, - "schema": { - "global": { - "declared": {}, - "reserved": {} - }, - "local": { - "declared": {}, - "reserved": {} - } - }, - "contract": { - "name": "Arc4DynamicArray", - "methods": [ - { - "name": "arc4_dynamic_array", - "args": [ - { - "type": "string", - "name": "name" - } - ], - "readonly": false, - "returns": { - "type": "string" - }, - "desc": "Dynamic Arrays have variable size and capacity.\nThey are similar to native Python lists because they can also append, extend, and pop." - }, - { - "name": "arc4_dynamic_bytes", - "args": [], - "readonly": false, - "returns": { - "type": "byte[]" - }, - "desc": "arc4.DynamicBytes are essentially an arc4.DynamicArray[arc4.Bytes] and some convenience methods." - } - ], - "networks": {} - }, - "bare_call_config": { - "no_op": "CREATE" - } -} diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.clear.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.clear.teal deleted file mode 100644 index ac284db..0000000 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.clear.teal +++ /dev/null @@ -1,5 +0,0 @@ -#pragma version 10 - -smart_contracts.arc4_types.contract.Arc4DynamicArray.clear_state_program: - int 1 - return diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.approval.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.approval.teal deleted file mode 100644 index 1521f1e..0000000 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.approval.teal +++ /dev/null @@ -1,84 +0,0 @@ -#pragma version 10 - -smart_contracts.arc4_types.contract.Arc4StaticArray.approval_program: - callsub __puya_arc4_router__ - return - - -// smart_contracts.arc4_types.contract.Arc4StaticArray.__puya_arc4_router__() -> uint64: -__puya_arc4_router__: - proto 0 1 - txn NumAppArgs - bz __puya_arc4_router___bare_routing@5 - method "arc4_static_array()void" - txna ApplicationArgs 0 - match __puya_arc4_router___arc4_static_array_route@2 - int 0 - retsub - -__puya_arc4_router___arc4_static_array_route@2: - txn OnCompletion - ! - assert // OnCompletion is NoOp - txn ApplicationID - assert // is not creating - callsub arc4_static_array - int 1 - retsub - -__puya_arc4_router___bare_routing@5: - txn OnCompletion - bnz __puya_arc4_router___after_if_else@9 - txn ApplicationID - ! - assert // is creating - int 1 - retsub - -__puya_arc4_router___after_if_else@9: - int 0 - retsub - - -// smart_contracts.arc4_types.contract.Arc4StaticArray.arc4_static_array() -> void: -arc4_static_array: - proto 0 0 - int 0 - dup - -arc4_static_array_for_header@1: - frame_dig 1 - int 4 - < - bz arc4_static_array_after_for@4 - frame_dig 1 - dup - int 4 - * - byte 0x000000010000000a000000ff00000080 - swap - int 4 - extract3 // on error: Index access is out of bounds - btoi - frame_dig 0 - + - frame_bury 0 - int 1 - + - frame_bury 1 - b arc4_static_array_for_header@1 - -arc4_static_array_after_for@4: - frame_dig 0 - int 394 - == - assert - byte 0x65 - byte 0xca - replace2 0 - extract 0 1 // on error: Index access is out of bounds - btoi - int 202 - == - assert - retsub diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.arc32.json b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.arc32.json deleted file mode 100644 index 1148733..0000000 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.arc32.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "hints": { - "arc4_static_array()void": { - "call_config": { - "no_op": "CALL" - } - } - }, - "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RhdGljQXJyYXkuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRTdGF0aWNBcnJheS5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANQogICAgbWV0aG9kICJhcmM0X3N0YXRpY19hcnJheSgpdm9pZCIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfc3RhdGljX2FycmF5X3JvdXRlQDIKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfc3RhdGljX2FycmF5X3JvdXRlQDI6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICBjYWxsc3ViIGFyYzRfc3RhdGljX2FycmF5CiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANToKICAgIHR4biBPbkNvbXBsZXRpb24KICAgIGJueiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDkKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICAhCiAgICBhc3NlcnQgLy8gaXMgY3JlYXRpbmcKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAOToKICAgIGludCAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RhdGljQXJyYXkuYXJjNF9zdGF0aWNfYXJyYXkoKSAtPiB2b2lkOgphcmM0X3N0YXRpY19hcnJheToKICAgIHByb3RvIDAgMAogICAgaW50IDAKICAgIGR1cAoKYXJjNF9zdGF0aWNfYXJyYXlfZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDEKICAgIGludCA0CiAgICA8CiAgICBieiBhcmM0X3N0YXRpY19hcnJheV9hZnRlcl9mb3JANAogICAgZnJhbWVfZGlnIDEKICAgIGR1cAogICAgaW50IDQKICAgICoKICAgIGJ5dGUgMHgwMDAwMDAwMTAwMDAwMDBhMDAwMDAwZmYwMDAwMDA4MAogICAgc3dhcAogICAgaW50IDQKICAgIGV4dHJhY3QzIC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgYnRvaQogICAgZnJhbWVfZGlnIDAKICAgICsKICAgIGZyYW1lX2J1cnkgMAogICAgaW50IDEKICAgICsKICAgIGZyYW1lX2J1cnkgMQogICAgYiBhcmM0X3N0YXRpY19hcnJheV9mb3JfaGVhZGVyQDEKCmFyYzRfc3RhdGljX2FycmF5X2FmdGVyX2ZvckA0OgogICAgZnJhbWVfZGlnIDAKICAgIGludCAzOTQKICAgID09CiAgICBhc3NlcnQKICAgIGJ5dGUgMHg2NQogICAgYnl0ZSAweGNhCiAgICByZXBsYWNlMiAwCiAgICBleHRyYWN0IDAgMSAvLyBvbiBlcnJvcjogSW5kZXggYWNjZXNzIGlzIG91dCBvZiBib3VuZHMKICAgIGJ0b2kKICAgIGludCAyMDIKICAgID09CiAgICBhc3NlcnQKICAgIHJldHN1Ygo=", - "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RhdGljQXJyYXkuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" - }, - "state": { - "global": { - "num_byte_slices": 0, - "num_uints": 0 - }, - "local": { - "num_byte_slices": 0, - "num_uints": 0 - } - }, - "schema": { - "global": { - "declared": {}, - "reserved": {} - }, - "local": { - "declared": {}, - "reserved": {} - } - }, - "contract": { - "name": "Arc4StaticArray", - "methods": [ - { - "name": "arc4_static_array", - "args": [], - "readonly": false, - "returns": { - "type": "void" - }, - "desc": "You can create a static array directly from the contract." - } - ], - "networks": {} - }, - "bare_call_config": { - "no_op": "CREATE" - } -} \ No newline at end of file diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.clear.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.clear.teal deleted file mode 100644 index 2fb8183..0000000 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.clear.teal +++ /dev/null @@ -1,5 +0,0 @@ -#pragma version 10 - -smart_contracts.arc4_types.contract.Arc4StaticArray.clear_state_program: - int 1 - return diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.approval.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.approval.teal deleted file mode 100644 index eda3118..0000000 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.approval.teal +++ /dev/null @@ -1,567 +0,0 @@ -#pragma version 10 - -smart_contracts.arc4_types.contract.Arc4Struct.approval_program: - txn ApplicationID - bnz main_entrypoint@2 - callsub __init__ - -main_entrypoint@2: - callsub __puya_arc4_router__ - return - - -// smart_contracts.arc4_types.contract.Arc4Struct.__puya_arc4_router__() -> uint64: -__puya_arc4_router__: - proto 0 1 - txn NumAppArgs - bz __puya_arc4_router___bare_routing@7 - method "add_todo(string)(string,bool)[]" - method "complete_todo(string)void" - method "return_todo(string)(string,bool)" - txna ApplicationArgs 0 - match __puya_arc4_router___add_todo_route@2 __puya_arc4_router___complete_todo_route@3 __puya_arc4_router___return_todo_route@4 - int 0 - retsub - -__puya_arc4_router___add_todo_route@2: - txn OnCompletion - ! - assert // OnCompletion is NoOp - txn ApplicationID - assert // is not creating - txna ApplicationArgs 1 - callsub add_todo - byte 0x151f7c75 - swap - concat - log - int 1 - retsub - -__puya_arc4_router___complete_todo_route@3: - txn OnCompletion - ! - assert // OnCompletion is NoOp - txn ApplicationID - assert // is not creating - txna ApplicationArgs 1 - callsub complete_todo - int 1 - retsub - -__puya_arc4_router___return_todo_route@4: - txn OnCompletion - ! - assert // OnCompletion is NoOp - txn ApplicationID - assert // is not creating - txna ApplicationArgs 1 - callsub return_todo - byte 0x151f7c75 - swap - concat - log - int 1 - retsub - -__puya_arc4_router___bare_routing@7: - txn OnCompletion - bnz __puya_arc4_router___after_if_else@11 - txn ApplicationID - ! - assert // is creating - int 1 - retsub - -__puya_arc4_router___after_if_else@11: - int 0 - retsub - - -// smart_contracts.arc4_types.contract.Arc4Struct.add_todo(task: bytes) -> bytes: -add_todo: - proto 1 1 - byte 0x000300 - frame_dig -1 - concat - int 0 - byte "todos" - app_global_get_ex - assert // check self.todos exists - int 0 - extract_uint16 - bnz add_todo_else_body@2 - byte 0x0002 - swap - concat - byte 0x0001 - swap - concat - byte "todos" - swap - app_global_put - b add_todo_after_if_else@3 - -add_todo_else_body@2: - int 0 - byte "todos" - app_global_get_ex - assert // check self.todos exists - byte 0x0002 - uncover 2 - concat - swap - dup - int 0 - extract_uint16 - swap - extract 2 0 - int 1 - uncover 3 - callsub dynamic_array_concat_dynamic_element - byte "todos" - swap - app_global_put - -add_todo_after_if_else@3: - int 0 - byte "todos" - app_global_get_ex - assert // check self.todos exists - retsub - - -// smart_contracts.arc4_types.contract.Arc4Struct.complete_todo(task: bytes) -> void: -complete_todo: - proto 1 0 - byte "" - dup - int 0 - byte "todos" - app_global_get_ex - assert // check self.todos exists - int 0 - extract_uint16 - int 0 - -complete_todo_for_header@1: - frame_dig 3 - frame_dig 2 - < - bz complete_todo_after_for@6 - int 0 - byte "todos" - app_global_get_ex - assert // check self.todos exists - dup - extract 2 0 - frame_dig 3 - dup - cover 3 - int 2 - * - dup - frame_bury 0 - dig 1 - swap - extract_uint16 - cover 3 - swap - int 0 - extract_uint16 - uncover 2 - int 1 - + - dup - cover 4 - dup - cover 2 - - // on error: Index access is out of bounds - swap - dig 2 - len - cover 2 - int 2 - * - dup - frame_bury 1 - dig 3 - swap - extract_uint16 - swap - select - swap - cover 2 - substring3 - dup - int 0 - extract_uint16 - swap - dup - len - swap - cover 2 - substring3 - frame_dig -1 - == - bz complete_todo_after_if_else@4 - int 0 - byte "todos" - app_global_get_ex - assert // check self.todos exists - dup - extract 2 0 - dup - frame_dig 0 - extract_uint16 - cover 2 - swap - int 0 - extract_uint16 - uncover 3 - - // on error: Index access is out of bounds - dig 1 - len - swap - dig 2 - frame_dig 1 - extract_uint16 - swap - select - swap - cover 2 - substring3 - int 16 - int 1 - setbit - int 0 - byte "todos" - app_global_get_ex - assert // check self.todos exists - swap - frame_dig 3 - callsub dynamic_array_replace_dynamic_element - byte "todos" - swap - app_global_put - b complete_todo_after_for@6 - -complete_todo_after_if_else@4: - frame_bury 3 - b complete_todo_for_header@1 - -complete_todo_after_for@6: - retsub - - -// smart_contracts.arc4_types.contract.Arc4Struct.return_todo(task: bytes) -> bytes: -return_todo: - proto 1 1 - int 0 - byte "" - dup - int 0 - dup - byte "todos" - app_global_get_ex - assert // check self.todos exists - int 0 - extract_uint16 - int 0 - -return_todo_for_header@1: - frame_dig 5 - frame_dig 4 - < - bz return_todo_after_for@6 - int 0 - byte "todos" - app_global_get_ex - assert // check self.todos exists - dup - extract 2 0 - frame_dig 5 - dup - cover 3 - int 2 - * - dup - frame_bury 1 - dig 1 - swap - extract_uint16 - cover 3 - swap - int 0 - extract_uint16 - uncover 2 - int 1 - + - dup - frame_bury 5 - dup - cover 2 - - // on error: Index access is out of bounds - swap - dig 2 - len - cover 2 - int 2 - * - dup - frame_bury 2 - dig 3 - swap - extract_uint16 - swap - select - swap - cover 2 - substring3 - dup - int 0 - extract_uint16 - swap - dup - len - swap - cover 2 - substring3 - frame_dig -1 - == - bz return_todo_for_header@1 - int 0 - byte "todos" - app_global_get_ex - assert // check self.todos exists - dup - extract 2 0 - dup - frame_dig 1 - extract_uint16 - cover 2 - swap - int 0 - extract_uint16 - frame_dig 5 - - // on error: Index access is out of bounds - dig 1 - len - swap - dig 2 - frame_dig 2 - extract_uint16 - swap - select - swap - cover 2 - substring3 - frame_bury 0 - int 1 - frame_bury 3 - b return_todo_for_header@1 - -return_todo_after_for@6: - frame_dig 3 - assert - retsub - - -// smart_contracts.arc4_types.contract.Arc4Struct.__init__() -> void: -__init__: - proto 0 0 - byte "todos" - byte 0x0000 - app_global_put - retsub - - -// _puya_lib.arc4.dynamic_array_concat_dynamic_element(array_items_count: uint64, array_head_and_tail: bytes, new_items_count: uint64, new_head_and_tail: bytes) -> bytes: -dynamic_array_concat_dynamic_element: - proto 4 1 - byte "" - byte 0x - frame_dig -2 - int 2 - * - frame_dig -4 - int 2 - * - int 0 - -dynamic_array_concat_dynamic_element_for_header@1: - frame_dig 4 - frame_dig 3 - < - bz dynamic_array_concat_dynamic_element_after_for@4 - frame_dig -3 - frame_dig 4 - dup - cover 2 - extract_uint16 - frame_dig 2 - + - itob - extract 6 2 - frame_dig 1 - swap - concat - frame_bury 1 - int 2 - + - frame_bury 4 - b dynamic_array_concat_dynamic_element_for_header@1 - -dynamic_array_concat_dynamic_element_after_for@4: - frame_dig -3 - len - frame_bury 0 - int 0 - frame_bury 4 - -dynamic_array_concat_dynamic_element_for_header@5: - frame_dig 4 - frame_dig 2 - < - bz dynamic_array_concat_dynamic_element_after_for@8 - frame_dig -1 - frame_dig 4 - dup - cover 2 - extract_uint16 - frame_dig 0 - + - itob - extract 6 2 - frame_dig 1 - swap - concat - frame_bury 1 - int 2 - + - frame_bury 4 - b dynamic_array_concat_dynamic_element_for_header@5 - -dynamic_array_concat_dynamic_element_after_for@8: - frame_dig -4 - frame_dig -2 - + - itob - extract 6 2 - frame_dig 1 - concat - frame_dig -3 - frame_dig 3 - frame_dig 0 - substring3 - concat - frame_dig -1 - len - frame_dig -1 - frame_dig 2 - uncover 2 - substring3 - concat - frame_bury 0 - retsub - - -// _puya_lib.arc4.dynamic_array_replace_dynamic_element(source: bytes, new_item: bytes, index: uint64) -> bytes: -dynamic_array_replace_dynamic_element: - proto 3 1 - frame_dig -3 - substring 0 2 - dup - btoi - frame_dig -3 - extract 2 0 - frame_dig -2 - frame_dig -1 - uncover 3 - callsub static_array_replace_dynamic_element - concat - retsub - - -// _puya_lib.arc4.static_array_replace_dynamic_element(array_head_and_tail: bytes, new_item: bytes, index: uint64, array_length: uint64) -> bytes: -static_array_replace_dynamic_element: - proto 4 1 - frame_dig -2 - int 2 - * - frame_dig -4 - swap - extract_uint16 - frame_dig -2 - int 1 - + - int 2 - * - dup - cover 2 - frame_dig -4 - swap - extract_uint16 - frame_dig -4 - len - frame_dig -1 - frame_dig -2 - - - int 1 - - - dig 1 - uncover 3 - uncover 2 - select - dup - dig 3 - - - cover 3 - frame_dig -3 - len - cover 3 - frame_dig -4 - int 0 - uncover 4 - substring3 - frame_dig -3 - concat - frame_dig -4 - uncover 2 - uncover 3 - substring3 - concat - frame_dig -1 - int 2 - * - -static_array_replace_dynamic_element_for_header@1: - frame_dig 0 - frame_dig 4 - < - bz static_array_replace_dynamic_element_after_for@4 - frame_dig 3 - dup - frame_dig 0 - dup - cover 3 - extract_uint16 - frame_dig 2 - + - frame_dig 1 - - - itob - extract 6 2 - dig 2 - swap - replace3 - frame_bury 3 - int 2 - + - frame_bury 0 - b static_array_replace_dynamic_element_for_header@1 - -static_array_replace_dynamic_element_after_for@4: - frame_dig 3 - frame_bury 0 - retsub diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.arc32.json b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.arc32.json deleted file mode 100644 index e9a1bf4..0000000 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.arc32.json +++ /dev/null @@ -1,111 +0,0 @@ -{ - "hints": { - "add_todo(string)(string,bool)[]": { - "call_config": { - "no_op": "CALL" - } - }, - "complete_todo(string)void": { - "call_config": { - "no_op": "CALL" - } - }, - "return_todo(string)(string,bool)": { - "call_config": { - "no_op": "CALL" - }, - "structs": { - "output": { - "name": "Todo", - "elements": [ - [ - "task", - "string" - ], - [ - "completed", - "bool" - ] - ] - } - } - } - }, - "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RydWN0LmFwcHJvdmFsX3Byb2dyYW06CiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYm56IG1haW5fZW50cnlwb2ludEAyCiAgICBjYWxsc3ViIF9faW5pdF9fCgptYWluX2VudHJ5cG9pbnRAMjoKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRTdHJ1Y3QuX19wdXlhX2FyYzRfcm91dGVyX18oKSAtPiB1aW50NjQ6Cl9fcHV5YV9hcmM0X3JvdXRlcl9fOgogICAgcHJvdG8gMCAxCiAgICB0eG4gTnVtQXBwQXJncwogICAgYnogX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDcKICAgIG1ldGhvZCAiYWRkX3RvZG8oc3RyaW5nKShzdHJpbmcsYm9vbClbXSIKICAgIG1ldGhvZCAiY29tcGxldGVfdG9kbyhzdHJpbmcpdm9pZCIKICAgIG1ldGhvZCAicmV0dXJuX3RvZG8oc3RyaW5nKShzdHJpbmcsYm9vbCkiCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAwCiAgICBtYXRjaCBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZGRfdG9kb19yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2NvbXBsZXRlX3RvZG9fcm91dGVAMyBfX3B1eWFfYXJjNF9yb3V0ZXJfX19yZXR1cm5fdG9kb19yb3V0ZUA0CiAgICBpbnQgMAogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZGRfdG9kb19yb3V0ZUAyOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgY2FsbHN1YiBhZGRfdG9kbwogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fY29tcGxldGVfdG9kb19yb3V0ZUAzOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgY2FsbHN1YiBjb21wbGV0ZV90b2RvCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19yZXR1cm5fdG9kb19yb3V0ZUA0OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgY2FsbHN1YiByZXR1cm5fdG9kbwogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDc6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBibnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMQogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgICEKICAgIGFzc2VydCAvLyBpcyBjcmVhdGluZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMToKICAgIGludCAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RydWN0LmFkZF90b2RvKHRhc2s6IGJ5dGVzKSAtPiBieXRlczoKYWRkX3RvZG86CiAgICBwcm90byAxIDEKICAgIGJ5dGUgMHgwMDAzMDAKICAgIGZyYW1lX2RpZyAtMQogICAgY29uY2F0CiAgICBpbnQgMAogICAgYnl0ZSAidG9kb3MiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIHNlbGYudG9kb3MgZXhpc3RzCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGJueiBhZGRfdG9kb19lbHNlX2JvZHlAMgogICAgYnl0ZSAweDAwMDIKICAgIHN3YXAKICAgIGNvbmNhdAogICAgYnl0ZSAweDAwMDEKICAgIHN3YXAKICAgIGNvbmNhdAogICAgYnl0ZSAidG9kb3MiCiAgICBzd2FwCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgYiBhZGRfdG9kb19hZnRlcl9pZl9lbHNlQDMKCmFkZF90b2RvX2Vsc2VfYm9keUAyOgogICAgaW50IDAKICAgIGJ5dGUgInRvZG9zIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBzZWxmLnRvZG9zIGV4aXN0cwogICAgYnl0ZSAweDAwMDIKICAgIHVuY292ZXIgMgogICAgY29uY2F0CiAgICBzd2FwCiAgICBkdXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgc3dhcAogICAgZXh0cmFjdCAyIDAKICAgIGludCAxCiAgICB1bmNvdmVyIDMKICAgIGNhbGxzdWIgZHluYW1pY19hcnJheV9jb25jYXRfZHluYW1pY19lbGVtZW50CiAgICBieXRlICJ0b2RvcyIKICAgIHN3YXAKICAgIGFwcF9nbG9iYWxfcHV0CgphZGRfdG9kb19hZnRlcl9pZl9lbHNlQDM6CiAgICBpbnQgMAogICAgYnl0ZSAidG9kb3MiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIHNlbGYudG9kb3MgZXhpc3RzCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RydWN0LmNvbXBsZXRlX3RvZG8odGFzazogYnl0ZXMpIC0+IHZvaWQ6CmNvbXBsZXRlX3RvZG86CiAgICBwcm90byAxIDAKICAgIGJ5dGUgIiIKICAgIGR1cAogICAgaW50IDAKICAgIGJ5dGUgInRvZG9zIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBzZWxmLnRvZG9zIGV4aXN0cwogICAgaW50IDAKICAgIGV4dHJhY3RfdWludDE2CiAgICBpbnQgMAoKY29tcGxldGVfdG9kb19mb3JfaGVhZGVyQDE6CiAgICBmcmFtZV9kaWcgMwogICAgZnJhbWVfZGlnIDIKICAgIDwKICAgIGJ6IGNvbXBsZXRlX3RvZG9fYWZ0ZXJfZm9yQDYKICAgIGludCAwCiAgICBieXRlICJ0b2RvcyIKICAgIGFwcF9nbG9iYWxfZ2V0X2V4CiAgICBhc3NlcnQgLy8gY2hlY2sgc2VsZi50b2RvcyBleGlzdHMKICAgIGR1cAogICAgZXh0cmFjdCAyIDAKICAgIGZyYW1lX2RpZyAzCiAgICBkdXAKICAgIGNvdmVyIDMKICAgIGludCAyCiAgICAqCiAgICBkdXAKICAgIGZyYW1lX2J1cnkgMAogICAgZGlnIDEKICAgIHN3YXAKICAgIGV4dHJhY3RfdWludDE2CiAgICBjb3ZlciAzCiAgICBzd2FwCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIHVuY292ZXIgMgogICAgaW50IDEKICAgICsKICAgIGR1cAogICAgY292ZXIgNAogICAgZHVwCiAgICBjb3ZlciAyCiAgICAtIC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgc3dhcAogICAgZGlnIDIKICAgIGxlbgogICAgY292ZXIgMgogICAgaW50IDIKICAgICoKICAgIGR1cAogICAgZnJhbWVfYnVyeSAxCiAgICBkaWcgMwogICAgc3dhcAogICAgZXh0cmFjdF91aW50MTYKICAgIHN3YXAKICAgIHNlbGVjdAogICAgc3dhcAogICAgY292ZXIgMgogICAgc3Vic3RyaW5nMwogICAgZHVwCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIHN3YXAKICAgIGR1cAogICAgbGVuCiAgICBzd2FwCiAgICBjb3ZlciAyCiAgICBzdWJzdHJpbmczCiAgICBmcmFtZV9kaWcgLTEKICAgID09CiAgICBieiBjb21wbGV0ZV90b2RvX2FmdGVyX2lmX2Vsc2VANAogICAgaW50IDAKICAgIGJ5dGUgInRvZG9zIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBzZWxmLnRvZG9zIGV4aXN0cwogICAgZHVwCiAgICBleHRyYWN0IDIgMAogICAgZHVwCiAgICBmcmFtZV9kaWcgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGNvdmVyIDIKICAgIHN3YXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgdW5jb3ZlciAzCiAgICAtIC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgZGlnIDEKICAgIGxlbgogICAgc3dhcAogICAgZGlnIDIKICAgIGZyYW1lX2RpZyAxCiAgICBleHRyYWN0X3VpbnQxNgogICAgc3dhcAogICAgc2VsZWN0CiAgICBzd2FwCiAgICBjb3ZlciAyCiAgICBzdWJzdHJpbmczCiAgICBpbnQgMTYKICAgIGludCAxCiAgICBzZXRiaXQKICAgIGludCAwCiAgICBieXRlICJ0b2RvcyIKICAgIGFwcF9nbG9iYWxfZ2V0X2V4CiAgICBhc3NlcnQgLy8gY2hlY2sgc2VsZi50b2RvcyBleGlzdHMKICAgIHN3YXAKICAgIGZyYW1lX2RpZyAzCiAgICBjYWxsc3ViIGR5bmFtaWNfYXJyYXlfcmVwbGFjZV9keW5hbWljX2VsZW1lbnQKICAgIGJ5dGUgInRvZG9zIgogICAgc3dhcAogICAgYXBwX2dsb2JhbF9wdXQKICAgIGIgY29tcGxldGVfdG9kb19hZnRlcl9mb3JANgoKY29tcGxldGVfdG9kb19hZnRlcl9pZl9lbHNlQDQ6CiAgICBmcmFtZV9idXJ5IDMKICAgIGIgY29tcGxldGVfdG9kb19mb3JfaGVhZGVyQDEKCmNvbXBsZXRlX3RvZG9fYWZ0ZXJfZm9yQDY6CiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RydWN0LnJldHVybl90b2RvKHRhc2s6IGJ5dGVzKSAtPiBieXRlczoKcmV0dXJuX3RvZG86CiAgICBwcm90byAxIDEKICAgIGludCAwCiAgICBieXRlICIiCiAgICBkdXAKICAgIGludCAwCiAgICBkdXAKICAgIGJ5dGUgInRvZG9zIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBzZWxmLnRvZG9zIGV4aXN0cwogICAgaW50IDAKICAgIGV4dHJhY3RfdWludDE2CiAgICBpbnQgMAoKcmV0dXJuX3RvZG9fZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDUKICAgIGZyYW1lX2RpZyA0CiAgICA8CiAgICBieiByZXR1cm5fdG9kb19hZnRlcl9mb3JANgogICAgaW50IDAKICAgIGJ5dGUgInRvZG9zIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBzZWxmLnRvZG9zIGV4aXN0cwogICAgZHVwCiAgICBleHRyYWN0IDIgMAogICAgZnJhbWVfZGlnIDUKICAgIGR1cAogICAgY292ZXIgMwogICAgaW50IDIKICAgICoKICAgIGR1cAogICAgZnJhbWVfYnVyeSAxCiAgICBkaWcgMQogICAgc3dhcAogICAgZXh0cmFjdF91aW50MTYKICAgIGNvdmVyIDMKICAgIHN3YXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgdW5jb3ZlciAyCiAgICBpbnQgMQogICAgKwogICAgZHVwCiAgICBmcmFtZV9idXJ5IDUKICAgIGR1cAogICAgY292ZXIgMgogICAgLSAvLyBvbiBlcnJvcjogSW5kZXggYWNjZXNzIGlzIG91dCBvZiBib3VuZHMKICAgIHN3YXAKICAgIGRpZyAyCiAgICBsZW4KICAgIGNvdmVyIDIKICAgIGludCAyCiAgICAqCiAgICBkdXAKICAgIGZyYW1lX2J1cnkgMgogICAgZGlnIDMKICAgIHN3YXAKICAgIGV4dHJhY3RfdWludDE2CiAgICBzd2FwCiAgICBzZWxlY3QKICAgIHN3YXAKICAgIGNvdmVyIDIKICAgIHN1YnN0cmluZzMKICAgIGR1cAogICAgaW50IDAKICAgIGV4dHJhY3RfdWludDE2CiAgICBzd2FwCiAgICBkdXAKICAgIGxlbgogICAgc3dhcAogICAgY292ZXIgMgogICAgc3Vic3RyaW5nMwogICAgZnJhbWVfZGlnIC0xCiAgICA9PQogICAgYnogcmV0dXJuX3RvZG9fZm9yX2hlYWRlckAxCiAgICBpbnQgMAogICAgYnl0ZSAidG9kb3MiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIHNlbGYudG9kb3MgZXhpc3RzCiAgICBkdXAKICAgIGV4dHJhY3QgMiAwCiAgICBkdXAKICAgIGZyYW1lX2RpZyAxCiAgICBleHRyYWN0X3VpbnQxNgogICAgY292ZXIgMgogICAgc3dhcAogICAgaW50IDAKICAgIGV4dHJhY3RfdWludDE2CiAgICBmcmFtZV9kaWcgNQogICAgLSAvLyBvbiBlcnJvcjogSW5kZXggYWNjZXNzIGlzIG91dCBvZiBib3VuZHMKICAgIGRpZyAxCiAgICBsZW4KICAgIHN3YXAKICAgIGRpZyAyCiAgICBmcmFtZV9kaWcgMgogICAgZXh0cmFjdF91aW50MTYKICAgIHN3YXAKICAgIHNlbGVjdAogICAgc3dhcAogICAgY292ZXIgMgogICAgc3Vic3RyaW5nMwogICAgZnJhbWVfYnVyeSAwCiAgICBpbnQgMQogICAgZnJhbWVfYnVyeSAzCiAgICBiIHJldHVybl90b2RvX2Zvcl9oZWFkZXJAMQoKcmV0dXJuX3RvZG9fYWZ0ZXJfZm9yQDY6CiAgICBmcmFtZV9kaWcgMwogICAgYXNzZXJ0CiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RydWN0Ll9faW5pdF9fKCkgLT4gdm9pZDoKX19pbml0X186CiAgICBwcm90byAwIDAKICAgIGJ5dGUgInRvZG9zIgogICAgYnl0ZSAweDAwMDAKICAgIGFwcF9nbG9iYWxfcHV0CiAgICByZXRzdWIKCgovLyBfcHV5YV9saWIuYXJjNC5keW5hbWljX2FycmF5X2NvbmNhdF9keW5hbWljX2VsZW1lbnQoYXJyYXlfaXRlbXNfY291bnQ6IHVpbnQ2NCwgYXJyYXlfaGVhZF9hbmRfdGFpbDogYnl0ZXMsIG5ld19pdGVtc19jb3VudDogdWludDY0LCBuZXdfaGVhZF9hbmRfdGFpbDogYnl0ZXMpIC0+IGJ5dGVzOgpkeW5hbWljX2FycmF5X2NvbmNhdF9keW5hbWljX2VsZW1lbnQ6CiAgICBwcm90byA0IDEKICAgIGJ5dGUgIiIKICAgIGJ5dGUgMHgKICAgIGZyYW1lX2RpZyAtMgogICAgaW50IDIKICAgICoKICAgIGZyYW1lX2RpZyAtNAogICAgaW50IDIKICAgICoKICAgIGludCAwCgpkeW5hbWljX2FycmF5X2NvbmNhdF9keW5hbWljX2VsZW1lbnRfZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDQKICAgIGZyYW1lX2RpZyAzCiAgICA8CiAgICBieiBkeW5hbWljX2FycmF5X2NvbmNhdF9keW5hbWljX2VsZW1lbnRfYWZ0ZXJfZm9yQDQKICAgIGZyYW1lX2RpZyAtMwogICAgZnJhbWVfZGlnIDQKICAgIGR1cAogICAgY292ZXIgMgogICAgZXh0cmFjdF91aW50MTYKICAgIGZyYW1lX2RpZyAyCiAgICArCiAgICBpdG9iCiAgICBleHRyYWN0IDYgMgogICAgZnJhbWVfZGlnIDEKICAgIHN3YXAKICAgIGNvbmNhdAogICAgZnJhbWVfYnVyeSAxCiAgICBpbnQgMgogICAgKwogICAgZnJhbWVfYnVyeSA0CiAgICBiIGR5bmFtaWNfYXJyYXlfY29uY2F0X2R5bmFtaWNfZWxlbWVudF9mb3JfaGVhZGVyQDEKCmR5bmFtaWNfYXJyYXlfY29uY2F0X2R5bmFtaWNfZWxlbWVudF9hZnRlcl9mb3JANDoKICAgIGZyYW1lX2RpZyAtMwogICAgbGVuCiAgICBmcmFtZV9idXJ5IDAKICAgIGludCAwCiAgICBmcmFtZV9idXJ5IDQKCmR5bmFtaWNfYXJyYXlfY29uY2F0X2R5bmFtaWNfZWxlbWVudF9mb3JfaGVhZGVyQDU6CiAgICBmcmFtZV9kaWcgNAogICAgZnJhbWVfZGlnIDIKICAgIDwKICAgIGJ6IGR5bmFtaWNfYXJyYXlfY29uY2F0X2R5bmFtaWNfZWxlbWVudF9hZnRlcl9mb3JAOAogICAgZnJhbWVfZGlnIC0xCiAgICBmcmFtZV9kaWcgNAogICAgZHVwCiAgICBjb3ZlciAyCiAgICBleHRyYWN0X3VpbnQxNgogICAgZnJhbWVfZGlnIDAKICAgICsKICAgIGl0b2IKICAgIGV4dHJhY3QgNiAyCiAgICBmcmFtZV9kaWcgMQogICAgc3dhcAogICAgY29uY2F0CiAgICBmcmFtZV9idXJ5IDEKICAgIGludCAyCiAgICArCiAgICBmcmFtZV9idXJ5IDQKICAgIGIgZHluYW1pY19hcnJheV9jb25jYXRfZHluYW1pY19lbGVtZW50X2Zvcl9oZWFkZXJANQoKZHluYW1pY19hcnJheV9jb25jYXRfZHluYW1pY19lbGVtZW50X2FmdGVyX2ZvckA4OgogICAgZnJhbWVfZGlnIC00CiAgICBmcmFtZV9kaWcgLTIKICAgICsKICAgIGl0b2IKICAgIGV4dHJhY3QgNiAyCiAgICBmcmFtZV9kaWcgMQogICAgY29uY2F0CiAgICBmcmFtZV9kaWcgLTMKICAgIGZyYW1lX2RpZyAzCiAgICBmcmFtZV9kaWcgMAogICAgc3Vic3RyaW5nMwogICAgY29uY2F0CiAgICBmcmFtZV9kaWcgLTEKICAgIGxlbgogICAgZnJhbWVfZGlnIC0xCiAgICBmcmFtZV9kaWcgMgogICAgdW5jb3ZlciAyCiAgICBzdWJzdHJpbmczCiAgICBjb25jYXQKICAgIGZyYW1lX2J1cnkgMAogICAgcmV0c3ViCgoKLy8gX3B1eWFfbGliLmFyYzQuZHluYW1pY19hcnJheV9yZXBsYWNlX2R5bmFtaWNfZWxlbWVudChzb3VyY2U6IGJ5dGVzLCBuZXdfaXRlbTogYnl0ZXMsIGluZGV4OiB1aW50NjQpIC0+IGJ5dGVzOgpkeW5hbWljX2FycmF5X3JlcGxhY2VfZHluYW1pY19lbGVtZW50OgogICAgcHJvdG8gMyAxCiAgICBmcmFtZV9kaWcgLTMKICAgIHN1YnN0cmluZyAwIDIKICAgIGR1cAogICAgYnRvaQogICAgZnJhbWVfZGlnIC0zCiAgICBleHRyYWN0IDIgMAogICAgZnJhbWVfZGlnIC0yCiAgICBmcmFtZV9kaWcgLTEKICAgIHVuY292ZXIgMwogICAgY2FsbHN1YiBzdGF0aWNfYXJyYXlfcmVwbGFjZV9keW5hbWljX2VsZW1lbnQKICAgIGNvbmNhdAogICAgcmV0c3ViCgoKLy8gX3B1eWFfbGliLmFyYzQuc3RhdGljX2FycmF5X3JlcGxhY2VfZHluYW1pY19lbGVtZW50KGFycmF5X2hlYWRfYW5kX3RhaWw6IGJ5dGVzLCBuZXdfaXRlbTogYnl0ZXMsIGluZGV4OiB1aW50NjQsIGFycmF5X2xlbmd0aDogdWludDY0KSAtPiBieXRlczoKc3RhdGljX2FycmF5X3JlcGxhY2VfZHluYW1pY19lbGVtZW50OgogICAgcHJvdG8gNCAxCiAgICBmcmFtZV9kaWcgLTIKICAgIGludCAyCiAgICAqCiAgICBmcmFtZV9kaWcgLTQKICAgIHN3YXAKICAgIGV4dHJhY3RfdWludDE2CiAgICBmcmFtZV9kaWcgLTIKICAgIGludCAxCiAgICArCiAgICBpbnQgMgogICAgKgogICAgZHVwCiAgICBjb3ZlciAyCiAgICBmcmFtZV9kaWcgLTQKICAgIHN3YXAKICAgIGV4dHJhY3RfdWludDE2CiAgICBmcmFtZV9kaWcgLTQKICAgIGxlbgogICAgZnJhbWVfZGlnIC0xCiAgICBmcmFtZV9kaWcgLTIKICAgIC0KICAgIGludCAxCiAgICAtCiAgICBkaWcgMQogICAgdW5jb3ZlciAzCiAgICB1bmNvdmVyIDIKICAgIHNlbGVjdAogICAgZHVwCiAgICBkaWcgMwogICAgLQogICAgY292ZXIgMwogICAgZnJhbWVfZGlnIC0zCiAgICBsZW4KICAgIGNvdmVyIDMKICAgIGZyYW1lX2RpZyAtNAogICAgaW50IDAKICAgIHVuY292ZXIgNAogICAgc3Vic3RyaW5nMwogICAgZnJhbWVfZGlnIC0zCiAgICBjb25jYXQKICAgIGZyYW1lX2RpZyAtNAogICAgdW5jb3ZlciAyCiAgICB1bmNvdmVyIDMKICAgIHN1YnN0cmluZzMKICAgIGNvbmNhdAogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMgogICAgKgoKc3RhdGljX2FycmF5X3JlcGxhY2VfZHluYW1pY19lbGVtZW50X2Zvcl9oZWFkZXJAMToKICAgIGZyYW1lX2RpZyAwCiAgICBmcmFtZV9kaWcgNAogICAgPAogICAgYnogc3RhdGljX2FycmF5X3JlcGxhY2VfZHluYW1pY19lbGVtZW50X2FmdGVyX2ZvckA0CiAgICBmcmFtZV9kaWcgMwogICAgZHVwCiAgICBmcmFtZV9kaWcgMAogICAgZHVwCiAgICBjb3ZlciAzCiAgICBleHRyYWN0X3VpbnQxNgogICAgZnJhbWVfZGlnIDIKICAgICsKICAgIGZyYW1lX2RpZyAxCiAgICAtCiAgICBpdG9iCiAgICBleHRyYWN0IDYgMgogICAgZGlnIDIKICAgIHN3YXAKICAgIHJlcGxhY2UzCiAgICBmcmFtZV9idXJ5IDMKICAgIGludCAyCiAgICArCiAgICBmcmFtZV9idXJ5IDAKICAgIGIgc3RhdGljX2FycmF5X3JlcGxhY2VfZHluYW1pY19lbGVtZW50X2Zvcl9oZWFkZXJAMQoKc3RhdGljX2FycmF5X3JlcGxhY2VfZHluYW1pY19lbGVtZW50X2FmdGVyX2ZvckA0OgogICAgZnJhbWVfZGlnIDMKICAgIGZyYW1lX2J1cnkgMAogICAgcmV0c3ViCg==", - "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RydWN0LmNsZWFyX3N0YXRlX3Byb2dyYW06CiAgICBpbnQgMQogICAgcmV0dXJuCg==" - }, - "state": { - "global": { - "num_byte_slices": 1, - "num_uints": 0 - }, - "local": { - "num_byte_slices": 0, - "num_uints": 0 - } - }, - "schema": { - "global": { - "declared": { - "todos": { - "type": "bytes", - "key": "todos" - } - }, - "reserved": {} - }, - "local": { - "declared": {}, - "reserved": {} - } - }, - "contract": { - "name": "Arc4Struct", - "methods": [ - { - "name": "add_todo", - "args": [ - { - "type": "string", - "name": "task" - } - ], - "readonly": false, - "returns": { - "type": "(string,bool)[]" - } - }, - { - "name": "complete_todo", - "args": [ - { - "type": "string", - "name": "task" - } - ], - "readonly": false, - "returns": { - "type": "void" - } - }, - { - "name": "return_todo", - "args": [ - { - "type": "string", - "name": "task" - } - ], - "readonly": false, - "returns": { - "type": "(string,bool)" - } - } - ], - "networks": {} - }, - "bare_call_config": { - "no_op": "CREATE" - } -} \ No newline at end of file diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.clear.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.clear.teal deleted file mode 100644 index 095349f..0000000 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.clear.teal +++ /dev/null @@ -1,5 +0,0 @@ -#pragma version 10 - -smart_contracts.arc4_types.contract.Arc4Struct.clear_state_program: - int 1 - return diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.approval.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.approval.teal deleted file mode 100644 index 4de542f..0000000 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.approval.teal +++ /dev/null @@ -1,145 +0,0 @@ -#pragma version 10 - -smart_contracts.arc4_types.contract.Arc4Tuple.approval_program: - callsub __puya_arc4_router__ - return - - -// smart_contracts.arc4_types.contract.Arc4Tuple.__puya_arc4_router__() -> uint64: -__puya_arc4_router__: - proto 0 1 - txn NumAppArgs - bz __puya_arc4_router___bare_routing@6 - method "add_contact_info((string,string,uint64,uint8[]))uint64" - method "return_contact()(string,string,uint64)" - txna ApplicationArgs 0 - match __puya_arc4_router___add_contact_info_route@2 __puya_arc4_router___return_contact_route@3 - int 0 - retsub - -__puya_arc4_router___add_contact_info_route@2: - txn OnCompletion - ! - assert // OnCompletion is NoOp - txn ApplicationID - assert // is not creating - txna ApplicationArgs 1 - callsub add_contact_info - itob - byte 0x151f7c75 - swap - concat - log - int 1 - retsub - -__puya_arc4_router___return_contact_route@3: - txn OnCompletion - ! - assert // OnCompletion is NoOp - txn ApplicationID - assert // is not creating - callsub return_contact - byte 0x151f7c75 - swap - concat - log - int 1 - retsub - -__puya_arc4_router___bare_routing@6: - txn OnCompletion - bnz __puya_arc4_router___after_if_else@10 - txn ApplicationID - ! - assert // is creating - int 1 - retsub - -__puya_arc4_router___after_if_else@10: - int 0 - retsub - - -// smart_contracts.arc4_types.contract.Arc4Tuple.add_contact_info(contact: bytes) -> uint64: -add_contact_info: - proto 1 1 - frame_dig -1 - int 0 - extract_uint16 - frame_dig -1 - int 2 - extract_uint16 - frame_dig -1 - uncover 2 - dig 2 - substring3 - swap - frame_dig -1 - int 12 - extract_uint16 - frame_dig -1 - uncover 2 - dig 2 - substring3 - cover 2 - frame_dig -1 - extract 4 8 // on error: Index access is out of bounds - cover 3 - frame_dig -1 - len - frame_dig -1 - cover 2 - substring3 - dup - cover 4 - cover 4 - extract 2 0 - byte "John Woods" - == - assert - extract 2 0 - byte "john@something.com" - == - assert - byte 0x00000000211d1ae3 - b== - assert - int 0 - swap - int 0 - extract_uint16 - int 0 - -add_contact_info_for_header@1: - frame_dig 3 - frame_dig 2 - < - bz add_contact_info_after_for@4 - frame_dig 0 - extract 2 0 - frame_dig 3 - dup - cover 2 - int 1 - extract3 // on error: Index access is out of bounds - btoi - frame_dig 1 - + - frame_bury 1 - int 1 - + - frame_bury 3 - b add_contact_info_for_header@1 - -add_contact_info_after_for@4: - frame_dig 1 - frame_bury 0 - retsub - - -// smart_contracts.arc4_types.contract.Arc4Tuple.return_contact() -> bytes: -return_contact: - proto 0 1 - byte 0x000c001300000000211d1ae30005416c6963650013616c69636540736f6d657468696e672e636f6d - retsub diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.arc32.json b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.arc32.json deleted file mode 100644 index f60bdd6..0000000 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.arc32.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "hints": { - "add_contact_info((string,string,uint64,uint8[]))uint64": { - "call_config": { - "no_op": "CALL" - } - }, - "return_contact()(string,string,uint64)": { - "call_config": { - "no_op": "CALL" - } - } - }, - "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHVwbGUuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUdXBsZS5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANgogICAgbWV0aG9kICJhZGRfY29udGFjdF9pbmZvKChzdHJpbmcsc3RyaW5nLHVpbnQ2NCx1aW50OFtdKSl1aW50NjQiCiAgICBtZXRob2QgInJldHVybl9jb250YWN0KCkoc3RyaW5nLHN0cmluZyx1aW50NjQpIgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAogICAgbWF0Y2ggX19wdXlhX2FyYzRfcm91dGVyX19fYWRkX2NvbnRhY3RfaW5mb19yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX3JldHVybl9jb250YWN0X3JvdXRlQDMKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FkZF9jb250YWN0X2luZm9fcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYWRkX2NvbnRhY3RfaW5mbwogICAgaXRvYgogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fcmV0dXJuX2NvbnRhY3Rfcm91dGVAMzoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIGNhbGxzdWIgcmV0dXJuX2NvbnRhY3QKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgYm56IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTAKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICAhCiAgICBhc3NlcnQgLy8gaXMgY3JlYXRpbmcKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTA6CiAgICBpbnQgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLmFkZF9jb250YWN0X2luZm8oY29udGFjdDogYnl0ZXMpIC0+IHVpbnQ2NDoKYWRkX2NvbnRhY3RfaW5mbzoKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDIKICAgIGV4dHJhY3RfdWludDE2CiAgICBmcmFtZV9kaWcgLTEKICAgIHVuY292ZXIgMgogICAgZGlnIDIKICAgIHN1YnN0cmluZzMKICAgIHN3YXAKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDEyCiAgICBleHRyYWN0X3VpbnQxNgogICAgZnJhbWVfZGlnIC0xCiAgICB1bmNvdmVyIDIKICAgIGRpZyAyCiAgICBzdWJzdHJpbmczCiAgICBjb3ZlciAyCiAgICBmcmFtZV9kaWcgLTEKICAgIGV4dHJhY3QgNCA4IC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgY292ZXIgMwogICAgZnJhbWVfZGlnIC0xCiAgICBsZW4KICAgIGZyYW1lX2RpZyAtMQogICAgY292ZXIgMgogICAgc3Vic3RyaW5nMwogICAgZHVwCiAgICBjb3ZlciA0CiAgICBjb3ZlciA0CiAgICBleHRyYWN0IDIgMAogICAgYnl0ZSAiSm9obiBXb29kcyIKICAgID09CiAgICBhc3NlcnQKICAgIGV4dHJhY3QgMiAwCiAgICBieXRlICJqb2huQHNvbWV0aGluZy5jb20iCiAgICA9PQogICAgYXNzZXJ0CiAgICBieXRlIDB4MDAwMDAwMDAyMTFkMWFlMwogICAgYj09CiAgICBhc3NlcnQKICAgIGludCAwCiAgICBzd2FwCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGludCAwCgphZGRfY29udGFjdF9pbmZvX2Zvcl9oZWFkZXJAMToKICAgIGZyYW1lX2RpZyAzCiAgICBmcmFtZV9kaWcgMgogICAgPAogICAgYnogYWRkX2NvbnRhY3RfaW5mb19hZnRlcl9mb3JANAogICAgZnJhbWVfZGlnIDAKICAgIGV4dHJhY3QgMiAwCiAgICBmcmFtZV9kaWcgMwogICAgZHVwCiAgICBjb3ZlciAyCiAgICBpbnQgMQogICAgZXh0cmFjdDMgLy8gb24gZXJyb3I6IEluZGV4IGFjY2VzcyBpcyBvdXQgb2YgYm91bmRzCiAgICBidG9pCiAgICBmcmFtZV9kaWcgMQogICAgKwogICAgZnJhbWVfYnVyeSAxCiAgICBpbnQgMQogICAgKwogICAgZnJhbWVfYnVyeSAzCiAgICBiIGFkZF9jb250YWN0X2luZm9fZm9yX2hlYWRlckAxCgphZGRfY29udGFjdF9pbmZvX2FmdGVyX2ZvckA0OgogICAgZnJhbWVfZGlnIDEKICAgIGZyYW1lX2J1cnkgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLnJldHVybl9jb250YWN0KCkgLT4gYnl0ZXM6CnJldHVybl9jb250YWN0OgogICAgcHJvdG8gMCAxCiAgICBieXRlIDB4MDAwYzAwMTMwMDAwMDAwMDIxMWQxYWUzMDAwNTQxNmM2OTYzNjUwMDEzNjE2YzY5NjM2NTQwNzM2ZjZkNjU3NDY4Njk2ZTY3MmU2MzZmNmQKICAgIHJldHN1Ygo=", - "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHVwbGUuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" - }, - "state": { - "global": { - "num_byte_slices": 0, - "num_uints": 0 - }, - "local": { - "num_byte_slices": 0, - "num_uints": 0 - } - }, - "schema": { - "global": { - "declared": {}, - "reserved": {} - }, - "local": { - "declared": {}, - "reserved": {} - } - }, - "contract": { - "name": "Arc4Tuple", - "methods": [ - { - "name": "add_contact_info", - "args": [ - { - "type": "(string,string,uint64,uint8[])", - "name": "contact" - } - ], - "readonly": false, - "returns": { - "type": "uint64" - }, - "desc": "An arc4.Tuple is a heterogeneous collection of arc4 types." - }, - { - "name": "return_contact", - "args": [], - "readonly": false, - "returns": { - "type": "(string,string,uint64)" - }, - "desc": "An arc4.Tuple can be returned when more than one return value is needed." - } - ], - "networks": {} - }, - "bare_call_config": { - "no_op": "CREATE" - } -} \ No newline at end of file diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.clear.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.clear.teal deleted file mode 100644 index 3150069..0000000 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.clear.teal +++ /dev/null @@ -1,5 +0,0 @@ -#pragma version 10 - -smart_contracts.arc4_types.contract.Arc4Tuple.clear_state_program: - int 1 - return diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.approval.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.approval.teal deleted file mode 100644 index cf1936c..0000000 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.approval.teal +++ /dev/null @@ -1,248 +0,0 @@ -#pragma version 10 - -smart_contracts.arc4_types.contract.Arc4Types.approval_program: - callsub __puya_arc4_router__ - return - - -// smart_contracts.arc4_types.contract.Arc4Types.__puya_arc4_router__() -> uint64: -__puya_arc4_router__: - proto 0 1 - txn NumAppArgs - bz __puya_arc4_router___bare_routing@10 - method "arc4_uint64(uint64,uint64)uint64" - method "arc4_uint_n(uint8,uint16,uint32,uint64)uint64" - method "arc4_biguint_n(uint128,uint256,uint512)uint512" - method "arc4_byte(byte)byte" - method "arc4_address_properties(address)uint64" - method "arc4_address_return(address)address" - txna ApplicationArgs 0 - match __puya_arc4_router___arc4_uint64_route@2 __puya_arc4_router___arc4_uint_n_route@3 __puya_arc4_router___arc4_biguint_n_route@4 __puya_arc4_router___arc4_byte_route@5 __puya_arc4_router___arc4_address_properties_route@6 __puya_arc4_router___arc4_address_return_route@7 - int 0 - retsub - -__puya_arc4_router___arc4_uint64_route@2: - txn OnCompletion - ! - assert // OnCompletion is NoOp - txn ApplicationID - assert // is not creating - txna ApplicationArgs 1 - txna ApplicationArgs 2 - callsub arc4_uint64 - byte 0x151f7c75 - swap - concat - log - int 1 - retsub - -__puya_arc4_router___arc4_uint_n_route@3: - txn OnCompletion - ! - assert // OnCompletion is NoOp - txn ApplicationID - assert // is not creating - txna ApplicationArgs 1 - txna ApplicationArgs 2 - txna ApplicationArgs 3 - txna ApplicationArgs 4 - callsub arc4_uint_n - byte 0x151f7c75 - swap - concat - log - int 1 - retsub - -__puya_arc4_router___arc4_biguint_n_route@4: - txn OnCompletion - ! - assert // OnCompletion is NoOp - txn ApplicationID - assert // is not creating - txna ApplicationArgs 1 - txna ApplicationArgs 2 - txna ApplicationArgs 3 - callsub arc4_biguint_n - byte 0x151f7c75 - swap - concat - log - int 1 - retsub - -__puya_arc4_router___arc4_byte_route@5: - txn OnCompletion - ! - assert // OnCompletion is NoOp - txn ApplicationID - assert // is not creating - txna ApplicationArgs 1 - callsub arc4_byte - byte 0x151f7c75 - swap - concat - log - int 1 - retsub - -__puya_arc4_router___arc4_address_properties_route@6: - txn OnCompletion - ! - assert // OnCompletion is NoOp - txn ApplicationID - assert // is not creating - txna ApplicationArgs 1 - callsub arc4_address_properties - itob - byte 0x151f7c75 - swap - concat - log - int 1 - retsub - -__puya_arc4_router___arc4_address_return_route@7: - txn OnCompletion - ! - assert // OnCompletion is NoOp - txn ApplicationID - assert // is not creating - txna ApplicationArgs 1 - callsub arc4_address_return - byte 0x151f7c75 - swap - concat - log - int 1 - retsub - -__puya_arc4_router___bare_routing@10: - txn OnCompletion - bnz __puya_arc4_router___after_if_else@14 - txn ApplicationID - ! - assert // is creating - int 1 - retsub - -__puya_arc4_router___after_if_else@14: - int 0 - retsub - - -// smart_contracts.arc4_types.contract.Arc4Types.arc4_uint64(a: bytes, b: bytes) -> bytes: -arc4_uint64: - proto 2 1 - frame_dig -2 - btoi - frame_dig -1 - btoi - + - itob - retsub - - -// smart_contracts.arc4_types.contract.Arc4Types.arc4_uint_n(a: bytes, b: bytes, c: bytes, d: bytes) -> bytes: -arc4_uint_n: - proto 4 1 - frame_dig -4 - len - int 1 - == - assert - frame_dig -3 - len - int 2 - == - assert - frame_dig -2 - len - int 4 - == - assert - frame_dig -1 - len - int 8 - == - assert - frame_dig -4 - btoi - frame_dig -3 - btoi - + - frame_dig -2 - btoi - + - frame_dig -1 - btoi - + - itob - retsub - - -// smart_contracts.arc4_types.contract.Arc4Types.arc4_biguint_n(a: bytes, b: bytes, c: bytes) -> bytes: -arc4_biguint_n: - proto 3 1 - frame_dig -3 - len - int 16 - == - assert - frame_dig -2 - len - int 32 - == - assert - frame_dig -1 - len - int 64 - == - assert - frame_dig -3 - frame_dig -2 - b+ - frame_dig -1 - b+ - dup - len - int 64 - <= - assert // overflow - int 64 - bzero - b| - retsub - - -// smart_contracts.arc4_types.contract.Arc4Types.arc4_byte(a: bytes) -> bytes: -arc4_byte: - proto 1 1 - frame_dig -1 - btoi - int 1 - + - itob - extract 7 1 - retsub - - -// smart_contracts.arc4_types.contract.Arc4Types.arc4_address_properties(address: bytes) -> uint64: -arc4_address_properties: - proto 1 1 - frame_dig -1 - acct_params_get AcctBalance - assert // account funded - frame_dig -1 - acct_params_get AcctTotalAssets - bury 1 - assert // account funded - retsub - - -// smart_contracts.arc4_types.contract.Arc4Types.arc4_address_return(address: bytes) -> bytes: -arc4_address_return: - proto 1 1 - frame_dig -1 - retsub diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.arc32.json b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.arc32.json deleted file mode 100644 index 8fda8ad..0000000 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.arc32.json +++ /dev/null @@ -1,173 +0,0 @@ -{ - "hints": { - "arc4_uint64(uint64,uint64)uint64": { - "call_config": { - "no_op": "CALL" - } - }, - "arc4_uint_n(uint8,uint16,uint32,uint64)uint64": { - "call_config": { - "no_op": "CALL" - } - }, - "arc4_biguint_n(uint128,uint256,uint512)uint512": { - "call_config": { - "no_op": "CALL" - } - }, - "arc4_byte(byte)byte": { - "call_config": { - "no_op": "CALL" - } - }, - "arc4_address_properties(address)uint64": { - "call_config": { - "no_op": "CALL" - } - }, - "arc4_address_return(address)address": { - "call_config": { - "no_op": "CALL" - } - } - }, - "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdAMTAKICAgIG1ldGhvZCAiYXJjNF91aW50NjQodWludDY0LHVpbnQ2NCl1aW50NjQiCiAgICBtZXRob2QgImFyYzRfdWludF9uKHVpbnQ4LHVpbnQxNix1aW50MzIsdWludDY0KXVpbnQ2NCIKICAgIG1ldGhvZCAiYXJjNF9iaWd1aW50X24odWludDEyOCx1aW50MjU2LHVpbnQ1MTIpdWludDUxMiIKICAgIG1ldGhvZCAiYXJjNF9ieXRlKGJ5dGUpYnl0ZSIKICAgIG1ldGhvZCAiYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXMoYWRkcmVzcyl1aW50NjQiCiAgICBtZXRob2QgImFyYzRfYWRkcmVzc19yZXR1cm4oYWRkcmVzcylhZGRyZXNzIgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAogICAgbWF0Y2ggX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF91aW50NjRfcm91dGVAMiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X3VpbnRfbl9yb3V0ZUAzIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYmlndWludF9uX3JvdXRlQDQgX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9ieXRlX3JvdXRlQDUgX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXNfcm91dGVANiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2FkZHJlc3NfcmV0dXJuX3JvdXRlQDcKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdWludDY0X3JvdXRlQDI6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAyCiAgICBjYWxsc3ViIGFyYzRfdWludDY0CiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X3VpbnRfbl9yb3V0ZUAzOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgNAogICAgY2FsbHN1YiBhcmM0X3VpbnRfbgogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9iaWd1aW50X25fcm91dGVANDoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDMKICAgIGNhbGxzdWIgYXJjNF9iaWd1aW50X24KICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYnl0ZV9yb3V0ZUA1OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgY2FsbHN1YiBhcmM0X2J5dGUKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYWRkcmVzc19wcm9wZXJ0aWVzX3JvdXRlQDY6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICBjYWxsc3ViIGFyYzRfYWRkcmVzc19wcm9wZXJ0aWVzCiAgICBpdG9iCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2FkZHJlc3NfcmV0dXJuX3JvdXRlQDc6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICBjYWxsc3ViIGFyYzRfYWRkcmVzc19yZXR1cm4KICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0AxMDoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgIGJueiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDE0CiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgIQogICAgYXNzZXJ0IC8vIGlzIGNyZWF0aW5nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDE0OgogICAgaW50IDAKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X3VpbnQ2NChhOiBieXRlcywgYjogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X3VpbnQ2NDoKICAgIHByb3RvIDIgMQogICAgZnJhbWVfZGlnIC0yCiAgICBidG9pCiAgICBmcmFtZV9kaWcgLTEKICAgIGJ0b2kKICAgICsKICAgIGl0b2IKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X3VpbnRfbihhOiBieXRlcywgYjogYnl0ZXMsIGM6IGJ5dGVzLCBkOiBieXRlcykgLT4gYnl0ZXM6CmFyYzRfdWludF9uOgogICAgcHJvdG8gNCAxCiAgICBmcmFtZV9kaWcgLTQKICAgIGxlbgogICAgaW50IDEKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMwogICAgbGVuCiAgICBpbnQgMgogICAgPT0KICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0yCiAgICBsZW4KICAgIGludCA0CiAgICA9PQogICAgYXNzZXJ0CiAgICBmcmFtZV9kaWcgLTEKICAgIGxlbgogICAgaW50IDgKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtNAogICAgYnRvaQogICAgZnJhbWVfZGlnIC0zCiAgICBidG9pCiAgICArCiAgICBmcmFtZV9kaWcgLTIKICAgIGJ0b2kKICAgICsKICAgIGZyYW1lX2RpZyAtMQogICAgYnRvaQogICAgKwogICAgaXRvYgogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFyYzRfYmlndWludF9uKGE6IGJ5dGVzLCBiOiBieXRlcywgYzogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X2JpZ3VpbnRfbjoKICAgIHByb3RvIDMgMQogICAgZnJhbWVfZGlnIC0zCiAgICBsZW4KICAgIGludCAxNgogICAgPT0KICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0yCiAgICBsZW4KICAgIGludCAzMgogICAgPT0KICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0xCiAgICBsZW4KICAgIGludCA2NAogICAgPT0KICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0zCiAgICBmcmFtZV9kaWcgLTIKICAgIGIrCiAgICBmcmFtZV9kaWcgLTEKICAgIGIrCiAgICBkdXAKICAgIGxlbgogICAgaW50IDY0CiAgICA8PQogICAgYXNzZXJ0IC8vIG92ZXJmbG93CiAgICBpbnQgNjQKICAgIGJ6ZXJvCiAgICBifAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFyYzRfYnl0ZShhOiBieXRlcykgLT4gYnl0ZXM6CmFyYzRfYnl0ZToKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBidG9pCiAgICBpbnQgMQogICAgKwogICAgaXRvYgogICAgZXh0cmFjdCA3IDEKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X2FkZHJlc3NfcHJvcGVydGllcyhhZGRyZXNzOiBieXRlcykgLT4gdWludDY0OgphcmM0X2FkZHJlc3NfcHJvcGVydGllczoKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBhY2N0X3BhcmFtc19nZXQgQWNjdEJhbGFuY2UKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgZnJhbWVfZGlnIC0xCiAgICBhY2N0X3BhcmFtc19nZXQgQWNjdFRvdGFsQXNzZXRzCiAgICBidXJ5IDEKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFyYzRfYWRkcmVzc19yZXR1cm4oYWRkcmVzczogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X2FkZHJlc3NfcmV0dXJuOgogICAgcHJvdG8gMSAxCiAgICBmcmFtZV9kaWcgLTEKICAgIHJldHN1Ygo=", - "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" - }, - "state": { - "global": { - "num_byte_slices": 0, - "num_uints": 0 - }, - "local": { - "num_byte_slices": 0, - "num_uints": 0 - } - }, - "schema": { - "global": { - "declared": {}, - "reserved": {} - }, - "local": { - "declared": {}, - "reserved": {} - } - }, - "contract": { - "name": "Arc4Types", - "methods": [ - { - "name": "arc4_uint64", - "args": [ - { - "type": "uint64", - "name": "a" - }, - { - "type": "uint64", - "name": "b" - } - ], - "readonly": false, - "returns": { - "type": "uint64" - }, - "desc": "Math operations (like a + b) are not supported on arc4.UInt64 types\nsince they are internally represented as byte arrays in the AVM. Use the .native property to perform arithmetic operations." - }, - { - "name": "arc4_uint_n", - "args": [ - { - "type": "uint8", - "name": "a" - }, - { - "type": "uint16", - "name": "b" - }, - { - "type": "uint32", - "name": "c" - }, - { - "type": "uint64", - "name": "d" - } - ], - "readonly": false, - "returns": { - "type": "uint64" - }, - "desc": "The encoding of arc4 integers will be smaller if it uses fewer bits.\nUltimately, they are all represented with native UInt64." - }, - { - "name": "arc4_biguint_n", - "args": [ - { - "type": "uint128", - "name": "a" - }, - { - "type": "uint256", - "name": "b" - }, - { - "type": "uint512", - "name": "c" - } - ], - "readonly": false, - "returns": { - "type": "uint512" - }, - "desc": "Integers with larger bit size are supported up to 512 bits.\nUltimately, they are all represented with native BigUInt." - }, - { - "name": "arc4_byte", - "args": [ - { - "type": "byte", - "name": "a" - } - ], - "readonly": false, - "returns": { - "type": "byte" - }, - "desc": "An arc4.Byte is essentially an alias for an 8-bit integer." - }, - { - "name": "arc4_address_properties", - "args": [ - { - "type": "address", - "name": "address" - } - ], - "readonly": false, - "returns": { - "type": "uint64" - } - }, - { - "name": "arc4_address_return", - "args": [ - { - "type": "address", - "name": "address" - } - ], - "readonly": false, - "returns": { - "type": "address" - } - } - ], - "networks": {} - }, - "bare_call_config": { - "no_op": "CREATE" - } -} \ No newline at end of file diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.clear.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.clear.teal deleted file mode 100644 index 7b46465..0000000 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.clear.teal +++ /dev/null @@ -1,5 +0,0 @@ -#pragma version 10 - -smart_contracts.arc4_types.contract.Arc4Types.clear_state_program: - int 1 - return diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_dynamic_array_client.py b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_dynamic_array_client.py deleted file mode 100644 index 63e6c90..0000000 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_dynamic_array_client.py +++ /dev/null @@ -1,565 +0,0 @@ -# flake8: noqa -# fmt: off -# mypy: disable-error-code="no-any-return, no-untyped-call, misc, type-arg" -# This file was automatically generated by algokit-client-generator. -# DO NOT MODIFY IT BY HAND. -# requires: algokit-utils@^1.2.0 -import base64 -import dataclasses -import decimal -import typing -from abc import ABC, abstractmethod - -import algokit_utils -import algosdk -from algosdk.v2client import models -from algosdk.atomic_transaction_composer import ( - AtomicTransactionComposer, - AtomicTransactionResponse, - SimulateAtomicTransactionResponse, - TransactionSigner, - TransactionWithSigner -) - -_APP_SPEC_JSON = r"""{ - "hints": { - "arc4_dynamic_array(string)string": { - "call_config": { - "no_op": "CALL" - } - }, - "arc4_dynamic_bytes()byte[]": { - "call_config": { - "no_op": "CALL" - } - } - }, - "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5LmFwcHJvdmFsX3Byb2dyYW06CiAgICBjYWxsc3ViIF9fcHV5YV9hcmM0X3JvdXRlcl9fCiAgICByZXR1cm4KCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5Ll9fcHV5YV9hcmM0X3JvdXRlcl9fKCkgLT4gdWludDY0OgpfX3B1eWFfYXJjNF9yb3V0ZXJfXzoKICAgIHByb3RvIDAgMQogICAgdHhuIE51bUFwcEFyZ3MKICAgIGJ6IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2CiAgICBtZXRob2QgImFyYzRfZHluYW1pY19hcnJheShzdHJpbmcpc3RyaW5nIgogICAgbWV0aG9kICJhcmM0X2R5bmFtaWNfYnl0ZXMoKWJ5dGVbXSIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfZHluYW1pY19hcnJheV9yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfZHluYW1pY19ieXRlc19yb3V0ZUAzCiAgICBpbnQgMAogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2R5bmFtaWNfYXJyYXlfcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYXJjNF9keW5hbWljX2FycmF5CiAgICBkdXAKICAgIGxlbgogICAgaXRvYgogICAgZXh0cmFjdCA2IDIKICAgIHN3YXAKICAgIGNvbmNhdAogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9keW5hbWljX2J5dGVzX3JvdXRlQDM6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICBjYWxsc3ViIGFyYzRfZHluYW1pY19ieXRlcwogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDY6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBibnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgICEKICAgIGFzc2VydCAvLyBpcyBjcmVhdGluZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMDoKICAgIGludCAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5LmFyYzRfZHluYW1pY19hcnJheShuYW1lOiBieXRlcykgLT4gYnl0ZXM6CmFyYzRfZHluYW1pY19hcnJheToKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBsZW4KICAgIGludCA0CiAgICArCiAgICBpdG9iCiAgICBleHRyYWN0IDYgMgogICAgYnl0ZSAweDAwMDQKICAgIHN3YXAKICAgIGNvbmNhdAogICAgZnJhbWVfZGlnIC0xCiAgICBjb25jYXQKICAgIGJ5dGUgMHgwMDAxMjEKICAgIGNvbmNhdAogICAgYnl0ZSAweDAwMDIKICAgIHN3YXAKICAgIGNvbmNhdAogICAgZHVwCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIHN3YXAKICAgIGV4dHJhY3QgMiAwCiAgICBzd2FwCiAgICBkdXAKICAgIGludCAyCiAgICAqCiAgICBzd2FwCiAgICBkaWcgMgogICAgbGVuCiAgICBzd2FwCiAgICBjb3ZlciAzCiAgICBzdWJzdHJpbmczCiAgICBieXRlIDB4MDAwMTAwMDIwMDA2NDg2NTZjNmM2ZjIwCiAgICBzd2FwCiAgICB1bmNvdmVyIDIKICAgIGNhbGxzdWIgZHluYW1pY19hcnJheV9jb25jYXRfYnl0ZV9sZW5ndGhfaGVhZAogICAgZHVwbiAyCiAgICBjYWxsc3ViIGR5bmFtaWNfYXJyYXlfcG9wX2J5dGVfbGVuZ3RoX2hlYWQKICAgIGJ1cnkgMQogICAgY2FsbHN1YiBkeW5hbWljX2FycmF5X3BvcF9ieXRlX2xlbmd0aF9oZWFkCiAgICBidXJ5IDEKICAgIGJ5dGUgMHgwMDA2Nzc2ZjcyNmM2NDIxCiAgICBpbnQgMQogICAgY2FsbHN1YiBkeW5hbWljX2FycmF5X2NvbmNhdF9ieXRlX2xlbmd0aF9oZWFkCiAgICBwb3AKICAgIGJ5dGUgIiIKICAgIHN3YXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50IDAKCmFyYzRfZHluYW1pY19hcnJheV9mb3JfaGVhZGVyQDE6CiAgICBmcmFtZV9kaWcgMwogICAgZnJhbWVfZGlnIDIKICAgIDwKICAgIGJ6IGFyYzRfZHluYW1pY19hcnJheV9hZnRlcl9mb3JANAogICAgZnJhbWVfZGlnIDAKICAgIGV4dHJhY3QgMiAwCiAgICBmcmFtZV9kaWcgMwogICAgZHVwCiAgICBjb3ZlciAyCiAgICBpbnQgMgogICAgKgogICAgZGlnIDEKICAgIHN3YXAKICAgIGV4dHJhY3RfdWludDE2CiAgICBkdXAyCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50IDIKICAgICsKICAgIGV4dHJhY3QzCiAgICBleHRyYWN0IDIgMAogICAgZnJhbWVfZGlnIDEKICAgIHN3YXAKICAgIGNvbmNhdAogICAgZnJhbWVfYnVyeSAxCiAgICBpbnQgMQogICAgKwogICAgZnJhbWVfYnVyeSAzCiAgICBiIGFyYzRfZHluYW1pY19hcnJheV9mb3JfaGVhZGVyQDEKCmFyYzRfZHluYW1pY19hcnJheV9hZnRlcl9mb3JANDoKICAgIGZyYW1lX2RpZyAxCiAgICBmcmFtZV9idXJ5IDAKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzREeW5hbWljQXJyYXkuYXJjNF9keW5hbWljX2J5dGVzKCkgLT4gYnl0ZXM6CmFyYzRfZHluYW1pY19ieXRlczoKICAgIHByb3RvIDAgMQogICAgYnl0ZSAweDAwMDNmZmZmZmYKICAgIGJ5dGUgMHgwMAogICAgcmVwbGFjZTIgMgogICAgcmV0c3ViCgoKLy8gX3B1eWFfbGliLmFyYzQuZHluYW1pY19hcnJheV9wb3BfYnl0ZV9sZW5ndGhfaGVhZChhcnJheTogYnl0ZXMpIC0+IGJ5dGVzLCBieXRlczoKZHluYW1pY19hcnJheV9wb3BfYnl0ZV9sZW5ndGhfaGVhZDoKICAgIHByb3RvIDEgMgogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGludCAxCiAgICAtCiAgICBkdXAKICAgIGludCAyCiAgICAqCiAgICBmcmFtZV9kaWcgLTEKICAgIGV4dHJhY3QgMiAwCiAgICBkdXAKICAgIGRpZyAyCiAgICBleHRyYWN0X3VpbnQxNgogICAgc3dhcAogICAgZHVwCiAgICBsZW4KICAgIHN3YXAKICAgIGR1cAogICAgZGlnIDMKICAgIHVuY292ZXIgMwogICAgc3Vic3RyaW5nMwogICAgY292ZXIgMwogICAgZHVwCiAgICBpbnQgMAogICAgZGlnIDQKICAgIHN1YnN0cmluZzMKICAgIGNvdmVyIDIKICAgIHVuY292ZXIgMwogICAgaW50IDIKICAgICsKICAgIHVuY292ZXIgMgogICAgc3Vic3RyaW5nMwogICAgY29uY2F0CiAgICBkaWcgMgogICAgaXRvYgogICAgZXh0cmFjdCA2IDIKICAgIHN3YXAKICAgIHVuY292ZXIgMwogICAgaW50IDAKICAgIGNhbGxzdWIgcmVjYWxjdWxhdGVfaGVhZF9mb3JfZWxlbWVudHNfd2l0aF9ieXRlX2xlbmd0aF9oZWFkCiAgICBjb25jYXQKICAgIHJldHN1YgoKCi8vIF9wdXlhX2xpYi5hcmM0LmR5bmFtaWNfYXJyYXlfY29uY2F0X2J5dGVfbGVuZ3RoX2hlYWQoYXJyYXk6IGJ5dGVzLCBuZXdfaXRlbXNfYnl0ZXM6IGJ5dGVzLCBuZXdfaXRlbXNfY291bnQ6IHVpbnQ2NCkgLT4gYnl0ZXM6CmR5bmFtaWNfYXJyYXlfY29uY2F0X2J5dGVfbGVuZ3RoX2hlYWQ6CiAgICBwcm90byAzIDEKICAgIGZyYW1lX2RpZyAtMwogICAgaW50IDAKICAgIGV4dHJhY3RfdWludDE2CiAgICBkdXAKICAgIGZyYW1lX2RpZyAtMQogICAgKwogICAgc3dhcAogICAgaW50IDIKICAgICoKICAgIGludCAyCiAgICArCiAgICBzd2FwCiAgICBkdXAKICAgIGl0b2IKICAgIGV4dHJhY3QgNiAyCiAgICBzd2FwCiAgICBmcmFtZV9kaWcgLTMKICAgIGludCAyCiAgICBkaWcgNAogICAgc3Vic3RyaW5nMwogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMgogICAgKgogICAgYnplcm8KICAgIGNvbmNhdAogICAgZnJhbWVfZGlnIC0zCiAgICBsZW4KICAgIGZyYW1lX2RpZyAtMwogICAgdW5jb3ZlciA1CiAgICB1bmNvdmVyIDIKICAgIHN1YnN0cmluZzMKICAgIGNvbmNhdAogICAgZnJhbWVfZGlnIC0yCiAgICBjb25jYXQKICAgIHN3YXAKICAgIGludCAwCiAgICBjYWxsc3ViIHJlY2FsY3VsYXRlX2hlYWRfZm9yX2VsZW1lbnRzX3dpdGhfYnl0ZV9sZW5ndGhfaGVhZAogICAgY29uY2F0CiAgICByZXRzdWIKCgovLyBfcHV5YV9saWIuYXJjNC5yZWNhbGN1bGF0ZV9oZWFkX2Zvcl9lbGVtZW50c193aXRoX2J5dGVfbGVuZ3RoX2hlYWQoYXJyYXlfaGVhZF9hbmRfdGFpbDogYnl0ZXMsIGxlbmd0aDogdWludDY0LCBzdGFydF9hdF9pbmRleDogdWludDY0KSAtPiBieXRlczoKcmVjYWxjdWxhdGVfaGVhZF9mb3JfZWxlbWVudHNfd2l0aF9ieXRlX2xlbmd0aF9oZWFkOgogICAgcHJvdG8gMyAxCiAgICBmcmFtZV9kaWcgLTIKICAgIGludCAyCiAgICAqCiAgICBkdXAKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDIKICAgICoKICAgIGR1cAogICAgY292ZXIgMgogICAgZnJhbWVfZGlnIC0zCiAgICBzd2FwCiAgICBleHRyYWN0X3VpbnQxNgogICAgZnJhbWVfZGlnIC0xCiAgICBzZWxlY3QKCnJlY2FsY3VsYXRlX2hlYWRfZm9yX2VsZW1lbnRzX3dpdGhfYnl0ZV9sZW5ndGhfaGVhZF9mb3JfaGVhZGVyQDE6CiAgICBmcmFtZV9kaWcgMQogICAgZnJhbWVfZGlnIDAKICAgIDwKICAgIGJ6IHJlY2FsY3VsYXRlX2hlYWRfZm9yX2VsZW1lbnRzX3dpdGhfYnl0ZV9sZW5ndGhfaGVhZF9hZnRlcl9mb3JANAogICAgZnJhbWVfZGlnIDIKICAgIGR1cAogICAgaXRvYgogICAgZXh0cmFjdCA2IDIKICAgIGZyYW1lX2RpZyAtMwogICAgZnJhbWVfZGlnIDEKICAgIGR1cAogICAgY292ZXIgNAogICAgdW5jb3ZlciAyCiAgICByZXBsYWNlMwogICAgZHVwCiAgICBmcmFtZV9idXJ5IC0zCiAgICBkaWcgMQogICAgZXh0cmFjdF91aW50MTYKICAgIGludCAyCiAgICArCiAgICArCiAgICBmcmFtZV9idXJ5IDIKICAgIGludCAyCiAgICArCiAgICBmcmFtZV9idXJ5IDEKICAgIGIgcmVjYWxjdWxhdGVfaGVhZF9mb3JfZWxlbWVudHNfd2l0aF9ieXRlX2xlbmd0aF9oZWFkX2Zvcl9oZWFkZXJAMQoKcmVjYWxjdWxhdGVfaGVhZF9mb3JfZWxlbWVudHNfd2l0aF9ieXRlX2xlbmd0aF9oZWFkX2FmdGVyX2ZvckA0OgogICAgZnJhbWVfZGlnIC0zCiAgICBmcmFtZV9idXJ5IDAKICAgIHJldHN1Ygo=", - "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5LmNsZWFyX3N0YXRlX3Byb2dyYW06CiAgICBpbnQgMQogICAgcmV0dXJuCg==" - }, - "state": { - "global": { - "num_byte_slices": 0, - "num_uints": 0 - }, - "local": { - "num_byte_slices": 0, - "num_uints": 0 - } - }, - "schema": { - "global": { - "declared": {}, - "reserved": {} - }, - "local": { - "declared": {}, - "reserved": {} - } - }, - "contract": { - "name": "Arc4DynamicArray", - "methods": [ - { - "name": "arc4_dynamic_array", - "args": [ - { - "type": "string", - "name": "name" - } - ], - "returns": { - "type": "string" - }, - "desc": "Dynamic Arrays have variable size and capacity.\nThey are similar to native Python lists because they can also append, extend, and pop." - }, - { - "name": "arc4_dynamic_bytes", - "args": [], - "returns": { - "type": "byte[]" - }, - "desc": "arc4.DynamicBytes are essentially an arc4.DynamicArray[arc4.Bytes] and some convenience methods." - } - ], - "networks": {} - }, - "bare_call_config": { - "no_op": "CREATE" - } -}""" -APP_SPEC = algokit_utils.ApplicationSpecification.from_json(_APP_SPEC_JSON) -_TReturn = typing.TypeVar("_TReturn") - - -class _ArgsBase(ABC, typing.Generic[_TReturn]): - @staticmethod - @abstractmethod - def method() -> str: - ... - - -_TArgs = typing.TypeVar("_TArgs", bound=_ArgsBase[typing.Any]) - - -@dataclasses.dataclass(kw_only=True) -class _TArgsHolder(typing.Generic[_TArgs]): - args: _TArgs - - -def _filter_none(value: dict | typing.Any) -> dict | typing.Any: - if isinstance(value, dict): - return {k: _filter_none(v) for k, v in value.items() if v is not None} - return value - - -def _as_dict(data: typing.Any, *, convert_all: bool = True) -> dict[str, typing.Any]: - if data is None: - return {} - if not dataclasses.is_dataclass(data): - raise TypeError(f"{data} must be a dataclass") - if convert_all: - result = dataclasses.asdict(data) # type: ignore[call-overload] - else: - result = {f.name: getattr(data, f.name) for f in dataclasses.fields(data)} - return _filter_none(result) - - -def _convert_transaction_parameters( - transaction_parameters: algokit_utils.TransactionParameters | None, -) -> algokit_utils.TransactionParametersDict: - return typing.cast(algokit_utils.TransactionParametersDict, _as_dict(transaction_parameters)) - - -def _convert_call_transaction_parameters( - transaction_parameters: algokit_utils.TransactionParameters | None, -) -> algokit_utils.OnCompleteCallParametersDict: - return typing.cast(algokit_utils.OnCompleteCallParametersDict, _as_dict(transaction_parameters)) - - -def _convert_create_transaction_parameters( - transaction_parameters: algokit_utils.TransactionParameters | None, - on_complete: algokit_utils.OnCompleteActionName, -) -> algokit_utils.CreateCallParametersDict: - result = typing.cast(algokit_utils.CreateCallParametersDict, _as_dict(transaction_parameters)) - on_complete_enum = on_complete.replace("_", " ").title().replace(" ", "") + "OC" - result["on_complete"] = getattr(algosdk.transaction.OnComplete, on_complete_enum) - return result - - -def _convert_deploy_args( - deploy_args: algokit_utils.DeployCallArgs | None, -) -> algokit_utils.ABICreateCallArgsDict | None: - if deploy_args is None: - return None - - deploy_args_dict = typing.cast(algokit_utils.ABICreateCallArgsDict, _as_dict(deploy_args)) - if isinstance(deploy_args, _TArgsHolder): - deploy_args_dict["args"] = _as_dict(deploy_args.args) - deploy_args_dict["method"] = deploy_args.args.method() - - return deploy_args_dict - - -@dataclasses.dataclass(kw_only=True) -class Arc4DynamicArrayArgs(_ArgsBase[str]): - """Dynamic Arrays have variable size and capacity. - They are similar to native Python lists because they can also append, extend, and pop.""" - - name: str - - @staticmethod - def method() -> str: - return "arc4_dynamic_array(string)string" - - -@dataclasses.dataclass(kw_only=True) -class Arc4DynamicBytesArgs(_ArgsBase[bytes | bytearray]): - """arc4.DynamicBytes are essentially an arc4.DynamicArray[arc4.Bytes] and some convenience methods.""" - - @staticmethod - def method() -> str: - return "arc4_dynamic_bytes()byte[]" - - -@dataclasses.dataclass(kw_only=True) -class SimulateOptions: - allow_more_logs: bool = dataclasses.field(default=False) - allow_empty_signatures: bool = dataclasses.field(default=False) - extra_opcode_budget: int = dataclasses.field(default=0) - exec_trace_config: models.SimulateTraceConfig | None = dataclasses.field(default=None) - - -class Composer: - - def __init__(self, app_client: algokit_utils.ApplicationClient, atc: AtomicTransactionComposer): - self.app_client = app_client - self.atc = atc - - def build(self) -> AtomicTransactionComposer: - return self.atc - - def simulate(self, options: SimulateOptions | None = None) -> SimulateAtomicTransactionResponse: - request = models.SimulateRequest( - allow_more_logs=options.allow_more_logs, - allow_empty_signatures=options.allow_empty_signatures, - extra_opcode_budget=options.extra_opcode_budget, - exec_trace_config=options.exec_trace_config, - txn_groups=[] - ) if options else None - result = self.atc.simulate(self.app_client.algod_client, request) - return result - - def execute(self) -> AtomicTransactionResponse: - return self.app_client.execute_atc(self.atc) - - def arc4_dynamic_array( - self, - *, - name: str, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> "Composer": - """Dynamic Arrays have variable size and capacity. - They are similar to native Python lists because they can also append, extend, and pop. - - Adds a call to `arc4_dynamic_array(string)string` ABI method - - :param str name: The `name` ABI parameter - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns Composer: This Composer instance""" - - args = Arc4DynamicArrayArgs( - name=name, - ) - self.app_client.compose_call( - self.atc, - call_abi_method=args.method(), - transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), - **_as_dict(args, convert_all=True), - ) - return self - - def arc4_dynamic_bytes( - self, - *, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> "Composer": - """arc4.DynamicBytes are essentially an arc4.DynamicArray[arc4.Bytes] and some convenience methods. - - Adds a call to `arc4_dynamic_bytes()byte[]` ABI method - - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns Composer: This Composer instance""" - - args = Arc4DynamicBytesArgs() - self.app_client.compose_call( - self.atc, - call_abi_method=args.method(), - transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), - **_as_dict(args, convert_all=True), - ) - return self - - def create_bare( - self, - *, - on_complete: typing.Literal["no_op"] = "no_op", - transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, - ) -> "Composer": - """Adds a call to create an application using the no_op bare method - - :param typing.Literal[no_op] on_complete: On completion type to use - :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns Composer: This Composer instance""" - - self.app_client.compose_create( - self.atc, - call_abi_method=False, - transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), - ) - return self - - def clear_state( - self, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - app_args: list[bytes] | None = None, - ) -> "Composer": - """Adds a call to the application with on completion set to ClearState - - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :param list[bytes] | None app_args: (optional) Application args to pass""" - - self.app_client.compose_clear_state(self.atc, _convert_transaction_parameters(transaction_parameters), app_args) - return self - - -class Arc4DynamicArrayClient: - """A class for interacting with the Arc4DynamicArray app providing high productivity and - strongly typed methods to deploy and call the app""" - - @typing.overload - def __init__( - self, - algod_client: algosdk.v2client.algod.AlgodClient, - *, - app_id: int = 0, - signer: TransactionSigner | algokit_utils.Account | None = None, - sender: str | None = None, - suggested_params: algosdk.transaction.SuggestedParams | None = None, - template_values: algokit_utils.TemplateValueMapping | None = None, - app_name: str | None = None, - ) -> None: - ... - - @typing.overload - def __init__( - self, - algod_client: algosdk.v2client.algod.AlgodClient, - *, - creator: str | algokit_utils.Account, - indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, - existing_deployments: algokit_utils.AppLookup | None = None, - signer: TransactionSigner | algokit_utils.Account | None = None, - sender: str | None = None, - suggested_params: algosdk.transaction.SuggestedParams | None = None, - template_values: algokit_utils.TemplateValueMapping | None = None, - app_name: str | None = None, - ) -> None: - ... - - def __init__( - self, - algod_client: algosdk.v2client.algod.AlgodClient, - *, - creator: str | algokit_utils.Account | None = None, - indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, - existing_deployments: algokit_utils.AppLookup | None = None, - app_id: int = 0, - signer: TransactionSigner | algokit_utils.Account | None = None, - sender: str | None = None, - suggested_params: algosdk.transaction.SuggestedParams | None = None, - template_values: algokit_utils.TemplateValueMapping | None = None, - app_name: str | None = None, - ) -> None: - """ - Arc4DynamicArrayClient can be created with an app_id to interact with an existing application, alternatively - it can be created with a creator and indexer_client specified to find existing applications by name and creator. - - :param AlgodClient algod_client: AlgoSDK algod client - :param int app_id: The app_id of an existing application, to instead find the application by creator and name - use the creator and indexer_client parameters - :param str | Account creator: The address or Account of the app creator to resolve the app_id - :param IndexerClient indexer_client: AlgoSDK indexer client, only required if deploying or finding app_id by - creator and app name - :param AppLookup existing_deployments: - :param TransactionSigner | Account signer: Account or signer to use to sign transactions, if not specified and - creator was passed as an Account will use that. - :param str sender: Address to use as the sender for all transactions, will use the address associated with the - signer if not specified. - :param TemplateValueMapping template_values: Values to use for TMPL_* template variables, dictionary keys should - *NOT* include the TMPL_ prefix - :param str | None app_name: Name of application to use when deploying, defaults to name defined on the - Application Specification - """ - - self.app_spec = APP_SPEC - - # calling full __init__ signature, so ignoring mypy warning about overloads - self.app_client = algokit_utils.ApplicationClient( # type: ignore[call-overload, misc] - algod_client=algod_client, - app_spec=self.app_spec, - app_id=app_id, - creator=creator, - indexer_client=indexer_client, - existing_deployments=existing_deployments, - signer=signer, - sender=sender, - suggested_params=suggested_params, - template_values=template_values, - app_name=app_name, - ) - - @property - def algod_client(self) -> algosdk.v2client.algod.AlgodClient: - return self.app_client.algod_client - - @property - def app_id(self) -> int: - return self.app_client.app_id - - @app_id.setter - def app_id(self, value: int) -> None: - self.app_client.app_id = value - - @property - def app_address(self) -> str: - return self.app_client.app_address - - @property - def sender(self) -> str | None: - return self.app_client.sender - - @sender.setter - def sender(self, value: str) -> None: - self.app_client.sender = value - - @property - def signer(self) -> TransactionSigner | None: - return self.app_client.signer - - @signer.setter - def signer(self, value: TransactionSigner) -> None: - self.app_client.signer = value - - @property - def suggested_params(self) -> algosdk.transaction.SuggestedParams | None: - return self.app_client.suggested_params - - @suggested_params.setter - def suggested_params(self, value: algosdk.transaction.SuggestedParams | None) -> None: - self.app_client.suggested_params = value - - def arc4_dynamic_array( - self, - *, - name: str, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> algokit_utils.ABITransactionResponse[str]: - """Dynamic Arrays have variable size and capacity. - They are similar to native Python lists because they can also append, extend, and pop. - - Calls `arc4_dynamic_array(string)string` ABI method - - :param str name: The `name` ABI parameter - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns algokit_utils.ABITransactionResponse[str]: The result of the transaction""" - - args = Arc4DynamicArrayArgs( - name=name, - ) - result = self.app_client.call( - call_abi_method=args.method(), - transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), - **_as_dict(args, convert_all=True), - ) - return result - - def arc4_dynamic_bytes( - self, - *, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> algokit_utils.ABITransactionResponse[bytes | bytearray]: - """arc4.DynamicBytes are essentially an arc4.DynamicArray[arc4.Bytes] and some convenience methods. - - Calls `arc4_dynamic_bytes()byte[]` ABI method - - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns algokit_utils.ABITransactionResponse[bytes | bytearray]: The result of the transaction""" - - args = Arc4DynamicBytesArgs() - result = self.app_client.call( - call_abi_method=args.method(), - transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), - **_as_dict(args, convert_all=True), - ) - return result - - def create_bare( - self, - *, - on_complete: typing.Literal["no_op"] = "no_op", - transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, - ) -> algokit_utils.TransactionResponse: - """Creates an application using the no_op bare method - - :param typing.Literal[no_op] on_complete: On completion type to use - :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns algokit_utils.TransactionResponse: The result of the transaction""" - - result = self.app_client.create( - call_abi_method=False, - transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), - ) - return result - - def clear_state( - self, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - app_args: list[bytes] | None = None, - ) -> algokit_utils.TransactionResponse: - """Calls the application with on completion set to ClearState - - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :param list[bytes] | None app_args: (optional) Application args to pass - :returns algokit_utils.TransactionResponse: The result of the transaction""" - - return self.app_client.clear_state(_convert_transaction_parameters(transaction_parameters), app_args) - - def deploy( - self, - version: str | None = None, - *, - signer: TransactionSigner | None = None, - sender: str | None = None, - allow_update: bool | None = None, - allow_delete: bool | None = None, - on_update: algokit_utils.OnUpdate = algokit_utils.OnUpdate.Fail, - on_schema_break: algokit_utils.OnSchemaBreak = algokit_utils.OnSchemaBreak.Fail, - template_values: algokit_utils.TemplateValueMapping | None = None, - create_args: algokit_utils.DeployCallArgs | None = None, - update_args: algokit_utils.DeployCallArgs | None = None, - delete_args: algokit_utils.DeployCallArgs | None = None, - ) -> algokit_utils.DeployResponse: - """Deploy an application and update client to reference it. - - Idempotently deploy (create, update/delete if changed) an app against the given name via the given creator - account, including deploy-time template placeholder substitutions. - To understand the architecture decisions behind this functionality please see - - - ```{note} - If there is a breaking state schema change to an existing app (and `on_schema_break` is set to - 'ReplaceApp' the existing app will be deleted and re-created. - ``` - - ```{note} - If there is an update (different TEAL code) to an existing app (and `on_update` is set to 'ReplaceApp') - the existing app will be deleted and re-created. - ``` - - :param str version: version to use when creating or updating app, if None version will be auto incremented - :param algosdk.atomic_transaction_composer.TransactionSigner signer: signer to use when deploying app - , if None uses self.signer - :param str sender: sender address to use when deploying app, if None uses self.sender - :param bool allow_delete: Used to set the `TMPL_DELETABLE` template variable to conditionally control if an app - can be deleted - :param bool allow_update: Used to set the `TMPL_UPDATABLE` template variable to conditionally control if an app - can be updated - :param OnUpdate on_update: Determines what action to take if an application update is required - :param OnSchemaBreak on_schema_break: Determines what action to take if an application schema requirements - has increased beyond the current allocation - :param dict[str, int|str|bytes] template_values: Values to use for `TMPL_*` template variables, dictionary keys - should *NOT* include the TMPL_ prefix - :param algokit_utils.DeployCallArgs | None create_args: Arguments used when creating an application - :param algokit_utils.DeployCallArgs | None update_args: Arguments used when updating an application - :param algokit_utils.DeployCallArgs | None delete_args: Arguments used when deleting an application - :return DeployResponse: details action taken and relevant transactions - :raises DeploymentError: If the deployment failed""" - - return self.app_client.deploy( - version, - signer=signer, - sender=sender, - allow_update=allow_update, - allow_delete=allow_delete, - on_update=on_update, - on_schema_break=on_schema_break, - template_values=template_values, - create_args=_convert_deploy_args(create_args), - update_args=_convert_deploy_args(update_args), - delete_args=_convert_deploy_args(delete_args), - ) - - def compose(self, atc: AtomicTransactionComposer | None = None) -> Composer: - return Composer(self.app_client, atc or AtomicTransactionComposer()) diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_static_array_client.py b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_static_array_client.py deleted file mode 100644 index 363c953..0000000 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_static_array_client.py +++ /dev/null @@ -1,484 +0,0 @@ -# flake8: noqa -# fmt: off -# mypy: disable-error-code="no-any-return, no-untyped-call, misc, type-arg" -# This file was automatically generated by algokit-client-generator. -# DO NOT MODIFY IT BY HAND. -# requires: algokit-utils@^1.2.0 -import base64 -import dataclasses -import decimal -import typing -from abc import ABC, abstractmethod - -import algokit_utils -import algosdk -from algosdk.v2client import models -from algosdk.atomic_transaction_composer import ( - AtomicTransactionComposer, - AtomicTransactionResponse, - SimulateAtomicTransactionResponse, - TransactionSigner, - TransactionWithSigner -) - -_APP_SPEC_JSON = r"""{ - "hints": { - "arc4_static_array()void": { - "call_config": { - "no_op": "CALL" - } - } - }, - "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RhdGljQXJyYXkuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRTdGF0aWNBcnJheS5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANQogICAgbWV0aG9kICJhcmM0X3N0YXRpY19hcnJheSgpdm9pZCIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfc3RhdGljX2FycmF5X3JvdXRlQDIKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfc3RhdGljX2FycmF5X3JvdXRlQDI6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICBjYWxsc3ViIGFyYzRfc3RhdGljX2FycmF5CiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANToKICAgIHR4biBPbkNvbXBsZXRpb24KICAgIGJueiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDkKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICAhCiAgICBhc3NlcnQgLy8gaXMgY3JlYXRpbmcKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAOToKICAgIGludCAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RhdGljQXJyYXkuYXJjNF9zdGF0aWNfYXJyYXkoKSAtPiB2b2lkOgphcmM0X3N0YXRpY19hcnJheToKICAgIHByb3RvIDAgMAogICAgaW50IDAKICAgIGR1cAoKYXJjNF9zdGF0aWNfYXJyYXlfZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDEKICAgIGludCA0CiAgICA8CiAgICBieiBhcmM0X3N0YXRpY19hcnJheV9hZnRlcl9mb3JANAogICAgZnJhbWVfZGlnIDEKICAgIGR1cAogICAgaW50IDQKICAgICoKICAgIGJ5dGUgMHgwMDAwMDAwMTAwMDAwMDBhMDAwMDAwZmYwMDAwMDA4MAogICAgc3dhcAogICAgaW50IDQKICAgIGV4dHJhY3QzIC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgYnRvaQogICAgZnJhbWVfZGlnIDAKICAgICsKICAgIGZyYW1lX2J1cnkgMAogICAgaW50IDEKICAgICsKICAgIGZyYW1lX2J1cnkgMQogICAgYiBhcmM0X3N0YXRpY19hcnJheV9mb3JfaGVhZGVyQDEKCmFyYzRfc3RhdGljX2FycmF5X2FmdGVyX2ZvckA0OgogICAgZnJhbWVfZGlnIDAKICAgIGludCAzOTQKICAgID09CiAgICBhc3NlcnQKICAgIGJ5dGUgMHg2NQogICAgYnl0ZSAweGNhCiAgICByZXBsYWNlMiAwCiAgICBleHRyYWN0IDAgMSAvLyBvbiBlcnJvcjogSW5kZXggYWNjZXNzIGlzIG91dCBvZiBib3VuZHMKICAgIGJ0b2kKICAgIGludCAyMDIKICAgID09CiAgICBhc3NlcnQKICAgIHJldHN1Ygo=", - "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RhdGljQXJyYXkuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" - }, - "state": { - "global": { - "num_byte_slices": 0, - "num_uints": 0 - }, - "local": { - "num_byte_slices": 0, - "num_uints": 0 - } - }, - "schema": { - "global": { - "declared": {}, - "reserved": {} - }, - "local": { - "declared": {}, - "reserved": {} - } - }, - "contract": { - "name": "Arc4StaticArray", - "methods": [ - { - "name": "arc4_static_array", - "args": [], - "returns": { - "type": "void" - }, - "desc": "You can create a static array directly from the contract." - } - ], - "networks": {} - }, - "bare_call_config": { - "no_op": "CREATE" - } -}""" -APP_SPEC = algokit_utils.ApplicationSpecification.from_json(_APP_SPEC_JSON) -_TReturn = typing.TypeVar("_TReturn") - - -class _ArgsBase(ABC, typing.Generic[_TReturn]): - @staticmethod - @abstractmethod - def method() -> str: - ... - - -_TArgs = typing.TypeVar("_TArgs", bound=_ArgsBase[typing.Any]) - - -@dataclasses.dataclass(kw_only=True) -class _TArgsHolder(typing.Generic[_TArgs]): - args: _TArgs - - -def _filter_none(value: dict | typing.Any) -> dict | typing.Any: - if isinstance(value, dict): - return {k: _filter_none(v) for k, v in value.items() if v is not None} - return value - - -def _as_dict(data: typing.Any, *, convert_all: bool = True) -> dict[str, typing.Any]: - if data is None: - return {} - if not dataclasses.is_dataclass(data): - raise TypeError(f"{data} must be a dataclass") - if convert_all: - result = dataclasses.asdict(data) # type: ignore[call-overload] - else: - result = {f.name: getattr(data, f.name) for f in dataclasses.fields(data)} - return _filter_none(result) - - -def _convert_transaction_parameters( - transaction_parameters: algokit_utils.TransactionParameters | None, -) -> algokit_utils.TransactionParametersDict: - return typing.cast(algokit_utils.TransactionParametersDict, _as_dict(transaction_parameters)) - - -def _convert_call_transaction_parameters( - transaction_parameters: algokit_utils.TransactionParameters | None, -) -> algokit_utils.OnCompleteCallParametersDict: - return typing.cast(algokit_utils.OnCompleteCallParametersDict, _as_dict(transaction_parameters)) - - -def _convert_create_transaction_parameters( - transaction_parameters: algokit_utils.TransactionParameters | None, - on_complete: algokit_utils.OnCompleteActionName, -) -> algokit_utils.CreateCallParametersDict: - result = typing.cast(algokit_utils.CreateCallParametersDict, _as_dict(transaction_parameters)) - on_complete_enum = on_complete.replace("_", " ").title().replace(" ", "") + "OC" - result["on_complete"] = getattr(algosdk.transaction.OnComplete, on_complete_enum) - return result - - -def _convert_deploy_args( - deploy_args: algokit_utils.DeployCallArgs | None, -) -> algokit_utils.ABICreateCallArgsDict | None: - if deploy_args is None: - return None - - deploy_args_dict = typing.cast(algokit_utils.ABICreateCallArgsDict, _as_dict(deploy_args)) - if isinstance(deploy_args, _TArgsHolder): - deploy_args_dict["args"] = _as_dict(deploy_args.args) - deploy_args_dict["method"] = deploy_args.args.method() - - return deploy_args_dict - - -@dataclasses.dataclass(kw_only=True) -class Arc4StaticArrayArgs(_ArgsBase[None]): - """You can create a static array directly from the contract.""" - - @staticmethod - def method() -> str: - return "arc4_static_array()void" - - -@dataclasses.dataclass(kw_only=True) -class SimulateOptions: - allow_more_logs: bool = dataclasses.field(default=False) - allow_empty_signatures: bool = dataclasses.field(default=False) - extra_opcode_budget: int = dataclasses.field(default=0) - exec_trace_config: models.SimulateTraceConfig | None = dataclasses.field(default=None) - - -class Composer: - - def __init__(self, app_client: algokit_utils.ApplicationClient, atc: AtomicTransactionComposer): - self.app_client = app_client - self.atc = atc - - def build(self) -> AtomicTransactionComposer: - return self.atc - - def simulate(self, options: SimulateOptions | None = None) -> SimulateAtomicTransactionResponse: - request = models.SimulateRequest( - allow_more_logs=options.allow_more_logs, - allow_empty_signatures=options.allow_empty_signatures, - extra_opcode_budget=options.extra_opcode_budget, - exec_trace_config=options.exec_trace_config, - txn_groups=[] - ) if options else None - result = self.atc.simulate(self.app_client.algod_client, request) - return result - - def execute(self) -> AtomicTransactionResponse: - return self.app_client.execute_atc(self.atc) - - def arc4_static_array( - self, - *, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> "Composer": - """You can create a static array directly from the contract. - - Adds a call to `arc4_static_array()void` ABI method - - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns Composer: This Composer instance""" - - args = Arc4StaticArrayArgs() - self.app_client.compose_call( - self.atc, - call_abi_method=args.method(), - transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), - **_as_dict(args, convert_all=True), - ) - return self - - def create_bare( - self, - *, - on_complete: typing.Literal["no_op"] = "no_op", - transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, - ) -> "Composer": - """Adds a call to create an application using the no_op bare method - - :param typing.Literal[no_op] on_complete: On completion type to use - :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns Composer: This Composer instance""" - - self.app_client.compose_create( - self.atc, - call_abi_method=False, - transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), - ) - return self - - def clear_state( - self, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - app_args: list[bytes] | None = None, - ) -> "Composer": - """Adds a call to the application with on completion set to ClearState - - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :param list[bytes] | None app_args: (optional) Application args to pass""" - - self.app_client.compose_clear_state(self.atc, _convert_transaction_parameters(transaction_parameters), app_args) - return self - - -class Arc4StaticArrayClient: - """A class for interacting with the Arc4StaticArray app providing high productivity and - strongly typed methods to deploy and call the app""" - - @typing.overload - def __init__( - self, - algod_client: algosdk.v2client.algod.AlgodClient, - *, - app_id: int = 0, - signer: TransactionSigner | algokit_utils.Account | None = None, - sender: str | None = None, - suggested_params: algosdk.transaction.SuggestedParams | None = None, - template_values: algokit_utils.TemplateValueMapping | None = None, - app_name: str | None = None, - ) -> None: - ... - - @typing.overload - def __init__( - self, - algod_client: algosdk.v2client.algod.AlgodClient, - *, - creator: str | algokit_utils.Account, - indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, - existing_deployments: algokit_utils.AppLookup | None = None, - signer: TransactionSigner | algokit_utils.Account | None = None, - sender: str | None = None, - suggested_params: algosdk.transaction.SuggestedParams | None = None, - template_values: algokit_utils.TemplateValueMapping | None = None, - app_name: str | None = None, - ) -> None: - ... - - def __init__( - self, - algod_client: algosdk.v2client.algod.AlgodClient, - *, - creator: str | algokit_utils.Account | None = None, - indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, - existing_deployments: algokit_utils.AppLookup | None = None, - app_id: int = 0, - signer: TransactionSigner | algokit_utils.Account | None = None, - sender: str | None = None, - suggested_params: algosdk.transaction.SuggestedParams | None = None, - template_values: algokit_utils.TemplateValueMapping | None = None, - app_name: str | None = None, - ) -> None: - """ - Arc4StaticArrayClient can be created with an app_id to interact with an existing application, alternatively - it can be created with a creator and indexer_client specified to find existing applications by name and creator. - - :param AlgodClient algod_client: AlgoSDK algod client - :param int app_id: The app_id of an existing application, to instead find the application by creator and name - use the creator and indexer_client parameters - :param str | Account creator: The address or Account of the app creator to resolve the app_id - :param IndexerClient indexer_client: AlgoSDK indexer client, only required if deploying or finding app_id by - creator and app name - :param AppLookup existing_deployments: - :param TransactionSigner | Account signer: Account or signer to use to sign transactions, if not specified and - creator was passed as an Account will use that. - :param str sender: Address to use as the sender for all transactions, will use the address associated with the - signer if not specified. - :param TemplateValueMapping template_values: Values to use for TMPL_* template variables, dictionary keys should - *NOT* include the TMPL_ prefix - :param str | None app_name: Name of application to use when deploying, defaults to name defined on the - Application Specification - """ - - self.app_spec = APP_SPEC - - # calling full __init__ signature, so ignoring mypy warning about overloads - self.app_client = algokit_utils.ApplicationClient( # type: ignore[call-overload, misc] - algod_client=algod_client, - app_spec=self.app_spec, - app_id=app_id, - creator=creator, - indexer_client=indexer_client, - existing_deployments=existing_deployments, - signer=signer, - sender=sender, - suggested_params=suggested_params, - template_values=template_values, - app_name=app_name, - ) - - @property - def algod_client(self) -> algosdk.v2client.algod.AlgodClient: - return self.app_client.algod_client - - @property - def app_id(self) -> int: - return self.app_client.app_id - - @app_id.setter - def app_id(self, value: int) -> None: - self.app_client.app_id = value - - @property - def app_address(self) -> str: - return self.app_client.app_address - - @property - def sender(self) -> str | None: - return self.app_client.sender - - @sender.setter - def sender(self, value: str) -> None: - self.app_client.sender = value - - @property - def signer(self) -> TransactionSigner | None: - return self.app_client.signer - - @signer.setter - def signer(self, value: TransactionSigner) -> None: - self.app_client.signer = value - - @property - def suggested_params(self) -> algosdk.transaction.SuggestedParams | None: - return self.app_client.suggested_params - - @suggested_params.setter - def suggested_params(self, value: algosdk.transaction.SuggestedParams | None) -> None: - self.app_client.suggested_params = value - - def arc4_static_array( - self, - *, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> algokit_utils.ABITransactionResponse[None]: - """You can create a static array directly from the contract. - - Calls `arc4_static_array()void` ABI method - - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns algokit_utils.ABITransactionResponse[None]: The result of the transaction""" - - args = Arc4StaticArrayArgs() - result = self.app_client.call( - call_abi_method=args.method(), - transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), - **_as_dict(args, convert_all=True), - ) - return result - - def create_bare( - self, - *, - on_complete: typing.Literal["no_op"] = "no_op", - transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, - ) -> algokit_utils.TransactionResponse: - """Creates an application using the no_op bare method - - :param typing.Literal[no_op] on_complete: On completion type to use - :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns algokit_utils.TransactionResponse: The result of the transaction""" - - result = self.app_client.create( - call_abi_method=False, - transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), - ) - return result - - def clear_state( - self, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - app_args: list[bytes] | None = None, - ) -> algokit_utils.TransactionResponse: - """Calls the application with on completion set to ClearState - - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :param list[bytes] | None app_args: (optional) Application args to pass - :returns algokit_utils.TransactionResponse: The result of the transaction""" - - return self.app_client.clear_state(_convert_transaction_parameters(transaction_parameters), app_args) - - def deploy( - self, - version: str | None = None, - *, - signer: TransactionSigner | None = None, - sender: str | None = None, - allow_update: bool | None = None, - allow_delete: bool | None = None, - on_update: algokit_utils.OnUpdate = algokit_utils.OnUpdate.Fail, - on_schema_break: algokit_utils.OnSchemaBreak = algokit_utils.OnSchemaBreak.Fail, - template_values: algokit_utils.TemplateValueMapping | None = None, - create_args: algokit_utils.DeployCallArgs | None = None, - update_args: algokit_utils.DeployCallArgs | None = None, - delete_args: algokit_utils.DeployCallArgs | None = None, - ) -> algokit_utils.DeployResponse: - """Deploy an application and update client to reference it. - - Idempotently deploy (create, update/delete if changed) an app against the given name via the given creator - account, including deploy-time template placeholder substitutions. - To understand the architecture decisions behind this functionality please see - - - ```{note} - If there is a breaking state schema change to an existing app (and `on_schema_break` is set to - 'ReplaceApp' the existing app will be deleted and re-created. - ``` - - ```{note} - If there is an update (different TEAL code) to an existing app (and `on_update` is set to 'ReplaceApp') - the existing app will be deleted and re-created. - ``` - - :param str version: version to use when creating or updating app, if None version will be auto incremented - :param algosdk.atomic_transaction_composer.TransactionSigner signer: signer to use when deploying app - , if None uses self.signer - :param str sender: sender address to use when deploying app, if None uses self.sender - :param bool allow_delete: Used to set the `TMPL_DELETABLE` template variable to conditionally control if an app - can be deleted - :param bool allow_update: Used to set the `TMPL_UPDATABLE` template variable to conditionally control if an app - can be updated - :param OnUpdate on_update: Determines what action to take if an application update is required - :param OnSchemaBreak on_schema_break: Determines what action to take if an application schema requirements - has increased beyond the current allocation - :param dict[str, int|str|bytes] template_values: Values to use for `TMPL_*` template variables, dictionary keys - should *NOT* include the TMPL_ prefix - :param algokit_utils.DeployCallArgs | None create_args: Arguments used when creating an application - :param algokit_utils.DeployCallArgs | None update_args: Arguments used when updating an application - :param algokit_utils.DeployCallArgs | None delete_args: Arguments used when deleting an application - :return DeployResponse: details action taken and relevant transactions - :raises DeploymentError: If the deployment failed""" - - return self.app_client.deploy( - version, - signer=signer, - sender=sender, - allow_update=allow_update, - allow_delete=allow_delete, - on_update=on_update, - on_schema_break=on_schema_break, - template_values=template_values, - create_args=_convert_deploy_args(create_args), - update_args=_convert_deploy_args(update_args), - delete_args=_convert_deploy_args(delete_args), - ) - - def compose(self, atc: AtomicTransactionComposer | None = None) -> Composer: - return Composer(self.app_client, atc or AtomicTransactionComposer()) diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_struct_client.py b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_struct_client.py deleted file mode 100644 index 36e879a..0000000 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_struct_client.py +++ /dev/null @@ -1,695 +0,0 @@ -# flake8: noqa -# fmt: off -# mypy: disable-error-code="no-any-return, no-untyped-call, misc, type-arg" -# This file was automatically generated by algokit-client-generator. -# DO NOT MODIFY IT BY HAND. -# requires: algokit-utils@^1.2.0 -import base64 -import dataclasses -import decimal -import typing -from abc import ABC, abstractmethod - -import algokit_utils -import algosdk -from algosdk.v2client import models -from algosdk.atomic_transaction_composer import ( - AtomicTransactionComposer, - AtomicTransactionResponse, - SimulateAtomicTransactionResponse, - TransactionSigner, - TransactionWithSigner -) - -_APP_SPEC_JSON = r"""{ - "hints": { - "add_todo(string)(string,bool)[]": { - "call_config": { - "no_op": "CALL" - } - }, - "complete_todo(string)void": { - "call_config": { - "no_op": "CALL" - } - }, - "return_todo(string)(string,bool)": { - "structs": { - "output": { - "name": "Todo", - "elements": [ - [ - "task", - "string" - ], - [ - "completed", - "bool" - ] - ] - } - }, - "call_config": { - "no_op": "CALL" - } - } - }, - "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RydWN0LmFwcHJvdmFsX3Byb2dyYW06CiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYm56IG1haW5fZW50cnlwb2ludEAyCiAgICBjYWxsc3ViIF9faW5pdF9fCgptYWluX2VudHJ5cG9pbnRAMjoKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRTdHJ1Y3QuX19wdXlhX2FyYzRfcm91dGVyX18oKSAtPiB1aW50NjQ6Cl9fcHV5YV9hcmM0X3JvdXRlcl9fOgogICAgcHJvdG8gMCAxCiAgICB0eG4gTnVtQXBwQXJncwogICAgYnogX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDcKICAgIG1ldGhvZCAiYWRkX3RvZG8oc3RyaW5nKShzdHJpbmcsYm9vbClbXSIKICAgIG1ldGhvZCAiY29tcGxldGVfdG9kbyhzdHJpbmcpdm9pZCIKICAgIG1ldGhvZCAicmV0dXJuX3RvZG8oc3RyaW5nKShzdHJpbmcsYm9vbCkiCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAwCiAgICBtYXRjaCBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZGRfdG9kb19yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2NvbXBsZXRlX3RvZG9fcm91dGVAMyBfX3B1eWFfYXJjNF9yb3V0ZXJfX19yZXR1cm5fdG9kb19yb3V0ZUA0CiAgICBpbnQgMAogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZGRfdG9kb19yb3V0ZUAyOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgY2FsbHN1YiBhZGRfdG9kbwogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fY29tcGxldGVfdG9kb19yb3V0ZUAzOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgY2FsbHN1YiBjb21wbGV0ZV90b2RvCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19yZXR1cm5fdG9kb19yb3V0ZUA0OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgY2FsbHN1YiByZXR1cm5fdG9kbwogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDc6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBibnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMQogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgICEKICAgIGFzc2VydCAvLyBpcyBjcmVhdGluZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMToKICAgIGludCAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RydWN0LmFkZF90b2RvKHRhc2s6IGJ5dGVzKSAtPiBieXRlczoKYWRkX3RvZG86CiAgICBwcm90byAxIDEKICAgIGJ5dGUgMHgwMDAzMDAKICAgIGZyYW1lX2RpZyAtMQogICAgY29uY2F0CiAgICBpbnQgMAogICAgYnl0ZSAidG9kb3MiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIHNlbGYudG9kb3MgZXhpc3RzCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGJueiBhZGRfdG9kb19lbHNlX2JvZHlAMgogICAgYnl0ZSAweDAwMDIKICAgIHN3YXAKICAgIGNvbmNhdAogICAgYnl0ZSAweDAwMDEKICAgIHN3YXAKICAgIGNvbmNhdAogICAgYnl0ZSAidG9kb3MiCiAgICBzd2FwCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgYiBhZGRfdG9kb19hZnRlcl9pZl9lbHNlQDMKCmFkZF90b2RvX2Vsc2VfYm9keUAyOgogICAgaW50IDAKICAgIGJ5dGUgInRvZG9zIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBzZWxmLnRvZG9zIGV4aXN0cwogICAgYnl0ZSAweDAwMDIKICAgIHVuY292ZXIgMgogICAgY29uY2F0CiAgICBzd2FwCiAgICBkdXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgc3dhcAogICAgZXh0cmFjdCAyIDAKICAgIGludCAxCiAgICB1bmNvdmVyIDMKICAgIGNhbGxzdWIgZHluYW1pY19hcnJheV9jb25jYXRfZHluYW1pY19lbGVtZW50CiAgICBieXRlICJ0b2RvcyIKICAgIHN3YXAKICAgIGFwcF9nbG9iYWxfcHV0CgphZGRfdG9kb19hZnRlcl9pZl9lbHNlQDM6CiAgICBpbnQgMAogICAgYnl0ZSAidG9kb3MiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIHNlbGYudG9kb3MgZXhpc3RzCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RydWN0LmNvbXBsZXRlX3RvZG8odGFzazogYnl0ZXMpIC0+IHZvaWQ6CmNvbXBsZXRlX3RvZG86CiAgICBwcm90byAxIDAKICAgIGJ5dGUgIiIKICAgIGR1cAogICAgaW50IDAKICAgIGJ5dGUgInRvZG9zIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBzZWxmLnRvZG9zIGV4aXN0cwogICAgaW50IDAKICAgIGV4dHJhY3RfdWludDE2CiAgICBpbnQgMAoKY29tcGxldGVfdG9kb19mb3JfaGVhZGVyQDE6CiAgICBmcmFtZV9kaWcgMwogICAgZnJhbWVfZGlnIDIKICAgIDwKICAgIGJ6IGNvbXBsZXRlX3RvZG9fYWZ0ZXJfZm9yQDYKICAgIGludCAwCiAgICBieXRlICJ0b2RvcyIKICAgIGFwcF9nbG9iYWxfZ2V0X2V4CiAgICBhc3NlcnQgLy8gY2hlY2sgc2VsZi50b2RvcyBleGlzdHMKICAgIGR1cAogICAgZXh0cmFjdCAyIDAKICAgIGZyYW1lX2RpZyAzCiAgICBkdXAKICAgIGNvdmVyIDMKICAgIGludCAyCiAgICAqCiAgICBkdXAKICAgIGZyYW1lX2J1cnkgMAogICAgZGlnIDEKICAgIHN3YXAKICAgIGV4dHJhY3RfdWludDE2CiAgICBjb3ZlciAzCiAgICBzd2FwCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIHVuY292ZXIgMgogICAgaW50IDEKICAgICsKICAgIGR1cAogICAgY292ZXIgNAogICAgZHVwCiAgICBjb3ZlciAyCiAgICAtIC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgc3dhcAogICAgZGlnIDIKICAgIGxlbgogICAgY292ZXIgMgogICAgaW50IDIKICAgICoKICAgIGR1cAogICAgZnJhbWVfYnVyeSAxCiAgICBkaWcgMwogICAgc3dhcAogICAgZXh0cmFjdF91aW50MTYKICAgIHN3YXAKICAgIHNlbGVjdAogICAgc3dhcAogICAgY292ZXIgMgogICAgc3Vic3RyaW5nMwogICAgZHVwCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIHN3YXAKICAgIGR1cAogICAgbGVuCiAgICBzd2FwCiAgICBjb3ZlciAyCiAgICBzdWJzdHJpbmczCiAgICBmcmFtZV9kaWcgLTEKICAgID09CiAgICBieiBjb21wbGV0ZV90b2RvX2FmdGVyX2lmX2Vsc2VANAogICAgaW50IDAKICAgIGJ5dGUgInRvZG9zIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBzZWxmLnRvZG9zIGV4aXN0cwogICAgZHVwCiAgICBleHRyYWN0IDIgMAogICAgZHVwCiAgICBmcmFtZV9kaWcgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGNvdmVyIDIKICAgIHN3YXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgdW5jb3ZlciAzCiAgICAtIC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgZGlnIDEKICAgIGxlbgogICAgc3dhcAogICAgZGlnIDIKICAgIGZyYW1lX2RpZyAxCiAgICBleHRyYWN0X3VpbnQxNgogICAgc3dhcAogICAgc2VsZWN0CiAgICBzd2FwCiAgICBjb3ZlciAyCiAgICBzdWJzdHJpbmczCiAgICBpbnQgMTYKICAgIGludCAxCiAgICBzZXRiaXQKICAgIGludCAwCiAgICBieXRlICJ0b2RvcyIKICAgIGFwcF9nbG9iYWxfZ2V0X2V4CiAgICBhc3NlcnQgLy8gY2hlY2sgc2VsZi50b2RvcyBleGlzdHMKICAgIHN3YXAKICAgIGZyYW1lX2RpZyAzCiAgICBjYWxsc3ViIGR5bmFtaWNfYXJyYXlfcmVwbGFjZV9keW5hbWljX2VsZW1lbnQKICAgIGJ5dGUgInRvZG9zIgogICAgc3dhcAogICAgYXBwX2dsb2JhbF9wdXQKICAgIGIgY29tcGxldGVfdG9kb19hZnRlcl9mb3JANgoKY29tcGxldGVfdG9kb19hZnRlcl9pZl9lbHNlQDQ6CiAgICBmcmFtZV9idXJ5IDMKICAgIGIgY29tcGxldGVfdG9kb19mb3JfaGVhZGVyQDEKCmNvbXBsZXRlX3RvZG9fYWZ0ZXJfZm9yQDY6CiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RydWN0LnJldHVybl90b2RvKHRhc2s6IGJ5dGVzKSAtPiBieXRlczoKcmV0dXJuX3RvZG86CiAgICBwcm90byAxIDEKICAgIGludCAwCiAgICBieXRlICIiCiAgICBkdXAKICAgIGludCAwCiAgICBkdXAKICAgIGJ5dGUgInRvZG9zIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBzZWxmLnRvZG9zIGV4aXN0cwogICAgaW50IDAKICAgIGV4dHJhY3RfdWludDE2CiAgICBpbnQgMAoKcmV0dXJuX3RvZG9fZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDUKICAgIGZyYW1lX2RpZyA0CiAgICA8CiAgICBieiByZXR1cm5fdG9kb19hZnRlcl9mb3JANgogICAgaW50IDAKICAgIGJ5dGUgInRvZG9zIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBzZWxmLnRvZG9zIGV4aXN0cwogICAgZHVwCiAgICBleHRyYWN0IDIgMAogICAgZnJhbWVfZGlnIDUKICAgIGR1cAogICAgY292ZXIgMwogICAgaW50IDIKICAgICoKICAgIGR1cAogICAgZnJhbWVfYnVyeSAxCiAgICBkaWcgMQogICAgc3dhcAogICAgZXh0cmFjdF91aW50MTYKICAgIGNvdmVyIDMKICAgIHN3YXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgdW5jb3ZlciAyCiAgICBpbnQgMQogICAgKwogICAgZHVwCiAgICBmcmFtZV9idXJ5IDUKICAgIGR1cAogICAgY292ZXIgMgogICAgLSAvLyBvbiBlcnJvcjogSW5kZXggYWNjZXNzIGlzIG91dCBvZiBib3VuZHMKICAgIHN3YXAKICAgIGRpZyAyCiAgICBsZW4KICAgIGNvdmVyIDIKICAgIGludCAyCiAgICAqCiAgICBkdXAKICAgIGZyYW1lX2J1cnkgMgogICAgZGlnIDMKICAgIHN3YXAKICAgIGV4dHJhY3RfdWludDE2CiAgICBzd2FwCiAgICBzZWxlY3QKICAgIHN3YXAKICAgIGNvdmVyIDIKICAgIHN1YnN0cmluZzMKICAgIGR1cAogICAgaW50IDAKICAgIGV4dHJhY3RfdWludDE2CiAgICBzd2FwCiAgICBkdXAKICAgIGxlbgogICAgc3dhcAogICAgY292ZXIgMgogICAgc3Vic3RyaW5nMwogICAgZnJhbWVfZGlnIC0xCiAgICA9PQogICAgYnogcmV0dXJuX3RvZG9fZm9yX2hlYWRlckAxCiAgICBpbnQgMAogICAgYnl0ZSAidG9kb3MiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIHNlbGYudG9kb3MgZXhpc3RzCiAgICBkdXAKICAgIGV4dHJhY3QgMiAwCiAgICBkdXAKICAgIGZyYW1lX2RpZyAxCiAgICBleHRyYWN0X3VpbnQxNgogICAgY292ZXIgMgogICAgc3dhcAogICAgaW50IDAKICAgIGV4dHJhY3RfdWludDE2CiAgICBmcmFtZV9kaWcgNQogICAgLSAvLyBvbiBlcnJvcjogSW5kZXggYWNjZXNzIGlzIG91dCBvZiBib3VuZHMKICAgIGRpZyAxCiAgICBsZW4KICAgIHN3YXAKICAgIGRpZyAyCiAgICBmcmFtZV9kaWcgMgogICAgZXh0cmFjdF91aW50MTYKICAgIHN3YXAKICAgIHNlbGVjdAogICAgc3dhcAogICAgY292ZXIgMgogICAgc3Vic3RyaW5nMwogICAgZnJhbWVfYnVyeSAwCiAgICBpbnQgMQogICAgZnJhbWVfYnVyeSAzCiAgICBiIHJldHVybl90b2RvX2Zvcl9oZWFkZXJAMQoKcmV0dXJuX3RvZG9fYWZ0ZXJfZm9yQDY6CiAgICBmcmFtZV9kaWcgMwogICAgYXNzZXJ0CiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RydWN0Ll9faW5pdF9fKCkgLT4gdm9pZDoKX19pbml0X186CiAgICBwcm90byAwIDAKICAgIGJ5dGUgInRvZG9zIgogICAgYnl0ZSAweDAwMDAKICAgIGFwcF9nbG9iYWxfcHV0CiAgICByZXRzdWIKCgovLyBfcHV5YV9saWIuYXJjNC5keW5hbWljX2FycmF5X2NvbmNhdF9keW5hbWljX2VsZW1lbnQoYXJyYXlfaXRlbXNfY291bnQ6IHVpbnQ2NCwgYXJyYXlfaGVhZF9hbmRfdGFpbDogYnl0ZXMsIG5ld19pdGVtc19jb3VudDogdWludDY0LCBuZXdfaGVhZF9hbmRfdGFpbDogYnl0ZXMpIC0+IGJ5dGVzOgpkeW5hbWljX2FycmF5X2NvbmNhdF9keW5hbWljX2VsZW1lbnQ6CiAgICBwcm90byA0IDEKICAgIGJ5dGUgIiIKICAgIGJ5dGUgMHgKICAgIGZyYW1lX2RpZyAtMgogICAgaW50IDIKICAgICoKICAgIGZyYW1lX2RpZyAtNAogICAgaW50IDIKICAgICoKICAgIGludCAwCgpkeW5hbWljX2FycmF5X2NvbmNhdF9keW5hbWljX2VsZW1lbnRfZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDQKICAgIGZyYW1lX2RpZyAzCiAgICA8CiAgICBieiBkeW5hbWljX2FycmF5X2NvbmNhdF9keW5hbWljX2VsZW1lbnRfYWZ0ZXJfZm9yQDQKICAgIGZyYW1lX2RpZyAtMwogICAgZnJhbWVfZGlnIDQKICAgIGR1cAogICAgY292ZXIgMgogICAgZXh0cmFjdF91aW50MTYKICAgIGZyYW1lX2RpZyAyCiAgICArCiAgICBpdG9iCiAgICBleHRyYWN0IDYgMgogICAgZnJhbWVfZGlnIDEKICAgIHN3YXAKICAgIGNvbmNhdAogICAgZnJhbWVfYnVyeSAxCiAgICBpbnQgMgogICAgKwogICAgZnJhbWVfYnVyeSA0CiAgICBiIGR5bmFtaWNfYXJyYXlfY29uY2F0X2R5bmFtaWNfZWxlbWVudF9mb3JfaGVhZGVyQDEKCmR5bmFtaWNfYXJyYXlfY29uY2F0X2R5bmFtaWNfZWxlbWVudF9hZnRlcl9mb3JANDoKICAgIGZyYW1lX2RpZyAtMwogICAgbGVuCiAgICBmcmFtZV9idXJ5IDAKICAgIGludCAwCiAgICBmcmFtZV9idXJ5IDQKCmR5bmFtaWNfYXJyYXlfY29uY2F0X2R5bmFtaWNfZWxlbWVudF9mb3JfaGVhZGVyQDU6CiAgICBmcmFtZV9kaWcgNAogICAgZnJhbWVfZGlnIDIKICAgIDwKICAgIGJ6IGR5bmFtaWNfYXJyYXlfY29uY2F0X2R5bmFtaWNfZWxlbWVudF9hZnRlcl9mb3JAOAogICAgZnJhbWVfZGlnIC0xCiAgICBmcmFtZV9kaWcgNAogICAgZHVwCiAgICBjb3ZlciAyCiAgICBleHRyYWN0X3VpbnQxNgogICAgZnJhbWVfZGlnIDAKICAgICsKICAgIGl0b2IKICAgIGV4dHJhY3QgNiAyCiAgICBmcmFtZV9kaWcgMQogICAgc3dhcAogICAgY29uY2F0CiAgICBmcmFtZV9idXJ5IDEKICAgIGludCAyCiAgICArCiAgICBmcmFtZV9idXJ5IDQKICAgIGIgZHluYW1pY19hcnJheV9jb25jYXRfZHluYW1pY19lbGVtZW50X2Zvcl9oZWFkZXJANQoKZHluYW1pY19hcnJheV9jb25jYXRfZHluYW1pY19lbGVtZW50X2FmdGVyX2ZvckA4OgogICAgZnJhbWVfZGlnIC00CiAgICBmcmFtZV9kaWcgLTIKICAgICsKICAgIGl0b2IKICAgIGV4dHJhY3QgNiAyCiAgICBmcmFtZV9kaWcgMQogICAgY29uY2F0CiAgICBmcmFtZV9kaWcgLTMKICAgIGZyYW1lX2RpZyAzCiAgICBmcmFtZV9kaWcgMAogICAgc3Vic3RyaW5nMwogICAgY29uY2F0CiAgICBmcmFtZV9kaWcgLTEKICAgIGxlbgogICAgZnJhbWVfZGlnIC0xCiAgICBmcmFtZV9kaWcgMgogICAgdW5jb3ZlciAyCiAgICBzdWJzdHJpbmczCiAgICBjb25jYXQKICAgIGZyYW1lX2J1cnkgMAogICAgcmV0c3ViCgoKLy8gX3B1eWFfbGliLmFyYzQuZHluYW1pY19hcnJheV9yZXBsYWNlX2R5bmFtaWNfZWxlbWVudChzb3VyY2U6IGJ5dGVzLCBuZXdfaXRlbTogYnl0ZXMsIGluZGV4OiB1aW50NjQpIC0+IGJ5dGVzOgpkeW5hbWljX2FycmF5X3JlcGxhY2VfZHluYW1pY19lbGVtZW50OgogICAgcHJvdG8gMyAxCiAgICBmcmFtZV9kaWcgLTMKICAgIHN1YnN0cmluZyAwIDIKICAgIGR1cAogICAgYnRvaQogICAgZnJhbWVfZGlnIC0zCiAgICBleHRyYWN0IDIgMAogICAgZnJhbWVfZGlnIC0yCiAgICBmcmFtZV9kaWcgLTEKICAgIHVuY292ZXIgMwogICAgY2FsbHN1YiBzdGF0aWNfYXJyYXlfcmVwbGFjZV9keW5hbWljX2VsZW1lbnQKICAgIGNvbmNhdAogICAgcmV0c3ViCgoKLy8gX3B1eWFfbGliLmFyYzQuc3RhdGljX2FycmF5X3JlcGxhY2VfZHluYW1pY19lbGVtZW50KGFycmF5X2hlYWRfYW5kX3RhaWw6IGJ5dGVzLCBuZXdfaXRlbTogYnl0ZXMsIGluZGV4OiB1aW50NjQsIGFycmF5X2xlbmd0aDogdWludDY0KSAtPiBieXRlczoKc3RhdGljX2FycmF5X3JlcGxhY2VfZHluYW1pY19lbGVtZW50OgogICAgcHJvdG8gNCAxCiAgICBmcmFtZV9kaWcgLTIKICAgIGludCAyCiAgICAqCiAgICBmcmFtZV9kaWcgLTQKICAgIHN3YXAKICAgIGV4dHJhY3RfdWludDE2CiAgICBmcmFtZV9kaWcgLTIKICAgIGludCAxCiAgICArCiAgICBpbnQgMgogICAgKgogICAgZHVwCiAgICBjb3ZlciAyCiAgICBmcmFtZV9kaWcgLTQKICAgIHN3YXAKICAgIGV4dHJhY3RfdWludDE2CiAgICBmcmFtZV9kaWcgLTQKICAgIGxlbgogICAgZnJhbWVfZGlnIC0xCiAgICBmcmFtZV9kaWcgLTIKICAgIC0KICAgIGludCAxCiAgICAtCiAgICBkaWcgMQogICAgdW5jb3ZlciAzCiAgICB1bmNvdmVyIDIKICAgIHNlbGVjdAogICAgZHVwCiAgICBkaWcgMwogICAgLQogICAgY292ZXIgMwogICAgZnJhbWVfZGlnIC0zCiAgICBsZW4KICAgIGNvdmVyIDMKICAgIGZyYW1lX2RpZyAtNAogICAgaW50IDAKICAgIHVuY292ZXIgNAogICAgc3Vic3RyaW5nMwogICAgZnJhbWVfZGlnIC0zCiAgICBjb25jYXQKICAgIGZyYW1lX2RpZyAtNAogICAgdW5jb3ZlciAyCiAgICB1bmNvdmVyIDMKICAgIHN1YnN0cmluZzMKICAgIGNvbmNhdAogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMgogICAgKgoKc3RhdGljX2FycmF5X3JlcGxhY2VfZHluYW1pY19lbGVtZW50X2Zvcl9oZWFkZXJAMToKICAgIGZyYW1lX2RpZyAwCiAgICBmcmFtZV9kaWcgNAogICAgPAogICAgYnogc3RhdGljX2FycmF5X3JlcGxhY2VfZHluYW1pY19lbGVtZW50X2FmdGVyX2ZvckA0CiAgICBmcmFtZV9kaWcgMwogICAgZHVwCiAgICBmcmFtZV9kaWcgMAogICAgZHVwCiAgICBjb3ZlciAzCiAgICBleHRyYWN0X3VpbnQxNgogICAgZnJhbWVfZGlnIDIKICAgICsKICAgIGZyYW1lX2RpZyAxCiAgICAtCiAgICBpdG9iCiAgICBleHRyYWN0IDYgMgogICAgZGlnIDIKICAgIHN3YXAKICAgIHJlcGxhY2UzCiAgICBmcmFtZV9idXJ5IDMKICAgIGludCAyCiAgICArCiAgICBmcmFtZV9idXJ5IDAKICAgIGIgc3RhdGljX2FycmF5X3JlcGxhY2VfZHluYW1pY19lbGVtZW50X2Zvcl9oZWFkZXJAMQoKc3RhdGljX2FycmF5X3JlcGxhY2VfZHluYW1pY19lbGVtZW50X2FmdGVyX2ZvckA0OgogICAgZnJhbWVfZGlnIDMKICAgIGZyYW1lX2J1cnkgMAogICAgcmV0c3ViCg==", - "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RydWN0LmNsZWFyX3N0YXRlX3Byb2dyYW06CiAgICBpbnQgMQogICAgcmV0dXJuCg==" - }, - "state": { - "global": { - "num_byte_slices": 1, - "num_uints": 0 - }, - "local": { - "num_byte_slices": 0, - "num_uints": 0 - } - }, - "schema": { - "global": { - "declared": { - "todos": { - "type": "bytes", - "key": "todos" - } - }, - "reserved": {} - }, - "local": { - "declared": {}, - "reserved": {} - } - }, - "contract": { - "name": "Arc4Struct", - "methods": [ - { - "name": "add_todo", - "args": [ - { - "type": "string", - "name": "task" - } - ], - "returns": { - "type": "(string,bool)[]" - } - }, - { - "name": "complete_todo", - "args": [ - { - "type": "string", - "name": "task" - } - ], - "returns": { - "type": "void" - } - }, - { - "name": "return_todo", - "args": [ - { - "type": "string", - "name": "task" - } - ], - "returns": { - "type": "(string,bool)" - } - } - ], - "networks": {} - }, - "bare_call_config": { - "no_op": "CREATE" - } -}""" -APP_SPEC = algokit_utils.ApplicationSpecification.from_json(_APP_SPEC_JSON) -_TReturn = typing.TypeVar("_TReturn") - - -class _ArgsBase(ABC, typing.Generic[_TReturn]): - @staticmethod - @abstractmethod - def method() -> str: - ... - - -_TArgs = typing.TypeVar("_TArgs", bound=_ArgsBase[typing.Any]) - - -@dataclasses.dataclass(kw_only=True) -class _TArgsHolder(typing.Generic[_TArgs]): - args: _TArgs - - -def _filter_none(value: dict | typing.Any) -> dict | typing.Any: - if isinstance(value, dict): - return {k: _filter_none(v) for k, v in value.items() if v is not None} - return value - - -def _as_dict(data: typing.Any, *, convert_all: bool = True) -> dict[str, typing.Any]: - if data is None: - return {} - if not dataclasses.is_dataclass(data): - raise TypeError(f"{data} must be a dataclass") - if convert_all: - result = dataclasses.asdict(data) # type: ignore[call-overload] - else: - result = {f.name: getattr(data, f.name) for f in dataclasses.fields(data)} - return _filter_none(result) - - -def _convert_transaction_parameters( - transaction_parameters: algokit_utils.TransactionParameters | None, -) -> algokit_utils.TransactionParametersDict: - return typing.cast(algokit_utils.TransactionParametersDict, _as_dict(transaction_parameters)) - - -def _convert_call_transaction_parameters( - transaction_parameters: algokit_utils.TransactionParameters | None, -) -> algokit_utils.OnCompleteCallParametersDict: - return typing.cast(algokit_utils.OnCompleteCallParametersDict, _as_dict(transaction_parameters)) - - -def _convert_create_transaction_parameters( - transaction_parameters: algokit_utils.TransactionParameters | None, - on_complete: algokit_utils.OnCompleteActionName, -) -> algokit_utils.CreateCallParametersDict: - result = typing.cast(algokit_utils.CreateCallParametersDict, _as_dict(transaction_parameters)) - on_complete_enum = on_complete.replace("_", " ").title().replace(" ", "") + "OC" - result["on_complete"] = getattr(algosdk.transaction.OnComplete, on_complete_enum) - return result - - -def _convert_deploy_args( - deploy_args: algokit_utils.DeployCallArgs | None, -) -> algokit_utils.ABICreateCallArgsDict | None: - if deploy_args is None: - return None - - deploy_args_dict = typing.cast(algokit_utils.ABICreateCallArgsDict, _as_dict(deploy_args)) - if isinstance(deploy_args, _TArgsHolder): - deploy_args_dict["args"] = _as_dict(deploy_args.args) - deploy_args_dict["method"] = deploy_args.args.method() - - return deploy_args_dict - - -@dataclasses.dataclass(kw_only=True) -class AddTodoArgs(_ArgsBase[list[tuple[str, bool]]]): - task: str - - @staticmethod - def method() -> str: - return "add_todo(string)(string,bool)[]" - - -@dataclasses.dataclass(kw_only=True) -class CompleteTodoArgs(_ArgsBase[None]): - task: str - - @staticmethod - def method() -> str: - return "complete_todo(string)void" - - -@dataclasses.dataclass(kw_only=True) -class Todo: - task: str - completed: bool - - -@dataclasses.dataclass(kw_only=True) -class ReturnTodoArgs(_ArgsBase[Todo]): - task: str - - @staticmethod - def method() -> str: - return "return_todo(string)(string,bool)" - - -class ByteReader: - def __init__(self, data: bytes): - self._data = data - - @property - def as_bytes(self) -> bytes: - return self._data - - @property - def as_str(self) -> str: - return self._data.decode("utf8") - - @property - def as_base64(self) -> str: - return base64.b64encode(self._data).decode("utf8") - - @property - def as_hex(self) -> str: - return self._data.hex() - - -class GlobalState: - def __init__(self, data: dict[bytes, bytes | int]): - self.todos = ByteReader(typing.cast(bytes, data.get(b"todos"))) - - -@dataclasses.dataclass(kw_only=True) -class SimulateOptions: - allow_more_logs: bool = dataclasses.field(default=False) - allow_empty_signatures: bool = dataclasses.field(default=False) - extra_opcode_budget: int = dataclasses.field(default=0) - exec_trace_config: models.SimulateTraceConfig | None = dataclasses.field(default=None) - - -class Composer: - - def __init__(self, app_client: algokit_utils.ApplicationClient, atc: AtomicTransactionComposer): - self.app_client = app_client - self.atc = atc - - def build(self) -> AtomicTransactionComposer: - return self.atc - - def simulate(self, options: SimulateOptions | None = None) -> SimulateAtomicTransactionResponse: - request = models.SimulateRequest( - allow_more_logs=options.allow_more_logs, - allow_empty_signatures=options.allow_empty_signatures, - extra_opcode_budget=options.extra_opcode_budget, - exec_trace_config=options.exec_trace_config, - txn_groups=[] - ) if options else None - result = self.atc.simulate(self.app_client.algod_client, request) - return result - - def execute(self) -> AtomicTransactionResponse: - return self.app_client.execute_atc(self.atc) - - def add_todo( - self, - *, - task: str, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> "Composer": - """Adds a call to `add_todo(string)(string,bool)[]` ABI method - - :param str task: The `task` ABI parameter - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns Composer: This Composer instance""" - - args = AddTodoArgs( - task=task, - ) - self.app_client.compose_call( - self.atc, - call_abi_method=args.method(), - transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), - **_as_dict(args, convert_all=True), - ) - return self - - def complete_todo( - self, - *, - task: str, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> "Composer": - """Adds a call to `complete_todo(string)void` ABI method - - :param str task: The `task` ABI parameter - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns Composer: This Composer instance""" - - args = CompleteTodoArgs( - task=task, - ) - self.app_client.compose_call( - self.atc, - call_abi_method=args.method(), - transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), - **_as_dict(args, convert_all=True), - ) - return self - - def return_todo( - self, - *, - task: str, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> "Composer": - """Adds a call to `return_todo(string)(string,bool)` ABI method - - :param str task: The `task` ABI parameter - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns Composer: This Composer instance""" - - args = ReturnTodoArgs( - task=task, - ) - self.app_client.compose_call( - self.atc, - call_abi_method=args.method(), - transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), - **_as_dict(args, convert_all=True), - ) - return self - - def create_bare( - self, - *, - on_complete: typing.Literal["no_op"] = "no_op", - transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, - ) -> "Composer": - """Adds a call to create an application using the no_op bare method - - :param typing.Literal[no_op] on_complete: On completion type to use - :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns Composer: This Composer instance""" - - self.app_client.compose_create( - self.atc, - call_abi_method=False, - transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), - ) - return self - - def clear_state( - self, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - app_args: list[bytes] | None = None, - ) -> "Composer": - """Adds a call to the application with on completion set to ClearState - - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :param list[bytes] | None app_args: (optional) Application args to pass""" - - self.app_client.compose_clear_state(self.atc, _convert_transaction_parameters(transaction_parameters), app_args) - return self - - -class Arc4StructClient: - """A class for interacting with the Arc4Struct app providing high productivity and - strongly typed methods to deploy and call the app""" - - @typing.overload - def __init__( - self, - algod_client: algosdk.v2client.algod.AlgodClient, - *, - app_id: int = 0, - signer: TransactionSigner | algokit_utils.Account | None = None, - sender: str | None = None, - suggested_params: algosdk.transaction.SuggestedParams | None = None, - template_values: algokit_utils.TemplateValueMapping | None = None, - app_name: str | None = None, - ) -> None: - ... - - @typing.overload - def __init__( - self, - algod_client: algosdk.v2client.algod.AlgodClient, - *, - creator: str | algokit_utils.Account, - indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, - existing_deployments: algokit_utils.AppLookup | None = None, - signer: TransactionSigner | algokit_utils.Account | None = None, - sender: str | None = None, - suggested_params: algosdk.transaction.SuggestedParams | None = None, - template_values: algokit_utils.TemplateValueMapping | None = None, - app_name: str | None = None, - ) -> None: - ... - - def __init__( - self, - algod_client: algosdk.v2client.algod.AlgodClient, - *, - creator: str | algokit_utils.Account | None = None, - indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, - existing_deployments: algokit_utils.AppLookup | None = None, - app_id: int = 0, - signer: TransactionSigner | algokit_utils.Account | None = None, - sender: str | None = None, - suggested_params: algosdk.transaction.SuggestedParams | None = None, - template_values: algokit_utils.TemplateValueMapping | None = None, - app_name: str | None = None, - ) -> None: - """ - Arc4StructClient can be created with an app_id to interact with an existing application, alternatively - it can be created with a creator and indexer_client specified to find existing applications by name and creator. - - :param AlgodClient algod_client: AlgoSDK algod client - :param int app_id: The app_id of an existing application, to instead find the application by creator and name - use the creator and indexer_client parameters - :param str | Account creator: The address or Account of the app creator to resolve the app_id - :param IndexerClient indexer_client: AlgoSDK indexer client, only required if deploying or finding app_id by - creator and app name - :param AppLookup existing_deployments: - :param TransactionSigner | Account signer: Account or signer to use to sign transactions, if not specified and - creator was passed as an Account will use that. - :param str sender: Address to use as the sender for all transactions, will use the address associated with the - signer if not specified. - :param TemplateValueMapping template_values: Values to use for TMPL_* template variables, dictionary keys should - *NOT* include the TMPL_ prefix - :param str | None app_name: Name of application to use when deploying, defaults to name defined on the - Application Specification - """ - - self.app_spec = APP_SPEC - - # calling full __init__ signature, so ignoring mypy warning about overloads - self.app_client = algokit_utils.ApplicationClient( # type: ignore[call-overload, misc] - algod_client=algod_client, - app_spec=self.app_spec, - app_id=app_id, - creator=creator, - indexer_client=indexer_client, - existing_deployments=existing_deployments, - signer=signer, - sender=sender, - suggested_params=suggested_params, - template_values=template_values, - app_name=app_name, - ) - - @property - def algod_client(self) -> algosdk.v2client.algod.AlgodClient: - return self.app_client.algod_client - - @property - def app_id(self) -> int: - return self.app_client.app_id - - @app_id.setter - def app_id(self, value: int) -> None: - self.app_client.app_id = value - - @property - def app_address(self) -> str: - return self.app_client.app_address - - @property - def sender(self) -> str | None: - return self.app_client.sender - - @sender.setter - def sender(self, value: str) -> None: - self.app_client.sender = value - - @property - def signer(self) -> TransactionSigner | None: - return self.app_client.signer - - @signer.setter - def signer(self, value: TransactionSigner) -> None: - self.app_client.signer = value - - @property - def suggested_params(self) -> algosdk.transaction.SuggestedParams | None: - return self.app_client.suggested_params - - @suggested_params.setter - def suggested_params(self, value: algosdk.transaction.SuggestedParams | None) -> None: - self.app_client.suggested_params = value - - def get_global_state(self) -> GlobalState: - """Returns the application's global state wrapped in a strongly typed class with options to format the stored value""" - - state = typing.cast(dict[bytes, bytes | int], self.app_client.get_global_state(raw=True)) - return GlobalState(state) - - def add_todo( - self, - *, - task: str, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> algokit_utils.ABITransactionResponse[list[tuple[str, bool]]]: - """Calls `add_todo(string)(string,bool)[]` ABI method - - :param str task: The `task` ABI parameter - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns algokit_utils.ABITransactionResponse[list[tuple[str, bool]]]: The result of the transaction""" - - args = AddTodoArgs( - task=task, - ) - result = self.app_client.call( - call_abi_method=args.method(), - transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), - **_as_dict(args, convert_all=True), - ) - return result - - def complete_todo( - self, - *, - task: str, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> algokit_utils.ABITransactionResponse[None]: - """Calls `complete_todo(string)void` ABI method - - :param str task: The `task` ABI parameter - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns algokit_utils.ABITransactionResponse[None]: The result of the transaction""" - - args = CompleteTodoArgs( - task=task, - ) - result = self.app_client.call( - call_abi_method=args.method(), - transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), - **_as_dict(args, convert_all=True), - ) - return result - - def return_todo( - self, - *, - task: str, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> algokit_utils.ABITransactionResponse[Todo]: - """Calls `return_todo(string)(string,bool)` ABI method - - :param str task: The `task` ABI parameter - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns algokit_utils.ABITransactionResponse[Todo]: The result of the transaction""" - - args = ReturnTodoArgs( - task=task, - ) - result = self.app_client.call( - call_abi_method=args.method(), - transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), - **_as_dict(args, convert_all=True), - ) - elements = self.app_spec.hints[args.method()].structs["output"]["elements"] - result_dict = {element[0]: value for element, value in zip(elements, result.return_value)} - result.return_value = Todo(**result_dict) - return result - - def create_bare( - self, - *, - on_complete: typing.Literal["no_op"] = "no_op", - transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, - ) -> algokit_utils.TransactionResponse: - """Creates an application using the no_op bare method - - :param typing.Literal[no_op] on_complete: On completion type to use - :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns algokit_utils.TransactionResponse: The result of the transaction""" - - result = self.app_client.create( - call_abi_method=False, - transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), - ) - return result - - def clear_state( - self, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - app_args: list[bytes] | None = None, - ) -> algokit_utils.TransactionResponse: - """Calls the application with on completion set to ClearState - - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :param list[bytes] | None app_args: (optional) Application args to pass - :returns algokit_utils.TransactionResponse: The result of the transaction""" - - return self.app_client.clear_state(_convert_transaction_parameters(transaction_parameters), app_args) - - def deploy( - self, - version: str | None = None, - *, - signer: TransactionSigner | None = None, - sender: str | None = None, - allow_update: bool | None = None, - allow_delete: bool | None = None, - on_update: algokit_utils.OnUpdate = algokit_utils.OnUpdate.Fail, - on_schema_break: algokit_utils.OnSchemaBreak = algokit_utils.OnSchemaBreak.Fail, - template_values: algokit_utils.TemplateValueMapping | None = None, - create_args: algokit_utils.DeployCallArgs | None = None, - update_args: algokit_utils.DeployCallArgs | None = None, - delete_args: algokit_utils.DeployCallArgs | None = None, - ) -> algokit_utils.DeployResponse: - """Deploy an application and update client to reference it. - - Idempotently deploy (create, update/delete if changed) an app against the given name via the given creator - account, including deploy-time template placeholder substitutions. - To understand the architecture decisions behind this functionality please see - - - ```{note} - If there is a breaking state schema change to an existing app (and `on_schema_break` is set to - 'ReplaceApp' the existing app will be deleted and re-created. - ``` - - ```{note} - If there is an update (different TEAL code) to an existing app (and `on_update` is set to 'ReplaceApp') - the existing app will be deleted and re-created. - ``` - - :param str version: version to use when creating or updating app, if None version will be auto incremented - :param algosdk.atomic_transaction_composer.TransactionSigner signer: signer to use when deploying app - , if None uses self.signer - :param str sender: sender address to use when deploying app, if None uses self.sender - :param bool allow_delete: Used to set the `TMPL_DELETABLE` template variable to conditionally control if an app - can be deleted - :param bool allow_update: Used to set the `TMPL_UPDATABLE` template variable to conditionally control if an app - can be updated - :param OnUpdate on_update: Determines what action to take if an application update is required - :param OnSchemaBreak on_schema_break: Determines what action to take if an application schema requirements - has increased beyond the current allocation - :param dict[str, int|str|bytes] template_values: Values to use for `TMPL_*` template variables, dictionary keys - should *NOT* include the TMPL_ prefix - :param algokit_utils.DeployCallArgs | None create_args: Arguments used when creating an application - :param algokit_utils.DeployCallArgs | None update_args: Arguments used when updating an application - :param algokit_utils.DeployCallArgs | None delete_args: Arguments used when deleting an application - :return DeployResponse: details action taken and relevant transactions - :raises DeploymentError: If the deployment failed""" - - return self.app_client.deploy( - version, - signer=signer, - sender=sender, - allow_update=allow_update, - allow_delete=allow_delete, - on_update=on_update, - on_schema_break=on_schema_break, - template_values=template_values, - create_args=_convert_deploy_args(create_args), - update_args=_convert_deploy_args(update_args), - delete_args=_convert_deploy_args(delete_args), - ) - - def compose(self, atc: AtomicTransactionComposer | None = None) -> Composer: - return Composer(self.app_client, atc or AtomicTransactionComposer()) diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_tuple_client.py b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_tuple_client.py deleted file mode 100644 index b7555e3..0000000 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_tuple_client.py +++ /dev/null @@ -1,562 +0,0 @@ -# flake8: noqa -# fmt: off -# mypy: disable-error-code="no-any-return, no-untyped-call, misc, type-arg" -# This file was automatically generated by algokit-client-generator. -# DO NOT MODIFY IT BY HAND. -# requires: algokit-utils@^1.2.0 -import base64 -import dataclasses -import decimal -import typing -from abc import ABC, abstractmethod - -import algokit_utils -import algosdk -from algosdk.v2client import models -from algosdk.atomic_transaction_composer import ( - AtomicTransactionComposer, - AtomicTransactionResponse, - SimulateAtomicTransactionResponse, - TransactionSigner, - TransactionWithSigner -) - -_APP_SPEC_JSON = r"""{ - "hints": { - "add_contact_info((string,string,uint64,uint8[]))uint64": { - "call_config": { - "no_op": "CALL" - } - }, - "return_contact()(string,string,uint64)": { - "call_config": { - "no_op": "CALL" - } - } - }, - "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHVwbGUuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUdXBsZS5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANgogICAgbWV0aG9kICJhZGRfY29udGFjdF9pbmZvKChzdHJpbmcsc3RyaW5nLHVpbnQ2NCx1aW50OFtdKSl1aW50NjQiCiAgICBtZXRob2QgInJldHVybl9jb250YWN0KCkoc3RyaW5nLHN0cmluZyx1aW50NjQpIgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAogICAgbWF0Y2ggX19wdXlhX2FyYzRfcm91dGVyX19fYWRkX2NvbnRhY3RfaW5mb19yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX3JldHVybl9jb250YWN0X3JvdXRlQDMKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FkZF9jb250YWN0X2luZm9fcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYWRkX2NvbnRhY3RfaW5mbwogICAgaXRvYgogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fcmV0dXJuX2NvbnRhY3Rfcm91dGVAMzoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIGNhbGxzdWIgcmV0dXJuX2NvbnRhY3QKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgYm56IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTAKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICAhCiAgICBhc3NlcnQgLy8gaXMgY3JlYXRpbmcKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTA6CiAgICBpbnQgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLmFkZF9jb250YWN0X2luZm8oY29udGFjdDogYnl0ZXMpIC0+IHVpbnQ2NDoKYWRkX2NvbnRhY3RfaW5mbzoKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDIKICAgIGV4dHJhY3RfdWludDE2CiAgICBmcmFtZV9kaWcgLTEKICAgIHVuY292ZXIgMgogICAgZGlnIDIKICAgIHN1YnN0cmluZzMKICAgIHN3YXAKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDEyCiAgICBleHRyYWN0X3VpbnQxNgogICAgZnJhbWVfZGlnIC0xCiAgICB1bmNvdmVyIDIKICAgIGRpZyAyCiAgICBzdWJzdHJpbmczCiAgICBjb3ZlciAyCiAgICBmcmFtZV9kaWcgLTEKICAgIGV4dHJhY3QgNCA4IC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgY292ZXIgMwogICAgZnJhbWVfZGlnIC0xCiAgICBsZW4KICAgIGZyYW1lX2RpZyAtMQogICAgY292ZXIgMgogICAgc3Vic3RyaW5nMwogICAgZHVwCiAgICBjb3ZlciA0CiAgICBjb3ZlciA0CiAgICBleHRyYWN0IDIgMAogICAgYnl0ZSAiSm9obiBXb29kcyIKICAgID09CiAgICBhc3NlcnQKICAgIGV4dHJhY3QgMiAwCiAgICBieXRlICJqb2huQHNvbWV0aGluZy5jb20iCiAgICA9PQogICAgYXNzZXJ0CiAgICBieXRlIDB4MDAwMDAwMDAyMTFkMWFlMwogICAgYj09CiAgICBhc3NlcnQKICAgIGludCAwCiAgICBzd2FwCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGludCAwCgphZGRfY29udGFjdF9pbmZvX2Zvcl9oZWFkZXJAMToKICAgIGZyYW1lX2RpZyAzCiAgICBmcmFtZV9kaWcgMgogICAgPAogICAgYnogYWRkX2NvbnRhY3RfaW5mb19hZnRlcl9mb3JANAogICAgZnJhbWVfZGlnIDAKICAgIGV4dHJhY3QgMiAwCiAgICBmcmFtZV9kaWcgMwogICAgZHVwCiAgICBjb3ZlciAyCiAgICBpbnQgMQogICAgZXh0cmFjdDMgLy8gb24gZXJyb3I6IEluZGV4IGFjY2VzcyBpcyBvdXQgb2YgYm91bmRzCiAgICBidG9pCiAgICBmcmFtZV9kaWcgMQogICAgKwogICAgZnJhbWVfYnVyeSAxCiAgICBpbnQgMQogICAgKwogICAgZnJhbWVfYnVyeSAzCiAgICBiIGFkZF9jb250YWN0X2luZm9fZm9yX2hlYWRlckAxCgphZGRfY29udGFjdF9pbmZvX2FmdGVyX2ZvckA0OgogICAgZnJhbWVfZGlnIDEKICAgIGZyYW1lX2J1cnkgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLnJldHVybl9jb250YWN0KCkgLT4gYnl0ZXM6CnJldHVybl9jb250YWN0OgogICAgcHJvdG8gMCAxCiAgICBieXRlIDB4MDAwYzAwMTMwMDAwMDAwMDIxMWQxYWUzMDAwNTQxNmM2OTYzNjUwMDEzNjE2YzY5NjM2NTQwNzM2ZjZkNjU3NDY4Njk2ZTY3MmU2MzZmNmQKICAgIHJldHN1Ygo=", - "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHVwbGUuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" - }, - "state": { - "global": { - "num_byte_slices": 0, - "num_uints": 0 - }, - "local": { - "num_byte_slices": 0, - "num_uints": 0 - } - }, - "schema": { - "global": { - "declared": {}, - "reserved": {} - }, - "local": { - "declared": {}, - "reserved": {} - } - }, - "contract": { - "name": "Arc4Tuple", - "methods": [ - { - "name": "add_contact_info", - "args": [ - { - "type": "(string,string,uint64,uint8[])", - "name": "contact" - } - ], - "returns": { - "type": "uint64" - }, - "desc": "An arc4.Tuple is a heterogeneous collection of arc4 types." - }, - { - "name": "return_contact", - "args": [], - "returns": { - "type": "(string,string,uint64)" - }, - "desc": "An arc4.Tuple can be returned when more than one return value is needed." - } - ], - "networks": {} - }, - "bare_call_config": { - "no_op": "CREATE" - } -}""" -APP_SPEC = algokit_utils.ApplicationSpecification.from_json(_APP_SPEC_JSON) -_TReturn = typing.TypeVar("_TReturn") - - -class _ArgsBase(ABC, typing.Generic[_TReturn]): - @staticmethod - @abstractmethod - def method() -> str: - ... - - -_TArgs = typing.TypeVar("_TArgs", bound=_ArgsBase[typing.Any]) - - -@dataclasses.dataclass(kw_only=True) -class _TArgsHolder(typing.Generic[_TArgs]): - args: _TArgs - - -def _filter_none(value: dict | typing.Any) -> dict | typing.Any: - if isinstance(value, dict): - return {k: _filter_none(v) for k, v in value.items() if v is not None} - return value - - -def _as_dict(data: typing.Any, *, convert_all: bool = True) -> dict[str, typing.Any]: - if data is None: - return {} - if not dataclasses.is_dataclass(data): - raise TypeError(f"{data} must be a dataclass") - if convert_all: - result = dataclasses.asdict(data) # type: ignore[call-overload] - else: - result = {f.name: getattr(data, f.name) for f in dataclasses.fields(data)} - return _filter_none(result) - - -def _convert_transaction_parameters( - transaction_parameters: algokit_utils.TransactionParameters | None, -) -> algokit_utils.TransactionParametersDict: - return typing.cast(algokit_utils.TransactionParametersDict, _as_dict(transaction_parameters)) - - -def _convert_call_transaction_parameters( - transaction_parameters: algokit_utils.TransactionParameters | None, -) -> algokit_utils.OnCompleteCallParametersDict: - return typing.cast(algokit_utils.OnCompleteCallParametersDict, _as_dict(transaction_parameters)) - - -def _convert_create_transaction_parameters( - transaction_parameters: algokit_utils.TransactionParameters | None, - on_complete: algokit_utils.OnCompleteActionName, -) -> algokit_utils.CreateCallParametersDict: - result = typing.cast(algokit_utils.CreateCallParametersDict, _as_dict(transaction_parameters)) - on_complete_enum = on_complete.replace("_", " ").title().replace(" ", "") + "OC" - result["on_complete"] = getattr(algosdk.transaction.OnComplete, on_complete_enum) - return result - - -def _convert_deploy_args( - deploy_args: algokit_utils.DeployCallArgs | None, -) -> algokit_utils.ABICreateCallArgsDict | None: - if deploy_args is None: - return None - - deploy_args_dict = typing.cast(algokit_utils.ABICreateCallArgsDict, _as_dict(deploy_args)) - if isinstance(deploy_args, _TArgsHolder): - deploy_args_dict["args"] = _as_dict(deploy_args.args) - deploy_args_dict["method"] = deploy_args.args.method() - - return deploy_args_dict - - -@dataclasses.dataclass(kw_only=True) -class AddContactInfoArgs(_ArgsBase[int]): - """An arc4.Tuple is a heterogeneous collection of arc4 types.""" - - contact: tuple[str, str, int, list[int]] - - @staticmethod - def method() -> str: - return "add_contact_info((string,string,uint64,uint8[]))uint64" - - -@dataclasses.dataclass(kw_only=True) -class ReturnContactArgs(_ArgsBase[tuple[str, str, int]]): - """An arc4.Tuple can be returned when more than one return value is needed.""" - - @staticmethod - def method() -> str: - return "return_contact()(string,string,uint64)" - - -@dataclasses.dataclass(kw_only=True) -class SimulateOptions: - allow_more_logs: bool = dataclasses.field(default=False) - allow_empty_signatures: bool = dataclasses.field(default=False) - extra_opcode_budget: int = dataclasses.field(default=0) - exec_trace_config: models.SimulateTraceConfig | None = dataclasses.field(default=None) - - -class Composer: - - def __init__(self, app_client: algokit_utils.ApplicationClient, atc: AtomicTransactionComposer): - self.app_client = app_client - self.atc = atc - - def build(self) -> AtomicTransactionComposer: - return self.atc - - def simulate(self, options: SimulateOptions | None = None) -> SimulateAtomicTransactionResponse: - request = models.SimulateRequest( - allow_more_logs=options.allow_more_logs, - allow_empty_signatures=options.allow_empty_signatures, - extra_opcode_budget=options.extra_opcode_budget, - exec_trace_config=options.exec_trace_config, - txn_groups=[] - ) if options else None - result = self.atc.simulate(self.app_client.algod_client, request) - return result - - def execute(self) -> AtomicTransactionResponse: - return self.app_client.execute_atc(self.atc) - - def add_contact_info( - self, - *, - contact: tuple[str, str, int, list[int]], - transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> "Composer": - """An arc4.Tuple is a heterogeneous collection of arc4 types. - - Adds a call to `add_contact_info((string,string,uint64,uint8[]))uint64` ABI method - - :param tuple[str, str, int, list[int]] contact: The `contact` ABI parameter - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns Composer: This Composer instance""" - - args = AddContactInfoArgs( - contact=contact, - ) - self.app_client.compose_call( - self.atc, - call_abi_method=args.method(), - transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), - **_as_dict(args, convert_all=True), - ) - return self - - def return_contact( - self, - *, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> "Composer": - """An arc4.Tuple can be returned when more than one return value is needed. - - Adds a call to `return_contact()(string,string,uint64)` ABI method - - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns Composer: This Composer instance""" - - args = ReturnContactArgs() - self.app_client.compose_call( - self.atc, - call_abi_method=args.method(), - transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), - **_as_dict(args, convert_all=True), - ) - return self - - def create_bare( - self, - *, - on_complete: typing.Literal["no_op"] = "no_op", - transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, - ) -> "Composer": - """Adds a call to create an application using the no_op bare method - - :param typing.Literal[no_op] on_complete: On completion type to use - :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns Composer: This Composer instance""" - - self.app_client.compose_create( - self.atc, - call_abi_method=False, - transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), - ) - return self - - def clear_state( - self, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - app_args: list[bytes] | None = None, - ) -> "Composer": - """Adds a call to the application with on completion set to ClearState - - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :param list[bytes] | None app_args: (optional) Application args to pass""" - - self.app_client.compose_clear_state(self.atc, _convert_transaction_parameters(transaction_parameters), app_args) - return self - - -class Arc4TupleClient: - """A class for interacting with the Arc4Tuple app providing high productivity and - strongly typed methods to deploy and call the app""" - - @typing.overload - def __init__( - self, - algod_client: algosdk.v2client.algod.AlgodClient, - *, - app_id: int = 0, - signer: TransactionSigner | algokit_utils.Account | None = None, - sender: str | None = None, - suggested_params: algosdk.transaction.SuggestedParams | None = None, - template_values: algokit_utils.TemplateValueMapping | None = None, - app_name: str | None = None, - ) -> None: - ... - - @typing.overload - def __init__( - self, - algod_client: algosdk.v2client.algod.AlgodClient, - *, - creator: str | algokit_utils.Account, - indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, - existing_deployments: algokit_utils.AppLookup | None = None, - signer: TransactionSigner | algokit_utils.Account | None = None, - sender: str | None = None, - suggested_params: algosdk.transaction.SuggestedParams | None = None, - template_values: algokit_utils.TemplateValueMapping | None = None, - app_name: str | None = None, - ) -> None: - ... - - def __init__( - self, - algod_client: algosdk.v2client.algod.AlgodClient, - *, - creator: str | algokit_utils.Account | None = None, - indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, - existing_deployments: algokit_utils.AppLookup | None = None, - app_id: int = 0, - signer: TransactionSigner | algokit_utils.Account | None = None, - sender: str | None = None, - suggested_params: algosdk.transaction.SuggestedParams | None = None, - template_values: algokit_utils.TemplateValueMapping | None = None, - app_name: str | None = None, - ) -> None: - """ - Arc4TupleClient can be created with an app_id to interact with an existing application, alternatively - it can be created with a creator and indexer_client specified to find existing applications by name and creator. - - :param AlgodClient algod_client: AlgoSDK algod client - :param int app_id: The app_id of an existing application, to instead find the application by creator and name - use the creator and indexer_client parameters - :param str | Account creator: The address or Account of the app creator to resolve the app_id - :param IndexerClient indexer_client: AlgoSDK indexer client, only required if deploying or finding app_id by - creator and app name - :param AppLookup existing_deployments: - :param TransactionSigner | Account signer: Account or signer to use to sign transactions, if not specified and - creator was passed as an Account will use that. - :param str sender: Address to use as the sender for all transactions, will use the address associated with the - signer if not specified. - :param TemplateValueMapping template_values: Values to use for TMPL_* template variables, dictionary keys should - *NOT* include the TMPL_ prefix - :param str | None app_name: Name of application to use when deploying, defaults to name defined on the - Application Specification - """ - - self.app_spec = APP_SPEC - - # calling full __init__ signature, so ignoring mypy warning about overloads - self.app_client = algokit_utils.ApplicationClient( # type: ignore[call-overload, misc] - algod_client=algod_client, - app_spec=self.app_spec, - app_id=app_id, - creator=creator, - indexer_client=indexer_client, - existing_deployments=existing_deployments, - signer=signer, - sender=sender, - suggested_params=suggested_params, - template_values=template_values, - app_name=app_name, - ) - - @property - def algod_client(self) -> algosdk.v2client.algod.AlgodClient: - return self.app_client.algod_client - - @property - def app_id(self) -> int: - return self.app_client.app_id - - @app_id.setter - def app_id(self, value: int) -> None: - self.app_client.app_id = value - - @property - def app_address(self) -> str: - return self.app_client.app_address - - @property - def sender(self) -> str | None: - return self.app_client.sender - - @sender.setter - def sender(self, value: str) -> None: - self.app_client.sender = value - - @property - def signer(self) -> TransactionSigner | None: - return self.app_client.signer - - @signer.setter - def signer(self, value: TransactionSigner) -> None: - self.app_client.signer = value - - @property - def suggested_params(self) -> algosdk.transaction.SuggestedParams | None: - return self.app_client.suggested_params - - @suggested_params.setter - def suggested_params(self, value: algosdk.transaction.SuggestedParams | None) -> None: - self.app_client.suggested_params = value - - def add_contact_info( - self, - *, - contact: tuple[str, str, int, list[int]], - transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> algokit_utils.ABITransactionResponse[int]: - """An arc4.Tuple is a heterogeneous collection of arc4 types. - - Calls `add_contact_info((string,string,uint64,uint8[]))uint64` ABI method - - :param tuple[str, str, int, list[int]] contact: The `contact` ABI parameter - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns algokit_utils.ABITransactionResponse[int]: The result of the transaction""" - - args = AddContactInfoArgs( - contact=contact, - ) - result = self.app_client.call( - call_abi_method=args.method(), - transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), - **_as_dict(args, convert_all=True), - ) - return result - - def return_contact( - self, - *, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> algokit_utils.ABITransactionResponse[tuple[str, str, int]]: - """An arc4.Tuple can be returned when more than one return value is needed. - - Calls `return_contact()(string,string,uint64)` ABI method - - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns algokit_utils.ABITransactionResponse[tuple[str, str, int]]: The result of the transaction""" - - args = ReturnContactArgs() - result = self.app_client.call( - call_abi_method=args.method(), - transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), - **_as_dict(args, convert_all=True), - ) - return result - - def create_bare( - self, - *, - on_complete: typing.Literal["no_op"] = "no_op", - transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, - ) -> algokit_utils.TransactionResponse: - """Creates an application using the no_op bare method - - :param typing.Literal[no_op] on_complete: On completion type to use - :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns algokit_utils.TransactionResponse: The result of the transaction""" - - result = self.app_client.create( - call_abi_method=False, - transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), - ) - return result - - def clear_state( - self, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - app_args: list[bytes] | None = None, - ) -> algokit_utils.TransactionResponse: - """Calls the application with on completion set to ClearState - - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :param list[bytes] | None app_args: (optional) Application args to pass - :returns algokit_utils.TransactionResponse: The result of the transaction""" - - return self.app_client.clear_state(_convert_transaction_parameters(transaction_parameters), app_args) - - def deploy( - self, - version: str | None = None, - *, - signer: TransactionSigner | None = None, - sender: str | None = None, - allow_update: bool | None = None, - allow_delete: bool | None = None, - on_update: algokit_utils.OnUpdate = algokit_utils.OnUpdate.Fail, - on_schema_break: algokit_utils.OnSchemaBreak = algokit_utils.OnSchemaBreak.Fail, - template_values: algokit_utils.TemplateValueMapping | None = None, - create_args: algokit_utils.DeployCallArgs | None = None, - update_args: algokit_utils.DeployCallArgs | None = None, - delete_args: algokit_utils.DeployCallArgs | None = None, - ) -> algokit_utils.DeployResponse: - """Deploy an application and update client to reference it. - - Idempotently deploy (create, update/delete if changed) an app against the given name via the given creator - account, including deploy-time template placeholder substitutions. - To understand the architecture decisions behind this functionality please see - - - ```{note} - If there is a breaking state schema change to an existing app (and `on_schema_break` is set to - 'ReplaceApp' the existing app will be deleted and re-created. - ``` - - ```{note} - If there is an update (different TEAL code) to an existing app (and `on_update` is set to 'ReplaceApp') - the existing app will be deleted and re-created. - ``` - - :param str version: version to use when creating or updating app, if None version will be auto incremented - :param algosdk.atomic_transaction_composer.TransactionSigner signer: signer to use when deploying app - , if None uses self.signer - :param str sender: sender address to use when deploying app, if None uses self.sender - :param bool allow_delete: Used to set the `TMPL_DELETABLE` template variable to conditionally control if an app - can be deleted - :param bool allow_update: Used to set the `TMPL_UPDATABLE` template variable to conditionally control if an app - can be updated - :param OnUpdate on_update: Determines what action to take if an application update is required - :param OnSchemaBreak on_schema_break: Determines what action to take if an application schema requirements - has increased beyond the current allocation - :param dict[str, int|str|bytes] template_values: Values to use for `TMPL_*` template variables, dictionary keys - should *NOT* include the TMPL_ prefix - :param algokit_utils.DeployCallArgs | None create_args: Arguments used when creating an application - :param algokit_utils.DeployCallArgs | None update_args: Arguments used when updating an application - :param algokit_utils.DeployCallArgs | None delete_args: Arguments used when deleting an application - :return DeployResponse: details action taken and relevant transactions - :raises DeploymentError: If the deployment failed""" - - return self.app_client.deploy( - version, - signer=signer, - sender=sender, - allow_update=allow_update, - allow_delete=allow_delete, - on_update=on_update, - on_schema_break=on_schema_break, - template_values=template_values, - create_args=_convert_deploy_args(create_args), - update_args=_convert_deploy_args(update_args), - delete_args=_convert_deploy_args(delete_args), - ) - - def compose(self, atc: AtomicTransactionComposer | None = None) -> Composer: - return Composer(self.app_client, atc or AtomicTransactionComposer()) diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_types_client.py b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_types_client.py deleted file mode 100644 index fa693aa..0000000 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_types_client.py +++ /dev/null @@ -1,950 +0,0 @@ -# flake8: noqa -# fmt: off -# mypy: disable-error-code="no-any-return, no-untyped-call, misc, type-arg" -# This file was automatically generated by algokit-client-generator. -# DO NOT MODIFY IT BY HAND. -# requires: algokit-utils@^1.2.0 -import base64 -import dataclasses -import decimal -import typing -from abc import ABC, abstractmethod - -import algokit_utils -import algosdk -from algosdk.v2client import models -from algosdk.atomic_transaction_composer import ( - AtomicTransactionComposer, - AtomicTransactionResponse, - SimulateAtomicTransactionResponse, - TransactionSigner, - TransactionWithSigner -) - -_APP_SPEC_JSON = r"""{ - "hints": { - "arc4_uint64(uint64,uint64)uint64": { - "call_config": { - "no_op": "CALL" - } - }, - "arc4_uint_n(uint8,uint16,uint32,uint64)uint64": { - "call_config": { - "no_op": "CALL" - } - }, - "arc4_biguint_n(uint128,uint256,uint512)uint512": { - "call_config": { - "no_op": "CALL" - } - }, - "arc4_byte(byte)byte": { - "call_config": { - "no_op": "CALL" - } - }, - "arc4_address_properties(address)uint64": { - "call_config": { - "no_op": "CALL" - } - }, - "arc4_address_return(address)address": { - "call_config": { - "no_op": "CALL" - } - } - }, - "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdAMTAKICAgIG1ldGhvZCAiYXJjNF91aW50NjQodWludDY0LHVpbnQ2NCl1aW50NjQiCiAgICBtZXRob2QgImFyYzRfdWludF9uKHVpbnQ4LHVpbnQxNix1aW50MzIsdWludDY0KXVpbnQ2NCIKICAgIG1ldGhvZCAiYXJjNF9iaWd1aW50X24odWludDEyOCx1aW50MjU2LHVpbnQ1MTIpdWludDUxMiIKICAgIG1ldGhvZCAiYXJjNF9ieXRlKGJ5dGUpYnl0ZSIKICAgIG1ldGhvZCAiYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXMoYWRkcmVzcyl1aW50NjQiCiAgICBtZXRob2QgImFyYzRfYWRkcmVzc19yZXR1cm4oYWRkcmVzcylhZGRyZXNzIgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAogICAgbWF0Y2ggX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF91aW50NjRfcm91dGVAMiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X3VpbnRfbl9yb3V0ZUAzIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYmlndWludF9uX3JvdXRlQDQgX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9ieXRlX3JvdXRlQDUgX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXNfcm91dGVANiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2FkZHJlc3NfcmV0dXJuX3JvdXRlQDcKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfdWludDY0X3JvdXRlQDI6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAyCiAgICBjYWxsc3ViIGFyYzRfdWludDY0CiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X3VpbnRfbl9yb3V0ZUAzOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgNAogICAgY2FsbHN1YiBhcmM0X3VpbnRfbgogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9iaWd1aW50X25fcm91dGVANDoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDMKICAgIGNhbGxzdWIgYXJjNF9iaWd1aW50X24KICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYnl0ZV9yb3V0ZUA1OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgY2FsbHN1YiBhcmM0X2J5dGUKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYWRkcmVzc19wcm9wZXJ0aWVzX3JvdXRlQDY6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICBjYWxsc3ViIGFyYzRfYWRkcmVzc19wcm9wZXJ0aWVzCiAgICBpdG9iCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2FkZHJlc3NfcmV0dXJuX3JvdXRlQDc6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICBjYWxsc3ViIGFyYzRfYWRkcmVzc19yZXR1cm4KICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0AxMDoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgIGJueiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDE0CiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgIQogICAgYXNzZXJ0IC8vIGlzIGNyZWF0aW5nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDE0OgogICAgaW50IDAKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X3VpbnQ2NChhOiBieXRlcywgYjogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X3VpbnQ2NDoKICAgIHByb3RvIDIgMQogICAgZnJhbWVfZGlnIC0yCiAgICBidG9pCiAgICBmcmFtZV9kaWcgLTEKICAgIGJ0b2kKICAgICsKICAgIGl0b2IKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X3VpbnRfbihhOiBieXRlcywgYjogYnl0ZXMsIGM6IGJ5dGVzLCBkOiBieXRlcykgLT4gYnl0ZXM6CmFyYzRfdWludF9uOgogICAgcHJvdG8gNCAxCiAgICBmcmFtZV9kaWcgLTQKICAgIGxlbgogICAgaW50IDEKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMwogICAgbGVuCiAgICBpbnQgMgogICAgPT0KICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0yCiAgICBsZW4KICAgIGludCA0CiAgICA9PQogICAgYXNzZXJ0CiAgICBmcmFtZV9kaWcgLTEKICAgIGxlbgogICAgaW50IDgKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtNAogICAgYnRvaQogICAgZnJhbWVfZGlnIC0zCiAgICBidG9pCiAgICArCiAgICBmcmFtZV9kaWcgLTIKICAgIGJ0b2kKICAgICsKICAgIGZyYW1lX2RpZyAtMQogICAgYnRvaQogICAgKwogICAgaXRvYgogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFyYzRfYmlndWludF9uKGE6IGJ5dGVzLCBiOiBieXRlcywgYzogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X2JpZ3VpbnRfbjoKICAgIHByb3RvIDMgMQogICAgZnJhbWVfZGlnIC0zCiAgICBsZW4KICAgIGludCAxNgogICAgPT0KICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0yCiAgICBsZW4KICAgIGludCAzMgogICAgPT0KICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0xCiAgICBsZW4KICAgIGludCA2NAogICAgPT0KICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0zCiAgICBmcmFtZV9kaWcgLTIKICAgIGIrCiAgICBmcmFtZV9kaWcgLTEKICAgIGIrCiAgICBkdXAKICAgIGxlbgogICAgaW50IDY0CiAgICA8PQogICAgYXNzZXJ0IC8vIG92ZXJmbG93CiAgICBpbnQgNjQKICAgIGJ6ZXJvCiAgICBifAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFyYzRfYnl0ZShhOiBieXRlcykgLT4gYnl0ZXM6CmFyYzRfYnl0ZToKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBidG9pCiAgICBpbnQgMQogICAgKwogICAgaXRvYgogICAgZXh0cmFjdCA3IDEKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X2FkZHJlc3NfcHJvcGVydGllcyhhZGRyZXNzOiBieXRlcykgLT4gdWludDY0OgphcmM0X2FkZHJlc3NfcHJvcGVydGllczoKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBhY2N0X3BhcmFtc19nZXQgQWNjdEJhbGFuY2UKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgZnJhbWVfZGlnIC0xCiAgICBhY2N0X3BhcmFtc19nZXQgQWNjdFRvdGFsQXNzZXRzCiAgICBidXJ5IDEKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFyYzRfYWRkcmVzc19yZXR1cm4oYWRkcmVzczogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X2FkZHJlc3NfcmV0dXJuOgogICAgcHJvdG8gMSAxCiAgICBmcmFtZV9kaWcgLTEKICAgIHJldHN1Ygo=", - "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" - }, - "state": { - "global": { - "num_byte_slices": 0, - "num_uints": 0 - }, - "local": { - "num_byte_slices": 0, - "num_uints": 0 - } - }, - "schema": { - "global": { - "declared": {}, - "reserved": {} - }, - "local": { - "declared": {}, - "reserved": {} - } - }, - "contract": { - "name": "Arc4Types", - "methods": [ - { - "name": "arc4_uint64", - "args": [ - { - "type": "uint64", - "name": "a" - }, - { - "type": "uint64", - "name": "b" - } - ], - "returns": { - "type": "uint64" - }, - "desc": "Math operations (like a + b) are not supported on arc4.UInt64 types\nsince they are internally represented as byte arrays in the AVM. Use the .native property to perform arithmetic operations." - }, - { - "name": "arc4_uint_n", - "args": [ - { - "type": "uint8", - "name": "a" - }, - { - "type": "uint16", - "name": "b" - }, - { - "type": "uint32", - "name": "c" - }, - { - "type": "uint64", - "name": "d" - } - ], - "returns": { - "type": "uint64" - }, - "desc": "The encoding of arc4 integers will be smaller if it uses fewer bits.\nUltimately, they are all represented with native UInt64." - }, - { - "name": "arc4_biguint_n", - "args": [ - { - "type": "uint128", - "name": "a" - }, - { - "type": "uint256", - "name": "b" - }, - { - "type": "uint512", - "name": "c" - } - ], - "returns": { - "type": "uint512" - }, - "desc": "Integers with larger bit size are supported up to 512 bits.\nUltimately, they are all represented with native BigUInt." - }, - { - "name": "arc4_byte", - "args": [ - { - "type": "byte", - "name": "a" - } - ], - "returns": { - "type": "byte" - }, - "desc": "An arc4.Byte is essentially an alias for an 8-bit integer." - }, - { - "name": "arc4_address_properties", - "args": [ - { - "type": "address", - "name": "address" - } - ], - "returns": { - "type": "uint64" - } - }, - { - "name": "arc4_address_return", - "args": [ - { - "type": "address", - "name": "address" - } - ], - "returns": { - "type": "address" - } - } - ], - "networks": {} - }, - "bare_call_config": { - "no_op": "CREATE" - } -}""" -APP_SPEC = algokit_utils.ApplicationSpecification.from_json(_APP_SPEC_JSON) -_TReturn = typing.TypeVar("_TReturn") - - -class _ArgsBase(ABC, typing.Generic[_TReturn]): - @staticmethod - @abstractmethod - def method() -> str: - ... - - -_TArgs = typing.TypeVar("_TArgs", bound=_ArgsBase[typing.Any]) - - -@dataclasses.dataclass(kw_only=True) -class _TArgsHolder(typing.Generic[_TArgs]): - args: _TArgs - - -def _filter_none(value: dict | typing.Any) -> dict | typing.Any: - if isinstance(value, dict): - return {k: _filter_none(v) for k, v in value.items() if v is not None} - return value - - -def _as_dict(data: typing.Any, *, convert_all: bool = True) -> dict[str, typing.Any]: - if data is None: - return {} - if not dataclasses.is_dataclass(data): - raise TypeError(f"{data} must be a dataclass") - if convert_all: - result = dataclasses.asdict(data) # type: ignore[call-overload] - else: - result = {f.name: getattr(data, f.name) for f in dataclasses.fields(data)} - return _filter_none(result) - - -def _convert_transaction_parameters( - transaction_parameters: algokit_utils.TransactionParameters | None, -) -> algokit_utils.TransactionParametersDict: - return typing.cast(algokit_utils.TransactionParametersDict, _as_dict(transaction_parameters)) - - -def _convert_call_transaction_parameters( - transaction_parameters: algokit_utils.TransactionParameters | None, -) -> algokit_utils.OnCompleteCallParametersDict: - return typing.cast(algokit_utils.OnCompleteCallParametersDict, _as_dict(transaction_parameters)) - - -def _convert_create_transaction_parameters( - transaction_parameters: algokit_utils.TransactionParameters | None, - on_complete: algokit_utils.OnCompleteActionName, -) -> algokit_utils.CreateCallParametersDict: - result = typing.cast(algokit_utils.CreateCallParametersDict, _as_dict(transaction_parameters)) - on_complete_enum = on_complete.replace("_", " ").title().replace(" ", "") + "OC" - result["on_complete"] = getattr(algosdk.transaction.OnComplete, on_complete_enum) - return result - - -def _convert_deploy_args( - deploy_args: algokit_utils.DeployCallArgs | None, -) -> algokit_utils.ABICreateCallArgsDict | None: - if deploy_args is None: - return None - - deploy_args_dict = typing.cast(algokit_utils.ABICreateCallArgsDict, _as_dict(deploy_args)) - if isinstance(deploy_args, _TArgsHolder): - deploy_args_dict["args"] = _as_dict(deploy_args.args) - deploy_args_dict["method"] = deploy_args.args.method() - - return deploy_args_dict - - -@dataclasses.dataclass(kw_only=True) -class Arc4Uint64Args(_ArgsBase[int]): - """Math operations (like a + b) are not supported on arc4.UInt64 types - since they are internally represented as byte arrays in the AVM. Use the .native property to perform arithmetic operations.""" - - a: int - b: int - - @staticmethod - def method() -> str: - return "arc4_uint64(uint64,uint64)uint64" - - -@dataclasses.dataclass(kw_only=True) -class Arc4UintNArgs(_ArgsBase[int]): - """The encoding of arc4 integers will be smaller if it uses fewer bits. - Ultimately, they are all represented with native UInt64.""" - - a: int - b: int - c: int - d: int - - @staticmethod - def method() -> str: - return "arc4_uint_n(uint8,uint16,uint32,uint64)uint64" - - -@dataclasses.dataclass(kw_only=True) -class Arc4BiguintNArgs(_ArgsBase[int]): - """Integers with larger bit size are supported up to 512 bits. - Ultimately, they are all represented with native BigUInt.""" - - a: int - b: int - c: int - - @staticmethod - def method() -> str: - return "arc4_biguint_n(uint128,uint256,uint512)uint512" - - -@dataclasses.dataclass(kw_only=True) -class Arc4ByteArgs(_ArgsBase[int]): - """An arc4.Byte is essentially an alias for an 8-bit integer.""" - - a: int - - @staticmethod - def method() -> str: - return "arc4_byte(byte)byte" - - -@dataclasses.dataclass(kw_only=True) -class Arc4AddressPropertiesArgs(_ArgsBase[int]): - address: str - - @staticmethod - def method() -> str: - return "arc4_address_properties(address)uint64" - - -@dataclasses.dataclass(kw_only=True) -class Arc4AddressReturnArgs(_ArgsBase[str]): - address: str - - @staticmethod - def method() -> str: - return "arc4_address_return(address)address" - - -@dataclasses.dataclass(kw_only=True) -class SimulateOptions: - allow_more_logs: bool = dataclasses.field(default=False) - allow_empty_signatures: bool = dataclasses.field(default=False) - extra_opcode_budget: int = dataclasses.field(default=0) - exec_trace_config: models.SimulateTraceConfig | None = dataclasses.field(default=None) - - -class Composer: - - def __init__(self, app_client: algokit_utils.ApplicationClient, atc: AtomicTransactionComposer): - self.app_client = app_client - self.atc = atc - - def build(self) -> AtomicTransactionComposer: - return self.atc - - def simulate(self, options: SimulateOptions | None = None) -> SimulateAtomicTransactionResponse: - request = models.SimulateRequest( - allow_more_logs=options.allow_more_logs, - allow_empty_signatures=options.allow_empty_signatures, - extra_opcode_budget=options.extra_opcode_budget, - exec_trace_config=options.exec_trace_config, - txn_groups=[] - ) if options else None - result = self.atc.simulate(self.app_client.algod_client, request) - return result - - def execute(self) -> AtomicTransactionResponse: - return self.app_client.execute_atc(self.atc) - - def arc4_uint64( - self, - *, - a: int, - b: int, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> "Composer": - """Math operations (like a + b) are not supported on arc4.UInt64 types - since they are internally represented as byte arrays in the AVM. Use the .native property to perform arithmetic operations. - - Adds a call to `arc4_uint64(uint64,uint64)uint64` ABI method - - :param int a: The `a` ABI parameter - :param int b: The `b` ABI parameter - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns Composer: This Composer instance""" - - args = Arc4Uint64Args( - a=a, - b=b, - ) - self.app_client.compose_call( - self.atc, - call_abi_method=args.method(), - transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), - **_as_dict(args, convert_all=True), - ) - return self - - def arc4_uint_n( - self, - *, - a: int, - b: int, - c: int, - d: int, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> "Composer": - """The encoding of arc4 integers will be smaller if it uses fewer bits. - Ultimately, they are all represented with native UInt64. - - Adds a call to `arc4_uint_n(uint8,uint16,uint32,uint64)uint64` ABI method - - :param int a: The `a` ABI parameter - :param int b: The `b` ABI parameter - :param int c: The `c` ABI parameter - :param int d: The `d` ABI parameter - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns Composer: This Composer instance""" - - args = Arc4UintNArgs( - a=a, - b=b, - c=c, - d=d, - ) - self.app_client.compose_call( - self.atc, - call_abi_method=args.method(), - transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), - **_as_dict(args, convert_all=True), - ) - return self - - def arc4_biguint_n( - self, - *, - a: int, - b: int, - c: int, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> "Composer": - """Integers with larger bit size are supported up to 512 bits. - Ultimately, they are all represented with native BigUInt. - - Adds a call to `arc4_biguint_n(uint128,uint256,uint512)uint512` ABI method - - :param int a: The `a` ABI parameter - :param int b: The `b` ABI parameter - :param int c: The `c` ABI parameter - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns Composer: This Composer instance""" - - args = Arc4BiguintNArgs( - a=a, - b=b, - c=c, - ) - self.app_client.compose_call( - self.atc, - call_abi_method=args.method(), - transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), - **_as_dict(args, convert_all=True), - ) - return self - - def arc4_byte( - self, - *, - a: int, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> "Composer": - """An arc4.Byte is essentially an alias for an 8-bit integer. - - Adds a call to `arc4_byte(byte)byte` ABI method - - :param int a: The `a` ABI parameter - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns Composer: This Composer instance""" - - args = Arc4ByteArgs( - a=a, - ) - self.app_client.compose_call( - self.atc, - call_abi_method=args.method(), - transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), - **_as_dict(args, convert_all=True), - ) - return self - - def arc4_address_properties( - self, - *, - address: str, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> "Composer": - """Adds a call to `arc4_address_properties(address)uint64` ABI method - - :param str address: The `address` ABI parameter - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns Composer: This Composer instance""" - - args = Arc4AddressPropertiesArgs( - address=address, - ) - self.app_client.compose_call( - self.atc, - call_abi_method=args.method(), - transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), - **_as_dict(args, convert_all=True), - ) - return self - - def arc4_address_return( - self, - *, - address: str, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> "Composer": - """Adds a call to `arc4_address_return(address)address` ABI method - - :param str address: The `address` ABI parameter - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns Composer: This Composer instance""" - - args = Arc4AddressReturnArgs( - address=address, - ) - self.app_client.compose_call( - self.atc, - call_abi_method=args.method(), - transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), - **_as_dict(args, convert_all=True), - ) - return self - - def create_bare( - self, - *, - on_complete: typing.Literal["no_op"] = "no_op", - transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, - ) -> "Composer": - """Adds a call to create an application using the no_op bare method - - :param typing.Literal[no_op] on_complete: On completion type to use - :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns Composer: This Composer instance""" - - self.app_client.compose_create( - self.atc, - call_abi_method=False, - transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), - ) - return self - - def clear_state( - self, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - app_args: list[bytes] | None = None, - ) -> "Composer": - """Adds a call to the application with on completion set to ClearState - - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :param list[bytes] | None app_args: (optional) Application args to pass""" - - self.app_client.compose_clear_state(self.atc, _convert_transaction_parameters(transaction_parameters), app_args) - return self - - -class Arc4TypesClient: - """A class for interacting with the Arc4Types app providing high productivity and - strongly typed methods to deploy and call the app""" - - @typing.overload - def __init__( - self, - algod_client: algosdk.v2client.algod.AlgodClient, - *, - app_id: int = 0, - signer: TransactionSigner | algokit_utils.Account | None = None, - sender: str | None = None, - suggested_params: algosdk.transaction.SuggestedParams | None = None, - template_values: algokit_utils.TemplateValueMapping | None = None, - app_name: str | None = None, - ) -> None: - ... - - @typing.overload - def __init__( - self, - algod_client: algosdk.v2client.algod.AlgodClient, - *, - creator: str | algokit_utils.Account, - indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, - existing_deployments: algokit_utils.AppLookup | None = None, - signer: TransactionSigner | algokit_utils.Account | None = None, - sender: str | None = None, - suggested_params: algosdk.transaction.SuggestedParams | None = None, - template_values: algokit_utils.TemplateValueMapping | None = None, - app_name: str | None = None, - ) -> None: - ... - - def __init__( - self, - algod_client: algosdk.v2client.algod.AlgodClient, - *, - creator: str | algokit_utils.Account | None = None, - indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, - existing_deployments: algokit_utils.AppLookup | None = None, - app_id: int = 0, - signer: TransactionSigner | algokit_utils.Account | None = None, - sender: str | None = None, - suggested_params: algosdk.transaction.SuggestedParams | None = None, - template_values: algokit_utils.TemplateValueMapping | None = None, - app_name: str | None = None, - ) -> None: - """ - Arc4TypesClient can be created with an app_id to interact with an existing application, alternatively - it can be created with a creator and indexer_client specified to find existing applications by name and creator. - - :param AlgodClient algod_client: AlgoSDK algod client - :param int app_id: The app_id of an existing application, to instead find the application by creator and name - use the creator and indexer_client parameters - :param str | Account creator: The address or Account of the app creator to resolve the app_id - :param IndexerClient indexer_client: AlgoSDK indexer client, only required if deploying or finding app_id by - creator and app name - :param AppLookup existing_deployments: - :param TransactionSigner | Account signer: Account or signer to use to sign transactions, if not specified and - creator was passed as an Account will use that. - :param str sender: Address to use as the sender for all transactions, will use the address associated with the - signer if not specified. - :param TemplateValueMapping template_values: Values to use for TMPL_* template variables, dictionary keys should - *NOT* include the TMPL_ prefix - :param str | None app_name: Name of application to use when deploying, defaults to name defined on the - Application Specification - """ - - self.app_spec = APP_SPEC - - # calling full __init__ signature, so ignoring mypy warning about overloads - self.app_client = algokit_utils.ApplicationClient( # type: ignore[call-overload, misc] - algod_client=algod_client, - app_spec=self.app_spec, - app_id=app_id, - creator=creator, - indexer_client=indexer_client, - existing_deployments=existing_deployments, - signer=signer, - sender=sender, - suggested_params=suggested_params, - template_values=template_values, - app_name=app_name, - ) - - @property - def algod_client(self) -> algosdk.v2client.algod.AlgodClient: - return self.app_client.algod_client - - @property - def app_id(self) -> int: - return self.app_client.app_id - - @app_id.setter - def app_id(self, value: int) -> None: - self.app_client.app_id = value - - @property - def app_address(self) -> str: - return self.app_client.app_address - - @property - def sender(self) -> str | None: - return self.app_client.sender - - @sender.setter - def sender(self, value: str) -> None: - self.app_client.sender = value - - @property - def signer(self) -> TransactionSigner | None: - return self.app_client.signer - - @signer.setter - def signer(self, value: TransactionSigner) -> None: - self.app_client.signer = value - - @property - def suggested_params(self) -> algosdk.transaction.SuggestedParams | None: - return self.app_client.suggested_params - - @suggested_params.setter - def suggested_params(self, value: algosdk.transaction.SuggestedParams | None) -> None: - self.app_client.suggested_params = value - - def arc4_uint64( - self, - *, - a: int, - b: int, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> algokit_utils.ABITransactionResponse[int]: - """Math operations (like a + b) are not supported on arc4.UInt64 types - since they are internally represented as byte arrays in the AVM. Use the .native property to perform arithmetic operations. - - Calls `arc4_uint64(uint64,uint64)uint64` ABI method - - :param int a: The `a` ABI parameter - :param int b: The `b` ABI parameter - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns algokit_utils.ABITransactionResponse[int]: The result of the transaction""" - - args = Arc4Uint64Args( - a=a, - b=b, - ) - result = self.app_client.call( - call_abi_method=args.method(), - transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), - **_as_dict(args, convert_all=True), - ) - return result - - def arc4_uint_n( - self, - *, - a: int, - b: int, - c: int, - d: int, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> algokit_utils.ABITransactionResponse[int]: - """The encoding of arc4 integers will be smaller if it uses fewer bits. - Ultimately, they are all represented with native UInt64. - - Calls `arc4_uint_n(uint8,uint16,uint32,uint64)uint64` ABI method - - :param int a: The `a` ABI parameter - :param int b: The `b` ABI parameter - :param int c: The `c` ABI parameter - :param int d: The `d` ABI parameter - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns algokit_utils.ABITransactionResponse[int]: The result of the transaction""" - - args = Arc4UintNArgs( - a=a, - b=b, - c=c, - d=d, - ) - result = self.app_client.call( - call_abi_method=args.method(), - transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), - **_as_dict(args, convert_all=True), - ) - return result - - def arc4_biguint_n( - self, - *, - a: int, - b: int, - c: int, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> algokit_utils.ABITransactionResponse[int]: - """Integers with larger bit size are supported up to 512 bits. - Ultimately, they are all represented with native BigUInt. - - Calls `arc4_biguint_n(uint128,uint256,uint512)uint512` ABI method - - :param int a: The `a` ABI parameter - :param int b: The `b` ABI parameter - :param int c: The `c` ABI parameter - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns algokit_utils.ABITransactionResponse[int]: The result of the transaction""" - - args = Arc4BiguintNArgs( - a=a, - b=b, - c=c, - ) - result = self.app_client.call( - call_abi_method=args.method(), - transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), - **_as_dict(args, convert_all=True), - ) - return result - - def arc4_byte( - self, - *, - a: int, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> algokit_utils.ABITransactionResponse[int]: - """An arc4.Byte is essentially an alias for an 8-bit integer. - - Calls `arc4_byte(byte)byte` ABI method - - :param int a: The `a` ABI parameter - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns algokit_utils.ABITransactionResponse[int]: The result of the transaction""" - - args = Arc4ByteArgs( - a=a, - ) - result = self.app_client.call( - call_abi_method=args.method(), - transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), - **_as_dict(args, convert_all=True), - ) - return result - - def arc4_address_properties( - self, - *, - address: str, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> algokit_utils.ABITransactionResponse[int]: - """Calls `arc4_address_properties(address)uint64` ABI method - - :param str address: The `address` ABI parameter - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns algokit_utils.ABITransactionResponse[int]: The result of the transaction""" - - args = Arc4AddressPropertiesArgs( - address=address, - ) - result = self.app_client.call( - call_abi_method=args.method(), - transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), - **_as_dict(args, convert_all=True), - ) - return result - - def arc4_address_return( - self, - *, - address: str, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> algokit_utils.ABITransactionResponse[str]: - """Calls `arc4_address_return(address)address` ABI method - - :param str address: The `address` ABI parameter - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns algokit_utils.ABITransactionResponse[str]: The result of the transaction""" - - args = Arc4AddressReturnArgs( - address=address, - ) - result = self.app_client.call( - call_abi_method=args.method(), - transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), - **_as_dict(args, convert_all=True), - ) - return result - - def create_bare( - self, - *, - on_complete: typing.Literal["no_op"] = "no_op", - transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, - ) -> algokit_utils.TransactionResponse: - """Creates an application using the no_op bare method - - :param typing.Literal[no_op] on_complete: On completion type to use - :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns algokit_utils.TransactionResponse: The result of the transaction""" - - result = self.app_client.create( - call_abi_method=False, - transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), - ) - return result - - def clear_state( - self, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - app_args: list[bytes] | None = None, - ) -> algokit_utils.TransactionResponse: - """Calls the application with on completion set to ClearState - - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :param list[bytes] | None app_args: (optional) Application args to pass - :returns algokit_utils.TransactionResponse: The result of the transaction""" - - return self.app_client.clear_state(_convert_transaction_parameters(transaction_parameters), app_args) - - def deploy( - self, - version: str | None = None, - *, - signer: TransactionSigner | None = None, - sender: str | None = None, - allow_update: bool | None = None, - allow_delete: bool | None = None, - on_update: algokit_utils.OnUpdate = algokit_utils.OnUpdate.Fail, - on_schema_break: algokit_utils.OnSchemaBreak = algokit_utils.OnSchemaBreak.Fail, - template_values: algokit_utils.TemplateValueMapping | None = None, - create_args: algokit_utils.DeployCallArgs | None = None, - update_args: algokit_utils.DeployCallArgs | None = None, - delete_args: algokit_utils.DeployCallArgs | None = None, - ) -> algokit_utils.DeployResponse: - """Deploy an application and update client to reference it. - - Idempotently deploy (create, update/delete if changed) an app against the given name via the given creator - account, including deploy-time template placeholder substitutions. - To understand the architecture decisions behind this functionality please see - - - ```{note} - If there is a breaking state schema change to an existing app (and `on_schema_break` is set to - 'ReplaceApp' the existing app will be deleted and re-created. - ``` - - ```{note} - If there is an update (different TEAL code) to an existing app (and `on_update` is set to 'ReplaceApp') - the existing app will be deleted and re-created. - ``` - - :param str version: version to use when creating or updating app, if None version will be auto incremented - :param algosdk.atomic_transaction_composer.TransactionSigner signer: signer to use when deploying app - , if None uses self.signer - :param str sender: sender address to use when deploying app, if None uses self.sender - :param bool allow_delete: Used to set the `TMPL_DELETABLE` template variable to conditionally control if an app - can be deleted - :param bool allow_update: Used to set the `TMPL_UPDATABLE` template variable to conditionally control if an app - can be updated - :param OnUpdate on_update: Determines what action to take if an application update is required - :param OnSchemaBreak on_schema_break: Determines what action to take if an application schema requirements - has increased beyond the current allocation - :param dict[str, int|str|bytes] template_values: Values to use for `TMPL_*` template variables, dictionary keys - should *NOT* include the TMPL_ prefix - :param algokit_utils.DeployCallArgs | None create_args: Arguments used when creating an application - :param algokit_utils.DeployCallArgs | None update_args: Arguments used when updating an application - :param algokit_utils.DeployCallArgs | None delete_args: Arguments used when deleting an application - :return DeployResponse: details action taken and relevant transactions - :raises DeploymentError: If the deployment failed""" - - return self.app_client.deploy( - version, - signer=signer, - sender=sender, - allow_update=allow_update, - allow_delete=allow_delete, - on_update=on_update, - on_schema_break=on_schema_break, - template_values=template_values, - create_args=_convert_deploy_args(create_args), - update_args=_convert_deploy_args(update_args), - delete_args=_convert_deploy_args(delete_args), - ) - - def compose(self, atc: AtomicTransactionComposer | None = None) -> Composer: - return Composer(self.app_client, atc or AtomicTransactionComposer()) From 108718472b685844ffc1dd8e31b82daf6e7f9c67 Mon Sep 17 00:00:00 2001 From: "Chris Kim (Hyunggun)" Date: Thu, 7 Nov 2024 16:44:52 -0800 Subject: [PATCH 16/23] change method names, dynamic array, tuple, lint --- .../smart_contracts/arc4_types/contract.py | 78 +- .../arc4_types/Arc4DynamicArray.approval.teal | 383 +++++++ .../arc4_types/Arc4DynamicArray.arc32.json | 88 ++ .../arc4_types/Arc4DynamicArray.clear.teal | 5 + .../arc4_types/Arc4StaticArray.approval.teal | 84 ++ .../arc4_types/Arc4StaticArray.arc32.json | 51 + .../arc4_types/Arc4StaticArray.clear.teal | 5 + .../arc4_types/Arc4Struct.approval.teal | 567 +++++++++++ .../arc4_types/Arc4Struct.arc32.json | 111 ++ .../arc4_types/Arc4Struct.clear.teal | 5 + .../arc4_types/Arc4Tuple.approval.teal | 127 +++ .../artifacts/arc4_types/Arc4Tuple.arc32.json | 75 ++ .../artifacts/arc4_types/Arc4Tuple.clear.teal | 5 + .../arc4_types/Arc4Types.approval.teal | 248 +++++ .../artifacts/arc4_types/Arc4Types.arc32.json | 173 ++++ .../artifacts/arc4_types/Arc4Types.clear.teal | 5 + .../arc4_types/TransactionTypes.approval.teal | 123 +++ .../arc4_types/TransactionTypes.arc32.json | 73 ++ .../arc4_types/TransactionTypes.clear.teal | 5 + .../arc4_types/arc4_dynamic_array_client.py | 636 ++++++++++++ .../arc4_types/arc4_static_array_client.py | 484 +++++++++ .../arc4_types/arc4_struct_client.py | 695 +++++++++++++ .../artifacts/arc4_types/arc4_tuple_client.py | 599 +++++++++++ .../artifacts/arc4_types/arc4_types_client.py | 950 ++++++++++++++++++ .../arc4_types/transaction_types_client.py | 563 +++++++++++ 25 files changed, 6106 insertions(+), 32 deletions(-) create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.approval.teal create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.arc32.json create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.clear.teal create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.approval.teal create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.arc32.json create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.clear.teal create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.approval.teal create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.arc32.json create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.clear.teal create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.approval.teal create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.arc32.json create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.clear.teal create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.approval.teal create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.arc32.json create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.clear.teal create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/TransactionTypes.approval.teal create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/TransactionTypes.arc32.json create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/TransactionTypes.clear.teal create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_dynamic_array_client.py create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_static_array_client.py create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_struct_client.py create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_tuple_client.py create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_types_client.py create mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/transaction_types_client.py diff --git a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py index 8be8277..ff026e5 100644 --- a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py +++ b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py @@ -1,15 +1,24 @@ # pyright: reportMissingModuleSource=false import typing as t -# from algopy import ARC4Contract, GlobalState, String, UInt64, arc4, urange -from algopy import * +from algopy import ( + ARC4Contract, + Global, + GlobalState, + String, + Txn, + UInt64, + arc4, + gtxn, + urange, +) from algopy.arc4 import abimethod class Arc4Types(ARC4Contract): @abimethod() - def arc4_uint64(self, a: arc4.UInt64, b: arc4.UInt64) -> arc4.UInt64: + def add_arc4_uint64(self, a: arc4.UInt64, b: arc4.UInt64) -> arc4.UInt64: """ Math operations (like a + b) are not supported on arc4.UInt64 types since they are internally represented as byte arrays in the AVM. @@ -22,7 +31,7 @@ def arc4_uint64(self, a: arc4.UInt64, b: arc4.UInt64) -> arc4.UInt64: return arc4.UInt64(c) @abimethod() - def arc4_uint_n( + def add_arc4_uint_n( self, a: arc4.UInt8, b: arc4.UInt16, c: arc4.UInt32, d: arc4.UInt64 ) -> arc4.UInt64: """ @@ -39,7 +48,7 @@ def arc4_uint_n( return arc4.UInt64(total) @abimethod() - def arc4_biguint_n( + def add_arc4_biguint_n( self, a: arc4.UInt128, b: arc4.UInt256, c: arc4.UInt512 ) -> arc4.UInt512: """ @@ -136,26 +145,33 @@ def arc4_static_array(self) -> None: """ +goodbye: t.TypeAlias = arc4.DynamicArray[arc4.String] + + class Arc4DynamicArray(ARC4Contract): + @abimethod + def goodbye(self, name: arc4.String) -> goodbye: + bye = goodbye(arc4.String("Good bye "), name) + + return bye + @abimethod() - def arc4_dynamic_array(self, name: arc4.String) -> String: + def hello(self, name: arc4.String) -> String: """ Dynamic Arrays have variable size and capacity. They are similar to native Python lists because they can also append, extend, and pop. """ dynamic_string_array = arc4.DynamicArray[arc4.String](arc4.String("Hello ")) - extension = arc4.DynamicArray[arc4.String]( - name, arc4.String("!") - ) + extension = arc4.DynamicArray[arc4.String](name, arc4.String("!")) dynamic_string_array.extend(extension) copied_dynamic_string_array = dynamic_string_array.copy() copied_dynamic_string_array.pop() copied_dynamic_string_array.pop() copied_dynamic_string_array.append(arc4.String("world!")) - + greeting = String() for x in dynamic_string_array: greeting += x.native @@ -229,60 +245,58 @@ def return_todo(self, task: arc4.String) -> Todo: return todo_to_return -contact_info_tuple = arc4.Tuple[arc4.String, arc4.String, arc4.UInt64, arc4.DynamicArray[arc4.UInt8]] # name, email, phone +contact_info_tuple = arc4.Tuple[ + arc4.String, arc4.String, arc4.UInt64 +] # name, email, phone + class Arc4Tuple(ARC4Contract): def __init__(self) -> None: - self.contact_info = GlobalState(contact_info_tuple((arc4.String(""), arc4.String(""), arc4.UInt64(0), arc4.DynamicArray[arc4.UInt8]()))) + self.contact_info = GlobalState( + contact_info_tuple((arc4.String(""), arc4.String(""), arc4.UInt64(0))) + ) @abimethod() - def add_contact_info( - self, - contact: contact_info_tuple - ) -> UInt64: + def add_contact_info(self, contact: contact_info_tuple) -> UInt64: """An arc4.Tuple is a heterogeneous collection of arc4 types.""" - name, email, phone, donate_history = contact.native + name, email, phone = contact.native assert name.native == "John Woods" assert email.native == "john@something.com" assert phone == arc4.UInt64(555_555_555) - total_donation = UInt64(0) - - for x in donate_history: - total_donation += x.native - self.contact_info.value = contact - return total_donation + return phone.native @abimethod() - def return_contact(self) -> arc4.Tuple[arc4.String, arc4.String, arc4.UInt64, arc4.DynamicArray[arc4.UInt8]]: + def return_contact(self) -> arc4.Tuple[arc4.String, arc4.String, arc4.UInt64]: """An arc4.Tuple can be returned when more than one return value is needed.""" - # arc4_tuple = arc4.Tuple((arc4.String("Alice"), arc4.String("alice@something.com"), arc4.UInt64(555_555_555))) - return self.contact_info.value + class TransactionTypes(ARC4Contract): @abimethod - def paymentTxn(self, pay:gtxn.PaymentTransaction) -> UInt64: + def payment_txn(self, pay: gtxn.PaymentTransaction) -> UInt64: assert pay.amount > 0 assert pay.receiver == Global.current_application_address assert pay.sender == Txn.sender return pay.amount - + @abimethod - def assetTransferTxn(self, asset_transfer: gtxn.AssetTransferTransaction) -> UInt64: - assert Global.current_application_address.is_opted_in(asset_transfer.xfer_asset), "Asset not opted in" + def asset_transfer_txn( + self, asset_transfer: gtxn.AssetTransferTransaction + ) -> UInt64: + assert Global.current_application_address.is_opted_in( + asset_transfer.xfer_asset + ), "Asset not opted in" assert asset_transfer.asset_amount > 0 assert asset_transfer.asset_receiver == Global.current_application_address assert asset_transfer.sender == Txn.sender return asset_transfer.asset_amount - - diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.approval.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.approval.teal new file mode 100644 index 0000000..49ced5f --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.approval.teal @@ -0,0 +1,383 @@ +#pragma version 10 + +smart_contracts.arc4_types.contract.Arc4DynamicArray.approval_program: + callsub __puya_arc4_router__ + return + + +// smart_contracts.arc4_types.contract.Arc4DynamicArray.__puya_arc4_router__() -> uint64: +__puya_arc4_router__: + proto 0 1 + txn NumAppArgs + bz __puya_arc4_router___bare_routing@7 + method "goodbye(string)string[]" + method "hello(string)string" + method "arc4_dynamic_bytes()byte[]" + txna ApplicationArgs 0 + match __puya_arc4_router___goodbye_route@2 __puya_arc4_router___hello_route@3 __puya_arc4_router___arc4_dynamic_bytes_route@4 + int 0 + retsub + +__puya_arc4_router___goodbye_route@2: + txn OnCompletion + ! + assert // OnCompletion is NoOp + txn ApplicationID + assert // is not creating + txna ApplicationArgs 1 + callsub goodbye + byte 0x151f7c75 + swap + concat + log + int 1 + retsub + +__puya_arc4_router___hello_route@3: + txn OnCompletion + ! + assert // OnCompletion is NoOp + txn ApplicationID + assert // is not creating + txna ApplicationArgs 1 + callsub hello + dup + len + itob + extract 6 2 + swap + concat + byte 0x151f7c75 + swap + concat + log + int 1 + retsub + +__puya_arc4_router___arc4_dynamic_bytes_route@4: + txn OnCompletion + ! + assert // OnCompletion is NoOp + txn ApplicationID + assert // is not creating + callsub arc4_dynamic_bytes + byte 0x151f7c75 + swap + concat + log + int 1 + retsub + +__puya_arc4_router___bare_routing@7: + txn OnCompletion + bnz __puya_arc4_router___after_if_else@11 + txn ApplicationID + ! + assert // is creating + int 1 + retsub + +__puya_arc4_router___after_if_else@11: + int 0 + retsub + + +// smart_contracts.arc4_types.contract.Arc4DynamicArray.goodbye(name: bytes) -> bytes: +goodbye: + proto 1 1 + byte 0x0004000f0009476f6f642062796520 + frame_dig -1 + concat + byte 0x0002 + swap + concat + retsub + + +// smart_contracts.arc4_types.contract.Arc4DynamicArray.hello(name: bytes) -> bytes: +hello: + proto 1 1 + frame_dig -1 + len + int 4 + + + itob + extract 6 2 + byte 0x0004 + swap + concat + frame_dig -1 + concat + byte 0x000121 + concat + byte 0x0002 + swap + concat + dup + int 0 + extract_uint16 + swap + extract 2 0 + swap + dup + int 2 + * + swap + dig 2 + len + swap + cover 3 + substring3 + byte 0x00010002000648656c6c6f20 + swap + uncover 2 + callsub dynamic_array_concat_byte_length_head + dupn 2 + callsub dynamic_array_pop_byte_length_head + bury 1 + callsub dynamic_array_pop_byte_length_head + bury 1 + byte 0x0006776f726c6421 + int 1 + callsub dynamic_array_concat_byte_length_head + pop + byte "" + swap + int 0 + extract_uint16 + int 0 + +hello_for_header@1: + frame_dig 3 + frame_dig 2 + < + bz hello_after_for@4 + frame_dig 0 + extract 2 0 + frame_dig 3 + dup + cover 2 + int 2 + * + dig 1 + swap + extract_uint16 + dup2 + extract_uint16 + int 2 + + + extract3 + extract 2 0 + frame_dig 1 + swap + concat + frame_bury 1 + int 1 + + + frame_bury 3 + b hello_for_header@1 + +hello_after_for@4: + frame_dig 1 + frame_bury 0 + retsub + + +// smart_contracts.arc4_types.contract.Arc4DynamicArray.arc4_dynamic_bytes() -> bytes: +arc4_dynamic_bytes: + proto 0 1 + byte 0x0003ffffff + byte 0x00 + replace2 2 + extract 2 0 + byte 0xaabbcc + concat + dup + len + itob + extract 6 2 + swap + concat + int 1 + callsub dynamic_array_pop_fixed_size + bury 1 + extract 2 0 + byte 0xff + concat + dup + len + itob + extract 6 2 + swap + concat + retsub + + +// _puya_lib.arc4.dynamic_array_pop_fixed_size(array: bytes, fixed_byte_size: uint64) -> bytes, bytes: +dynamic_array_pop_fixed_size: + proto 2 2 + frame_dig -2 + int 0 + extract_uint16 + int 1 + - + itob + extract 6 0 + frame_dig -2 + swap + replace2 0 + dup + len + frame_dig -1 + - + dup2 + frame_dig -1 + extract3 + cover 2 + int 0 + swap + substring3 + retsub + + +// _puya_lib.arc4.dynamic_array_pop_byte_length_head(array: bytes) -> bytes, bytes: +dynamic_array_pop_byte_length_head: + proto 1 2 + frame_dig -1 + int 0 + extract_uint16 + int 1 + - + dup + int 2 + * + frame_dig -1 + extract 2 0 + dup + dig 2 + extract_uint16 + swap + dup + len + swap + dup + dig 3 + uncover 3 + substring3 + cover 3 + dup + int 0 + dig 4 + substring3 + cover 2 + uncover 3 + int 2 + + + uncover 2 + substring3 + concat + dig 2 + itob + extract 6 2 + swap + uncover 3 + int 0 + callsub recalculate_head_for_elements_with_byte_length_head + concat + retsub + + +// _puya_lib.arc4.dynamic_array_concat_byte_length_head(array: bytes, new_items_bytes: bytes, new_items_count: uint64) -> bytes: +dynamic_array_concat_byte_length_head: + proto 3 1 + frame_dig -3 + int 0 + extract_uint16 + dup + frame_dig -1 + + + swap + int 2 + * + int 2 + + + swap + dup + itob + extract 6 2 + swap + frame_dig -3 + int 2 + dig 4 + substring3 + frame_dig -1 + int 2 + * + bzero + concat + frame_dig -3 + len + frame_dig -3 + uncover 5 + uncover 2 + substring3 + concat + frame_dig -2 + concat + swap + int 0 + callsub recalculate_head_for_elements_with_byte_length_head + concat + retsub + + +// _puya_lib.arc4.recalculate_head_for_elements_with_byte_length_head(array_head_and_tail: bytes, length: uint64, start_at_index: uint64) -> bytes: +recalculate_head_for_elements_with_byte_length_head: + proto 3 1 + frame_dig -2 + int 2 + * + dup + frame_dig -1 + int 2 + * + dup + cover 2 + frame_dig -3 + swap + extract_uint16 + frame_dig -1 + select + +recalculate_head_for_elements_with_byte_length_head_for_header@1: + frame_dig 1 + frame_dig 0 + < + bz recalculate_head_for_elements_with_byte_length_head_after_for@4 + frame_dig 2 + dup + itob + extract 6 2 + frame_dig -3 + frame_dig 1 + dup + cover 4 + uncover 2 + replace3 + dup + frame_bury -3 + dig 1 + extract_uint16 + int 2 + + + + + frame_bury 2 + int 2 + + + frame_bury 1 + b recalculate_head_for_elements_with_byte_length_head_for_header@1 + +recalculate_head_for_elements_with_byte_length_head_after_for@4: + frame_dig -3 + frame_bury 0 + retsub diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.arc32.json b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.arc32.json new file mode 100644 index 0000000..6b5c000 --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.arc32.json @@ -0,0 +1,88 @@ +{ + "hints": { + "goodbye(string)string[]": { + "call_config": { + "no_op": "CALL" + } + }, + "hello(string)string": { + "call_config": { + "no_op": "CALL" + } + }, + "arc4_dynamic_bytes()byte[]": { + "call_config": { + "no_op": "CALL" + } + } + }, + "source": { + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5LmFwcHJvdmFsX3Byb2dyYW06CiAgICBjYWxsc3ViIF9fcHV5YV9hcmM0X3JvdXRlcl9fCiAgICByZXR1cm4KCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5Ll9fcHV5YV9hcmM0X3JvdXRlcl9fKCkgLT4gdWludDY0OgpfX3B1eWFfYXJjNF9yb3V0ZXJfXzoKICAgIHByb3RvIDAgMQogICAgdHhuIE51bUFwcEFyZ3MKICAgIGJ6IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A3CiAgICBtZXRob2QgImdvb2RieWUoc3RyaW5nKXN0cmluZ1tdIgogICAgbWV0aG9kICJoZWxsbyhzdHJpbmcpc3RyaW5nIgogICAgbWV0aG9kICJhcmM0X2R5bmFtaWNfYnl0ZXMoKWJ5dGVbXSIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2dvb2RieWVfcm91dGVAMiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19oZWxsb19yb3V0ZUAzIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfZHluYW1pY19ieXRlc19yb3V0ZUA0CiAgICBpbnQgMAogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19nb29kYnllX3JvdXRlQDI6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICBjYWxsc3ViIGdvb2RieWUKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2hlbGxvX3JvdXRlQDM6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICBjYWxsc3ViIGhlbGxvCiAgICBkdXAKICAgIGxlbgogICAgaXRvYgogICAgZXh0cmFjdCA2IDIKICAgIHN3YXAKICAgIGNvbmNhdAogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9keW5hbWljX2J5dGVzX3JvdXRlQDQ6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICBjYWxsc3ViIGFyYzRfZHluYW1pY19ieXRlcwogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDc6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBibnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMQogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgICEKICAgIGFzc2VydCAvLyBpcyBjcmVhdGluZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMToKICAgIGludCAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5Lmdvb2RieWUobmFtZTogYnl0ZXMpIC0+IGJ5dGVzOgpnb29kYnllOgogICAgcHJvdG8gMSAxCiAgICBieXRlIDB4MDAwNDAwMGYwMDA5NDc2ZjZmNjQyMDYyNzk2NTIwCiAgICBmcmFtZV9kaWcgLTEKICAgIGNvbmNhdAogICAgYnl0ZSAweDAwMDIKICAgIHN3YXAKICAgIGNvbmNhdAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNER5bmFtaWNBcnJheS5oZWxsbyhuYW1lOiBieXRlcykgLT4gYnl0ZXM6CmhlbGxvOgogICAgcHJvdG8gMSAxCiAgICBmcmFtZV9kaWcgLTEKICAgIGxlbgogICAgaW50IDQKICAgICsKICAgIGl0b2IKICAgIGV4dHJhY3QgNiAyCiAgICBieXRlIDB4MDAwNAogICAgc3dhcAogICAgY29uY2F0CiAgICBmcmFtZV9kaWcgLTEKICAgIGNvbmNhdAogICAgYnl0ZSAweDAwMDEyMQogICAgY29uY2F0CiAgICBieXRlIDB4MDAwMgogICAgc3dhcAogICAgY29uY2F0CiAgICBkdXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgc3dhcAogICAgZXh0cmFjdCAyIDAKICAgIHN3YXAKICAgIGR1cAogICAgaW50IDIKICAgICoKICAgIHN3YXAKICAgIGRpZyAyCiAgICBsZW4KICAgIHN3YXAKICAgIGNvdmVyIDMKICAgIHN1YnN0cmluZzMKICAgIGJ5dGUgMHgwMDAxMDAwMjAwMDY0ODY1NmM2YzZmMjAKICAgIHN3YXAKICAgIHVuY292ZXIgMgogICAgY2FsbHN1YiBkeW5hbWljX2FycmF5X2NvbmNhdF9ieXRlX2xlbmd0aF9oZWFkCiAgICBkdXBuIDIKICAgIGNhbGxzdWIgZHluYW1pY19hcnJheV9wb3BfYnl0ZV9sZW5ndGhfaGVhZAogICAgYnVyeSAxCiAgICBjYWxsc3ViIGR5bmFtaWNfYXJyYXlfcG9wX2J5dGVfbGVuZ3RoX2hlYWQKICAgIGJ1cnkgMQogICAgYnl0ZSAweDAwMDY3NzZmNzI2YzY0MjEKICAgIGludCAxCiAgICBjYWxsc3ViIGR5bmFtaWNfYXJyYXlfY29uY2F0X2J5dGVfbGVuZ3RoX2hlYWQKICAgIHBvcAogICAgYnl0ZSAiIgogICAgc3dhcAogICAgaW50IDAKICAgIGV4dHJhY3RfdWludDE2CiAgICBpbnQgMAoKaGVsbG9fZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDMKICAgIGZyYW1lX2RpZyAyCiAgICA8CiAgICBieiBoZWxsb19hZnRlcl9mb3JANAogICAgZnJhbWVfZGlnIDAKICAgIGV4dHJhY3QgMiAwCiAgICBmcmFtZV9kaWcgMwogICAgZHVwCiAgICBjb3ZlciAyCiAgICBpbnQgMgogICAgKgogICAgZGlnIDEKICAgIHN3YXAKICAgIGV4dHJhY3RfdWludDE2CiAgICBkdXAyCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50IDIKICAgICsKICAgIGV4dHJhY3QzCiAgICBleHRyYWN0IDIgMAogICAgZnJhbWVfZGlnIDEKICAgIHN3YXAKICAgIGNvbmNhdAogICAgZnJhbWVfYnVyeSAxCiAgICBpbnQgMQogICAgKwogICAgZnJhbWVfYnVyeSAzCiAgICBiIGhlbGxvX2Zvcl9oZWFkZXJAMQoKaGVsbG9fYWZ0ZXJfZm9yQDQ6CiAgICBmcmFtZV9kaWcgMQogICAgZnJhbWVfYnVyeSAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5LmFyYzRfZHluYW1pY19ieXRlcygpIC0+IGJ5dGVzOgphcmM0X2R5bmFtaWNfYnl0ZXM6CiAgICBwcm90byAwIDEKICAgIGJ5dGUgMHgwMDAzZmZmZmZmCiAgICBieXRlIDB4MDAKICAgIHJlcGxhY2UyIDIKICAgIGV4dHJhY3QgMiAwCiAgICBieXRlIDB4YWFiYmNjCiAgICBjb25jYXQKICAgIGR1cAogICAgbGVuCiAgICBpdG9iCiAgICBleHRyYWN0IDYgMgogICAgc3dhcAogICAgY29uY2F0CiAgICBpbnQgMQogICAgY2FsbHN1YiBkeW5hbWljX2FycmF5X3BvcF9maXhlZF9zaXplCiAgICBidXJ5IDEKICAgIGV4dHJhY3QgMiAwCiAgICBieXRlIDB4ZmYKICAgIGNvbmNhdAogICAgZHVwCiAgICBsZW4KICAgIGl0b2IKICAgIGV4dHJhY3QgNiAyCiAgICBzd2FwCiAgICBjb25jYXQKICAgIHJldHN1YgoKCi8vIF9wdXlhX2xpYi5hcmM0LmR5bmFtaWNfYXJyYXlfcG9wX2ZpeGVkX3NpemUoYXJyYXk6IGJ5dGVzLCBmaXhlZF9ieXRlX3NpemU6IHVpbnQ2NCkgLT4gYnl0ZXMsIGJ5dGVzOgpkeW5hbWljX2FycmF5X3BvcF9maXhlZF9zaXplOgogICAgcHJvdG8gMiAyCiAgICBmcmFtZV9kaWcgLTIKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50IDEKICAgIC0KICAgIGl0b2IKICAgIGV4dHJhY3QgNiAwCiAgICBmcmFtZV9kaWcgLTIKICAgIHN3YXAKICAgIHJlcGxhY2UyIDAKICAgIGR1cAogICAgbGVuCiAgICBmcmFtZV9kaWcgLTEKICAgIC0KICAgIGR1cDIKICAgIGZyYW1lX2RpZyAtMQogICAgZXh0cmFjdDMKICAgIGNvdmVyIDIKICAgIGludCAwCiAgICBzd2FwCiAgICBzdWJzdHJpbmczCiAgICByZXRzdWIKCgovLyBfcHV5YV9saWIuYXJjNC5keW5hbWljX2FycmF5X3BvcF9ieXRlX2xlbmd0aF9oZWFkKGFycmF5OiBieXRlcykgLT4gYnl0ZXMsIGJ5dGVzOgpkeW5hbWljX2FycmF5X3BvcF9ieXRlX2xlbmd0aF9oZWFkOgogICAgcHJvdG8gMSAyCiAgICBmcmFtZV9kaWcgLTEKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50IDEKICAgIC0KICAgIGR1cAogICAgaW50IDIKICAgICoKICAgIGZyYW1lX2RpZyAtMQogICAgZXh0cmFjdCAyIDAKICAgIGR1cAogICAgZGlnIDIKICAgIGV4dHJhY3RfdWludDE2CiAgICBzd2FwCiAgICBkdXAKICAgIGxlbgogICAgc3dhcAogICAgZHVwCiAgICBkaWcgMwogICAgdW5jb3ZlciAzCiAgICBzdWJzdHJpbmczCiAgICBjb3ZlciAzCiAgICBkdXAKICAgIGludCAwCiAgICBkaWcgNAogICAgc3Vic3RyaW5nMwogICAgY292ZXIgMgogICAgdW5jb3ZlciAzCiAgICBpbnQgMgogICAgKwogICAgdW5jb3ZlciAyCiAgICBzdWJzdHJpbmczCiAgICBjb25jYXQKICAgIGRpZyAyCiAgICBpdG9iCiAgICBleHRyYWN0IDYgMgogICAgc3dhcAogICAgdW5jb3ZlciAzCiAgICBpbnQgMAogICAgY2FsbHN1YiByZWNhbGN1bGF0ZV9oZWFkX2Zvcl9lbGVtZW50c193aXRoX2J5dGVfbGVuZ3RoX2hlYWQKICAgIGNvbmNhdAogICAgcmV0c3ViCgoKLy8gX3B1eWFfbGliLmFyYzQuZHluYW1pY19hcnJheV9jb25jYXRfYnl0ZV9sZW5ndGhfaGVhZChhcnJheTogYnl0ZXMsIG5ld19pdGVtc19ieXRlczogYnl0ZXMsIG5ld19pdGVtc19jb3VudDogdWludDY0KSAtPiBieXRlczoKZHluYW1pY19hcnJheV9jb25jYXRfYnl0ZV9sZW5ndGhfaGVhZDoKICAgIHByb3RvIDMgMQogICAgZnJhbWVfZGlnIC0zCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGR1cAogICAgZnJhbWVfZGlnIC0xCiAgICArCiAgICBzd2FwCiAgICBpbnQgMgogICAgKgogICAgaW50IDIKICAgICsKICAgIHN3YXAKICAgIGR1cAogICAgaXRvYgogICAgZXh0cmFjdCA2IDIKICAgIHN3YXAKICAgIGZyYW1lX2RpZyAtMwogICAgaW50IDIKICAgIGRpZyA0CiAgICBzdWJzdHJpbmczCiAgICBmcmFtZV9kaWcgLTEKICAgIGludCAyCiAgICAqCiAgICBiemVybwogICAgY29uY2F0CiAgICBmcmFtZV9kaWcgLTMKICAgIGxlbgogICAgZnJhbWVfZGlnIC0zCiAgICB1bmNvdmVyIDUKICAgIHVuY292ZXIgMgogICAgc3Vic3RyaW5nMwogICAgY29uY2F0CiAgICBmcmFtZV9kaWcgLTIKICAgIGNvbmNhdAogICAgc3dhcAogICAgaW50IDAKICAgIGNhbGxzdWIgcmVjYWxjdWxhdGVfaGVhZF9mb3JfZWxlbWVudHNfd2l0aF9ieXRlX2xlbmd0aF9oZWFkCiAgICBjb25jYXQKICAgIHJldHN1YgoKCi8vIF9wdXlhX2xpYi5hcmM0LnJlY2FsY3VsYXRlX2hlYWRfZm9yX2VsZW1lbnRzX3dpdGhfYnl0ZV9sZW5ndGhfaGVhZChhcnJheV9oZWFkX2FuZF90YWlsOiBieXRlcywgbGVuZ3RoOiB1aW50NjQsIHN0YXJ0X2F0X2luZGV4OiB1aW50NjQpIC0+IGJ5dGVzOgpyZWNhbGN1bGF0ZV9oZWFkX2Zvcl9lbGVtZW50c193aXRoX2J5dGVfbGVuZ3RoX2hlYWQ6CiAgICBwcm90byAzIDEKICAgIGZyYW1lX2RpZyAtMgogICAgaW50IDIKICAgICoKICAgIGR1cAogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMgogICAgKgogICAgZHVwCiAgICBjb3ZlciAyCiAgICBmcmFtZV9kaWcgLTMKICAgIHN3YXAKICAgIGV4dHJhY3RfdWludDE2CiAgICBmcmFtZV9kaWcgLTEKICAgIHNlbGVjdAoKcmVjYWxjdWxhdGVfaGVhZF9mb3JfZWxlbWVudHNfd2l0aF9ieXRlX2xlbmd0aF9oZWFkX2Zvcl9oZWFkZXJAMToKICAgIGZyYW1lX2RpZyAxCiAgICBmcmFtZV9kaWcgMAogICAgPAogICAgYnogcmVjYWxjdWxhdGVfaGVhZF9mb3JfZWxlbWVudHNfd2l0aF9ieXRlX2xlbmd0aF9oZWFkX2FmdGVyX2ZvckA0CiAgICBmcmFtZV9kaWcgMgogICAgZHVwCiAgICBpdG9iCiAgICBleHRyYWN0IDYgMgogICAgZnJhbWVfZGlnIC0zCiAgICBmcmFtZV9kaWcgMQogICAgZHVwCiAgICBjb3ZlciA0CiAgICB1bmNvdmVyIDIKICAgIHJlcGxhY2UzCiAgICBkdXAKICAgIGZyYW1lX2J1cnkgLTMKICAgIGRpZyAxCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50IDIKICAgICsKICAgICsKICAgIGZyYW1lX2J1cnkgMgogICAgaW50IDIKICAgICsKICAgIGZyYW1lX2J1cnkgMQogICAgYiByZWNhbGN1bGF0ZV9oZWFkX2Zvcl9lbGVtZW50c193aXRoX2J5dGVfbGVuZ3RoX2hlYWRfZm9yX2hlYWRlckAxCgpyZWNhbGN1bGF0ZV9oZWFkX2Zvcl9lbGVtZW50c193aXRoX2J5dGVfbGVuZ3RoX2hlYWRfYWZ0ZXJfZm9yQDQ6CiAgICBmcmFtZV9kaWcgLTMKICAgIGZyYW1lX2J1cnkgMAogICAgcmV0c3ViCg==", + "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5LmNsZWFyX3N0YXRlX3Byb2dyYW06CiAgICBpbnQgMQogICAgcmV0dXJuCg==" + }, + "state": { + "global": { + "num_byte_slices": 0, + "num_uints": 0 + }, + "local": { + "num_byte_slices": 0, + "num_uints": 0 + } + }, + "schema": { + "global": { + "declared": {}, + "reserved": {} + }, + "local": { + "declared": {}, + "reserved": {} + } + }, + "contract": { + "name": "Arc4DynamicArray", + "methods": [ + { + "name": "goodbye", + "args": [ + { + "type": "string", + "name": "name" + } + ], + "readonly": false, + "returns": { + "type": "string[]" + } + }, + { + "name": "hello", + "args": [ + { + "type": "string", + "name": "name" + } + ], + "readonly": false, + "returns": { + "type": "string" + }, + "desc": "Dynamic Arrays have variable size and capacity.\nThey are similar to native Python lists because they can also append, extend, and pop." + }, + { + "name": "arc4_dynamic_bytes", + "args": [], + "readonly": false, + "returns": { + "type": "byte[]" + }, + "desc": "arc4.DynamicBytes are essentially an arc4.DynamicArray[arc4.Bytes] and some convenience methods." + } + ], + "networks": {} + }, + "bare_call_config": { + "no_op": "CREATE" + } +} \ No newline at end of file diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.clear.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.clear.teal new file mode 100644 index 0000000..ac284db --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.clear.teal @@ -0,0 +1,5 @@ +#pragma version 10 + +smart_contracts.arc4_types.contract.Arc4DynamicArray.clear_state_program: + int 1 + return diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.approval.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.approval.teal new file mode 100644 index 0000000..1521f1e --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.approval.teal @@ -0,0 +1,84 @@ +#pragma version 10 + +smart_contracts.arc4_types.contract.Arc4StaticArray.approval_program: + callsub __puya_arc4_router__ + return + + +// smart_contracts.arc4_types.contract.Arc4StaticArray.__puya_arc4_router__() -> uint64: +__puya_arc4_router__: + proto 0 1 + txn NumAppArgs + bz __puya_arc4_router___bare_routing@5 + method "arc4_static_array()void" + txna ApplicationArgs 0 + match __puya_arc4_router___arc4_static_array_route@2 + int 0 + retsub + +__puya_arc4_router___arc4_static_array_route@2: + txn OnCompletion + ! + assert // OnCompletion is NoOp + txn ApplicationID + assert // is not creating + callsub arc4_static_array + int 1 + retsub + +__puya_arc4_router___bare_routing@5: + txn OnCompletion + bnz __puya_arc4_router___after_if_else@9 + txn ApplicationID + ! + assert // is creating + int 1 + retsub + +__puya_arc4_router___after_if_else@9: + int 0 + retsub + + +// smart_contracts.arc4_types.contract.Arc4StaticArray.arc4_static_array() -> void: +arc4_static_array: + proto 0 0 + int 0 + dup + +arc4_static_array_for_header@1: + frame_dig 1 + int 4 + < + bz arc4_static_array_after_for@4 + frame_dig 1 + dup + int 4 + * + byte 0x000000010000000a000000ff00000080 + swap + int 4 + extract3 // on error: Index access is out of bounds + btoi + frame_dig 0 + + + frame_bury 0 + int 1 + + + frame_bury 1 + b arc4_static_array_for_header@1 + +arc4_static_array_after_for@4: + frame_dig 0 + int 394 + == + assert + byte 0x65 + byte 0xca + replace2 0 + extract 0 1 // on error: Index access is out of bounds + btoi + int 202 + == + assert + retsub diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.arc32.json b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.arc32.json new file mode 100644 index 0000000..1148733 --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.arc32.json @@ -0,0 +1,51 @@ +{ + "hints": { + "arc4_static_array()void": { + "call_config": { + "no_op": "CALL" + } + } + }, + "source": { + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RhdGljQXJyYXkuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRTdGF0aWNBcnJheS5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANQogICAgbWV0aG9kICJhcmM0X3N0YXRpY19hcnJheSgpdm9pZCIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfc3RhdGljX2FycmF5X3JvdXRlQDIKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfc3RhdGljX2FycmF5X3JvdXRlQDI6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICBjYWxsc3ViIGFyYzRfc3RhdGljX2FycmF5CiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANToKICAgIHR4biBPbkNvbXBsZXRpb24KICAgIGJueiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDkKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICAhCiAgICBhc3NlcnQgLy8gaXMgY3JlYXRpbmcKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAOToKICAgIGludCAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RhdGljQXJyYXkuYXJjNF9zdGF0aWNfYXJyYXkoKSAtPiB2b2lkOgphcmM0X3N0YXRpY19hcnJheToKICAgIHByb3RvIDAgMAogICAgaW50IDAKICAgIGR1cAoKYXJjNF9zdGF0aWNfYXJyYXlfZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDEKICAgIGludCA0CiAgICA8CiAgICBieiBhcmM0X3N0YXRpY19hcnJheV9hZnRlcl9mb3JANAogICAgZnJhbWVfZGlnIDEKICAgIGR1cAogICAgaW50IDQKICAgICoKICAgIGJ5dGUgMHgwMDAwMDAwMTAwMDAwMDBhMDAwMDAwZmYwMDAwMDA4MAogICAgc3dhcAogICAgaW50IDQKICAgIGV4dHJhY3QzIC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgYnRvaQogICAgZnJhbWVfZGlnIDAKICAgICsKICAgIGZyYW1lX2J1cnkgMAogICAgaW50IDEKICAgICsKICAgIGZyYW1lX2J1cnkgMQogICAgYiBhcmM0X3N0YXRpY19hcnJheV9mb3JfaGVhZGVyQDEKCmFyYzRfc3RhdGljX2FycmF5X2FmdGVyX2ZvckA0OgogICAgZnJhbWVfZGlnIDAKICAgIGludCAzOTQKICAgID09CiAgICBhc3NlcnQKICAgIGJ5dGUgMHg2NQogICAgYnl0ZSAweGNhCiAgICByZXBsYWNlMiAwCiAgICBleHRyYWN0IDAgMSAvLyBvbiBlcnJvcjogSW5kZXggYWNjZXNzIGlzIG91dCBvZiBib3VuZHMKICAgIGJ0b2kKICAgIGludCAyMDIKICAgID09CiAgICBhc3NlcnQKICAgIHJldHN1Ygo=", + "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RhdGljQXJyYXkuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" + }, + "state": { + "global": { + "num_byte_slices": 0, + "num_uints": 0 + }, + "local": { + "num_byte_slices": 0, + "num_uints": 0 + } + }, + "schema": { + "global": { + "declared": {}, + "reserved": {} + }, + "local": { + "declared": {}, + "reserved": {} + } + }, + "contract": { + "name": "Arc4StaticArray", + "methods": [ + { + "name": "arc4_static_array", + "args": [], + "readonly": false, + "returns": { + "type": "void" + }, + "desc": "You can create a static array directly from the contract." + } + ], + "networks": {} + }, + "bare_call_config": { + "no_op": "CREATE" + } +} \ No newline at end of file diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.clear.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.clear.teal new file mode 100644 index 0000000..2fb8183 --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4StaticArray.clear.teal @@ -0,0 +1,5 @@ +#pragma version 10 + +smart_contracts.arc4_types.contract.Arc4StaticArray.clear_state_program: + int 1 + return diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.approval.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.approval.teal new file mode 100644 index 0000000..d3bb36e --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.approval.teal @@ -0,0 +1,567 @@ +#pragma version 10 + +smart_contracts.arc4_types.contract.Arc4Struct.approval_program: + txn ApplicationID + bnz main_entrypoint@2 + callsub __init__ + +main_entrypoint@2: + callsub __puya_arc4_router__ + return + + +// smart_contracts.arc4_types.contract.Arc4Struct.__puya_arc4_router__() -> uint64: +__puya_arc4_router__: + proto 0 1 + txn NumAppArgs + bz __puya_arc4_router___bare_routing@7 + method "add_todo(string)(string,bool)[]" + method "complete_todo(string)void" + method "return_todo(string)(string,bool)" + txna ApplicationArgs 0 + match __puya_arc4_router___add_todo_route@2 __puya_arc4_router___complete_todo_route@3 __puya_arc4_router___return_todo_route@4 + int 0 + retsub + +__puya_arc4_router___add_todo_route@2: + txn OnCompletion + ! + assert // OnCompletion is NoOp + txn ApplicationID + assert // is not creating + txna ApplicationArgs 1 + callsub add_todo + byte 0x151f7c75 + swap + concat + log + int 1 + retsub + +__puya_arc4_router___complete_todo_route@3: + txn OnCompletion + ! + assert // OnCompletion is NoOp + txn ApplicationID + assert // is not creating + txna ApplicationArgs 1 + callsub complete_todo + int 1 + retsub + +__puya_arc4_router___return_todo_route@4: + txn OnCompletion + ! + assert // OnCompletion is NoOp + txn ApplicationID + assert // is not creating + txna ApplicationArgs 1 + callsub return_todo + byte 0x151f7c75 + swap + concat + log + int 1 + retsub + +__puya_arc4_router___bare_routing@7: + txn OnCompletion + bnz __puya_arc4_router___after_if_else@11 + txn ApplicationID + ! + assert // is creating + int 1 + retsub + +__puya_arc4_router___after_if_else@11: + int 0 + retsub + + +// smart_contracts.arc4_types.contract.Arc4Struct.add_todo(task: bytes) -> bytes: +add_todo: + proto 1 1 + byte 0x000300 + frame_dig -1 + concat + int 0 + byte "todos" + app_global_get_ex + assert // check self.todos exists + byte 0x0000 + == + bz add_todo_else_body@2 + byte 0x0002 + swap + concat + byte 0x0001 + swap + concat + byte "todos" + swap + app_global_put + b add_todo_after_if_else@3 + +add_todo_else_body@2: + int 0 + byte "todos" + app_global_get_ex + assert // check self.todos exists + byte 0x0002 + uncover 2 + concat + swap + dup + int 0 + extract_uint16 + swap + extract 2 0 + int 1 + uncover 3 + callsub dynamic_array_concat_dynamic_element + byte "todos" + swap + app_global_put + +add_todo_after_if_else@3: + int 0 + byte "todos" + app_global_get_ex + assert // check self.todos exists + retsub + + +// smart_contracts.arc4_types.contract.Arc4Struct.complete_todo(task: bytes) -> void: +complete_todo: + proto 1 0 + byte "" + dup + int 0 + byte "todos" + app_global_get_ex + assert // check self.todos exists + int 0 + extract_uint16 + int 0 + +complete_todo_for_header@1: + frame_dig 3 + frame_dig 2 + < + bz complete_todo_after_for@6 + int 0 + byte "todos" + app_global_get_ex + assert // check self.todos exists + dup + extract 2 0 + frame_dig 3 + dup + cover 3 + int 2 + * + dup + frame_bury 0 + dig 1 + swap + extract_uint16 + cover 3 + swap + int 0 + extract_uint16 + uncover 2 + int 1 + + + dup + cover 4 + dup + cover 2 + - // on error: Index access is out of bounds + swap + dig 2 + len + cover 2 + int 2 + * + dup + frame_bury 1 + dig 3 + swap + extract_uint16 + swap + select + swap + cover 2 + substring3 + dup + int 0 + extract_uint16 + swap + dup + len + swap + cover 2 + substring3 + frame_dig -1 + == + bz complete_todo_after_if_else@4 + int 0 + byte "todos" + app_global_get_ex + assert // check self.todos exists + dup + extract 2 0 + dup + frame_dig 0 + extract_uint16 + cover 2 + swap + int 0 + extract_uint16 + uncover 3 + - // on error: Index access is out of bounds + dig 1 + len + swap + dig 2 + frame_dig 1 + extract_uint16 + swap + select + swap + cover 2 + substring3 + int 16 + int 1 + setbit + int 0 + byte "todos" + app_global_get_ex + assert // check self.todos exists + swap + frame_dig 3 + callsub dynamic_array_replace_dynamic_element + byte "todos" + swap + app_global_put + b complete_todo_after_for@6 + +complete_todo_after_if_else@4: + frame_bury 3 + b complete_todo_for_header@1 + +complete_todo_after_for@6: + retsub + + +// smart_contracts.arc4_types.contract.Arc4Struct.return_todo(task: bytes) -> bytes: +return_todo: + proto 1 1 + int 0 + byte "" + dup + int 0 + dup + byte "todos" + app_global_get_ex + assert // check self.todos exists + int 0 + extract_uint16 + int 0 + +return_todo_for_header@1: + frame_dig 5 + frame_dig 4 + < + bz return_todo_after_for@6 + int 0 + byte "todos" + app_global_get_ex + assert // check self.todos exists + dup + extract 2 0 + frame_dig 5 + dup + cover 3 + int 2 + * + dup + frame_bury 1 + dig 1 + swap + extract_uint16 + cover 3 + swap + int 0 + extract_uint16 + uncover 2 + int 1 + + + dup + frame_bury 5 + dup + cover 2 + - // on error: Index access is out of bounds + swap + dig 2 + len + cover 2 + int 2 + * + dup + frame_bury 2 + dig 3 + swap + extract_uint16 + swap + select + swap + cover 2 + substring3 + dup + int 0 + extract_uint16 + swap + dup + len + swap + cover 2 + substring3 + frame_dig -1 + == + bz return_todo_for_header@1 + int 0 + byte "todos" + app_global_get_ex + assert // check self.todos exists + dup + extract 2 0 + dup + frame_dig 1 + extract_uint16 + cover 2 + swap + int 0 + extract_uint16 + frame_dig 5 + - // on error: Index access is out of bounds + dig 1 + len + swap + dig 2 + frame_dig 2 + extract_uint16 + swap + select + swap + cover 2 + substring3 + frame_bury 0 + int 1 + frame_bury 3 + b return_todo_for_header@1 + +return_todo_after_for@6: + frame_dig 3 + assert + retsub + + +// smart_contracts.arc4_types.contract.Arc4Struct.__init__() -> void: +__init__: + proto 0 0 + byte "todos" + byte 0x0000 + app_global_put + retsub + + +// _puya_lib.arc4.dynamic_array_concat_dynamic_element(array_items_count: uint64, array_head_and_tail: bytes, new_items_count: uint64, new_head_and_tail: bytes) -> bytes: +dynamic_array_concat_dynamic_element: + proto 4 1 + byte "" + byte 0x + frame_dig -2 + int 2 + * + frame_dig -4 + int 2 + * + int 0 + +dynamic_array_concat_dynamic_element_for_header@1: + frame_dig 4 + frame_dig 3 + < + bz dynamic_array_concat_dynamic_element_after_for@4 + frame_dig -3 + frame_dig 4 + dup + cover 2 + extract_uint16 + frame_dig 2 + + + itob + extract 6 2 + frame_dig 1 + swap + concat + frame_bury 1 + int 2 + + + frame_bury 4 + b dynamic_array_concat_dynamic_element_for_header@1 + +dynamic_array_concat_dynamic_element_after_for@4: + frame_dig -3 + len + frame_bury 0 + int 0 + frame_bury 4 + +dynamic_array_concat_dynamic_element_for_header@5: + frame_dig 4 + frame_dig 2 + < + bz dynamic_array_concat_dynamic_element_after_for@8 + frame_dig -1 + frame_dig 4 + dup + cover 2 + extract_uint16 + frame_dig 0 + + + itob + extract 6 2 + frame_dig 1 + swap + concat + frame_bury 1 + int 2 + + + frame_bury 4 + b dynamic_array_concat_dynamic_element_for_header@5 + +dynamic_array_concat_dynamic_element_after_for@8: + frame_dig -4 + frame_dig -2 + + + itob + extract 6 2 + frame_dig 1 + concat + frame_dig -3 + frame_dig 3 + frame_dig 0 + substring3 + concat + frame_dig -1 + len + frame_dig -1 + frame_dig 2 + uncover 2 + substring3 + concat + frame_bury 0 + retsub + + +// _puya_lib.arc4.dynamic_array_replace_dynamic_element(source: bytes, new_item: bytes, index: uint64) -> bytes: +dynamic_array_replace_dynamic_element: + proto 3 1 + frame_dig -3 + substring 0 2 + dup + btoi + frame_dig -3 + extract 2 0 + frame_dig -2 + frame_dig -1 + uncover 3 + callsub static_array_replace_dynamic_element + concat + retsub + + +// _puya_lib.arc4.static_array_replace_dynamic_element(array_head_and_tail: bytes, new_item: bytes, index: uint64, array_length: uint64) -> bytes: +static_array_replace_dynamic_element: + proto 4 1 + frame_dig -2 + int 2 + * + frame_dig -4 + swap + extract_uint16 + frame_dig -2 + int 1 + + + int 2 + * + dup + cover 2 + frame_dig -4 + swap + extract_uint16 + frame_dig -4 + len + frame_dig -1 + frame_dig -2 + - + int 1 + - + dig 1 + uncover 3 + uncover 2 + select + dup + dig 3 + - + cover 3 + frame_dig -3 + len + cover 3 + frame_dig -4 + int 0 + uncover 4 + substring3 + frame_dig -3 + concat + frame_dig -4 + uncover 2 + uncover 3 + substring3 + concat + frame_dig -1 + int 2 + * + +static_array_replace_dynamic_element_for_header@1: + frame_dig 0 + frame_dig 4 + < + bz static_array_replace_dynamic_element_after_for@4 + frame_dig 3 + dup + frame_dig 0 + dup + cover 3 + extract_uint16 + frame_dig 2 + + + frame_dig 1 + - + itob + extract 6 2 + dig 2 + swap + replace3 + frame_bury 3 + int 2 + + + frame_bury 0 + b static_array_replace_dynamic_element_for_header@1 + +static_array_replace_dynamic_element_after_for@4: + frame_dig 3 + frame_bury 0 + retsub diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.arc32.json b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.arc32.json new file mode 100644 index 0000000..581543c --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.arc32.json @@ -0,0 +1,111 @@ +{ + "hints": { + "add_todo(string)(string,bool)[]": { + "call_config": { + "no_op": "CALL" + } + }, + "complete_todo(string)void": { + "call_config": { + "no_op": "CALL" + } + }, + "return_todo(string)(string,bool)": { + "call_config": { + "no_op": "CALL" + }, + "structs": { + "output": { + "name": "Todo", + "elements": [ + [ + "task", + "string" + ], + [ + "completed", + "bool" + ] + ] + } + } + } + }, + "source": { + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RydWN0LmFwcHJvdmFsX3Byb2dyYW06CiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYm56IG1haW5fZW50cnlwb2ludEAyCiAgICBjYWxsc3ViIF9faW5pdF9fCgptYWluX2VudHJ5cG9pbnRAMjoKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRTdHJ1Y3QuX19wdXlhX2FyYzRfcm91dGVyX18oKSAtPiB1aW50NjQ6Cl9fcHV5YV9hcmM0X3JvdXRlcl9fOgogICAgcHJvdG8gMCAxCiAgICB0eG4gTnVtQXBwQXJncwogICAgYnogX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDcKICAgIG1ldGhvZCAiYWRkX3RvZG8oc3RyaW5nKShzdHJpbmcsYm9vbClbXSIKICAgIG1ldGhvZCAiY29tcGxldGVfdG9kbyhzdHJpbmcpdm9pZCIKICAgIG1ldGhvZCAicmV0dXJuX3RvZG8oc3RyaW5nKShzdHJpbmcsYm9vbCkiCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAwCiAgICBtYXRjaCBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZGRfdG9kb19yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2NvbXBsZXRlX3RvZG9fcm91dGVAMyBfX3B1eWFfYXJjNF9yb3V0ZXJfX19yZXR1cm5fdG9kb19yb3V0ZUA0CiAgICBpbnQgMAogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZGRfdG9kb19yb3V0ZUAyOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgY2FsbHN1YiBhZGRfdG9kbwogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fY29tcGxldGVfdG9kb19yb3V0ZUAzOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgY2FsbHN1YiBjb21wbGV0ZV90b2RvCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19yZXR1cm5fdG9kb19yb3V0ZUA0OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgY2FsbHN1YiByZXR1cm5fdG9kbwogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDc6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBibnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMQogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgICEKICAgIGFzc2VydCAvLyBpcyBjcmVhdGluZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMToKICAgIGludCAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RydWN0LmFkZF90b2RvKHRhc2s6IGJ5dGVzKSAtPiBieXRlczoKYWRkX3RvZG86CiAgICBwcm90byAxIDEKICAgIGJ5dGUgMHgwMDAzMDAKICAgIGZyYW1lX2RpZyAtMQogICAgY29uY2F0CiAgICBpbnQgMAogICAgYnl0ZSAidG9kb3MiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIHNlbGYudG9kb3MgZXhpc3RzCiAgICBieXRlIDB4MDAwMAogICAgPT0KICAgIGJ6IGFkZF90b2RvX2Vsc2VfYm9keUAyCiAgICBieXRlIDB4MDAwMgogICAgc3dhcAogICAgY29uY2F0CiAgICBieXRlIDB4MDAwMQogICAgc3dhcAogICAgY29uY2F0CiAgICBieXRlICJ0b2RvcyIKICAgIHN3YXAKICAgIGFwcF9nbG9iYWxfcHV0CiAgICBiIGFkZF90b2RvX2FmdGVyX2lmX2Vsc2VAMwoKYWRkX3RvZG9fZWxzZV9ib2R5QDI6CiAgICBpbnQgMAogICAgYnl0ZSAidG9kb3MiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIHNlbGYudG9kb3MgZXhpc3RzCiAgICBieXRlIDB4MDAwMgogICAgdW5jb3ZlciAyCiAgICBjb25jYXQKICAgIHN3YXAKICAgIGR1cAogICAgaW50IDAKICAgIGV4dHJhY3RfdWludDE2CiAgICBzd2FwCiAgICBleHRyYWN0IDIgMAogICAgaW50IDEKICAgIHVuY292ZXIgMwogICAgY2FsbHN1YiBkeW5hbWljX2FycmF5X2NvbmNhdF9keW5hbWljX2VsZW1lbnQKICAgIGJ5dGUgInRvZG9zIgogICAgc3dhcAogICAgYXBwX2dsb2JhbF9wdXQKCmFkZF90b2RvX2FmdGVyX2lmX2Vsc2VAMzoKICAgIGludCAwCiAgICBieXRlICJ0b2RvcyIKICAgIGFwcF9nbG9iYWxfZ2V0X2V4CiAgICBhc3NlcnQgLy8gY2hlY2sgc2VsZi50b2RvcyBleGlzdHMKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRTdHJ1Y3QuY29tcGxldGVfdG9kbyh0YXNrOiBieXRlcykgLT4gdm9pZDoKY29tcGxldGVfdG9kbzoKICAgIHByb3RvIDEgMAogICAgYnl0ZSAiIgogICAgZHVwCiAgICBpbnQgMAogICAgYnl0ZSAidG9kb3MiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIHNlbGYudG9kb3MgZXhpc3RzCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGludCAwCgpjb21wbGV0ZV90b2RvX2Zvcl9oZWFkZXJAMToKICAgIGZyYW1lX2RpZyAzCiAgICBmcmFtZV9kaWcgMgogICAgPAogICAgYnogY29tcGxldGVfdG9kb19hZnRlcl9mb3JANgogICAgaW50IDAKICAgIGJ5dGUgInRvZG9zIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBzZWxmLnRvZG9zIGV4aXN0cwogICAgZHVwCiAgICBleHRyYWN0IDIgMAogICAgZnJhbWVfZGlnIDMKICAgIGR1cAogICAgY292ZXIgMwogICAgaW50IDIKICAgICoKICAgIGR1cAogICAgZnJhbWVfYnVyeSAwCiAgICBkaWcgMQogICAgc3dhcAogICAgZXh0cmFjdF91aW50MTYKICAgIGNvdmVyIDMKICAgIHN3YXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgdW5jb3ZlciAyCiAgICBpbnQgMQogICAgKwogICAgZHVwCiAgICBjb3ZlciA0CiAgICBkdXAKICAgIGNvdmVyIDIKICAgIC0gLy8gb24gZXJyb3I6IEluZGV4IGFjY2VzcyBpcyBvdXQgb2YgYm91bmRzCiAgICBzd2FwCiAgICBkaWcgMgogICAgbGVuCiAgICBjb3ZlciAyCiAgICBpbnQgMgogICAgKgogICAgZHVwCiAgICBmcmFtZV9idXJ5IDEKICAgIGRpZyAzCiAgICBzd2FwCiAgICBleHRyYWN0X3VpbnQxNgogICAgc3dhcAogICAgc2VsZWN0CiAgICBzd2FwCiAgICBjb3ZlciAyCiAgICBzdWJzdHJpbmczCiAgICBkdXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgc3dhcAogICAgZHVwCiAgICBsZW4KICAgIHN3YXAKICAgIGNvdmVyIDIKICAgIHN1YnN0cmluZzMKICAgIGZyYW1lX2RpZyAtMQogICAgPT0KICAgIGJ6IGNvbXBsZXRlX3RvZG9fYWZ0ZXJfaWZfZWxzZUA0CiAgICBpbnQgMAogICAgYnl0ZSAidG9kb3MiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIHNlbGYudG9kb3MgZXhpc3RzCiAgICBkdXAKICAgIGV4dHJhY3QgMiAwCiAgICBkdXAKICAgIGZyYW1lX2RpZyAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgY292ZXIgMgogICAgc3dhcAogICAgaW50IDAKICAgIGV4dHJhY3RfdWludDE2CiAgICB1bmNvdmVyIDMKICAgIC0gLy8gb24gZXJyb3I6IEluZGV4IGFjY2VzcyBpcyBvdXQgb2YgYm91bmRzCiAgICBkaWcgMQogICAgbGVuCiAgICBzd2FwCiAgICBkaWcgMgogICAgZnJhbWVfZGlnIDEKICAgIGV4dHJhY3RfdWludDE2CiAgICBzd2FwCiAgICBzZWxlY3QKICAgIHN3YXAKICAgIGNvdmVyIDIKICAgIHN1YnN0cmluZzMKICAgIGludCAxNgogICAgaW50IDEKICAgIHNldGJpdAogICAgaW50IDAKICAgIGJ5dGUgInRvZG9zIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBzZWxmLnRvZG9zIGV4aXN0cwogICAgc3dhcAogICAgZnJhbWVfZGlnIDMKICAgIGNhbGxzdWIgZHluYW1pY19hcnJheV9yZXBsYWNlX2R5bmFtaWNfZWxlbWVudAogICAgYnl0ZSAidG9kb3MiCiAgICBzd2FwCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgYiBjb21wbGV0ZV90b2RvX2FmdGVyX2ZvckA2Cgpjb21wbGV0ZV90b2RvX2FmdGVyX2lmX2Vsc2VANDoKICAgIGZyYW1lX2J1cnkgMwogICAgYiBjb21wbGV0ZV90b2RvX2Zvcl9oZWFkZXJAMQoKY29tcGxldGVfdG9kb19hZnRlcl9mb3JANjoKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRTdHJ1Y3QucmV0dXJuX3RvZG8odGFzazogYnl0ZXMpIC0+IGJ5dGVzOgpyZXR1cm5fdG9kbzoKICAgIHByb3RvIDEgMQogICAgaW50IDAKICAgIGJ5dGUgIiIKICAgIGR1cAogICAgaW50IDAKICAgIGR1cAogICAgYnl0ZSAidG9kb3MiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIHNlbGYudG9kb3MgZXhpc3RzCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGludCAwCgpyZXR1cm5fdG9kb19mb3JfaGVhZGVyQDE6CiAgICBmcmFtZV9kaWcgNQogICAgZnJhbWVfZGlnIDQKICAgIDwKICAgIGJ6IHJldHVybl90b2RvX2FmdGVyX2ZvckA2CiAgICBpbnQgMAogICAgYnl0ZSAidG9kb3MiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIHNlbGYudG9kb3MgZXhpc3RzCiAgICBkdXAKICAgIGV4dHJhY3QgMiAwCiAgICBmcmFtZV9kaWcgNQogICAgZHVwCiAgICBjb3ZlciAzCiAgICBpbnQgMgogICAgKgogICAgZHVwCiAgICBmcmFtZV9idXJ5IDEKICAgIGRpZyAxCiAgICBzd2FwCiAgICBleHRyYWN0X3VpbnQxNgogICAgY292ZXIgMwogICAgc3dhcAogICAgaW50IDAKICAgIGV4dHJhY3RfdWludDE2CiAgICB1bmNvdmVyIDIKICAgIGludCAxCiAgICArCiAgICBkdXAKICAgIGZyYW1lX2J1cnkgNQogICAgZHVwCiAgICBjb3ZlciAyCiAgICAtIC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgc3dhcAogICAgZGlnIDIKICAgIGxlbgogICAgY292ZXIgMgogICAgaW50IDIKICAgICoKICAgIGR1cAogICAgZnJhbWVfYnVyeSAyCiAgICBkaWcgMwogICAgc3dhcAogICAgZXh0cmFjdF91aW50MTYKICAgIHN3YXAKICAgIHNlbGVjdAogICAgc3dhcAogICAgY292ZXIgMgogICAgc3Vic3RyaW5nMwogICAgZHVwCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIHN3YXAKICAgIGR1cAogICAgbGVuCiAgICBzd2FwCiAgICBjb3ZlciAyCiAgICBzdWJzdHJpbmczCiAgICBmcmFtZV9kaWcgLTEKICAgID09CiAgICBieiByZXR1cm5fdG9kb19mb3JfaGVhZGVyQDEKICAgIGludCAwCiAgICBieXRlICJ0b2RvcyIKICAgIGFwcF9nbG9iYWxfZ2V0X2V4CiAgICBhc3NlcnQgLy8gY2hlY2sgc2VsZi50b2RvcyBleGlzdHMKICAgIGR1cAogICAgZXh0cmFjdCAyIDAKICAgIGR1cAogICAgZnJhbWVfZGlnIDEKICAgIGV4dHJhY3RfdWludDE2CiAgICBjb3ZlciAyCiAgICBzd2FwCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGZyYW1lX2RpZyA1CiAgICAtIC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgZGlnIDEKICAgIGxlbgogICAgc3dhcAogICAgZGlnIDIKICAgIGZyYW1lX2RpZyAyCiAgICBleHRyYWN0X3VpbnQxNgogICAgc3dhcAogICAgc2VsZWN0CiAgICBzd2FwCiAgICBjb3ZlciAyCiAgICBzdWJzdHJpbmczCiAgICBmcmFtZV9idXJ5IDAKICAgIGludCAxCiAgICBmcmFtZV9idXJ5IDMKICAgIGIgcmV0dXJuX3RvZG9fZm9yX2hlYWRlckAxCgpyZXR1cm5fdG9kb19hZnRlcl9mb3JANjoKICAgIGZyYW1lX2RpZyAzCiAgICBhc3NlcnQKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRTdHJ1Y3QuX19pbml0X18oKSAtPiB2b2lkOgpfX2luaXRfXzoKICAgIHByb3RvIDAgMAogICAgYnl0ZSAidG9kb3MiCiAgICBieXRlIDB4MDAwMAogICAgYXBwX2dsb2JhbF9wdXQKICAgIHJldHN1YgoKCi8vIF9wdXlhX2xpYi5hcmM0LmR5bmFtaWNfYXJyYXlfY29uY2F0X2R5bmFtaWNfZWxlbWVudChhcnJheV9pdGVtc19jb3VudDogdWludDY0LCBhcnJheV9oZWFkX2FuZF90YWlsOiBieXRlcywgbmV3X2l0ZW1zX2NvdW50OiB1aW50NjQsIG5ld19oZWFkX2FuZF90YWlsOiBieXRlcykgLT4gYnl0ZXM6CmR5bmFtaWNfYXJyYXlfY29uY2F0X2R5bmFtaWNfZWxlbWVudDoKICAgIHByb3RvIDQgMQogICAgYnl0ZSAiIgogICAgYnl0ZSAweAogICAgZnJhbWVfZGlnIC0yCiAgICBpbnQgMgogICAgKgogICAgZnJhbWVfZGlnIC00CiAgICBpbnQgMgogICAgKgogICAgaW50IDAKCmR5bmFtaWNfYXJyYXlfY29uY2F0X2R5bmFtaWNfZWxlbWVudF9mb3JfaGVhZGVyQDE6CiAgICBmcmFtZV9kaWcgNAogICAgZnJhbWVfZGlnIDMKICAgIDwKICAgIGJ6IGR5bmFtaWNfYXJyYXlfY29uY2F0X2R5bmFtaWNfZWxlbWVudF9hZnRlcl9mb3JANAogICAgZnJhbWVfZGlnIC0zCiAgICBmcmFtZV9kaWcgNAogICAgZHVwCiAgICBjb3ZlciAyCiAgICBleHRyYWN0X3VpbnQxNgogICAgZnJhbWVfZGlnIDIKICAgICsKICAgIGl0b2IKICAgIGV4dHJhY3QgNiAyCiAgICBmcmFtZV9kaWcgMQogICAgc3dhcAogICAgY29uY2F0CiAgICBmcmFtZV9idXJ5IDEKICAgIGludCAyCiAgICArCiAgICBmcmFtZV9idXJ5IDQKICAgIGIgZHluYW1pY19hcnJheV9jb25jYXRfZHluYW1pY19lbGVtZW50X2Zvcl9oZWFkZXJAMQoKZHluYW1pY19hcnJheV9jb25jYXRfZHluYW1pY19lbGVtZW50X2FmdGVyX2ZvckA0OgogICAgZnJhbWVfZGlnIC0zCiAgICBsZW4KICAgIGZyYW1lX2J1cnkgMAogICAgaW50IDAKICAgIGZyYW1lX2J1cnkgNAoKZHluYW1pY19hcnJheV9jb25jYXRfZHluYW1pY19lbGVtZW50X2Zvcl9oZWFkZXJANToKICAgIGZyYW1lX2RpZyA0CiAgICBmcmFtZV9kaWcgMgogICAgPAogICAgYnogZHluYW1pY19hcnJheV9jb25jYXRfZHluYW1pY19lbGVtZW50X2FmdGVyX2ZvckA4CiAgICBmcmFtZV9kaWcgLTEKICAgIGZyYW1lX2RpZyA0CiAgICBkdXAKICAgIGNvdmVyIDIKICAgIGV4dHJhY3RfdWludDE2CiAgICBmcmFtZV9kaWcgMAogICAgKwogICAgaXRvYgogICAgZXh0cmFjdCA2IDIKICAgIGZyYW1lX2RpZyAxCiAgICBzd2FwCiAgICBjb25jYXQKICAgIGZyYW1lX2J1cnkgMQogICAgaW50IDIKICAgICsKICAgIGZyYW1lX2J1cnkgNAogICAgYiBkeW5hbWljX2FycmF5X2NvbmNhdF9keW5hbWljX2VsZW1lbnRfZm9yX2hlYWRlckA1CgpkeW5hbWljX2FycmF5X2NvbmNhdF9keW5hbWljX2VsZW1lbnRfYWZ0ZXJfZm9yQDg6CiAgICBmcmFtZV9kaWcgLTQKICAgIGZyYW1lX2RpZyAtMgogICAgKwogICAgaXRvYgogICAgZXh0cmFjdCA2IDIKICAgIGZyYW1lX2RpZyAxCiAgICBjb25jYXQKICAgIGZyYW1lX2RpZyAtMwogICAgZnJhbWVfZGlnIDMKICAgIGZyYW1lX2RpZyAwCiAgICBzdWJzdHJpbmczCiAgICBjb25jYXQKICAgIGZyYW1lX2RpZyAtMQogICAgbGVuCiAgICBmcmFtZV9kaWcgLTEKICAgIGZyYW1lX2RpZyAyCiAgICB1bmNvdmVyIDIKICAgIHN1YnN0cmluZzMKICAgIGNvbmNhdAogICAgZnJhbWVfYnVyeSAwCiAgICByZXRzdWIKCgovLyBfcHV5YV9saWIuYXJjNC5keW5hbWljX2FycmF5X3JlcGxhY2VfZHluYW1pY19lbGVtZW50KHNvdXJjZTogYnl0ZXMsIG5ld19pdGVtOiBieXRlcywgaW5kZXg6IHVpbnQ2NCkgLT4gYnl0ZXM6CmR5bmFtaWNfYXJyYXlfcmVwbGFjZV9keW5hbWljX2VsZW1lbnQ6CiAgICBwcm90byAzIDEKICAgIGZyYW1lX2RpZyAtMwogICAgc3Vic3RyaW5nIDAgMgogICAgZHVwCiAgICBidG9pCiAgICBmcmFtZV9kaWcgLTMKICAgIGV4dHJhY3QgMiAwCiAgICBmcmFtZV9kaWcgLTIKICAgIGZyYW1lX2RpZyAtMQogICAgdW5jb3ZlciAzCiAgICBjYWxsc3ViIHN0YXRpY19hcnJheV9yZXBsYWNlX2R5bmFtaWNfZWxlbWVudAogICAgY29uY2F0CiAgICByZXRzdWIKCgovLyBfcHV5YV9saWIuYXJjNC5zdGF0aWNfYXJyYXlfcmVwbGFjZV9keW5hbWljX2VsZW1lbnQoYXJyYXlfaGVhZF9hbmRfdGFpbDogYnl0ZXMsIG5ld19pdGVtOiBieXRlcywgaW5kZXg6IHVpbnQ2NCwgYXJyYXlfbGVuZ3RoOiB1aW50NjQpIC0+IGJ5dGVzOgpzdGF0aWNfYXJyYXlfcmVwbGFjZV9keW5hbWljX2VsZW1lbnQ6CiAgICBwcm90byA0IDEKICAgIGZyYW1lX2RpZyAtMgogICAgaW50IDIKICAgICoKICAgIGZyYW1lX2RpZyAtNAogICAgc3dhcAogICAgZXh0cmFjdF91aW50MTYKICAgIGZyYW1lX2RpZyAtMgogICAgaW50IDEKICAgICsKICAgIGludCAyCiAgICAqCiAgICBkdXAKICAgIGNvdmVyIDIKICAgIGZyYW1lX2RpZyAtNAogICAgc3dhcAogICAgZXh0cmFjdF91aW50MTYKICAgIGZyYW1lX2RpZyAtNAogICAgbGVuCiAgICBmcmFtZV9kaWcgLTEKICAgIGZyYW1lX2RpZyAtMgogICAgLQogICAgaW50IDEKICAgIC0KICAgIGRpZyAxCiAgICB1bmNvdmVyIDMKICAgIHVuY292ZXIgMgogICAgc2VsZWN0CiAgICBkdXAKICAgIGRpZyAzCiAgICAtCiAgICBjb3ZlciAzCiAgICBmcmFtZV9kaWcgLTMKICAgIGxlbgogICAgY292ZXIgMwogICAgZnJhbWVfZGlnIC00CiAgICBpbnQgMAogICAgdW5jb3ZlciA0CiAgICBzdWJzdHJpbmczCiAgICBmcmFtZV9kaWcgLTMKICAgIGNvbmNhdAogICAgZnJhbWVfZGlnIC00CiAgICB1bmNvdmVyIDIKICAgIHVuY292ZXIgMwogICAgc3Vic3RyaW5nMwogICAgY29uY2F0CiAgICBmcmFtZV9kaWcgLTEKICAgIGludCAyCiAgICAqCgpzdGF0aWNfYXJyYXlfcmVwbGFjZV9keW5hbWljX2VsZW1lbnRfZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDAKICAgIGZyYW1lX2RpZyA0CiAgICA8CiAgICBieiBzdGF0aWNfYXJyYXlfcmVwbGFjZV9keW5hbWljX2VsZW1lbnRfYWZ0ZXJfZm9yQDQKICAgIGZyYW1lX2RpZyAzCiAgICBkdXAKICAgIGZyYW1lX2RpZyAwCiAgICBkdXAKICAgIGNvdmVyIDMKICAgIGV4dHJhY3RfdWludDE2CiAgICBmcmFtZV9kaWcgMgogICAgKwogICAgZnJhbWVfZGlnIDEKICAgIC0KICAgIGl0b2IKICAgIGV4dHJhY3QgNiAyCiAgICBkaWcgMgogICAgc3dhcAogICAgcmVwbGFjZTMKICAgIGZyYW1lX2J1cnkgMwogICAgaW50IDIKICAgICsKICAgIGZyYW1lX2J1cnkgMAogICAgYiBzdGF0aWNfYXJyYXlfcmVwbGFjZV9keW5hbWljX2VsZW1lbnRfZm9yX2hlYWRlckAxCgpzdGF0aWNfYXJyYXlfcmVwbGFjZV9keW5hbWljX2VsZW1lbnRfYWZ0ZXJfZm9yQDQ6CiAgICBmcmFtZV9kaWcgMwogICAgZnJhbWVfYnVyeSAwCiAgICByZXRzdWIK", + "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RydWN0LmNsZWFyX3N0YXRlX3Byb2dyYW06CiAgICBpbnQgMQogICAgcmV0dXJuCg==" + }, + "state": { + "global": { + "num_byte_slices": 1, + "num_uints": 0 + }, + "local": { + "num_byte_slices": 0, + "num_uints": 0 + } + }, + "schema": { + "global": { + "declared": { + "todos": { + "type": "bytes", + "key": "todos" + } + }, + "reserved": {} + }, + "local": { + "declared": {}, + "reserved": {} + } + }, + "contract": { + "name": "Arc4Struct", + "methods": [ + { + "name": "add_todo", + "args": [ + { + "type": "string", + "name": "task" + } + ], + "readonly": false, + "returns": { + "type": "(string,bool)[]" + } + }, + { + "name": "complete_todo", + "args": [ + { + "type": "string", + "name": "task" + } + ], + "readonly": false, + "returns": { + "type": "void" + } + }, + { + "name": "return_todo", + "args": [ + { + "type": "string", + "name": "task" + } + ], + "readonly": false, + "returns": { + "type": "(string,bool)" + } + } + ], + "networks": {} + }, + "bare_call_config": { + "no_op": "CREATE" + } +} \ No newline at end of file diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.clear.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.clear.teal new file mode 100644 index 0000000..095349f --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Struct.clear.teal @@ -0,0 +1,5 @@ +#pragma version 10 + +smart_contracts.arc4_types.contract.Arc4Struct.clear_state_program: + int 1 + return diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.approval.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.approval.teal new file mode 100644 index 0000000..62aadc4 --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.approval.teal @@ -0,0 +1,127 @@ +#pragma version 10 + +smart_contracts.arc4_types.contract.Arc4Tuple.approval_program: + txn ApplicationID + bnz main_entrypoint@2 + callsub __init__ + +main_entrypoint@2: + callsub __puya_arc4_router__ + return + + +// smart_contracts.arc4_types.contract.Arc4Tuple.__puya_arc4_router__() -> uint64: +__puya_arc4_router__: + proto 0 1 + txn NumAppArgs + bz __puya_arc4_router___bare_routing@6 + method "add_contact_info((string,string,uint64))uint64" + method "return_contact()(string,string,uint64)" + txna ApplicationArgs 0 + match __puya_arc4_router___add_contact_info_route@2 __puya_arc4_router___return_contact_route@3 + int 0 + retsub + +__puya_arc4_router___add_contact_info_route@2: + txn OnCompletion + ! + assert // OnCompletion is NoOp + txn ApplicationID + assert // is not creating + txna ApplicationArgs 1 + callsub add_contact_info + itob + byte 0x151f7c75 + swap + concat + log + int 1 + retsub + +__puya_arc4_router___return_contact_route@3: + txn OnCompletion + ! + assert // OnCompletion is NoOp + txn ApplicationID + assert // is not creating + callsub return_contact + byte 0x151f7c75 + swap + concat + log + int 1 + retsub + +__puya_arc4_router___bare_routing@6: + txn OnCompletion + bnz __puya_arc4_router___after_if_else@10 + txn ApplicationID + ! + assert // is creating + int 1 + retsub + +__puya_arc4_router___after_if_else@10: + int 0 + retsub + + +// smart_contracts.arc4_types.contract.Arc4Tuple.add_contact_info(contact: bytes) -> uint64: +add_contact_info: + proto 1 1 + frame_dig -1 + int 0 + extract_uint16 + frame_dig -1 + int 2 + extract_uint16 + frame_dig -1 + uncover 2 + dig 2 + substring3 + swap + frame_dig -1 + len + frame_dig -1 + cover 2 + substring3 + swap + frame_dig -1 + extract 4 8 // on error: Index access is out of bounds + cover 2 + extract 2 0 + byte "John Woods" + == + assert + extract 2 0 + byte "john@something.com" + == + assert + dup + byte 0x00000000211d1ae3 + b== + assert + byte "contact_info" + frame_dig -1 + app_global_put + btoi + retsub + + +// smart_contracts.arc4_types.contract.Arc4Tuple.return_contact() -> bytes: +return_contact: + proto 0 1 + int 0 + byte "contact_info" + app_global_get_ex + assert // check self.contact_info exists + retsub + + +// smart_contracts.arc4_types.contract.Arc4Tuple.__init__() -> void: +__init__: + proto 0 0 + byte "contact_info" + byte 0x000c000e000000000000000000000000 + app_global_put + retsub diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.arc32.json b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.arc32.json new file mode 100644 index 0000000..8b437fd --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.arc32.json @@ -0,0 +1,75 @@ +{ + "hints": { + "add_contact_info((string,string,uint64))uint64": { + "call_config": { + "no_op": "CALL" + } + }, + "return_contact()(string,string,uint64)": { + "call_config": { + "no_op": "CALL" + } + } + }, + "source": { + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHVwbGUuYXBwcm92YWxfcHJvZ3JhbToKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBibnogbWFpbl9lbnRyeXBvaW50QDIKICAgIGNhbGxzdWIgX19pbml0X18KCm1haW5fZW50cnlwb2ludEAyOgogICAgY2FsbHN1YiBfX3B1eWFfYXJjNF9yb3V0ZXJfXwogICAgcmV0dXJuCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLl9fcHV5YV9hcmM0X3JvdXRlcl9fKCkgLT4gdWludDY0OgpfX3B1eWFfYXJjNF9yb3V0ZXJfXzoKICAgIHByb3RvIDAgMQogICAgdHhuIE51bUFwcEFyZ3MKICAgIGJ6IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2CiAgICBtZXRob2QgImFkZF9jb250YWN0X2luZm8oKHN0cmluZyxzdHJpbmcsdWludDY0KSl1aW50NjQiCiAgICBtZXRob2QgInJldHVybl9jb250YWN0KCkoc3RyaW5nLHN0cmluZyx1aW50NjQpIgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAogICAgbWF0Y2ggX19wdXlhX2FyYzRfcm91dGVyX19fYWRkX2NvbnRhY3RfaW5mb19yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX3JldHVybl9jb250YWN0X3JvdXRlQDMKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FkZF9jb250YWN0X2luZm9fcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYWRkX2NvbnRhY3RfaW5mbwogICAgaXRvYgogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fcmV0dXJuX2NvbnRhY3Rfcm91dGVAMzoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIGNhbGxzdWIgcmV0dXJuX2NvbnRhY3QKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgYm56IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTAKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICAhCiAgICBhc3NlcnQgLy8gaXMgY3JlYXRpbmcKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTA6CiAgICBpbnQgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLmFkZF9jb250YWN0X2luZm8oY29udGFjdDogYnl0ZXMpIC0+IHVpbnQ2NDoKYWRkX2NvbnRhY3RfaW5mbzoKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDIKICAgIGV4dHJhY3RfdWludDE2CiAgICBmcmFtZV9kaWcgLTEKICAgIHVuY292ZXIgMgogICAgZGlnIDIKICAgIHN1YnN0cmluZzMKICAgIHN3YXAKICAgIGZyYW1lX2RpZyAtMQogICAgbGVuCiAgICBmcmFtZV9kaWcgLTEKICAgIGNvdmVyIDIKICAgIHN1YnN0cmluZzMKICAgIHN3YXAKICAgIGZyYW1lX2RpZyAtMQogICAgZXh0cmFjdCA0IDggLy8gb24gZXJyb3I6IEluZGV4IGFjY2VzcyBpcyBvdXQgb2YgYm91bmRzCiAgICBjb3ZlciAyCiAgICBleHRyYWN0IDIgMAogICAgYnl0ZSAiSm9obiBXb29kcyIKICAgID09CiAgICBhc3NlcnQKICAgIGV4dHJhY3QgMiAwCiAgICBieXRlICJqb2huQHNvbWV0aGluZy5jb20iCiAgICA9PQogICAgYXNzZXJ0CiAgICBkdXAKICAgIGJ5dGUgMHgwMDAwMDAwMDIxMWQxYWUzCiAgICBiPT0KICAgIGFzc2VydAogICAgYnl0ZSAiY29udGFjdF9pbmZvIgogICAgZnJhbWVfZGlnIC0xCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgYnRvaQogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLnJldHVybl9jb250YWN0KCkgLT4gYnl0ZXM6CnJldHVybl9jb250YWN0OgogICAgcHJvdG8gMCAxCiAgICBpbnQgMAogICAgYnl0ZSAiY29udGFjdF9pbmZvIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBzZWxmLmNvbnRhY3RfaW5mbyBleGlzdHMKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUdXBsZS5fX2luaXRfXygpIC0+IHZvaWQ6Cl9faW5pdF9fOgogICAgcHJvdG8gMCAwCiAgICBieXRlICJjb250YWN0X2luZm8iCiAgICBieXRlIDB4MDAwYzAwMGUwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAKICAgIGFwcF9nbG9iYWxfcHV0CiAgICByZXRzdWIK", + "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHVwbGUuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" + }, + "state": { + "global": { + "num_byte_slices": 1, + "num_uints": 0 + }, + "local": { + "num_byte_slices": 0, + "num_uints": 0 + } + }, + "schema": { + "global": { + "declared": { + "contact_info": { + "type": "bytes", + "key": "contact_info" + } + }, + "reserved": {} + }, + "local": { + "declared": {}, + "reserved": {} + } + }, + "contract": { + "name": "Arc4Tuple", + "methods": [ + { + "name": "add_contact_info", + "args": [ + { + "type": "(string,string,uint64)", + "name": "contact" + } + ], + "readonly": false, + "returns": { + "type": "uint64" + }, + "desc": "An arc4.Tuple is a heterogeneous collection of arc4 types." + }, + { + "name": "return_contact", + "args": [], + "readonly": false, + "returns": { + "type": "(string,string,uint64)" + }, + "desc": "An arc4.Tuple can be returned when more than one return value is needed." + } + ], + "networks": {} + }, + "bare_call_config": { + "no_op": "CREATE" + } +} \ No newline at end of file diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.clear.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.clear.teal new file mode 100644 index 0000000..3150069 --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.clear.teal @@ -0,0 +1,5 @@ +#pragma version 10 + +smart_contracts.arc4_types.contract.Arc4Tuple.clear_state_program: + int 1 + return diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.approval.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.approval.teal new file mode 100644 index 0000000..14e2e59 --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.approval.teal @@ -0,0 +1,248 @@ +#pragma version 10 + +smart_contracts.arc4_types.contract.Arc4Types.approval_program: + callsub __puya_arc4_router__ + return + + +// smart_contracts.arc4_types.contract.Arc4Types.__puya_arc4_router__() -> uint64: +__puya_arc4_router__: + proto 0 1 + txn NumAppArgs + bz __puya_arc4_router___bare_routing@10 + method "add_arc4_uint64(uint64,uint64)uint64" + method "add_arc4_uint_n(uint8,uint16,uint32,uint64)uint64" + method "add_arc4_biguint_n(uint128,uint256,uint512)uint512" + method "arc4_byte(byte)byte" + method "arc4_address_properties(address)uint64" + method "arc4_address_return(address)address" + txna ApplicationArgs 0 + match __puya_arc4_router___add_arc4_uint64_route@2 __puya_arc4_router___add_arc4_uint_n_route@3 __puya_arc4_router___add_arc4_biguint_n_route@4 __puya_arc4_router___arc4_byte_route@5 __puya_arc4_router___arc4_address_properties_route@6 __puya_arc4_router___arc4_address_return_route@7 + int 0 + retsub + +__puya_arc4_router___add_arc4_uint64_route@2: + txn OnCompletion + ! + assert // OnCompletion is NoOp + txn ApplicationID + assert // is not creating + txna ApplicationArgs 1 + txna ApplicationArgs 2 + callsub add_arc4_uint64 + byte 0x151f7c75 + swap + concat + log + int 1 + retsub + +__puya_arc4_router___add_arc4_uint_n_route@3: + txn OnCompletion + ! + assert // OnCompletion is NoOp + txn ApplicationID + assert // is not creating + txna ApplicationArgs 1 + txna ApplicationArgs 2 + txna ApplicationArgs 3 + txna ApplicationArgs 4 + callsub add_arc4_uint_n + byte 0x151f7c75 + swap + concat + log + int 1 + retsub + +__puya_arc4_router___add_arc4_biguint_n_route@4: + txn OnCompletion + ! + assert // OnCompletion is NoOp + txn ApplicationID + assert // is not creating + txna ApplicationArgs 1 + txna ApplicationArgs 2 + txna ApplicationArgs 3 + callsub add_arc4_biguint_n + byte 0x151f7c75 + swap + concat + log + int 1 + retsub + +__puya_arc4_router___arc4_byte_route@5: + txn OnCompletion + ! + assert // OnCompletion is NoOp + txn ApplicationID + assert // is not creating + txna ApplicationArgs 1 + callsub arc4_byte + byte 0x151f7c75 + swap + concat + log + int 1 + retsub + +__puya_arc4_router___arc4_address_properties_route@6: + txn OnCompletion + ! + assert // OnCompletion is NoOp + txn ApplicationID + assert // is not creating + txna ApplicationArgs 1 + callsub arc4_address_properties + itob + byte 0x151f7c75 + swap + concat + log + int 1 + retsub + +__puya_arc4_router___arc4_address_return_route@7: + txn OnCompletion + ! + assert // OnCompletion is NoOp + txn ApplicationID + assert // is not creating + txna ApplicationArgs 1 + callsub arc4_address_return + byte 0x151f7c75 + swap + concat + log + int 1 + retsub + +__puya_arc4_router___bare_routing@10: + txn OnCompletion + bnz __puya_arc4_router___after_if_else@14 + txn ApplicationID + ! + assert // is creating + int 1 + retsub + +__puya_arc4_router___after_if_else@14: + int 0 + retsub + + +// smart_contracts.arc4_types.contract.Arc4Types.add_arc4_uint64(a: bytes, b: bytes) -> bytes: +add_arc4_uint64: + proto 2 1 + frame_dig -2 + btoi + frame_dig -1 + btoi + + + itob + retsub + + +// smart_contracts.arc4_types.contract.Arc4Types.add_arc4_uint_n(a: bytes, b: bytes, c: bytes, d: bytes) -> bytes: +add_arc4_uint_n: + proto 4 1 + frame_dig -4 + len + int 1 + == + assert + frame_dig -3 + len + int 2 + == + assert + frame_dig -2 + len + int 4 + == + assert + frame_dig -1 + len + int 8 + == + assert + frame_dig -4 + btoi + frame_dig -3 + btoi + + + frame_dig -2 + btoi + + + frame_dig -1 + btoi + + + itob + retsub + + +// smart_contracts.arc4_types.contract.Arc4Types.add_arc4_biguint_n(a: bytes, b: bytes, c: bytes) -> bytes: +add_arc4_biguint_n: + proto 3 1 + frame_dig -3 + len + int 16 + == + assert + frame_dig -2 + len + int 32 + == + assert + frame_dig -1 + len + int 64 + == + assert + frame_dig -3 + frame_dig -2 + b+ + frame_dig -1 + b+ + dup + len + int 64 + <= + assert // overflow + int 64 + bzero + b| + retsub + + +// smart_contracts.arc4_types.contract.Arc4Types.arc4_byte(a: bytes) -> bytes: +arc4_byte: + proto 1 1 + frame_dig -1 + btoi + int 1 + + + itob + extract 7 1 + retsub + + +// smart_contracts.arc4_types.contract.Arc4Types.arc4_address_properties(address: bytes) -> uint64: +arc4_address_properties: + proto 1 1 + frame_dig -1 + acct_params_get AcctBalance + assert // account funded + frame_dig -1 + acct_params_get AcctTotalAssets + bury 1 + assert // account funded + retsub + + +// smart_contracts.arc4_types.contract.Arc4Types.arc4_address_return(address: bytes) -> bytes: +arc4_address_return: + proto 1 1 + frame_dig -1 + retsub diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.arc32.json b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.arc32.json new file mode 100644 index 0000000..8bc4cbf --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.arc32.json @@ -0,0 +1,173 @@ +{ + "hints": { + "add_arc4_uint64(uint64,uint64)uint64": { + "call_config": { + "no_op": "CALL" + } + }, + "add_arc4_uint_n(uint8,uint16,uint32,uint64)uint64": { + "call_config": { + "no_op": "CALL" + } + }, + "add_arc4_biguint_n(uint128,uint256,uint512)uint512": { + "call_config": { + "no_op": "CALL" + } + }, + "arc4_byte(byte)byte": { + "call_config": { + "no_op": "CALL" + } + }, + "arc4_address_properties(address)uint64": { + "call_config": { + "no_op": "CALL" + } + }, + "arc4_address_return(address)address": { + "call_config": { + "no_op": "CALL" + } + } + }, + "source": { + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdAMTAKICAgIG1ldGhvZCAiYWRkX2FyYzRfdWludDY0KHVpbnQ2NCx1aW50NjQpdWludDY0IgogICAgbWV0aG9kICJhZGRfYXJjNF91aW50X24odWludDgsdWludDE2LHVpbnQzMix1aW50NjQpdWludDY0IgogICAgbWV0aG9kICJhZGRfYXJjNF9iaWd1aW50X24odWludDEyOCx1aW50MjU2LHVpbnQ1MTIpdWludDUxMiIKICAgIG1ldGhvZCAiYXJjNF9ieXRlKGJ5dGUpYnl0ZSIKICAgIG1ldGhvZCAiYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXMoYWRkcmVzcyl1aW50NjQiCiAgICBtZXRob2QgImFyYzRfYWRkcmVzc19yZXR1cm4oYWRkcmVzcylhZGRyZXNzIgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAogICAgbWF0Y2ggX19wdXlhX2FyYzRfcm91dGVyX19fYWRkX2FyYzRfdWludDY0X3JvdXRlQDIgX19wdXlhX2FyYzRfcm91dGVyX19fYWRkX2FyYzRfdWludF9uX3JvdXRlQDMgX19wdXlhX2FyYzRfcm91dGVyX19fYWRkX2FyYzRfYmlndWludF9uX3JvdXRlQDQgX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9ieXRlX3JvdXRlQDUgX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXNfcm91dGVANiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2FkZHJlc3NfcmV0dXJuX3JvdXRlQDcKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FkZF9hcmM0X3VpbnQ2NF9yb3V0ZUAyOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMgogICAgY2FsbHN1YiBhZGRfYXJjNF91aW50NjQKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FkZF9hcmM0X3VpbnRfbl9yb3V0ZUAzOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgNAogICAgY2FsbHN1YiBhZGRfYXJjNF91aW50X24KICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FkZF9hcmM0X2JpZ3VpbnRfbl9yb3V0ZUA0OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMwogICAgY2FsbHN1YiBhZGRfYXJjNF9iaWd1aW50X24KICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYnl0ZV9yb3V0ZUA1OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgY2FsbHN1YiBhcmM0X2J5dGUKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYWRkcmVzc19wcm9wZXJ0aWVzX3JvdXRlQDY6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICBjYWxsc3ViIGFyYzRfYWRkcmVzc19wcm9wZXJ0aWVzCiAgICBpdG9iCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2FkZHJlc3NfcmV0dXJuX3JvdXRlQDc6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICBjYWxsc3ViIGFyYzRfYWRkcmVzc19yZXR1cm4KICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0AxMDoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgIGJueiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDE0CiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgIQogICAgYXNzZXJ0IC8vIGlzIGNyZWF0aW5nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDE0OgogICAgaW50IDAKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hZGRfYXJjNF91aW50NjQoYTogYnl0ZXMsIGI6IGJ5dGVzKSAtPiBieXRlczoKYWRkX2FyYzRfdWludDY0OgogICAgcHJvdG8gMiAxCiAgICBmcmFtZV9kaWcgLTIKICAgIGJ0b2kKICAgIGZyYW1lX2RpZyAtMQogICAgYnRvaQogICAgKwogICAgaXRvYgogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFkZF9hcmM0X3VpbnRfbihhOiBieXRlcywgYjogYnl0ZXMsIGM6IGJ5dGVzLCBkOiBieXRlcykgLT4gYnl0ZXM6CmFkZF9hcmM0X3VpbnRfbjoKICAgIHByb3RvIDQgMQogICAgZnJhbWVfZGlnIC00CiAgICBsZW4KICAgIGludCAxCiAgICA9PQogICAgYXNzZXJ0CiAgICBmcmFtZV9kaWcgLTMKICAgIGxlbgogICAgaW50IDIKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMgogICAgbGVuCiAgICBpbnQgNAogICAgPT0KICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0xCiAgICBsZW4KICAgIGludCA4CiAgICA9PQogICAgYXNzZXJ0CiAgICBmcmFtZV9kaWcgLTQKICAgIGJ0b2kKICAgIGZyYW1lX2RpZyAtMwogICAgYnRvaQogICAgKwogICAgZnJhbWVfZGlnIC0yCiAgICBidG9pCiAgICArCiAgICBmcmFtZV9kaWcgLTEKICAgIGJ0b2kKICAgICsKICAgIGl0b2IKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hZGRfYXJjNF9iaWd1aW50X24oYTogYnl0ZXMsIGI6IGJ5dGVzLCBjOiBieXRlcykgLT4gYnl0ZXM6CmFkZF9hcmM0X2JpZ3VpbnRfbjoKICAgIHByb3RvIDMgMQogICAgZnJhbWVfZGlnIC0zCiAgICBsZW4KICAgIGludCAxNgogICAgPT0KICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0yCiAgICBsZW4KICAgIGludCAzMgogICAgPT0KICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0xCiAgICBsZW4KICAgIGludCA2NAogICAgPT0KICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0zCiAgICBmcmFtZV9kaWcgLTIKICAgIGIrCiAgICBmcmFtZV9kaWcgLTEKICAgIGIrCiAgICBkdXAKICAgIGxlbgogICAgaW50IDY0CiAgICA8PQogICAgYXNzZXJ0IC8vIG92ZXJmbG93CiAgICBpbnQgNjQKICAgIGJ6ZXJvCiAgICBifAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFyYzRfYnl0ZShhOiBieXRlcykgLT4gYnl0ZXM6CmFyYzRfYnl0ZToKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBidG9pCiAgICBpbnQgMQogICAgKwogICAgaXRvYgogICAgZXh0cmFjdCA3IDEKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X2FkZHJlc3NfcHJvcGVydGllcyhhZGRyZXNzOiBieXRlcykgLT4gdWludDY0OgphcmM0X2FkZHJlc3NfcHJvcGVydGllczoKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBhY2N0X3BhcmFtc19nZXQgQWNjdEJhbGFuY2UKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgZnJhbWVfZGlnIC0xCiAgICBhY2N0X3BhcmFtc19nZXQgQWNjdFRvdGFsQXNzZXRzCiAgICBidXJ5IDEKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFyYzRfYWRkcmVzc19yZXR1cm4oYWRkcmVzczogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X2FkZHJlc3NfcmV0dXJuOgogICAgcHJvdG8gMSAxCiAgICBmcmFtZV9kaWcgLTEKICAgIHJldHN1Ygo=", + "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" + }, + "state": { + "global": { + "num_byte_slices": 0, + "num_uints": 0 + }, + "local": { + "num_byte_slices": 0, + "num_uints": 0 + } + }, + "schema": { + "global": { + "declared": {}, + "reserved": {} + }, + "local": { + "declared": {}, + "reserved": {} + } + }, + "contract": { + "name": "Arc4Types", + "methods": [ + { + "name": "add_arc4_uint64", + "args": [ + { + "type": "uint64", + "name": "a" + }, + { + "type": "uint64", + "name": "b" + } + ], + "readonly": false, + "returns": { + "type": "uint64" + }, + "desc": "Math operations (like a + b) are not supported on arc4.UInt64 types\nsince they are internally represented as byte arrays in the AVM. Use the .native property to perform arithmetic operations." + }, + { + "name": "add_arc4_uint_n", + "args": [ + { + "type": "uint8", + "name": "a" + }, + { + "type": "uint16", + "name": "b" + }, + { + "type": "uint32", + "name": "c" + }, + { + "type": "uint64", + "name": "d" + } + ], + "readonly": false, + "returns": { + "type": "uint64" + }, + "desc": "The encoding of arc4 integers will be smaller if it uses fewer bits.\nUltimately, they are all represented with native UInt64." + }, + { + "name": "add_arc4_biguint_n", + "args": [ + { + "type": "uint128", + "name": "a" + }, + { + "type": "uint256", + "name": "b" + }, + { + "type": "uint512", + "name": "c" + } + ], + "readonly": false, + "returns": { + "type": "uint512" + }, + "desc": "Integers with larger bit size are supported up to 512 bits.\nUltimately, they are all represented with native BigUInt." + }, + { + "name": "arc4_byte", + "args": [ + { + "type": "byte", + "name": "a" + } + ], + "readonly": false, + "returns": { + "type": "byte" + }, + "desc": "An arc4.Byte is essentially an alias for an 8-bit integer." + }, + { + "name": "arc4_address_properties", + "args": [ + { + "type": "address", + "name": "address" + } + ], + "readonly": false, + "returns": { + "type": "uint64" + } + }, + { + "name": "arc4_address_return", + "args": [ + { + "type": "address", + "name": "address" + } + ], + "readonly": false, + "returns": { + "type": "address" + } + } + ], + "networks": {} + }, + "bare_call_config": { + "no_op": "CREATE" + } +} \ No newline at end of file diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.clear.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.clear.teal new file mode 100644 index 0000000..7b46465 --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Types.clear.teal @@ -0,0 +1,5 @@ +#pragma version 10 + +smart_contracts.arc4_types.contract.Arc4Types.clear_state_program: + int 1 + return diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/TransactionTypes.approval.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/TransactionTypes.approval.teal new file mode 100644 index 0000000..3cad3aa --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/TransactionTypes.approval.teal @@ -0,0 +1,123 @@ +#pragma version 10 + +smart_contracts.arc4_types.contract.TransactionTypes.approval_program: + callsub __puya_arc4_router__ + return + + +// smart_contracts.arc4_types.contract.TransactionTypes.__puya_arc4_router__() -> uint64: +__puya_arc4_router__: + proto 0 1 + txn NumAppArgs + bz __puya_arc4_router___bare_routing@6 + method "payment_txn(pay)uint64" + method "asset_transfer_txn(axfer)uint64" + txna ApplicationArgs 0 + match __puya_arc4_router___payment_txn_route@2 __puya_arc4_router___asset_transfer_txn_route@3 + int 0 + retsub + +__puya_arc4_router___payment_txn_route@2: + txn OnCompletion + ! + assert // OnCompletion is NoOp + txn ApplicationID + assert // is not creating + txn GroupIndex + int 1 + - + dup + gtxns TypeEnum + int pay + == + assert // transaction type is pay + callsub payment_txn + itob + byte 0x151f7c75 + swap + concat + log + int 1 + retsub + +__puya_arc4_router___asset_transfer_txn_route@3: + txn OnCompletion + ! + assert // OnCompletion is NoOp + txn ApplicationID + assert // is not creating + txn GroupIndex + int 1 + - + dup + gtxns TypeEnum + int axfer + == + assert // transaction type is axfer + callsub asset_transfer_txn + itob + byte 0x151f7c75 + swap + concat + log + int 1 + retsub + +__puya_arc4_router___bare_routing@6: + txn OnCompletion + bnz __puya_arc4_router___after_if_else@10 + txn ApplicationID + ! + assert // is creating + int 1 + retsub + +__puya_arc4_router___after_if_else@10: + int 0 + retsub + + +// smart_contracts.arc4_types.contract.TransactionTypes.payment_txn(pay: uint64) -> uint64: +payment_txn: + proto 1 1 + frame_dig -1 + gtxns Amount + dup + assert + frame_dig -1 + gtxns Receiver + global CurrentApplicationAddress + == + assert + frame_dig -1 + gtxns Sender + txn Sender + == + assert + retsub + + +// smart_contracts.arc4_types.contract.TransactionTypes.asset_transfer_txn(asset_transfer: uint64) -> uint64: +asset_transfer_txn: + proto 1 1 + global CurrentApplicationAddress + frame_dig -1 + gtxns XferAsset + asset_holding_get AssetBalance + bury 1 + assert // Asset not opted in + frame_dig -1 + gtxns AssetAmount + dup + assert + frame_dig -1 + gtxns AssetReceiver + global CurrentApplicationAddress + == + assert + frame_dig -1 + gtxns Sender + txn Sender + == + assert + retsub diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/TransactionTypes.arc32.json b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/TransactionTypes.arc32.json new file mode 100644 index 0000000..047ca0c --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/TransactionTypes.arc32.json @@ -0,0 +1,73 @@ +{ + "hints": { + "payment_txn(pay)uint64": { + "call_config": { + "no_op": "CALL" + } + }, + "asset_transfer_txn(axfer)uint64": { + "call_config": { + "no_op": "CALL" + } + } + }, + "source": { + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5UcmFuc2FjdGlvblR5cGVzLmFwcHJvdmFsX3Byb2dyYW06CiAgICBjYWxsc3ViIF9fcHV5YV9hcmM0X3JvdXRlcl9fCiAgICByZXR1cm4KCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5UcmFuc2FjdGlvblR5cGVzLl9fcHV5YV9hcmM0X3JvdXRlcl9fKCkgLT4gdWludDY0OgpfX3B1eWFfYXJjNF9yb3V0ZXJfXzoKICAgIHByb3RvIDAgMQogICAgdHhuIE51bUFwcEFyZ3MKICAgIGJ6IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2CiAgICBtZXRob2QgInBheW1lbnRfdHhuKHBheSl1aW50NjQiCiAgICBtZXRob2QgImFzc2V0X3RyYW5zZmVyX3R4bihheGZlcil1aW50NjQiCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAwCiAgICBtYXRjaCBfX3B1eWFfYXJjNF9yb3V0ZXJfX19wYXltZW50X3R4bl9yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2Fzc2V0X3RyYW5zZmVyX3R4bl9yb3V0ZUAzCiAgICBpbnQgMAogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19wYXltZW50X3R4bl9yb3V0ZUAyOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuIEdyb3VwSW5kZXgKICAgIGludCAxCiAgICAtCiAgICBkdXAKICAgIGd0eG5zIFR5cGVFbnVtCiAgICBpbnQgcGF5CiAgICA9PQogICAgYXNzZXJ0IC8vIHRyYW5zYWN0aW9uIHR5cGUgaXMgcGF5CiAgICBjYWxsc3ViIHBheW1lbnRfdHhuCiAgICBpdG9iCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hc3NldF90cmFuc2Zlcl90eG5fcm91dGVAMzoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4biBHcm91cEluZGV4CiAgICBpbnQgMQogICAgLQogICAgZHVwCiAgICBndHhucyBUeXBlRW51bQogICAgaW50IGF4ZmVyCiAgICA9PQogICAgYXNzZXJ0IC8vIHRyYW5zYWN0aW9uIHR5cGUgaXMgYXhmZXIKICAgIGNhbGxzdWIgYXNzZXRfdHJhbnNmZXJfdHhuCiAgICBpdG9iCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgIGJueiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDEwCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgIQogICAgYXNzZXJ0IC8vIGlzIGNyZWF0aW5nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDEwOgogICAgaW50IDAKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LlRyYW5zYWN0aW9uVHlwZXMucGF5bWVudF90eG4ocGF5OiB1aW50NjQpIC0+IHVpbnQ2NDoKcGF5bWVudF90eG46CiAgICBwcm90byAxIDEKICAgIGZyYW1lX2RpZyAtMQogICAgZ3R4bnMgQW1vdW50CiAgICBkdXAKICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0xCiAgICBndHhucyBSZWNlaXZlcgogICAgZ2xvYmFsIEN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMQogICAgZ3R4bnMgU2VuZGVyCiAgICB0eG4gU2VuZGVyCiAgICA9PQogICAgYXNzZXJ0CiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5UcmFuc2FjdGlvblR5cGVzLmFzc2V0X3RyYW5zZmVyX3R4bihhc3NldF90cmFuc2ZlcjogdWludDY0KSAtPiB1aW50NjQ6CmFzc2V0X3RyYW5zZmVyX3R4bjoKICAgIHByb3RvIDEgMQogICAgZ2xvYmFsIEN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MKICAgIGZyYW1lX2RpZyAtMQogICAgZ3R4bnMgWGZlckFzc2V0CiAgICBhc3NldF9ob2xkaW5nX2dldCBBc3NldEJhbGFuY2UKICAgIGJ1cnkgMQogICAgYXNzZXJ0IC8vIEFzc2V0IG5vdCBvcHRlZCBpbgogICAgZnJhbWVfZGlnIC0xCiAgICBndHhucyBBc3NldEFtb3VudAogICAgZHVwCiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMQogICAgZ3R4bnMgQXNzZXRSZWNlaXZlcgogICAgZ2xvYmFsIEN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMQogICAgZ3R4bnMgU2VuZGVyCiAgICB0eG4gU2VuZGVyCiAgICA9PQogICAgYXNzZXJ0CiAgICByZXRzdWIK", + "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5UcmFuc2FjdGlvblR5cGVzLmNsZWFyX3N0YXRlX3Byb2dyYW06CiAgICBpbnQgMQogICAgcmV0dXJuCg==" + }, + "state": { + "global": { + "num_byte_slices": 0, + "num_uints": 0 + }, + "local": { + "num_byte_slices": 0, + "num_uints": 0 + } + }, + "schema": { + "global": { + "declared": {}, + "reserved": {} + }, + "local": { + "declared": {}, + "reserved": {} + } + }, + "contract": { + "name": "TransactionTypes", + "methods": [ + { + "name": "payment_txn", + "args": [ + { + "type": "pay", + "name": "pay" + } + ], + "readonly": false, + "returns": { + "type": "uint64" + } + }, + { + "name": "asset_transfer_txn", + "args": [ + { + "type": "axfer", + "name": "asset_transfer" + } + ], + "readonly": false, + "returns": { + "type": "uint64" + } + } + ], + "networks": {} + }, + "bare_call_config": { + "no_op": "CREATE" + } +} \ No newline at end of file diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/TransactionTypes.clear.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/TransactionTypes.clear.teal new file mode 100644 index 0000000..fc120bb --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/TransactionTypes.clear.teal @@ -0,0 +1,5 @@ +#pragma version 10 + +smart_contracts.arc4_types.contract.TransactionTypes.clear_state_program: + int 1 + return diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_dynamic_array_client.py b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_dynamic_array_client.py new file mode 100644 index 0000000..4e88aab --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_dynamic_array_client.py @@ -0,0 +1,636 @@ +# flake8: noqa +# fmt: off +# mypy: disable-error-code="no-any-return, no-untyped-call, misc, type-arg" +# This file was automatically generated by algokit-client-generator. +# DO NOT MODIFY IT BY HAND. +# requires: algokit-utils@^1.2.0 +import base64 +import dataclasses +import decimal +import typing +from abc import ABC, abstractmethod + +import algokit_utils +import algosdk +from algosdk.v2client import models +from algosdk.atomic_transaction_composer import ( + AtomicTransactionComposer, + AtomicTransactionResponse, + SimulateAtomicTransactionResponse, + TransactionSigner, + TransactionWithSigner +) + +_APP_SPEC_JSON = r"""{ + "hints": { + "goodbye(string)string[]": { + "call_config": { + "no_op": "CALL" + } + }, + "hello(string)string": { + "call_config": { + "no_op": "CALL" + } + }, + "arc4_dynamic_bytes()byte[]": { + "call_config": { + "no_op": "CALL" + } + } + }, + "source": { + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5LmFwcHJvdmFsX3Byb2dyYW06CiAgICBjYWxsc3ViIF9fcHV5YV9hcmM0X3JvdXRlcl9fCiAgICByZXR1cm4KCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5Ll9fcHV5YV9hcmM0X3JvdXRlcl9fKCkgLT4gdWludDY0OgpfX3B1eWFfYXJjNF9yb3V0ZXJfXzoKICAgIHByb3RvIDAgMQogICAgdHhuIE51bUFwcEFyZ3MKICAgIGJ6IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A3CiAgICBtZXRob2QgImdvb2RieWUoc3RyaW5nKXN0cmluZ1tdIgogICAgbWV0aG9kICJoZWxsbyhzdHJpbmcpc3RyaW5nIgogICAgbWV0aG9kICJhcmM0X2R5bmFtaWNfYnl0ZXMoKWJ5dGVbXSIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2dvb2RieWVfcm91dGVAMiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19oZWxsb19yb3V0ZUAzIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfZHluYW1pY19ieXRlc19yb3V0ZUA0CiAgICBpbnQgMAogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19nb29kYnllX3JvdXRlQDI6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICBjYWxsc3ViIGdvb2RieWUKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2hlbGxvX3JvdXRlQDM6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICBjYWxsc3ViIGhlbGxvCiAgICBkdXAKICAgIGxlbgogICAgaXRvYgogICAgZXh0cmFjdCA2IDIKICAgIHN3YXAKICAgIGNvbmNhdAogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9keW5hbWljX2J5dGVzX3JvdXRlQDQ6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICBjYWxsc3ViIGFyYzRfZHluYW1pY19ieXRlcwogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDc6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBibnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMQogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgICEKICAgIGFzc2VydCAvLyBpcyBjcmVhdGluZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMToKICAgIGludCAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5Lmdvb2RieWUobmFtZTogYnl0ZXMpIC0+IGJ5dGVzOgpnb29kYnllOgogICAgcHJvdG8gMSAxCiAgICBieXRlIDB4MDAwNDAwMGYwMDA5NDc2ZjZmNjQyMDYyNzk2NTIwCiAgICBmcmFtZV9kaWcgLTEKICAgIGNvbmNhdAogICAgYnl0ZSAweDAwMDIKICAgIHN3YXAKICAgIGNvbmNhdAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNER5bmFtaWNBcnJheS5oZWxsbyhuYW1lOiBieXRlcykgLT4gYnl0ZXM6CmhlbGxvOgogICAgcHJvdG8gMSAxCiAgICBmcmFtZV9kaWcgLTEKICAgIGxlbgogICAgaW50IDQKICAgICsKICAgIGl0b2IKICAgIGV4dHJhY3QgNiAyCiAgICBieXRlIDB4MDAwNAogICAgc3dhcAogICAgY29uY2F0CiAgICBmcmFtZV9kaWcgLTEKICAgIGNvbmNhdAogICAgYnl0ZSAweDAwMDEyMQogICAgY29uY2F0CiAgICBieXRlIDB4MDAwMgogICAgc3dhcAogICAgY29uY2F0CiAgICBkdXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgc3dhcAogICAgZXh0cmFjdCAyIDAKICAgIHN3YXAKICAgIGR1cAogICAgaW50IDIKICAgICoKICAgIHN3YXAKICAgIGRpZyAyCiAgICBsZW4KICAgIHN3YXAKICAgIGNvdmVyIDMKICAgIHN1YnN0cmluZzMKICAgIGJ5dGUgMHgwMDAxMDAwMjAwMDY0ODY1NmM2YzZmMjAKICAgIHN3YXAKICAgIHVuY292ZXIgMgogICAgY2FsbHN1YiBkeW5hbWljX2FycmF5X2NvbmNhdF9ieXRlX2xlbmd0aF9oZWFkCiAgICBkdXBuIDIKICAgIGNhbGxzdWIgZHluYW1pY19hcnJheV9wb3BfYnl0ZV9sZW5ndGhfaGVhZAogICAgYnVyeSAxCiAgICBjYWxsc3ViIGR5bmFtaWNfYXJyYXlfcG9wX2J5dGVfbGVuZ3RoX2hlYWQKICAgIGJ1cnkgMQogICAgYnl0ZSAweDAwMDY3NzZmNzI2YzY0MjEKICAgIGludCAxCiAgICBjYWxsc3ViIGR5bmFtaWNfYXJyYXlfY29uY2F0X2J5dGVfbGVuZ3RoX2hlYWQKICAgIHBvcAogICAgYnl0ZSAiIgogICAgc3dhcAogICAgaW50IDAKICAgIGV4dHJhY3RfdWludDE2CiAgICBpbnQgMAoKaGVsbG9fZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDMKICAgIGZyYW1lX2RpZyAyCiAgICA8CiAgICBieiBoZWxsb19hZnRlcl9mb3JANAogICAgZnJhbWVfZGlnIDAKICAgIGV4dHJhY3QgMiAwCiAgICBmcmFtZV9kaWcgMwogICAgZHVwCiAgICBjb3ZlciAyCiAgICBpbnQgMgogICAgKgogICAgZGlnIDEKICAgIHN3YXAKICAgIGV4dHJhY3RfdWludDE2CiAgICBkdXAyCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50IDIKICAgICsKICAgIGV4dHJhY3QzCiAgICBleHRyYWN0IDIgMAogICAgZnJhbWVfZGlnIDEKICAgIHN3YXAKICAgIGNvbmNhdAogICAgZnJhbWVfYnVyeSAxCiAgICBpbnQgMQogICAgKwogICAgZnJhbWVfYnVyeSAzCiAgICBiIGhlbGxvX2Zvcl9oZWFkZXJAMQoKaGVsbG9fYWZ0ZXJfZm9yQDQ6CiAgICBmcmFtZV9kaWcgMQogICAgZnJhbWVfYnVyeSAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5LmFyYzRfZHluYW1pY19ieXRlcygpIC0+IGJ5dGVzOgphcmM0X2R5bmFtaWNfYnl0ZXM6CiAgICBwcm90byAwIDEKICAgIGJ5dGUgMHgwMDAzZmZmZmZmCiAgICBieXRlIDB4MDAKICAgIHJlcGxhY2UyIDIKICAgIGV4dHJhY3QgMiAwCiAgICBieXRlIDB4YWFiYmNjCiAgICBjb25jYXQKICAgIGR1cAogICAgbGVuCiAgICBpdG9iCiAgICBleHRyYWN0IDYgMgogICAgc3dhcAogICAgY29uY2F0CiAgICBpbnQgMQogICAgY2FsbHN1YiBkeW5hbWljX2FycmF5X3BvcF9maXhlZF9zaXplCiAgICBidXJ5IDEKICAgIGV4dHJhY3QgMiAwCiAgICBieXRlIDB4ZmYKICAgIGNvbmNhdAogICAgZHVwCiAgICBsZW4KICAgIGl0b2IKICAgIGV4dHJhY3QgNiAyCiAgICBzd2FwCiAgICBjb25jYXQKICAgIHJldHN1YgoKCi8vIF9wdXlhX2xpYi5hcmM0LmR5bmFtaWNfYXJyYXlfcG9wX2ZpeGVkX3NpemUoYXJyYXk6IGJ5dGVzLCBmaXhlZF9ieXRlX3NpemU6IHVpbnQ2NCkgLT4gYnl0ZXMsIGJ5dGVzOgpkeW5hbWljX2FycmF5X3BvcF9maXhlZF9zaXplOgogICAgcHJvdG8gMiAyCiAgICBmcmFtZV9kaWcgLTIKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50IDEKICAgIC0KICAgIGl0b2IKICAgIGV4dHJhY3QgNiAwCiAgICBmcmFtZV9kaWcgLTIKICAgIHN3YXAKICAgIHJlcGxhY2UyIDAKICAgIGR1cAogICAgbGVuCiAgICBmcmFtZV9kaWcgLTEKICAgIC0KICAgIGR1cDIKICAgIGZyYW1lX2RpZyAtMQogICAgZXh0cmFjdDMKICAgIGNvdmVyIDIKICAgIGludCAwCiAgICBzd2FwCiAgICBzdWJzdHJpbmczCiAgICByZXRzdWIKCgovLyBfcHV5YV9saWIuYXJjNC5keW5hbWljX2FycmF5X3BvcF9ieXRlX2xlbmd0aF9oZWFkKGFycmF5OiBieXRlcykgLT4gYnl0ZXMsIGJ5dGVzOgpkeW5hbWljX2FycmF5X3BvcF9ieXRlX2xlbmd0aF9oZWFkOgogICAgcHJvdG8gMSAyCiAgICBmcmFtZV9kaWcgLTEKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50IDEKICAgIC0KICAgIGR1cAogICAgaW50IDIKICAgICoKICAgIGZyYW1lX2RpZyAtMQogICAgZXh0cmFjdCAyIDAKICAgIGR1cAogICAgZGlnIDIKICAgIGV4dHJhY3RfdWludDE2CiAgICBzd2FwCiAgICBkdXAKICAgIGxlbgogICAgc3dhcAogICAgZHVwCiAgICBkaWcgMwogICAgdW5jb3ZlciAzCiAgICBzdWJzdHJpbmczCiAgICBjb3ZlciAzCiAgICBkdXAKICAgIGludCAwCiAgICBkaWcgNAogICAgc3Vic3RyaW5nMwogICAgY292ZXIgMgogICAgdW5jb3ZlciAzCiAgICBpbnQgMgogICAgKwogICAgdW5jb3ZlciAyCiAgICBzdWJzdHJpbmczCiAgICBjb25jYXQKICAgIGRpZyAyCiAgICBpdG9iCiAgICBleHRyYWN0IDYgMgogICAgc3dhcAogICAgdW5jb3ZlciAzCiAgICBpbnQgMAogICAgY2FsbHN1YiByZWNhbGN1bGF0ZV9oZWFkX2Zvcl9lbGVtZW50c193aXRoX2J5dGVfbGVuZ3RoX2hlYWQKICAgIGNvbmNhdAogICAgcmV0c3ViCgoKLy8gX3B1eWFfbGliLmFyYzQuZHluYW1pY19hcnJheV9jb25jYXRfYnl0ZV9sZW5ndGhfaGVhZChhcnJheTogYnl0ZXMsIG5ld19pdGVtc19ieXRlczogYnl0ZXMsIG5ld19pdGVtc19jb3VudDogdWludDY0KSAtPiBieXRlczoKZHluYW1pY19hcnJheV9jb25jYXRfYnl0ZV9sZW5ndGhfaGVhZDoKICAgIHByb3RvIDMgMQogICAgZnJhbWVfZGlnIC0zCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGR1cAogICAgZnJhbWVfZGlnIC0xCiAgICArCiAgICBzd2FwCiAgICBpbnQgMgogICAgKgogICAgaW50IDIKICAgICsKICAgIHN3YXAKICAgIGR1cAogICAgaXRvYgogICAgZXh0cmFjdCA2IDIKICAgIHN3YXAKICAgIGZyYW1lX2RpZyAtMwogICAgaW50IDIKICAgIGRpZyA0CiAgICBzdWJzdHJpbmczCiAgICBmcmFtZV9kaWcgLTEKICAgIGludCAyCiAgICAqCiAgICBiemVybwogICAgY29uY2F0CiAgICBmcmFtZV9kaWcgLTMKICAgIGxlbgogICAgZnJhbWVfZGlnIC0zCiAgICB1bmNvdmVyIDUKICAgIHVuY292ZXIgMgogICAgc3Vic3RyaW5nMwogICAgY29uY2F0CiAgICBmcmFtZV9kaWcgLTIKICAgIGNvbmNhdAogICAgc3dhcAogICAgaW50IDAKICAgIGNhbGxzdWIgcmVjYWxjdWxhdGVfaGVhZF9mb3JfZWxlbWVudHNfd2l0aF9ieXRlX2xlbmd0aF9oZWFkCiAgICBjb25jYXQKICAgIHJldHN1YgoKCi8vIF9wdXlhX2xpYi5hcmM0LnJlY2FsY3VsYXRlX2hlYWRfZm9yX2VsZW1lbnRzX3dpdGhfYnl0ZV9sZW5ndGhfaGVhZChhcnJheV9oZWFkX2FuZF90YWlsOiBieXRlcywgbGVuZ3RoOiB1aW50NjQsIHN0YXJ0X2F0X2luZGV4OiB1aW50NjQpIC0+IGJ5dGVzOgpyZWNhbGN1bGF0ZV9oZWFkX2Zvcl9lbGVtZW50c193aXRoX2J5dGVfbGVuZ3RoX2hlYWQ6CiAgICBwcm90byAzIDEKICAgIGZyYW1lX2RpZyAtMgogICAgaW50IDIKICAgICoKICAgIGR1cAogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMgogICAgKgogICAgZHVwCiAgICBjb3ZlciAyCiAgICBmcmFtZV9kaWcgLTMKICAgIHN3YXAKICAgIGV4dHJhY3RfdWludDE2CiAgICBmcmFtZV9kaWcgLTEKICAgIHNlbGVjdAoKcmVjYWxjdWxhdGVfaGVhZF9mb3JfZWxlbWVudHNfd2l0aF9ieXRlX2xlbmd0aF9oZWFkX2Zvcl9oZWFkZXJAMToKICAgIGZyYW1lX2RpZyAxCiAgICBmcmFtZV9kaWcgMAogICAgPAogICAgYnogcmVjYWxjdWxhdGVfaGVhZF9mb3JfZWxlbWVudHNfd2l0aF9ieXRlX2xlbmd0aF9oZWFkX2FmdGVyX2ZvckA0CiAgICBmcmFtZV9kaWcgMgogICAgZHVwCiAgICBpdG9iCiAgICBleHRyYWN0IDYgMgogICAgZnJhbWVfZGlnIC0zCiAgICBmcmFtZV9kaWcgMQogICAgZHVwCiAgICBjb3ZlciA0CiAgICB1bmNvdmVyIDIKICAgIHJlcGxhY2UzCiAgICBkdXAKICAgIGZyYW1lX2J1cnkgLTMKICAgIGRpZyAxCiAgICBleHRyYWN0X3VpbnQxNgogICAgaW50IDIKICAgICsKICAgICsKICAgIGZyYW1lX2J1cnkgMgogICAgaW50IDIKICAgICsKICAgIGZyYW1lX2J1cnkgMQogICAgYiByZWNhbGN1bGF0ZV9oZWFkX2Zvcl9lbGVtZW50c193aXRoX2J5dGVfbGVuZ3RoX2hlYWRfZm9yX2hlYWRlckAxCgpyZWNhbGN1bGF0ZV9oZWFkX2Zvcl9lbGVtZW50c193aXRoX2J5dGVfbGVuZ3RoX2hlYWRfYWZ0ZXJfZm9yQDQ6CiAgICBmcmFtZV9kaWcgLTMKICAgIGZyYW1lX2J1cnkgMAogICAgcmV0c3ViCg==", + "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0RHluYW1pY0FycmF5LmNsZWFyX3N0YXRlX3Byb2dyYW06CiAgICBpbnQgMQogICAgcmV0dXJuCg==" + }, + "state": { + "global": { + "num_byte_slices": 0, + "num_uints": 0 + }, + "local": { + "num_byte_slices": 0, + "num_uints": 0 + } + }, + "schema": { + "global": { + "declared": {}, + "reserved": {} + }, + "local": { + "declared": {}, + "reserved": {} + } + }, + "contract": { + "name": "Arc4DynamicArray", + "methods": [ + { + "name": "goodbye", + "args": [ + { + "type": "string", + "name": "name" + } + ], + "returns": { + "type": "string[]" + } + }, + { + "name": "hello", + "args": [ + { + "type": "string", + "name": "name" + } + ], + "returns": { + "type": "string" + }, + "desc": "Dynamic Arrays have variable size and capacity.\nThey are similar to native Python lists because they can also append, extend, and pop." + }, + { + "name": "arc4_dynamic_bytes", + "args": [], + "returns": { + "type": "byte[]" + }, + "desc": "arc4.DynamicBytes are essentially an arc4.DynamicArray[arc4.Bytes] and some convenience methods." + } + ], + "networks": {} + }, + "bare_call_config": { + "no_op": "CREATE" + } +}""" +APP_SPEC = algokit_utils.ApplicationSpecification.from_json(_APP_SPEC_JSON) +_TReturn = typing.TypeVar("_TReturn") + + +class _ArgsBase(ABC, typing.Generic[_TReturn]): + @staticmethod + @abstractmethod + def method() -> str: + ... + + +_TArgs = typing.TypeVar("_TArgs", bound=_ArgsBase[typing.Any]) + + +@dataclasses.dataclass(kw_only=True) +class _TArgsHolder(typing.Generic[_TArgs]): + args: _TArgs + + +def _filter_none(value: dict | typing.Any) -> dict | typing.Any: + if isinstance(value, dict): + return {k: _filter_none(v) for k, v in value.items() if v is not None} + return value + + +def _as_dict(data: typing.Any, *, convert_all: bool = True) -> dict[str, typing.Any]: + if data is None: + return {} + if not dataclasses.is_dataclass(data): + raise TypeError(f"{data} must be a dataclass") + if convert_all: + result = dataclasses.asdict(data) # type: ignore[call-overload] + else: + result = {f.name: getattr(data, f.name) for f in dataclasses.fields(data)} + return _filter_none(result) + + +def _convert_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, +) -> algokit_utils.TransactionParametersDict: + return typing.cast(algokit_utils.TransactionParametersDict, _as_dict(transaction_parameters)) + + +def _convert_call_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, +) -> algokit_utils.OnCompleteCallParametersDict: + return typing.cast(algokit_utils.OnCompleteCallParametersDict, _as_dict(transaction_parameters)) + + +def _convert_create_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, + on_complete: algokit_utils.OnCompleteActionName, +) -> algokit_utils.CreateCallParametersDict: + result = typing.cast(algokit_utils.CreateCallParametersDict, _as_dict(transaction_parameters)) + on_complete_enum = on_complete.replace("_", " ").title().replace(" ", "") + "OC" + result["on_complete"] = getattr(algosdk.transaction.OnComplete, on_complete_enum) + return result + + +def _convert_deploy_args( + deploy_args: algokit_utils.DeployCallArgs | None, +) -> algokit_utils.ABICreateCallArgsDict | None: + if deploy_args is None: + return None + + deploy_args_dict = typing.cast(algokit_utils.ABICreateCallArgsDict, _as_dict(deploy_args)) + if isinstance(deploy_args, _TArgsHolder): + deploy_args_dict["args"] = _as_dict(deploy_args.args) + deploy_args_dict["method"] = deploy_args.args.method() + + return deploy_args_dict + + +@dataclasses.dataclass(kw_only=True) +class GoodbyeArgs(_ArgsBase[list[str]]): + name: str + + @staticmethod + def method() -> str: + return "goodbye(string)string[]" + + +@dataclasses.dataclass(kw_only=True) +class HelloArgs(_ArgsBase[str]): + """Dynamic Arrays have variable size and capacity. + They are similar to native Python lists because they can also append, extend, and pop.""" + + name: str + + @staticmethod + def method() -> str: + return "hello(string)string" + + +@dataclasses.dataclass(kw_only=True) +class Arc4DynamicBytesArgs(_ArgsBase[bytes | bytearray]): + """arc4.DynamicBytes are essentially an arc4.DynamicArray[arc4.Bytes] and some convenience methods.""" + + @staticmethod + def method() -> str: + return "arc4_dynamic_bytes()byte[]" + + +@dataclasses.dataclass(kw_only=True) +class SimulateOptions: + allow_more_logs: bool = dataclasses.field(default=False) + allow_empty_signatures: bool = dataclasses.field(default=False) + extra_opcode_budget: int = dataclasses.field(default=0) + exec_trace_config: models.SimulateTraceConfig | None = dataclasses.field(default=None) + + +class Composer: + + def __init__(self, app_client: algokit_utils.ApplicationClient, atc: AtomicTransactionComposer): + self.app_client = app_client + self.atc = atc + + def build(self) -> AtomicTransactionComposer: + return self.atc + + def simulate(self, options: SimulateOptions | None = None) -> SimulateAtomicTransactionResponse: + request = models.SimulateRequest( + allow_more_logs=options.allow_more_logs, + allow_empty_signatures=options.allow_empty_signatures, + extra_opcode_budget=options.extra_opcode_budget, + exec_trace_config=options.exec_trace_config, + txn_groups=[] + ) if options else None + result = self.atc.simulate(self.app_client.algod_client, request) + return result + + def execute(self) -> AtomicTransactionResponse: + return self.app_client.execute_atc(self.atc) + + def goodbye( + self, + *, + name: str, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> "Composer": + """Adds a call to `goodbye(string)string[]` ABI method + + :param str name: The `name` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + args = GoodbyeArgs( + name=name, + ) + self.app_client.compose_call( + self.atc, + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return self + + def hello( + self, + *, + name: str, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> "Composer": + """Dynamic Arrays have variable size and capacity. + They are similar to native Python lists because they can also append, extend, and pop. + + Adds a call to `hello(string)string` ABI method + + :param str name: The `name` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + args = HelloArgs( + name=name, + ) + self.app_client.compose_call( + self.atc, + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return self + + def arc4_dynamic_bytes( + self, + *, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> "Composer": + """arc4.DynamicBytes are essentially an arc4.DynamicArray[arc4.Bytes] and some convenience methods. + + Adds a call to `arc4_dynamic_bytes()byte[]` ABI method + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + args = Arc4DynamicBytesArgs() + self.app_client.compose_call( + self.atc, + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return self + + def create_bare( + self, + *, + on_complete: typing.Literal["no_op"] = "no_op", + transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, + ) -> "Composer": + """Adds a call to create an application using the no_op bare method + + :param typing.Literal[no_op] on_complete: On completion type to use + :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + self.app_client.compose_create( + self.atc, + call_abi_method=False, + transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), + ) + return self + + def clear_state( + self, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + app_args: list[bytes] | None = None, + ) -> "Composer": + """Adds a call to the application with on completion set to ClearState + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :param list[bytes] | None app_args: (optional) Application args to pass""" + + self.app_client.compose_clear_state(self.atc, _convert_transaction_parameters(transaction_parameters), app_args) + return self + + +class Arc4DynamicArrayClient: + """A class for interacting with the Arc4DynamicArray app providing high productivity and + strongly typed methods to deploy and call the app""" + + @typing.overload + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + app_id: int = 0, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + ... + + @typing.overload + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + creator: str | algokit_utils.Account, + indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, + existing_deployments: algokit_utils.AppLookup | None = None, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + ... + + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + creator: str | algokit_utils.Account | None = None, + indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, + existing_deployments: algokit_utils.AppLookup | None = None, + app_id: int = 0, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + """ + Arc4DynamicArrayClient can be created with an app_id to interact with an existing application, alternatively + it can be created with a creator and indexer_client specified to find existing applications by name and creator. + + :param AlgodClient algod_client: AlgoSDK algod client + :param int app_id: The app_id of an existing application, to instead find the application by creator and name + use the creator and indexer_client parameters + :param str | Account creator: The address or Account of the app creator to resolve the app_id + :param IndexerClient indexer_client: AlgoSDK indexer client, only required if deploying or finding app_id by + creator and app name + :param AppLookup existing_deployments: + :param TransactionSigner | Account signer: Account or signer to use to sign transactions, if not specified and + creator was passed as an Account will use that. + :param str sender: Address to use as the sender for all transactions, will use the address associated with the + signer if not specified. + :param TemplateValueMapping template_values: Values to use for TMPL_* template variables, dictionary keys should + *NOT* include the TMPL_ prefix + :param str | None app_name: Name of application to use when deploying, defaults to name defined on the + Application Specification + """ + + self.app_spec = APP_SPEC + + # calling full __init__ signature, so ignoring mypy warning about overloads + self.app_client = algokit_utils.ApplicationClient( # type: ignore[call-overload, misc] + algod_client=algod_client, + app_spec=self.app_spec, + app_id=app_id, + creator=creator, + indexer_client=indexer_client, + existing_deployments=existing_deployments, + signer=signer, + sender=sender, + suggested_params=suggested_params, + template_values=template_values, + app_name=app_name, + ) + + @property + def algod_client(self) -> algosdk.v2client.algod.AlgodClient: + return self.app_client.algod_client + + @property + def app_id(self) -> int: + return self.app_client.app_id + + @app_id.setter + def app_id(self, value: int) -> None: + self.app_client.app_id = value + + @property + def app_address(self) -> str: + return self.app_client.app_address + + @property + def sender(self) -> str | None: + return self.app_client.sender + + @sender.setter + def sender(self, value: str) -> None: + self.app_client.sender = value + + @property + def signer(self) -> TransactionSigner | None: + return self.app_client.signer + + @signer.setter + def signer(self, value: TransactionSigner) -> None: + self.app_client.signer = value + + @property + def suggested_params(self) -> algosdk.transaction.SuggestedParams | None: + return self.app_client.suggested_params + + @suggested_params.setter + def suggested_params(self, value: algosdk.transaction.SuggestedParams | None) -> None: + self.app_client.suggested_params = value + + def goodbye( + self, + *, + name: str, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> algokit_utils.ABITransactionResponse[list[str]]: + """Calls `goodbye(string)string[]` ABI method + + :param str name: The `name` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.ABITransactionResponse[list[str]]: The result of the transaction""" + + args = GoodbyeArgs( + name=name, + ) + result = self.app_client.call( + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return result + + def hello( + self, + *, + name: str, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> algokit_utils.ABITransactionResponse[str]: + """Dynamic Arrays have variable size and capacity. + They are similar to native Python lists because they can also append, extend, and pop. + + Calls `hello(string)string` ABI method + + :param str name: The `name` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.ABITransactionResponse[str]: The result of the transaction""" + + args = HelloArgs( + name=name, + ) + result = self.app_client.call( + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return result + + def arc4_dynamic_bytes( + self, + *, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> algokit_utils.ABITransactionResponse[bytes | bytearray]: + """arc4.DynamicBytes are essentially an arc4.DynamicArray[arc4.Bytes] and some convenience methods. + + Calls `arc4_dynamic_bytes()byte[]` ABI method + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.ABITransactionResponse[bytes | bytearray]: The result of the transaction""" + + args = Arc4DynamicBytesArgs() + result = self.app_client.call( + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return result + + def create_bare( + self, + *, + on_complete: typing.Literal["no_op"] = "no_op", + transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, + ) -> algokit_utils.TransactionResponse: + """Creates an application using the no_op bare method + + :param typing.Literal[no_op] on_complete: On completion type to use + :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.TransactionResponse: The result of the transaction""" + + result = self.app_client.create( + call_abi_method=False, + transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), + ) + return result + + def clear_state( + self, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + app_args: list[bytes] | None = None, + ) -> algokit_utils.TransactionResponse: + """Calls the application with on completion set to ClearState + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :param list[bytes] | None app_args: (optional) Application args to pass + :returns algokit_utils.TransactionResponse: The result of the transaction""" + + return self.app_client.clear_state(_convert_transaction_parameters(transaction_parameters), app_args) + + def deploy( + self, + version: str | None = None, + *, + signer: TransactionSigner | None = None, + sender: str | None = None, + allow_update: bool | None = None, + allow_delete: bool | None = None, + on_update: algokit_utils.OnUpdate = algokit_utils.OnUpdate.Fail, + on_schema_break: algokit_utils.OnSchemaBreak = algokit_utils.OnSchemaBreak.Fail, + template_values: algokit_utils.TemplateValueMapping | None = None, + create_args: algokit_utils.DeployCallArgs | None = None, + update_args: algokit_utils.DeployCallArgs | None = None, + delete_args: algokit_utils.DeployCallArgs | None = None, + ) -> algokit_utils.DeployResponse: + """Deploy an application and update client to reference it. + + Idempotently deploy (create, update/delete if changed) an app against the given name via the given creator + account, including deploy-time template placeholder substitutions. + To understand the architecture decisions behind this functionality please see + + + ```{note} + If there is a breaking state schema change to an existing app (and `on_schema_break` is set to + 'ReplaceApp' the existing app will be deleted and re-created. + ``` + + ```{note} + If there is an update (different TEAL code) to an existing app (and `on_update` is set to 'ReplaceApp') + the existing app will be deleted and re-created. + ``` + + :param str version: version to use when creating or updating app, if None version will be auto incremented + :param algosdk.atomic_transaction_composer.TransactionSigner signer: signer to use when deploying app + , if None uses self.signer + :param str sender: sender address to use when deploying app, if None uses self.sender + :param bool allow_delete: Used to set the `TMPL_DELETABLE` template variable to conditionally control if an app + can be deleted + :param bool allow_update: Used to set the `TMPL_UPDATABLE` template variable to conditionally control if an app + can be updated + :param OnUpdate on_update: Determines what action to take if an application update is required + :param OnSchemaBreak on_schema_break: Determines what action to take if an application schema requirements + has increased beyond the current allocation + :param dict[str, int|str|bytes] template_values: Values to use for `TMPL_*` template variables, dictionary keys + should *NOT* include the TMPL_ prefix + :param algokit_utils.DeployCallArgs | None create_args: Arguments used when creating an application + :param algokit_utils.DeployCallArgs | None update_args: Arguments used when updating an application + :param algokit_utils.DeployCallArgs | None delete_args: Arguments used when deleting an application + :return DeployResponse: details action taken and relevant transactions + :raises DeploymentError: If the deployment failed""" + + return self.app_client.deploy( + version, + signer=signer, + sender=sender, + allow_update=allow_update, + allow_delete=allow_delete, + on_update=on_update, + on_schema_break=on_schema_break, + template_values=template_values, + create_args=_convert_deploy_args(create_args), + update_args=_convert_deploy_args(update_args), + delete_args=_convert_deploy_args(delete_args), + ) + + def compose(self, atc: AtomicTransactionComposer | None = None) -> Composer: + return Composer(self.app_client, atc or AtomicTransactionComposer()) diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_static_array_client.py b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_static_array_client.py new file mode 100644 index 0000000..363c953 --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_static_array_client.py @@ -0,0 +1,484 @@ +# flake8: noqa +# fmt: off +# mypy: disable-error-code="no-any-return, no-untyped-call, misc, type-arg" +# This file was automatically generated by algokit-client-generator. +# DO NOT MODIFY IT BY HAND. +# requires: algokit-utils@^1.2.0 +import base64 +import dataclasses +import decimal +import typing +from abc import ABC, abstractmethod + +import algokit_utils +import algosdk +from algosdk.v2client import models +from algosdk.atomic_transaction_composer import ( + AtomicTransactionComposer, + AtomicTransactionResponse, + SimulateAtomicTransactionResponse, + TransactionSigner, + TransactionWithSigner +) + +_APP_SPEC_JSON = r"""{ + "hints": { + "arc4_static_array()void": { + "call_config": { + "no_op": "CALL" + } + } + }, + "source": { + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RhdGljQXJyYXkuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRTdGF0aWNBcnJheS5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANQogICAgbWV0aG9kICJhcmM0X3N0YXRpY19hcnJheSgpdm9pZCIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfc3RhdGljX2FycmF5X3JvdXRlQDIKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfc3RhdGljX2FycmF5X3JvdXRlQDI6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICBjYWxsc3ViIGFyYzRfc3RhdGljX2FycmF5CiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANToKICAgIHR4biBPbkNvbXBsZXRpb24KICAgIGJueiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDkKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICAhCiAgICBhc3NlcnQgLy8gaXMgY3JlYXRpbmcKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAOToKICAgIGludCAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RhdGljQXJyYXkuYXJjNF9zdGF0aWNfYXJyYXkoKSAtPiB2b2lkOgphcmM0X3N0YXRpY19hcnJheToKICAgIHByb3RvIDAgMAogICAgaW50IDAKICAgIGR1cAoKYXJjNF9zdGF0aWNfYXJyYXlfZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDEKICAgIGludCA0CiAgICA8CiAgICBieiBhcmM0X3N0YXRpY19hcnJheV9hZnRlcl9mb3JANAogICAgZnJhbWVfZGlnIDEKICAgIGR1cAogICAgaW50IDQKICAgICoKICAgIGJ5dGUgMHgwMDAwMDAwMTAwMDAwMDBhMDAwMDAwZmYwMDAwMDA4MAogICAgc3dhcAogICAgaW50IDQKICAgIGV4dHJhY3QzIC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgYnRvaQogICAgZnJhbWVfZGlnIDAKICAgICsKICAgIGZyYW1lX2J1cnkgMAogICAgaW50IDEKICAgICsKICAgIGZyYW1lX2J1cnkgMQogICAgYiBhcmM0X3N0YXRpY19hcnJheV9mb3JfaGVhZGVyQDEKCmFyYzRfc3RhdGljX2FycmF5X2FmdGVyX2ZvckA0OgogICAgZnJhbWVfZGlnIDAKICAgIGludCAzOTQKICAgID09CiAgICBhc3NlcnQKICAgIGJ5dGUgMHg2NQogICAgYnl0ZSAweGNhCiAgICByZXBsYWNlMiAwCiAgICBleHRyYWN0IDAgMSAvLyBvbiBlcnJvcjogSW5kZXggYWNjZXNzIGlzIG91dCBvZiBib3VuZHMKICAgIGJ0b2kKICAgIGludCAyMDIKICAgID09CiAgICBhc3NlcnQKICAgIHJldHN1Ygo=", + "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RhdGljQXJyYXkuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" + }, + "state": { + "global": { + "num_byte_slices": 0, + "num_uints": 0 + }, + "local": { + "num_byte_slices": 0, + "num_uints": 0 + } + }, + "schema": { + "global": { + "declared": {}, + "reserved": {} + }, + "local": { + "declared": {}, + "reserved": {} + } + }, + "contract": { + "name": "Arc4StaticArray", + "methods": [ + { + "name": "arc4_static_array", + "args": [], + "returns": { + "type": "void" + }, + "desc": "You can create a static array directly from the contract." + } + ], + "networks": {} + }, + "bare_call_config": { + "no_op": "CREATE" + } +}""" +APP_SPEC = algokit_utils.ApplicationSpecification.from_json(_APP_SPEC_JSON) +_TReturn = typing.TypeVar("_TReturn") + + +class _ArgsBase(ABC, typing.Generic[_TReturn]): + @staticmethod + @abstractmethod + def method() -> str: + ... + + +_TArgs = typing.TypeVar("_TArgs", bound=_ArgsBase[typing.Any]) + + +@dataclasses.dataclass(kw_only=True) +class _TArgsHolder(typing.Generic[_TArgs]): + args: _TArgs + + +def _filter_none(value: dict | typing.Any) -> dict | typing.Any: + if isinstance(value, dict): + return {k: _filter_none(v) for k, v in value.items() if v is not None} + return value + + +def _as_dict(data: typing.Any, *, convert_all: bool = True) -> dict[str, typing.Any]: + if data is None: + return {} + if not dataclasses.is_dataclass(data): + raise TypeError(f"{data} must be a dataclass") + if convert_all: + result = dataclasses.asdict(data) # type: ignore[call-overload] + else: + result = {f.name: getattr(data, f.name) for f in dataclasses.fields(data)} + return _filter_none(result) + + +def _convert_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, +) -> algokit_utils.TransactionParametersDict: + return typing.cast(algokit_utils.TransactionParametersDict, _as_dict(transaction_parameters)) + + +def _convert_call_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, +) -> algokit_utils.OnCompleteCallParametersDict: + return typing.cast(algokit_utils.OnCompleteCallParametersDict, _as_dict(transaction_parameters)) + + +def _convert_create_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, + on_complete: algokit_utils.OnCompleteActionName, +) -> algokit_utils.CreateCallParametersDict: + result = typing.cast(algokit_utils.CreateCallParametersDict, _as_dict(transaction_parameters)) + on_complete_enum = on_complete.replace("_", " ").title().replace(" ", "") + "OC" + result["on_complete"] = getattr(algosdk.transaction.OnComplete, on_complete_enum) + return result + + +def _convert_deploy_args( + deploy_args: algokit_utils.DeployCallArgs | None, +) -> algokit_utils.ABICreateCallArgsDict | None: + if deploy_args is None: + return None + + deploy_args_dict = typing.cast(algokit_utils.ABICreateCallArgsDict, _as_dict(deploy_args)) + if isinstance(deploy_args, _TArgsHolder): + deploy_args_dict["args"] = _as_dict(deploy_args.args) + deploy_args_dict["method"] = deploy_args.args.method() + + return deploy_args_dict + + +@dataclasses.dataclass(kw_only=True) +class Arc4StaticArrayArgs(_ArgsBase[None]): + """You can create a static array directly from the contract.""" + + @staticmethod + def method() -> str: + return "arc4_static_array()void" + + +@dataclasses.dataclass(kw_only=True) +class SimulateOptions: + allow_more_logs: bool = dataclasses.field(default=False) + allow_empty_signatures: bool = dataclasses.field(default=False) + extra_opcode_budget: int = dataclasses.field(default=0) + exec_trace_config: models.SimulateTraceConfig | None = dataclasses.field(default=None) + + +class Composer: + + def __init__(self, app_client: algokit_utils.ApplicationClient, atc: AtomicTransactionComposer): + self.app_client = app_client + self.atc = atc + + def build(self) -> AtomicTransactionComposer: + return self.atc + + def simulate(self, options: SimulateOptions | None = None) -> SimulateAtomicTransactionResponse: + request = models.SimulateRequest( + allow_more_logs=options.allow_more_logs, + allow_empty_signatures=options.allow_empty_signatures, + extra_opcode_budget=options.extra_opcode_budget, + exec_trace_config=options.exec_trace_config, + txn_groups=[] + ) if options else None + result = self.atc.simulate(self.app_client.algod_client, request) + return result + + def execute(self) -> AtomicTransactionResponse: + return self.app_client.execute_atc(self.atc) + + def arc4_static_array( + self, + *, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> "Composer": + """You can create a static array directly from the contract. + + Adds a call to `arc4_static_array()void` ABI method + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + args = Arc4StaticArrayArgs() + self.app_client.compose_call( + self.atc, + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return self + + def create_bare( + self, + *, + on_complete: typing.Literal["no_op"] = "no_op", + transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, + ) -> "Composer": + """Adds a call to create an application using the no_op bare method + + :param typing.Literal[no_op] on_complete: On completion type to use + :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + self.app_client.compose_create( + self.atc, + call_abi_method=False, + transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), + ) + return self + + def clear_state( + self, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + app_args: list[bytes] | None = None, + ) -> "Composer": + """Adds a call to the application with on completion set to ClearState + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :param list[bytes] | None app_args: (optional) Application args to pass""" + + self.app_client.compose_clear_state(self.atc, _convert_transaction_parameters(transaction_parameters), app_args) + return self + + +class Arc4StaticArrayClient: + """A class for interacting with the Arc4StaticArray app providing high productivity and + strongly typed methods to deploy and call the app""" + + @typing.overload + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + app_id: int = 0, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + ... + + @typing.overload + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + creator: str | algokit_utils.Account, + indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, + existing_deployments: algokit_utils.AppLookup | None = None, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + ... + + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + creator: str | algokit_utils.Account | None = None, + indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, + existing_deployments: algokit_utils.AppLookup | None = None, + app_id: int = 0, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + """ + Arc4StaticArrayClient can be created with an app_id to interact with an existing application, alternatively + it can be created with a creator and indexer_client specified to find existing applications by name and creator. + + :param AlgodClient algod_client: AlgoSDK algod client + :param int app_id: The app_id of an existing application, to instead find the application by creator and name + use the creator and indexer_client parameters + :param str | Account creator: The address or Account of the app creator to resolve the app_id + :param IndexerClient indexer_client: AlgoSDK indexer client, only required if deploying or finding app_id by + creator and app name + :param AppLookup existing_deployments: + :param TransactionSigner | Account signer: Account or signer to use to sign transactions, if not specified and + creator was passed as an Account will use that. + :param str sender: Address to use as the sender for all transactions, will use the address associated with the + signer if not specified. + :param TemplateValueMapping template_values: Values to use for TMPL_* template variables, dictionary keys should + *NOT* include the TMPL_ prefix + :param str | None app_name: Name of application to use when deploying, defaults to name defined on the + Application Specification + """ + + self.app_spec = APP_SPEC + + # calling full __init__ signature, so ignoring mypy warning about overloads + self.app_client = algokit_utils.ApplicationClient( # type: ignore[call-overload, misc] + algod_client=algod_client, + app_spec=self.app_spec, + app_id=app_id, + creator=creator, + indexer_client=indexer_client, + existing_deployments=existing_deployments, + signer=signer, + sender=sender, + suggested_params=suggested_params, + template_values=template_values, + app_name=app_name, + ) + + @property + def algod_client(self) -> algosdk.v2client.algod.AlgodClient: + return self.app_client.algod_client + + @property + def app_id(self) -> int: + return self.app_client.app_id + + @app_id.setter + def app_id(self, value: int) -> None: + self.app_client.app_id = value + + @property + def app_address(self) -> str: + return self.app_client.app_address + + @property + def sender(self) -> str | None: + return self.app_client.sender + + @sender.setter + def sender(self, value: str) -> None: + self.app_client.sender = value + + @property + def signer(self) -> TransactionSigner | None: + return self.app_client.signer + + @signer.setter + def signer(self, value: TransactionSigner) -> None: + self.app_client.signer = value + + @property + def suggested_params(self) -> algosdk.transaction.SuggestedParams | None: + return self.app_client.suggested_params + + @suggested_params.setter + def suggested_params(self, value: algosdk.transaction.SuggestedParams | None) -> None: + self.app_client.suggested_params = value + + def arc4_static_array( + self, + *, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> algokit_utils.ABITransactionResponse[None]: + """You can create a static array directly from the contract. + + Calls `arc4_static_array()void` ABI method + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.ABITransactionResponse[None]: The result of the transaction""" + + args = Arc4StaticArrayArgs() + result = self.app_client.call( + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return result + + def create_bare( + self, + *, + on_complete: typing.Literal["no_op"] = "no_op", + transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, + ) -> algokit_utils.TransactionResponse: + """Creates an application using the no_op bare method + + :param typing.Literal[no_op] on_complete: On completion type to use + :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.TransactionResponse: The result of the transaction""" + + result = self.app_client.create( + call_abi_method=False, + transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), + ) + return result + + def clear_state( + self, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + app_args: list[bytes] | None = None, + ) -> algokit_utils.TransactionResponse: + """Calls the application with on completion set to ClearState + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :param list[bytes] | None app_args: (optional) Application args to pass + :returns algokit_utils.TransactionResponse: The result of the transaction""" + + return self.app_client.clear_state(_convert_transaction_parameters(transaction_parameters), app_args) + + def deploy( + self, + version: str | None = None, + *, + signer: TransactionSigner | None = None, + sender: str | None = None, + allow_update: bool | None = None, + allow_delete: bool | None = None, + on_update: algokit_utils.OnUpdate = algokit_utils.OnUpdate.Fail, + on_schema_break: algokit_utils.OnSchemaBreak = algokit_utils.OnSchemaBreak.Fail, + template_values: algokit_utils.TemplateValueMapping | None = None, + create_args: algokit_utils.DeployCallArgs | None = None, + update_args: algokit_utils.DeployCallArgs | None = None, + delete_args: algokit_utils.DeployCallArgs | None = None, + ) -> algokit_utils.DeployResponse: + """Deploy an application and update client to reference it. + + Idempotently deploy (create, update/delete if changed) an app against the given name via the given creator + account, including deploy-time template placeholder substitutions. + To understand the architecture decisions behind this functionality please see + + + ```{note} + If there is a breaking state schema change to an existing app (and `on_schema_break` is set to + 'ReplaceApp' the existing app will be deleted and re-created. + ``` + + ```{note} + If there is an update (different TEAL code) to an existing app (and `on_update` is set to 'ReplaceApp') + the existing app will be deleted and re-created. + ``` + + :param str version: version to use when creating or updating app, if None version will be auto incremented + :param algosdk.atomic_transaction_composer.TransactionSigner signer: signer to use when deploying app + , if None uses self.signer + :param str sender: sender address to use when deploying app, if None uses self.sender + :param bool allow_delete: Used to set the `TMPL_DELETABLE` template variable to conditionally control if an app + can be deleted + :param bool allow_update: Used to set the `TMPL_UPDATABLE` template variable to conditionally control if an app + can be updated + :param OnUpdate on_update: Determines what action to take if an application update is required + :param OnSchemaBreak on_schema_break: Determines what action to take if an application schema requirements + has increased beyond the current allocation + :param dict[str, int|str|bytes] template_values: Values to use for `TMPL_*` template variables, dictionary keys + should *NOT* include the TMPL_ prefix + :param algokit_utils.DeployCallArgs | None create_args: Arguments used when creating an application + :param algokit_utils.DeployCallArgs | None update_args: Arguments used when updating an application + :param algokit_utils.DeployCallArgs | None delete_args: Arguments used when deleting an application + :return DeployResponse: details action taken and relevant transactions + :raises DeploymentError: If the deployment failed""" + + return self.app_client.deploy( + version, + signer=signer, + sender=sender, + allow_update=allow_update, + allow_delete=allow_delete, + on_update=on_update, + on_schema_break=on_schema_break, + template_values=template_values, + create_args=_convert_deploy_args(create_args), + update_args=_convert_deploy_args(update_args), + delete_args=_convert_deploy_args(delete_args), + ) + + def compose(self, atc: AtomicTransactionComposer | None = None) -> Composer: + return Composer(self.app_client, atc or AtomicTransactionComposer()) diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_struct_client.py b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_struct_client.py new file mode 100644 index 0000000..041f72c --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_struct_client.py @@ -0,0 +1,695 @@ +# flake8: noqa +# fmt: off +# mypy: disable-error-code="no-any-return, no-untyped-call, misc, type-arg" +# This file was automatically generated by algokit-client-generator. +# DO NOT MODIFY IT BY HAND. +# requires: algokit-utils@^1.2.0 +import base64 +import dataclasses +import decimal +import typing +from abc import ABC, abstractmethod + +import algokit_utils +import algosdk +from algosdk.v2client import models +from algosdk.atomic_transaction_composer import ( + AtomicTransactionComposer, + AtomicTransactionResponse, + SimulateAtomicTransactionResponse, + TransactionSigner, + TransactionWithSigner +) + +_APP_SPEC_JSON = r"""{ + "hints": { + "add_todo(string)(string,bool)[]": { + "call_config": { + "no_op": "CALL" + } + }, + "complete_todo(string)void": { + "call_config": { + "no_op": "CALL" + } + }, + "return_todo(string)(string,bool)": { + "structs": { + "output": { + "name": "Todo", + "elements": [ + [ + "task", + "string" + ], + [ + "completed", + "bool" + ] + ] + } + }, + "call_config": { + "no_op": "CALL" + } + } + }, + "source": { + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RydWN0LmFwcHJvdmFsX3Byb2dyYW06CiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYm56IG1haW5fZW50cnlwb2ludEAyCiAgICBjYWxsc3ViIF9faW5pdF9fCgptYWluX2VudHJ5cG9pbnRAMjoKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRTdHJ1Y3QuX19wdXlhX2FyYzRfcm91dGVyX18oKSAtPiB1aW50NjQ6Cl9fcHV5YV9hcmM0X3JvdXRlcl9fOgogICAgcHJvdG8gMCAxCiAgICB0eG4gTnVtQXBwQXJncwogICAgYnogX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDcKICAgIG1ldGhvZCAiYWRkX3RvZG8oc3RyaW5nKShzdHJpbmcsYm9vbClbXSIKICAgIG1ldGhvZCAiY29tcGxldGVfdG9kbyhzdHJpbmcpdm9pZCIKICAgIG1ldGhvZCAicmV0dXJuX3RvZG8oc3RyaW5nKShzdHJpbmcsYm9vbCkiCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAwCiAgICBtYXRjaCBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZGRfdG9kb19yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2NvbXBsZXRlX3RvZG9fcm91dGVAMyBfX3B1eWFfYXJjNF9yb3V0ZXJfX19yZXR1cm5fdG9kb19yb3V0ZUA0CiAgICBpbnQgMAogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZGRfdG9kb19yb3V0ZUAyOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgY2FsbHN1YiBhZGRfdG9kbwogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fY29tcGxldGVfdG9kb19yb3V0ZUAzOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgY2FsbHN1YiBjb21wbGV0ZV90b2RvCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19yZXR1cm5fdG9kb19yb3V0ZUA0OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgY2FsbHN1YiByZXR1cm5fdG9kbwogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYmFyZV9yb3V0aW5nQDc6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBibnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMQogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgICEKICAgIGFzc2VydCAvLyBpcyBjcmVhdGluZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUAxMToKICAgIGludCAwCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RydWN0LmFkZF90b2RvKHRhc2s6IGJ5dGVzKSAtPiBieXRlczoKYWRkX3RvZG86CiAgICBwcm90byAxIDEKICAgIGJ5dGUgMHgwMDAzMDAKICAgIGZyYW1lX2RpZyAtMQogICAgY29uY2F0CiAgICBpbnQgMAogICAgYnl0ZSAidG9kb3MiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIHNlbGYudG9kb3MgZXhpc3RzCiAgICBieXRlIDB4MDAwMAogICAgPT0KICAgIGJ6IGFkZF90b2RvX2Vsc2VfYm9keUAyCiAgICBieXRlIDB4MDAwMgogICAgc3dhcAogICAgY29uY2F0CiAgICBieXRlIDB4MDAwMQogICAgc3dhcAogICAgY29uY2F0CiAgICBieXRlICJ0b2RvcyIKICAgIHN3YXAKICAgIGFwcF9nbG9iYWxfcHV0CiAgICBiIGFkZF90b2RvX2FmdGVyX2lmX2Vsc2VAMwoKYWRkX3RvZG9fZWxzZV9ib2R5QDI6CiAgICBpbnQgMAogICAgYnl0ZSAidG9kb3MiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIHNlbGYudG9kb3MgZXhpc3RzCiAgICBieXRlIDB4MDAwMgogICAgdW5jb3ZlciAyCiAgICBjb25jYXQKICAgIHN3YXAKICAgIGR1cAogICAgaW50IDAKICAgIGV4dHJhY3RfdWludDE2CiAgICBzd2FwCiAgICBleHRyYWN0IDIgMAogICAgaW50IDEKICAgIHVuY292ZXIgMwogICAgY2FsbHN1YiBkeW5hbWljX2FycmF5X2NvbmNhdF9keW5hbWljX2VsZW1lbnQKICAgIGJ5dGUgInRvZG9zIgogICAgc3dhcAogICAgYXBwX2dsb2JhbF9wdXQKCmFkZF90b2RvX2FmdGVyX2lmX2Vsc2VAMzoKICAgIGludCAwCiAgICBieXRlICJ0b2RvcyIKICAgIGFwcF9nbG9iYWxfZ2V0X2V4CiAgICBhc3NlcnQgLy8gY2hlY2sgc2VsZi50b2RvcyBleGlzdHMKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRTdHJ1Y3QuY29tcGxldGVfdG9kbyh0YXNrOiBieXRlcykgLT4gdm9pZDoKY29tcGxldGVfdG9kbzoKICAgIHByb3RvIDEgMAogICAgYnl0ZSAiIgogICAgZHVwCiAgICBpbnQgMAogICAgYnl0ZSAidG9kb3MiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIHNlbGYudG9kb3MgZXhpc3RzCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGludCAwCgpjb21wbGV0ZV90b2RvX2Zvcl9oZWFkZXJAMToKICAgIGZyYW1lX2RpZyAzCiAgICBmcmFtZV9kaWcgMgogICAgPAogICAgYnogY29tcGxldGVfdG9kb19hZnRlcl9mb3JANgogICAgaW50IDAKICAgIGJ5dGUgInRvZG9zIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBzZWxmLnRvZG9zIGV4aXN0cwogICAgZHVwCiAgICBleHRyYWN0IDIgMAogICAgZnJhbWVfZGlnIDMKICAgIGR1cAogICAgY292ZXIgMwogICAgaW50IDIKICAgICoKICAgIGR1cAogICAgZnJhbWVfYnVyeSAwCiAgICBkaWcgMQogICAgc3dhcAogICAgZXh0cmFjdF91aW50MTYKICAgIGNvdmVyIDMKICAgIHN3YXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgdW5jb3ZlciAyCiAgICBpbnQgMQogICAgKwogICAgZHVwCiAgICBjb3ZlciA0CiAgICBkdXAKICAgIGNvdmVyIDIKICAgIC0gLy8gb24gZXJyb3I6IEluZGV4IGFjY2VzcyBpcyBvdXQgb2YgYm91bmRzCiAgICBzd2FwCiAgICBkaWcgMgogICAgbGVuCiAgICBjb3ZlciAyCiAgICBpbnQgMgogICAgKgogICAgZHVwCiAgICBmcmFtZV9idXJ5IDEKICAgIGRpZyAzCiAgICBzd2FwCiAgICBleHRyYWN0X3VpbnQxNgogICAgc3dhcAogICAgc2VsZWN0CiAgICBzd2FwCiAgICBjb3ZlciAyCiAgICBzdWJzdHJpbmczCiAgICBkdXAKICAgIGludCAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgc3dhcAogICAgZHVwCiAgICBsZW4KICAgIHN3YXAKICAgIGNvdmVyIDIKICAgIHN1YnN0cmluZzMKICAgIGZyYW1lX2RpZyAtMQogICAgPT0KICAgIGJ6IGNvbXBsZXRlX3RvZG9fYWZ0ZXJfaWZfZWxzZUA0CiAgICBpbnQgMAogICAgYnl0ZSAidG9kb3MiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIHNlbGYudG9kb3MgZXhpc3RzCiAgICBkdXAKICAgIGV4dHJhY3QgMiAwCiAgICBkdXAKICAgIGZyYW1lX2RpZyAwCiAgICBleHRyYWN0X3VpbnQxNgogICAgY292ZXIgMgogICAgc3dhcAogICAgaW50IDAKICAgIGV4dHJhY3RfdWludDE2CiAgICB1bmNvdmVyIDMKICAgIC0gLy8gb24gZXJyb3I6IEluZGV4IGFjY2VzcyBpcyBvdXQgb2YgYm91bmRzCiAgICBkaWcgMQogICAgbGVuCiAgICBzd2FwCiAgICBkaWcgMgogICAgZnJhbWVfZGlnIDEKICAgIGV4dHJhY3RfdWludDE2CiAgICBzd2FwCiAgICBzZWxlY3QKICAgIHN3YXAKICAgIGNvdmVyIDIKICAgIHN1YnN0cmluZzMKICAgIGludCAxNgogICAgaW50IDEKICAgIHNldGJpdAogICAgaW50IDAKICAgIGJ5dGUgInRvZG9zIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBzZWxmLnRvZG9zIGV4aXN0cwogICAgc3dhcAogICAgZnJhbWVfZGlnIDMKICAgIGNhbGxzdWIgZHluYW1pY19hcnJheV9yZXBsYWNlX2R5bmFtaWNfZWxlbWVudAogICAgYnl0ZSAidG9kb3MiCiAgICBzd2FwCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgYiBjb21wbGV0ZV90b2RvX2FmdGVyX2ZvckA2Cgpjb21wbGV0ZV90b2RvX2FmdGVyX2lmX2Vsc2VANDoKICAgIGZyYW1lX2J1cnkgMwogICAgYiBjb21wbGV0ZV90b2RvX2Zvcl9oZWFkZXJAMQoKY29tcGxldGVfdG9kb19hZnRlcl9mb3JANjoKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRTdHJ1Y3QucmV0dXJuX3RvZG8odGFzazogYnl0ZXMpIC0+IGJ5dGVzOgpyZXR1cm5fdG9kbzoKICAgIHByb3RvIDEgMQogICAgaW50IDAKICAgIGJ5dGUgIiIKICAgIGR1cAogICAgaW50IDAKICAgIGR1cAogICAgYnl0ZSAidG9kb3MiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIHNlbGYudG9kb3MgZXhpc3RzCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGludCAwCgpyZXR1cm5fdG9kb19mb3JfaGVhZGVyQDE6CiAgICBmcmFtZV9kaWcgNQogICAgZnJhbWVfZGlnIDQKICAgIDwKICAgIGJ6IHJldHVybl90b2RvX2FmdGVyX2ZvckA2CiAgICBpbnQgMAogICAgYnl0ZSAidG9kb3MiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIHNlbGYudG9kb3MgZXhpc3RzCiAgICBkdXAKICAgIGV4dHJhY3QgMiAwCiAgICBmcmFtZV9kaWcgNQogICAgZHVwCiAgICBjb3ZlciAzCiAgICBpbnQgMgogICAgKgogICAgZHVwCiAgICBmcmFtZV9idXJ5IDEKICAgIGRpZyAxCiAgICBzd2FwCiAgICBleHRyYWN0X3VpbnQxNgogICAgY292ZXIgMwogICAgc3dhcAogICAgaW50IDAKICAgIGV4dHJhY3RfdWludDE2CiAgICB1bmNvdmVyIDIKICAgIGludCAxCiAgICArCiAgICBkdXAKICAgIGZyYW1lX2J1cnkgNQogICAgZHVwCiAgICBjb3ZlciAyCiAgICAtIC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgc3dhcAogICAgZGlnIDIKICAgIGxlbgogICAgY292ZXIgMgogICAgaW50IDIKICAgICoKICAgIGR1cAogICAgZnJhbWVfYnVyeSAyCiAgICBkaWcgMwogICAgc3dhcAogICAgZXh0cmFjdF91aW50MTYKICAgIHN3YXAKICAgIHNlbGVjdAogICAgc3dhcAogICAgY292ZXIgMgogICAgc3Vic3RyaW5nMwogICAgZHVwCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIHN3YXAKICAgIGR1cAogICAgbGVuCiAgICBzd2FwCiAgICBjb3ZlciAyCiAgICBzdWJzdHJpbmczCiAgICBmcmFtZV9kaWcgLTEKICAgID09CiAgICBieiByZXR1cm5fdG9kb19mb3JfaGVhZGVyQDEKICAgIGludCAwCiAgICBieXRlICJ0b2RvcyIKICAgIGFwcF9nbG9iYWxfZ2V0X2V4CiAgICBhc3NlcnQgLy8gY2hlY2sgc2VsZi50b2RvcyBleGlzdHMKICAgIGR1cAogICAgZXh0cmFjdCAyIDAKICAgIGR1cAogICAgZnJhbWVfZGlnIDEKICAgIGV4dHJhY3RfdWludDE2CiAgICBjb3ZlciAyCiAgICBzd2FwCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGZyYW1lX2RpZyA1CiAgICAtIC8vIG9uIGVycm9yOiBJbmRleCBhY2Nlc3MgaXMgb3V0IG9mIGJvdW5kcwogICAgZGlnIDEKICAgIGxlbgogICAgc3dhcAogICAgZGlnIDIKICAgIGZyYW1lX2RpZyAyCiAgICBleHRyYWN0X3VpbnQxNgogICAgc3dhcAogICAgc2VsZWN0CiAgICBzd2FwCiAgICBjb3ZlciAyCiAgICBzdWJzdHJpbmczCiAgICBmcmFtZV9idXJ5IDAKICAgIGludCAxCiAgICBmcmFtZV9idXJ5IDMKICAgIGIgcmV0dXJuX3RvZG9fZm9yX2hlYWRlckAxCgpyZXR1cm5fdG9kb19hZnRlcl9mb3JANjoKICAgIGZyYW1lX2RpZyAzCiAgICBhc3NlcnQKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRTdHJ1Y3QuX19pbml0X18oKSAtPiB2b2lkOgpfX2luaXRfXzoKICAgIHByb3RvIDAgMAogICAgYnl0ZSAidG9kb3MiCiAgICBieXRlIDB4MDAwMAogICAgYXBwX2dsb2JhbF9wdXQKICAgIHJldHN1YgoKCi8vIF9wdXlhX2xpYi5hcmM0LmR5bmFtaWNfYXJyYXlfY29uY2F0X2R5bmFtaWNfZWxlbWVudChhcnJheV9pdGVtc19jb3VudDogdWludDY0LCBhcnJheV9oZWFkX2FuZF90YWlsOiBieXRlcywgbmV3X2l0ZW1zX2NvdW50OiB1aW50NjQsIG5ld19oZWFkX2FuZF90YWlsOiBieXRlcykgLT4gYnl0ZXM6CmR5bmFtaWNfYXJyYXlfY29uY2F0X2R5bmFtaWNfZWxlbWVudDoKICAgIHByb3RvIDQgMQogICAgYnl0ZSAiIgogICAgYnl0ZSAweAogICAgZnJhbWVfZGlnIC0yCiAgICBpbnQgMgogICAgKgogICAgZnJhbWVfZGlnIC00CiAgICBpbnQgMgogICAgKgogICAgaW50IDAKCmR5bmFtaWNfYXJyYXlfY29uY2F0X2R5bmFtaWNfZWxlbWVudF9mb3JfaGVhZGVyQDE6CiAgICBmcmFtZV9kaWcgNAogICAgZnJhbWVfZGlnIDMKICAgIDwKICAgIGJ6IGR5bmFtaWNfYXJyYXlfY29uY2F0X2R5bmFtaWNfZWxlbWVudF9hZnRlcl9mb3JANAogICAgZnJhbWVfZGlnIC0zCiAgICBmcmFtZV9kaWcgNAogICAgZHVwCiAgICBjb3ZlciAyCiAgICBleHRyYWN0X3VpbnQxNgogICAgZnJhbWVfZGlnIDIKICAgICsKICAgIGl0b2IKICAgIGV4dHJhY3QgNiAyCiAgICBmcmFtZV9kaWcgMQogICAgc3dhcAogICAgY29uY2F0CiAgICBmcmFtZV9idXJ5IDEKICAgIGludCAyCiAgICArCiAgICBmcmFtZV9idXJ5IDQKICAgIGIgZHluYW1pY19hcnJheV9jb25jYXRfZHluYW1pY19lbGVtZW50X2Zvcl9oZWFkZXJAMQoKZHluYW1pY19hcnJheV9jb25jYXRfZHluYW1pY19lbGVtZW50X2FmdGVyX2ZvckA0OgogICAgZnJhbWVfZGlnIC0zCiAgICBsZW4KICAgIGZyYW1lX2J1cnkgMAogICAgaW50IDAKICAgIGZyYW1lX2J1cnkgNAoKZHluYW1pY19hcnJheV9jb25jYXRfZHluYW1pY19lbGVtZW50X2Zvcl9oZWFkZXJANToKICAgIGZyYW1lX2RpZyA0CiAgICBmcmFtZV9kaWcgMgogICAgPAogICAgYnogZHluYW1pY19hcnJheV9jb25jYXRfZHluYW1pY19lbGVtZW50X2FmdGVyX2ZvckA4CiAgICBmcmFtZV9kaWcgLTEKICAgIGZyYW1lX2RpZyA0CiAgICBkdXAKICAgIGNvdmVyIDIKICAgIGV4dHJhY3RfdWludDE2CiAgICBmcmFtZV9kaWcgMAogICAgKwogICAgaXRvYgogICAgZXh0cmFjdCA2IDIKICAgIGZyYW1lX2RpZyAxCiAgICBzd2FwCiAgICBjb25jYXQKICAgIGZyYW1lX2J1cnkgMQogICAgaW50IDIKICAgICsKICAgIGZyYW1lX2J1cnkgNAogICAgYiBkeW5hbWljX2FycmF5X2NvbmNhdF9keW5hbWljX2VsZW1lbnRfZm9yX2hlYWRlckA1CgpkeW5hbWljX2FycmF5X2NvbmNhdF9keW5hbWljX2VsZW1lbnRfYWZ0ZXJfZm9yQDg6CiAgICBmcmFtZV9kaWcgLTQKICAgIGZyYW1lX2RpZyAtMgogICAgKwogICAgaXRvYgogICAgZXh0cmFjdCA2IDIKICAgIGZyYW1lX2RpZyAxCiAgICBjb25jYXQKICAgIGZyYW1lX2RpZyAtMwogICAgZnJhbWVfZGlnIDMKICAgIGZyYW1lX2RpZyAwCiAgICBzdWJzdHJpbmczCiAgICBjb25jYXQKICAgIGZyYW1lX2RpZyAtMQogICAgbGVuCiAgICBmcmFtZV9kaWcgLTEKICAgIGZyYW1lX2RpZyAyCiAgICB1bmNvdmVyIDIKICAgIHN1YnN0cmluZzMKICAgIGNvbmNhdAogICAgZnJhbWVfYnVyeSAwCiAgICByZXRzdWIKCgovLyBfcHV5YV9saWIuYXJjNC5keW5hbWljX2FycmF5X3JlcGxhY2VfZHluYW1pY19lbGVtZW50KHNvdXJjZTogYnl0ZXMsIG5ld19pdGVtOiBieXRlcywgaW5kZXg6IHVpbnQ2NCkgLT4gYnl0ZXM6CmR5bmFtaWNfYXJyYXlfcmVwbGFjZV9keW5hbWljX2VsZW1lbnQ6CiAgICBwcm90byAzIDEKICAgIGZyYW1lX2RpZyAtMwogICAgc3Vic3RyaW5nIDAgMgogICAgZHVwCiAgICBidG9pCiAgICBmcmFtZV9kaWcgLTMKICAgIGV4dHJhY3QgMiAwCiAgICBmcmFtZV9kaWcgLTIKICAgIGZyYW1lX2RpZyAtMQogICAgdW5jb3ZlciAzCiAgICBjYWxsc3ViIHN0YXRpY19hcnJheV9yZXBsYWNlX2R5bmFtaWNfZWxlbWVudAogICAgY29uY2F0CiAgICByZXRzdWIKCgovLyBfcHV5YV9saWIuYXJjNC5zdGF0aWNfYXJyYXlfcmVwbGFjZV9keW5hbWljX2VsZW1lbnQoYXJyYXlfaGVhZF9hbmRfdGFpbDogYnl0ZXMsIG5ld19pdGVtOiBieXRlcywgaW5kZXg6IHVpbnQ2NCwgYXJyYXlfbGVuZ3RoOiB1aW50NjQpIC0+IGJ5dGVzOgpzdGF0aWNfYXJyYXlfcmVwbGFjZV9keW5hbWljX2VsZW1lbnQ6CiAgICBwcm90byA0IDEKICAgIGZyYW1lX2RpZyAtMgogICAgaW50IDIKICAgICoKICAgIGZyYW1lX2RpZyAtNAogICAgc3dhcAogICAgZXh0cmFjdF91aW50MTYKICAgIGZyYW1lX2RpZyAtMgogICAgaW50IDEKICAgICsKICAgIGludCAyCiAgICAqCiAgICBkdXAKICAgIGNvdmVyIDIKICAgIGZyYW1lX2RpZyAtNAogICAgc3dhcAogICAgZXh0cmFjdF91aW50MTYKICAgIGZyYW1lX2RpZyAtNAogICAgbGVuCiAgICBmcmFtZV9kaWcgLTEKICAgIGZyYW1lX2RpZyAtMgogICAgLQogICAgaW50IDEKICAgIC0KICAgIGRpZyAxCiAgICB1bmNvdmVyIDMKICAgIHVuY292ZXIgMgogICAgc2VsZWN0CiAgICBkdXAKICAgIGRpZyAzCiAgICAtCiAgICBjb3ZlciAzCiAgICBmcmFtZV9kaWcgLTMKICAgIGxlbgogICAgY292ZXIgMwogICAgZnJhbWVfZGlnIC00CiAgICBpbnQgMAogICAgdW5jb3ZlciA0CiAgICBzdWJzdHJpbmczCiAgICBmcmFtZV9kaWcgLTMKICAgIGNvbmNhdAogICAgZnJhbWVfZGlnIC00CiAgICB1bmNvdmVyIDIKICAgIHVuY292ZXIgMwogICAgc3Vic3RyaW5nMwogICAgY29uY2F0CiAgICBmcmFtZV9kaWcgLTEKICAgIGludCAyCiAgICAqCgpzdGF0aWNfYXJyYXlfcmVwbGFjZV9keW5hbWljX2VsZW1lbnRfZm9yX2hlYWRlckAxOgogICAgZnJhbWVfZGlnIDAKICAgIGZyYW1lX2RpZyA0CiAgICA8CiAgICBieiBzdGF0aWNfYXJyYXlfcmVwbGFjZV9keW5hbWljX2VsZW1lbnRfYWZ0ZXJfZm9yQDQKICAgIGZyYW1lX2RpZyAzCiAgICBkdXAKICAgIGZyYW1lX2RpZyAwCiAgICBkdXAKICAgIGNvdmVyIDMKICAgIGV4dHJhY3RfdWludDE2CiAgICBmcmFtZV9kaWcgMgogICAgKwogICAgZnJhbWVfZGlnIDEKICAgIC0KICAgIGl0b2IKICAgIGV4dHJhY3QgNiAyCiAgICBkaWcgMgogICAgc3dhcAogICAgcmVwbGFjZTMKICAgIGZyYW1lX2J1cnkgMwogICAgaW50IDIKICAgICsKICAgIGZyYW1lX2J1cnkgMAogICAgYiBzdGF0aWNfYXJyYXlfcmVwbGFjZV9keW5hbWljX2VsZW1lbnRfZm9yX2hlYWRlckAxCgpzdGF0aWNfYXJyYXlfcmVwbGFjZV9keW5hbWljX2VsZW1lbnRfYWZ0ZXJfZm9yQDQ6CiAgICBmcmFtZV9kaWcgMwogICAgZnJhbWVfYnVyeSAwCiAgICByZXRzdWIK", + "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0U3RydWN0LmNsZWFyX3N0YXRlX3Byb2dyYW06CiAgICBpbnQgMQogICAgcmV0dXJuCg==" + }, + "state": { + "global": { + "num_byte_slices": 1, + "num_uints": 0 + }, + "local": { + "num_byte_slices": 0, + "num_uints": 0 + } + }, + "schema": { + "global": { + "declared": { + "todos": { + "type": "bytes", + "key": "todos" + } + }, + "reserved": {} + }, + "local": { + "declared": {}, + "reserved": {} + } + }, + "contract": { + "name": "Arc4Struct", + "methods": [ + { + "name": "add_todo", + "args": [ + { + "type": "string", + "name": "task" + } + ], + "returns": { + "type": "(string,bool)[]" + } + }, + { + "name": "complete_todo", + "args": [ + { + "type": "string", + "name": "task" + } + ], + "returns": { + "type": "void" + } + }, + { + "name": "return_todo", + "args": [ + { + "type": "string", + "name": "task" + } + ], + "returns": { + "type": "(string,bool)" + } + } + ], + "networks": {} + }, + "bare_call_config": { + "no_op": "CREATE" + } +}""" +APP_SPEC = algokit_utils.ApplicationSpecification.from_json(_APP_SPEC_JSON) +_TReturn = typing.TypeVar("_TReturn") + + +class _ArgsBase(ABC, typing.Generic[_TReturn]): + @staticmethod + @abstractmethod + def method() -> str: + ... + + +_TArgs = typing.TypeVar("_TArgs", bound=_ArgsBase[typing.Any]) + + +@dataclasses.dataclass(kw_only=True) +class _TArgsHolder(typing.Generic[_TArgs]): + args: _TArgs + + +def _filter_none(value: dict | typing.Any) -> dict | typing.Any: + if isinstance(value, dict): + return {k: _filter_none(v) for k, v in value.items() if v is not None} + return value + + +def _as_dict(data: typing.Any, *, convert_all: bool = True) -> dict[str, typing.Any]: + if data is None: + return {} + if not dataclasses.is_dataclass(data): + raise TypeError(f"{data} must be a dataclass") + if convert_all: + result = dataclasses.asdict(data) # type: ignore[call-overload] + else: + result = {f.name: getattr(data, f.name) for f in dataclasses.fields(data)} + return _filter_none(result) + + +def _convert_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, +) -> algokit_utils.TransactionParametersDict: + return typing.cast(algokit_utils.TransactionParametersDict, _as_dict(transaction_parameters)) + + +def _convert_call_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, +) -> algokit_utils.OnCompleteCallParametersDict: + return typing.cast(algokit_utils.OnCompleteCallParametersDict, _as_dict(transaction_parameters)) + + +def _convert_create_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, + on_complete: algokit_utils.OnCompleteActionName, +) -> algokit_utils.CreateCallParametersDict: + result = typing.cast(algokit_utils.CreateCallParametersDict, _as_dict(transaction_parameters)) + on_complete_enum = on_complete.replace("_", " ").title().replace(" ", "") + "OC" + result["on_complete"] = getattr(algosdk.transaction.OnComplete, on_complete_enum) + return result + + +def _convert_deploy_args( + deploy_args: algokit_utils.DeployCallArgs | None, +) -> algokit_utils.ABICreateCallArgsDict | None: + if deploy_args is None: + return None + + deploy_args_dict = typing.cast(algokit_utils.ABICreateCallArgsDict, _as_dict(deploy_args)) + if isinstance(deploy_args, _TArgsHolder): + deploy_args_dict["args"] = _as_dict(deploy_args.args) + deploy_args_dict["method"] = deploy_args.args.method() + + return deploy_args_dict + + +@dataclasses.dataclass(kw_only=True) +class AddTodoArgs(_ArgsBase[list[tuple[str, bool]]]): + task: str + + @staticmethod + def method() -> str: + return "add_todo(string)(string,bool)[]" + + +@dataclasses.dataclass(kw_only=True) +class CompleteTodoArgs(_ArgsBase[None]): + task: str + + @staticmethod + def method() -> str: + return "complete_todo(string)void" + + +@dataclasses.dataclass(kw_only=True) +class Todo: + task: str + completed: bool + + +@dataclasses.dataclass(kw_only=True) +class ReturnTodoArgs(_ArgsBase[Todo]): + task: str + + @staticmethod + def method() -> str: + return "return_todo(string)(string,bool)" + + +class ByteReader: + def __init__(self, data: bytes): + self._data = data + + @property + def as_bytes(self) -> bytes: + return self._data + + @property + def as_str(self) -> str: + return self._data.decode("utf8") + + @property + def as_base64(self) -> str: + return base64.b64encode(self._data).decode("utf8") + + @property + def as_hex(self) -> str: + return self._data.hex() + + +class GlobalState: + def __init__(self, data: dict[bytes, bytes | int]): + self.todos = ByteReader(typing.cast(bytes, data.get(b"todos"))) + + +@dataclasses.dataclass(kw_only=True) +class SimulateOptions: + allow_more_logs: bool = dataclasses.field(default=False) + allow_empty_signatures: bool = dataclasses.field(default=False) + extra_opcode_budget: int = dataclasses.field(default=0) + exec_trace_config: models.SimulateTraceConfig | None = dataclasses.field(default=None) + + +class Composer: + + def __init__(self, app_client: algokit_utils.ApplicationClient, atc: AtomicTransactionComposer): + self.app_client = app_client + self.atc = atc + + def build(self) -> AtomicTransactionComposer: + return self.atc + + def simulate(self, options: SimulateOptions | None = None) -> SimulateAtomicTransactionResponse: + request = models.SimulateRequest( + allow_more_logs=options.allow_more_logs, + allow_empty_signatures=options.allow_empty_signatures, + extra_opcode_budget=options.extra_opcode_budget, + exec_trace_config=options.exec_trace_config, + txn_groups=[] + ) if options else None + result = self.atc.simulate(self.app_client.algod_client, request) + return result + + def execute(self) -> AtomicTransactionResponse: + return self.app_client.execute_atc(self.atc) + + def add_todo( + self, + *, + task: str, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> "Composer": + """Adds a call to `add_todo(string)(string,bool)[]` ABI method + + :param str task: The `task` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + args = AddTodoArgs( + task=task, + ) + self.app_client.compose_call( + self.atc, + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return self + + def complete_todo( + self, + *, + task: str, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> "Composer": + """Adds a call to `complete_todo(string)void` ABI method + + :param str task: The `task` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + args = CompleteTodoArgs( + task=task, + ) + self.app_client.compose_call( + self.atc, + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return self + + def return_todo( + self, + *, + task: str, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> "Composer": + """Adds a call to `return_todo(string)(string,bool)` ABI method + + :param str task: The `task` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + args = ReturnTodoArgs( + task=task, + ) + self.app_client.compose_call( + self.atc, + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return self + + def create_bare( + self, + *, + on_complete: typing.Literal["no_op"] = "no_op", + transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, + ) -> "Composer": + """Adds a call to create an application using the no_op bare method + + :param typing.Literal[no_op] on_complete: On completion type to use + :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + self.app_client.compose_create( + self.atc, + call_abi_method=False, + transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), + ) + return self + + def clear_state( + self, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + app_args: list[bytes] | None = None, + ) -> "Composer": + """Adds a call to the application with on completion set to ClearState + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :param list[bytes] | None app_args: (optional) Application args to pass""" + + self.app_client.compose_clear_state(self.atc, _convert_transaction_parameters(transaction_parameters), app_args) + return self + + +class Arc4StructClient: + """A class for interacting with the Arc4Struct app providing high productivity and + strongly typed methods to deploy and call the app""" + + @typing.overload + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + app_id: int = 0, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + ... + + @typing.overload + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + creator: str | algokit_utils.Account, + indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, + existing_deployments: algokit_utils.AppLookup | None = None, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + ... + + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + creator: str | algokit_utils.Account | None = None, + indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, + existing_deployments: algokit_utils.AppLookup | None = None, + app_id: int = 0, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + """ + Arc4StructClient can be created with an app_id to interact with an existing application, alternatively + it can be created with a creator and indexer_client specified to find existing applications by name and creator. + + :param AlgodClient algod_client: AlgoSDK algod client + :param int app_id: The app_id of an existing application, to instead find the application by creator and name + use the creator and indexer_client parameters + :param str | Account creator: The address or Account of the app creator to resolve the app_id + :param IndexerClient indexer_client: AlgoSDK indexer client, only required if deploying or finding app_id by + creator and app name + :param AppLookup existing_deployments: + :param TransactionSigner | Account signer: Account or signer to use to sign transactions, if not specified and + creator was passed as an Account will use that. + :param str sender: Address to use as the sender for all transactions, will use the address associated with the + signer if not specified. + :param TemplateValueMapping template_values: Values to use for TMPL_* template variables, dictionary keys should + *NOT* include the TMPL_ prefix + :param str | None app_name: Name of application to use when deploying, defaults to name defined on the + Application Specification + """ + + self.app_spec = APP_SPEC + + # calling full __init__ signature, so ignoring mypy warning about overloads + self.app_client = algokit_utils.ApplicationClient( # type: ignore[call-overload, misc] + algod_client=algod_client, + app_spec=self.app_spec, + app_id=app_id, + creator=creator, + indexer_client=indexer_client, + existing_deployments=existing_deployments, + signer=signer, + sender=sender, + suggested_params=suggested_params, + template_values=template_values, + app_name=app_name, + ) + + @property + def algod_client(self) -> algosdk.v2client.algod.AlgodClient: + return self.app_client.algod_client + + @property + def app_id(self) -> int: + return self.app_client.app_id + + @app_id.setter + def app_id(self, value: int) -> None: + self.app_client.app_id = value + + @property + def app_address(self) -> str: + return self.app_client.app_address + + @property + def sender(self) -> str | None: + return self.app_client.sender + + @sender.setter + def sender(self, value: str) -> None: + self.app_client.sender = value + + @property + def signer(self) -> TransactionSigner | None: + return self.app_client.signer + + @signer.setter + def signer(self, value: TransactionSigner) -> None: + self.app_client.signer = value + + @property + def suggested_params(self) -> algosdk.transaction.SuggestedParams | None: + return self.app_client.suggested_params + + @suggested_params.setter + def suggested_params(self, value: algosdk.transaction.SuggestedParams | None) -> None: + self.app_client.suggested_params = value + + def get_global_state(self) -> GlobalState: + """Returns the application's global state wrapped in a strongly typed class with options to format the stored value""" + + state = typing.cast(dict[bytes, bytes | int], self.app_client.get_global_state(raw=True)) + return GlobalState(state) + + def add_todo( + self, + *, + task: str, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> algokit_utils.ABITransactionResponse[list[tuple[str, bool]]]: + """Calls `add_todo(string)(string,bool)[]` ABI method + + :param str task: The `task` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.ABITransactionResponse[list[tuple[str, bool]]]: The result of the transaction""" + + args = AddTodoArgs( + task=task, + ) + result = self.app_client.call( + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return result + + def complete_todo( + self, + *, + task: str, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> algokit_utils.ABITransactionResponse[None]: + """Calls `complete_todo(string)void` ABI method + + :param str task: The `task` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.ABITransactionResponse[None]: The result of the transaction""" + + args = CompleteTodoArgs( + task=task, + ) + result = self.app_client.call( + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return result + + def return_todo( + self, + *, + task: str, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> algokit_utils.ABITransactionResponse[Todo]: + """Calls `return_todo(string)(string,bool)` ABI method + + :param str task: The `task` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.ABITransactionResponse[Todo]: The result of the transaction""" + + args = ReturnTodoArgs( + task=task, + ) + result = self.app_client.call( + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + elements = self.app_spec.hints[args.method()].structs["output"]["elements"] + result_dict = {element[0]: value for element, value in zip(elements, result.return_value)} + result.return_value = Todo(**result_dict) + return result + + def create_bare( + self, + *, + on_complete: typing.Literal["no_op"] = "no_op", + transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, + ) -> algokit_utils.TransactionResponse: + """Creates an application using the no_op bare method + + :param typing.Literal[no_op] on_complete: On completion type to use + :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.TransactionResponse: The result of the transaction""" + + result = self.app_client.create( + call_abi_method=False, + transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), + ) + return result + + def clear_state( + self, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + app_args: list[bytes] | None = None, + ) -> algokit_utils.TransactionResponse: + """Calls the application with on completion set to ClearState + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :param list[bytes] | None app_args: (optional) Application args to pass + :returns algokit_utils.TransactionResponse: The result of the transaction""" + + return self.app_client.clear_state(_convert_transaction_parameters(transaction_parameters), app_args) + + def deploy( + self, + version: str | None = None, + *, + signer: TransactionSigner | None = None, + sender: str | None = None, + allow_update: bool | None = None, + allow_delete: bool | None = None, + on_update: algokit_utils.OnUpdate = algokit_utils.OnUpdate.Fail, + on_schema_break: algokit_utils.OnSchemaBreak = algokit_utils.OnSchemaBreak.Fail, + template_values: algokit_utils.TemplateValueMapping | None = None, + create_args: algokit_utils.DeployCallArgs | None = None, + update_args: algokit_utils.DeployCallArgs | None = None, + delete_args: algokit_utils.DeployCallArgs | None = None, + ) -> algokit_utils.DeployResponse: + """Deploy an application and update client to reference it. + + Idempotently deploy (create, update/delete if changed) an app against the given name via the given creator + account, including deploy-time template placeholder substitutions. + To understand the architecture decisions behind this functionality please see + + + ```{note} + If there is a breaking state schema change to an existing app (and `on_schema_break` is set to + 'ReplaceApp' the existing app will be deleted and re-created. + ``` + + ```{note} + If there is an update (different TEAL code) to an existing app (and `on_update` is set to 'ReplaceApp') + the existing app will be deleted and re-created. + ``` + + :param str version: version to use when creating or updating app, if None version will be auto incremented + :param algosdk.atomic_transaction_composer.TransactionSigner signer: signer to use when deploying app + , if None uses self.signer + :param str sender: sender address to use when deploying app, if None uses self.sender + :param bool allow_delete: Used to set the `TMPL_DELETABLE` template variable to conditionally control if an app + can be deleted + :param bool allow_update: Used to set the `TMPL_UPDATABLE` template variable to conditionally control if an app + can be updated + :param OnUpdate on_update: Determines what action to take if an application update is required + :param OnSchemaBreak on_schema_break: Determines what action to take if an application schema requirements + has increased beyond the current allocation + :param dict[str, int|str|bytes] template_values: Values to use for `TMPL_*` template variables, dictionary keys + should *NOT* include the TMPL_ prefix + :param algokit_utils.DeployCallArgs | None create_args: Arguments used when creating an application + :param algokit_utils.DeployCallArgs | None update_args: Arguments used when updating an application + :param algokit_utils.DeployCallArgs | None delete_args: Arguments used when deleting an application + :return DeployResponse: details action taken and relevant transactions + :raises DeploymentError: If the deployment failed""" + + return self.app_client.deploy( + version, + signer=signer, + sender=sender, + allow_update=allow_update, + allow_delete=allow_delete, + on_update=on_update, + on_schema_break=on_schema_break, + template_values=template_values, + create_args=_convert_deploy_args(create_args), + update_args=_convert_deploy_args(update_args), + delete_args=_convert_deploy_args(delete_args), + ) + + def compose(self, atc: AtomicTransactionComposer | None = None) -> Composer: + return Composer(self.app_client, atc or AtomicTransactionComposer()) diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_tuple_client.py b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_tuple_client.py new file mode 100644 index 0000000..20dfa26 --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_tuple_client.py @@ -0,0 +1,599 @@ +# flake8: noqa +# fmt: off +# mypy: disable-error-code="no-any-return, no-untyped-call, misc, type-arg" +# This file was automatically generated by algokit-client-generator. +# DO NOT MODIFY IT BY HAND. +# requires: algokit-utils@^1.2.0 +import base64 +import dataclasses +import decimal +import typing +from abc import ABC, abstractmethod + +import algokit_utils +import algosdk +from algosdk.v2client import models +from algosdk.atomic_transaction_composer import ( + AtomicTransactionComposer, + AtomicTransactionResponse, + SimulateAtomicTransactionResponse, + TransactionSigner, + TransactionWithSigner +) + +_APP_SPEC_JSON = r"""{ + "hints": { + "add_contact_info((string,string,uint64))uint64": { + "call_config": { + "no_op": "CALL" + } + }, + "return_contact()(string,string,uint64)": { + "call_config": { + "no_op": "CALL" + } + } + }, + "source": { + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHVwbGUuYXBwcm92YWxfcHJvZ3JhbToKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBibnogbWFpbl9lbnRyeXBvaW50QDIKICAgIGNhbGxzdWIgX19pbml0X18KCm1haW5fZW50cnlwb2ludEAyOgogICAgY2FsbHN1YiBfX3B1eWFfYXJjNF9yb3V0ZXJfXwogICAgcmV0dXJuCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLl9fcHV5YV9hcmM0X3JvdXRlcl9fKCkgLT4gdWludDY0OgpfX3B1eWFfYXJjNF9yb3V0ZXJfXzoKICAgIHByb3RvIDAgMQogICAgdHhuIE51bUFwcEFyZ3MKICAgIGJ6IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2CiAgICBtZXRob2QgImFkZF9jb250YWN0X2luZm8oKHN0cmluZyxzdHJpbmcsdWludDY0KSl1aW50NjQiCiAgICBtZXRob2QgInJldHVybl9jb250YWN0KCkoc3RyaW5nLHN0cmluZyx1aW50NjQpIgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAogICAgbWF0Y2ggX19wdXlhX2FyYzRfcm91dGVyX19fYWRkX2NvbnRhY3RfaW5mb19yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX3JldHVybl9jb250YWN0X3JvdXRlQDMKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FkZF9jb250YWN0X2luZm9fcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYWRkX2NvbnRhY3RfaW5mbwogICAgaXRvYgogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fcmV0dXJuX2NvbnRhY3Rfcm91dGVAMzoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIGNhbGxzdWIgcmV0dXJuX2NvbnRhY3QKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgYm56IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTAKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICAhCiAgICBhc3NlcnQgLy8gaXMgY3JlYXRpbmcKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTA6CiAgICBpbnQgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLmFkZF9jb250YWN0X2luZm8oY29udGFjdDogYnl0ZXMpIC0+IHVpbnQ2NDoKYWRkX2NvbnRhY3RfaW5mbzoKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDIKICAgIGV4dHJhY3RfdWludDE2CiAgICBmcmFtZV9kaWcgLTEKICAgIHVuY292ZXIgMgogICAgZGlnIDIKICAgIHN1YnN0cmluZzMKICAgIHN3YXAKICAgIGZyYW1lX2RpZyAtMQogICAgbGVuCiAgICBmcmFtZV9kaWcgLTEKICAgIGNvdmVyIDIKICAgIHN1YnN0cmluZzMKICAgIHN3YXAKICAgIGZyYW1lX2RpZyAtMQogICAgZXh0cmFjdCA0IDggLy8gb24gZXJyb3I6IEluZGV4IGFjY2VzcyBpcyBvdXQgb2YgYm91bmRzCiAgICBjb3ZlciAyCiAgICBleHRyYWN0IDIgMAogICAgYnl0ZSAiSm9obiBXb29kcyIKICAgID09CiAgICBhc3NlcnQKICAgIGV4dHJhY3QgMiAwCiAgICBieXRlICJqb2huQHNvbWV0aGluZy5jb20iCiAgICA9PQogICAgYXNzZXJ0CiAgICBkdXAKICAgIGJ5dGUgMHgwMDAwMDAwMDIxMWQxYWUzCiAgICBiPT0KICAgIGFzc2VydAogICAgYnl0ZSAiY29udGFjdF9pbmZvIgogICAgZnJhbWVfZGlnIC0xCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgYnRvaQogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLnJldHVybl9jb250YWN0KCkgLT4gYnl0ZXM6CnJldHVybl9jb250YWN0OgogICAgcHJvdG8gMCAxCiAgICBpbnQgMAogICAgYnl0ZSAiY29udGFjdF9pbmZvIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBzZWxmLmNvbnRhY3RfaW5mbyBleGlzdHMKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUdXBsZS5fX2luaXRfXygpIC0+IHZvaWQ6Cl9faW5pdF9fOgogICAgcHJvdG8gMCAwCiAgICBieXRlICJjb250YWN0X2luZm8iCiAgICBieXRlIDB4MDAwYzAwMGUwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAKICAgIGFwcF9nbG9iYWxfcHV0CiAgICByZXRzdWIK", + "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHVwbGUuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" + }, + "state": { + "global": { + "num_byte_slices": 1, + "num_uints": 0 + }, + "local": { + "num_byte_slices": 0, + "num_uints": 0 + } + }, + "schema": { + "global": { + "declared": { + "contact_info": { + "type": "bytes", + "key": "contact_info" + } + }, + "reserved": {} + }, + "local": { + "declared": {}, + "reserved": {} + } + }, + "contract": { + "name": "Arc4Tuple", + "methods": [ + { + "name": "add_contact_info", + "args": [ + { + "type": "(string,string,uint64)", + "name": "contact" + } + ], + "returns": { + "type": "uint64" + }, + "desc": "An arc4.Tuple is a heterogeneous collection of arc4 types." + }, + { + "name": "return_contact", + "args": [], + "returns": { + "type": "(string,string,uint64)" + }, + "desc": "An arc4.Tuple can be returned when more than one return value is needed." + } + ], + "networks": {} + }, + "bare_call_config": { + "no_op": "CREATE" + } +}""" +APP_SPEC = algokit_utils.ApplicationSpecification.from_json(_APP_SPEC_JSON) +_TReturn = typing.TypeVar("_TReturn") + + +class _ArgsBase(ABC, typing.Generic[_TReturn]): + @staticmethod + @abstractmethod + def method() -> str: + ... + + +_TArgs = typing.TypeVar("_TArgs", bound=_ArgsBase[typing.Any]) + + +@dataclasses.dataclass(kw_only=True) +class _TArgsHolder(typing.Generic[_TArgs]): + args: _TArgs + + +def _filter_none(value: dict | typing.Any) -> dict | typing.Any: + if isinstance(value, dict): + return {k: _filter_none(v) for k, v in value.items() if v is not None} + return value + + +def _as_dict(data: typing.Any, *, convert_all: bool = True) -> dict[str, typing.Any]: + if data is None: + return {} + if not dataclasses.is_dataclass(data): + raise TypeError(f"{data} must be a dataclass") + if convert_all: + result = dataclasses.asdict(data) # type: ignore[call-overload] + else: + result = {f.name: getattr(data, f.name) for f in dataclasses.fields(data)} + return _filter_none(result) + + +def _convert_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, +) -> algokit_utils.TransactionParametersDict: + return typing.cast(algokit_utils.TransactionParametersDict, _as_dict(transaction_parameters)) + + +def _convert_call_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, +) -> algokit_utils.OnCompleteCallParametersDict: + return typing.cast(algokit_utils.OnCompleteCallParametersDict, _as_dict(transaction_parameters)) + + +def _convert_create_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, + on_complete: algokit_utils.OnCompleteActionName, +) -> algokit_utils.CreateCallParametersDict: + result = typing.cast(algokit_utils.CreateCallParametersDict, _as_dict(transaction_parameters)) + on_complete_enum = on_complete.replace("_", " ").title().replace(" ", "") + "OC" + result["on_complete"] = getattr(algosdk.transaction.OnComplete, on_complete_enum) + return result + + +def _convert_deploy_args( + deploy_args: algokit_utils.DeployCallArgs | None, +) -> algokit_utils.ABICreateCallArgsDict | None: + if deploy_args is None: + return None + + deploy_args_dict = typing.cast(algokit_utils.ABICreateCallArgsDict, _as_dict(deploy_args)) + if isinstance(deploy_args, _TArgsHolder): + deploy_args_dict["args"] = _as_dict(deploy_args.args) + deploy_args_dict["method"] = deploy_args.args.method() + + return deploy_args_dict + + +@dataclasses.dataclass(kw_only=True) +class AddContactInfoArgs(_ArgsBase[int]): + """An arc4.Tuple is a heterogeneous collection of arc4 types.""" + + contact: tuple[str, str, int] + + @staticmethod + def method() -> str: + return "add_contact_info((string,string,uint64))uint64" + + +@dataclasses.dataclass(kw_only=True) +class ReturnContactArgs(_ArgsBase[tuple[str, str, int]]): + """An arc4.Tuple can be returned when more than one return value is needed.""" + + @staticmethod + def method() -> str: + return "return_contact()(string,string,uint64)" + + +class ByteReader: + def __init__(self, data: bytes): + self._data = data + + @property + def as_bytes(self) -> bytes: + return self._data + + @property + def as_str(self) -> str: + return self._data.decode("utf8") + + @property + def as_base64(self) -> str: + return base64.b64encode(self._data).decode("utf8") + + @property + def as_hex(self) -> str: + return self._data.hex() + + +class GlobalState: + def __init__(self, data: dict[bytes, bytes | int]): + self.contact_info = ByteReader(typing.cast(bytes, data.get(b"contact_info"))) + + +@dataclasses.dataclass(kw_only=True) +class SimulateOptions: + allow_more_logs: bool = dataclasses.field(default=False) + allow_empty_signatures: bool = dataclasses.field(default=False) + extra_opcode_budget: int = dataclasses.field(default=0) + exec_trace_config: models.SimulateTraceConfig | None = dataclasses.field(default=None) + + +class Composer: + + def __init__(self, app_client: algokit_utils.ApplicationClient, atc: AtomicTransactionComposer): + self.app_client = app_client + self.atc = atc + + def build(self) -> AtomicTransactionComposer: + return self.atc + + def simulate(self, options: SimulateOptions | None = None) -> SimulateAtomicTransactionResponse: + request = models.SimulateRequest( + allow_more_logs=options.allow_more_logs, + allow_empty_signatures=options.allow_empty_signatures, + extra_opcode_budget=options.extra_opcode_budget, + exec_trace_config=options.exec_trace_config, + txn_groups=[] + ) if options else None + result = self.atc.simulate(self.app_client.algod_client, request) + return result + + def execute(self) -> AtomicTransactionResponse: + return self.app_client.execute_atc(self.atc) + + def add_contact_info( + self, + *, + contact: tuple[str, str, int], + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> "Composer": + """An arc4.Tuple is a heterogeneous collection of arc4 types. + + Adds a call to `add_contact_info((string,string,uint64))uint64` ABI method + + :param tuple[str, str, int] contact: The `contact` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + args = AddContactInfoArgs( + contact=contact, + ) + self.app_client.compose_call( + self.atc, + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return self + + def return_contact( + self, + *, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> "Composer": + """An arc4.Tuple can be returned when more than one return value is needed. + + Adds a call to `return_contact()(string,string,uint64)` ABI method + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + args = ReturnContactArgs() + self.app_client.compose_call( + self.atc, + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return self + + def create_bare( + self, + *, + on_complete: typing.Literal["no_op"] = "no_op", + transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, + ) -> "Composer": + """Adds a call to create an application using the no_op bare method + + :param typing.Literal[no_op] on_complete: On completion type to use + :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + self.app_client.compose_create( + self.atc, + call_abi_method=False, + transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), + ) + return self + + def clear_state( + self, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + app_args: list[bytes] | None = None, + ) -> "Composer": + """Adds a call to the application with on completion set to ClearState + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :param list[bytes] | None app_args: (optional) Application args to pass""" + + self.app_client.compose_clear_state(self.atc, _convert_transaction_parameters(transaction_parameters), app_args) + return self + + +class Arc4TupleClient: + """A class for interacting with the Arc4Tuple app providing high productivity and + strongly typed methods to deploy and call the app""" + + @typing.overload + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + app_id: int = 0, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + ... + + @typing.overload + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + creator: str | algokit_utils.Account, + indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, + existing_deployments: algokit_utils.AppLookup | None = None, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + ... + + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + creator: str | algokit_utils.Account | None = None, + indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, + existing_deployments: algokit_utils.AppLookup | None = None, + app_id: int = 0, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + """ + Arc4TupleClient can be created with an app_id to interact with an existing application, alternatively + it can be created with a creator and indexer_client specified to find existing applications by name and creator. + + :param AlgodClient algod_client: AlgoSDK algod client + :param int app_id: The app_id of an existing application, to instead find the application by creator and name + use the creator and indexer_client parameters + :param str | Account creator: The address or Account of the app creator to resolve the app_id + :param IndexerClient indexer_client: AlgoSDK indexer client, only required if deploying or finding app_id by + creator and app name + :param AppLookup existing_deployments: + :param TransactionSigner | Account signer: Account or signer to use to sign transactions, if not specified and + creator was passed as an Account will use that. + :param str sender: Address to use as the sender for all transactions, will use the address associated with the + signer if not specified. + :param TemplateValueMapping template_values: Values to use for TMPL_* template variables, dictionary keys should + *NOT* include the TMPL_ prefix + :param str | None app_name: Name of application to use when deploying, defaults to name defined on the + Application Specification + """ + + self.app_spec = APP_SPEC + + # calling full __init__ signature, so ignoring mypy warning about overloads + self.app_client = algokit_utils.ApplicationClient( # type: ignore[call-overload, misc] + algod_client=algod_client, + app_spec=self.app_spec, + app_id=app_id, + creator=creator, + indexer_client=indexer_client, + existing_deployments=existing_deployments, + signer=signer, + sender=sender, + suggested_params=suggested_params, + template_values=template_values, + app_name=app_name, + ) + + @property + def algod_client(self) -> algosdk.v2client.algod.AlgodClient: + return self.app_client.algod_client + + @property + def app_id(self) -> int: + return self.app_client.app_id + + @app_id.setter + def app_id(self, value: int) -> None: + self.app_client.app_id = value + + @property + def app_address(self) -> str: + return self.app_client.app_address + + @property + def sender(self) -> str | None: + return self.app_client.sender + + @sender.setter + def sender(self, value: str) -> None: + self.app_client.sender = value + + @property + def signer(self) -> TransactionSigner | None: + return self.app_client.signer + + @signer.setter + def signer(self, value: TransactionSigner) -> None: + self.app_client.signer = value + + @property + def suggested_params(self) -> algosdk.transaction.SuggestedParams | None: + return self.app_client.suggested_params + + @suggested_params.setter + def suggested_params(self, value: algosdk.transaction.SuggestedParams | None) -> None: + self.app_client.suggested_params = value + + def get_global_state(self) -> GlobalState: + """Returns the application's global state wrapped in a strongly typed class with options to format the stored value""" + + state = typing.cast(dict[bytes, bytes | int], self.app_client.get_global_state(raw=True)) + return GlobalState(state) + + def add_contact_info( + self, + *, + contact: tuple[str, str, int], + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> algokit_utils.ABITransactionResponse[int]: + """An arc4.Tuple is a heterogeneous collection of arc4 types. + + Calls `add_contact_info((string,string,uint64))uint64` ABI method + + :param tuple[str, str, int] contact: The `contact` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.ABITransactionResponse[int]: The result of the transaction""" + + args = AddContactInfoArgs( + contact=contact, + ) + result = self.app_client.call( + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return result + + def return_contact( + self, + *, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> algokit_utils.ABITransactionResponse[tuple[str, str, int]]: + """An arc4.Tuple can be returned when more than one return value is needed. + + Calls `return_contact()(string,string,uint64)` ABI method + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.ABITransactionResponse[tuple[str, str, int]]: The result of the transaction""" + + args = ReturnContactArgs() + result = self.app_client.call( + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return result + + def create_bare( + self, + *, + on_complete: typing.Literal["no_op"] = "no_op", + transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, + ) -> algokit_utils.TransactionResponse: + """Creates an application using the no_op bare method + + :param typing.Literal[no_op] on_complete: On completion type to use + :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.TransactionResponse: The result of the transaction""" + + result = self.app_client.create( + call_abi_method=False, + transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), + ) + return result + + def clear_state( + self, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + app_args: list[bytes] | None = None, + ) -> algokit_utils.TransactionResponse: + """Calls the application with on completion set to ClearState + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :param list[bytes] | None app_args: (optional) Application args to pass + :returns algokit_utils.TransactionResponse: The result of the transaction""" + + return self.app_client.clear_state(_convert_transaction_parameters(transaction_parameters), app_args) + + def deploy( + self, + version: str | None = None, + *, + signer: TransactionSigner | None = None, + sender: str | None = None, + allow_update: bool | None = None, + allow_delete: bool | None = None, + on_update: algokit_utils.OnUpdate = algokit_utils.OnUpdate.Fail, + on_schema_break: algokit_utils.OnSchemaBreak = algokit_utils.OnSchemaBreak.Fail, + template_values: algokit_utils.TemplateValueMapping | None = None, + create_args: algokit_utils.DeployCallArgs | None = None, + update_args: algokit_utils.DeployCallArgs | None = None, + delete_args: algokit_utils.DeployCallArgs | None = None, + ) -> algokit_utils.DeployResponse: + """Deploy an application and update client to reference it. + + Idempotently deploy (create, update/delete if changed) an app against the given name via the given creator + account, including deploy-time template placeholder substitutions. + To understand the architecture decisions behind this functionality please see + + + ```{note} + If there is a breaking state schema change to an existing app (and `on_schema_break` is set to + 'ReplaceApp' the existing app will be deleted and re-created. + ``` + + ```{note} + If there is an update (different TEAL code) to an existing app (and `on_update` is set to 'ReplaceApp') + the existing app will be deleted and re-created. + ``` + + :param str version: version to use when creating or updating app, if None version will be auto incremented + :param algosdk.atomic_transaction_composer.TransactionSigner signer: signer to use when deploying app + , if None uses self.signer + :param str sender: sender address to use when deploying app, if None uses self.sender + :param bool allow_delete: Used to set the `TMPL_DELETABLE` template variable to conditionally control if an app + can be deleted + :param bool allow_update: Used to set the `TMPL_UPDATABLE` template variable to conditionally control if an app + can be updated + :param OnUpdate on_update: Determines what action to take if an application update is required + :param OnSchemaBreak on_schema_break: Determines what action to take if an application schema requirements + has increased beyond the current allocation + :param dict[str, int|str|bytes] template_values: Values to use for `TMPL_*` template variables, dictionary keys + should *NOT* include the TMPL_ prefix + :param algokit_utils.DeployCallArgs | None create_args: Arguments used when creating an application + :param algokit_utils.DeployCallArgs | None update_args: Arguments used when updating an application + :param algokit_utils.DeployCallArgs | None delete_args: Arguments used when deleting an application + :return DeployResponse: details action taken and relevant transactions + :raises DeploymentError: If the deployment failed""" + + return self.app_client.deploy( + version, + signer=signer, + sender=sender, + allow_update=allow_update, + allow_delete=allow_delete, + on_update=on_update, + on_schema_break=on_schema_break, + template_values=template_values, + create_args=_convert_deploy_args(create_args), + update_args=_convert_deploy_args(update_args), + delete_args=_convert_deploy_args(delete_args), + ) + + def compose(self, atc: AtomicTransactionComposer | None = None) -> Composer: + return Composer(self.app_client, atc or AtomicTransactionComposer()) diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_types_client.py b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_types_client.py new file mode 100644 index 0000000..e2f9db9 --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_types_client.py @@ -0,0 +1,950 @@ +# flake8: noqa +# fmt: off +# mypy: disable-error-code="no-any-return, no-untyped-call, misc, type-arg" +# This file was automatically generated by algokit-client-generator. +# DO NOT MODIFY IT BY HAND. +# requires: algokit-utils@^1.2.0 +import base64 +import dataclasses +import decimal +import typing +from abc import ABC, abstractmethod + +import algokit_utils +import algosdk +from algosdk.v2client import models +from algosdk.atomic_transaction_composer import ( + AtomicTransactionComposer, + AtomicTransactionResponse, + SimulateAtomicTransactionResponse, + TransactionSigner, + TransactionWithSigner +) + +_APP_SPEC_JSON = r"""{ + "hints": { + "add_arc4_uint64(uint64,uint64)uint64": { + "call_config": { + "no_op": "CALL" + } + }, + "add_arc4_uint_n(uint8,uint16,uint32,uint64)uint64": { + "call_config": { + "no_op": "CALL" + } + }, + "add_arc4_biguint_n(uint128,uint256,uint512)uint512": { + "call_config": { + "no_op": "CALL" + } + }, + "arc4_byte(byte)byte": { + "call_config": { + "no_op": "CALL" + } + }, + "arc4_address_properties(address)uint64": { + "call_config": { + "no_op": "CALL" + } + }, + "arc4_address_return(address)address": { + "call_config": { + "no_op": "CALL" + } + } + }, + "source": { + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuYXBwcm92YWxfcHJvZ3JhbToKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5fX3B1eWFfYXJjNF9yb3V0ZXJfXygpIC0+IHVpbnQ2NDoKX19wdXlhX2FyYzRfcm91dGVyX186CiAgICBwcm90byAwIDEKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdAMTAKICAgIG1ldGhvZCAiYWRkX2FyYzRfdWludDY0KHVpbnQ2NCx1aW50NjQpdWludDY0IgogICAgbWV0aG9kICJhZGRfYXJjNF91aW50X24odWludDgsdWludDE2LHVpbnQzMix1aW50NjQpdWludDY0IgogICAgbWV0aG9kICJhZGRfYXJjNF9iaWd1aW50X24odWludDEyOCx1aW50MjU2LHVpbnQ1MTIpdWludDUxMiIKICAgIG1ldGhvZCAiYXJjNF9ieXRlKGJ5dGUpYnl0ZSIKICAgIG1ldGhvZCAiYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXMoYWRkcmVzcyl1aW50NjQiCiAgICBtZXRob2QgImFyYzRfYWRkcmVzc19yZXR1cm4oYWRkcmVzcylhZGRyZXNzIgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAogICAgbWF0Y2ggX19wdXlhX2FyYzRfcm91dGVyX19fYWRkX2FyYzRfdWludDY0X3JvdXRlQDIgX19wdXlhX2FyYzRfcm91dGVyX19fYWRkX2FyYzRfdWludF9uX3JvdXRlQDMgX19wdXlhX2FyYzRfcm91dGVyX19fYWRkX2FyYzRfYmlndWludF9uX3JvdXRlQDQgX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9ieXRlX3JvdXRlQDUgX19wdXlhX2FyYzRfcm91dGVyX19fYXJjNF9hZGRyZXNzX3Byb3BlcnRpZXNfcm91dGVANiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2FkZHJlc3NfcmV0dXJuX3JvdXRlQDcKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FkZF9hcmM0X3VpbnQ2NF9yb3V0ZUAyOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMgogICAgY2FsbHN1YiBhZGRfYXJjNF91aW50NjQKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FkZF9hcmM0X3VpbnRfbl9yb3V0ZUAzOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgNAogICAgY2FsbHN1YiBhZGRfYXJjNF91aW50X24KICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FkZF9hcmM0X2JpZ3VpbnRfbl9yb3V0ZUA0OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMwogICAgY2FsbHN1YiBhZGRfYXJjNF9iaWd1aW50X24KICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYnl0ZV9yb3V0ZUA1OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgY2FsbHN1YiBhcmM0X2J5dGUKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FyYzRfYWRkcmVzc19wcm9wZXJ0aWVzX3JvdXRlQDY6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICBjYWxsc3ViIGFyYzRfYWRkcmVzc19wcm9wZXJ0aWVzCiAgICBpdG9iCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hcmM0X2FkZHJlc3NfcmV0dXJuX3JvdXRlQDc6CiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAxCiAgICBjYWxsc3ViIGFyYzRfYWRkcmVzc19yZXR1cm4KICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0AxMDoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgIGJueiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDE0CiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgIQogICAgYXNzZXJ0IC8vIGlzIGNyZWF0aW5nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDE0OgogICAgaW50IDAKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hZGRfYXJjNF91aW50NjQoYTogYnl0ZXMsIGI6IGJ5dGVzKSAtPiBieXRlczoKYWRkX2FyYzRfdWludDY0OgogICAgcHJvdG8gMiAxCiAgICBmcmFtZV9kaWcgLTIKICAgIGJ0b2kKICAgIGZyYW1lX2RpZyAtMQogICAgYnRvaQogICAgKwogICAgaXRvYgogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFkZF9hcmM0X3VpbnRfbihhOiBieXRlcywgYjogYnl0ZXMsIGM6IGJ5dGVzLCBkOiBieXRlcykgLT4gYnl0ZXM6CmFkZF9hcmM0X3VpbnRfbjoKICAgIHByb3RvIDQgMQogICAgZnJhbWVfZGlnIC00CiAgICBsZW4KICAgIGludCAxCiAgICA9PQogICAgYXNzZXJ0CiAgICBmcmFtZV9kaWcgLTMKICAgIGxlbgogICAgaW50IDIKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMgogICAgbGVuCiAgICBpbnQgNAogICAgPT0KICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0xCiAgICBsZW4KICAgIGludCA4CiAgICA9PQogICAgYXNzZXJ0CiAgICBmcmFtZV9kaWcgLTQKICAgIGJ0b2kKICAgIGZyYW1lX2RpZyAtMwogICAgYnRvaQogICAgKwogICAgZnJhbWVfZGlnIC0yCiAgICBidG9pCiAgICArCiAgICBmcmFtZV9kaWcgLTEKICAgIGJ0b2kKICAgICsKICAgIGl0b2IKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hZGRfYXJjNF9iaWd1aW50X24oYTogYnl0ZXMsIGI6IGJ5dGVzLCBjOiBieXRlcykgLT4gYnl0ZXM6CmFkZF9hcmM0X2JpZ3VpbnRfbjoKICAgIHByb3RvIDMgMQogICAgZnJhbWVfZGlnIC0zCiAgICBsZW4KICAgIGludCAxNgogICAgPT0KICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0yCiAgICBsZW4KICAgIGludCAzMgogICAgPT0KICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0xCiAgICBsZW4KICAgIGludCA2NAogICAgPT0KICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0zCiAgICBmcmFtZV9kaWcgLTIKICAgIGIrCiAgICBmcmFtZV9kaWcgLTEKICAgIGIrCiAgICBkdXAKICAgIGxlbgogICAgaW50IDY0CiAgICA8PQogICAgYXNzZXJ0IC8vIG92ZXJmbG93CiAgICBpbnQgNjQKICAgIGJ6ZXJvCiAgICBifAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFyYzRfYnl0ZShhOiBieXRlcykgLT4gYnl0ZXM6CmFyYzRfYnl0ZToKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBidG9pCiAgICBpbnQgMQogICAgKwogICAgaXRvYgogICAgZXh0cmFjdCA3IDEKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUeXBlcy5hcmM0X2FkZHJlc3NfcHJvcGVydGllcyhhZGRyZXNzOiBieXRlcykgLT4gdWludDY0OgphcmM0X2FkZHJlc3NfcHJvcGVydGllczoKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBhY2N0X3BhcmFtc19nZXQgQWNjdEJhbGFuY2UKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgZnJhbWVfZGlnIC0xCiAgICBhY2N0X3BhcmFtc19nZXQgQWNjdFRvdGFsQXNzZXRzCiAgICBidXJ5IDEKICAgIGFzc2VydCAvLyBhY2NvdW50IGZ1bmRlZAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR5cGVzLmFyYzRfYWRkcmVzc19yZXR1cm4oYWRkcmVzczogYnl0ZXMpIC0+IGJ5dGVzOgphcmM0X2FkZHJlc3NfcmV0dXJuOgogICAgcHJvdG8gMSAxCiAgICBmcmFtZV9kaWcgLTEKICAgIHJldHN1Ygo=", + "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHlwZXMuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" + }, + "state": { + "global": { + "num_byte_slices": 0, + "num_uints": 0 + }, + "local": { + "num_byte_slices": 0, + "num_uints": 0 + } + }, + "schema": { + "global": { + "declared": {}, + "reserved": {} + }, + "local": { + "declared": {}, + "reserved": {} + } + }, + "contract": { + "name": "Arc4Types", + "methods": [ + { + "name": "add_arc4_uint64", + "args": [ + { + "type": "uint64", + "name": "a" + }, + { + "type": "uint64", + "name": "b" + } + ], + "returns": { + "type": "uint64" + }, + "desc": "Math operations (like a + b) are not supported on arc4.UInt64 types\nsince they are internally represented as byte arrays in the AVM. Use the .native property to perform arithmetic operations." + }, + { + "name": "add_arc4_uint_n", + "args": [ + { + "type": "uint8", + "name": "a" + }, + { + "type": "uint16", + "name": "b" + }, + { + "type": "uint32", + "name": "c" + }, + { + "type": "uint64", + "name": "d" + } + ], + "returns": { + "type": "uint64" + }, + "desc": "The encoding of arc4 integers will be smaller if it uses fewer bits.\nUltimately, they are all represented with native UInt64." + }, + { + "name": "add_arc4_biguint_n", + "args": [ + { + "type": "uint128", + "name": "a" + }, + { + "type": "uint256", + "name": "b" + }, + { + "type": "uint512", + "name": "c" + } + ], + "returns": { + "type": "uint512" + }, + "desc": "Integers with larger bit size are supported up to 512 bits.\nUltimately, they are all represented with native BigUInt." + }, + { + "name": "arc4_byte", + "args": [ + { + "type": "byte", + "name": "a" + } + ], + "returns": { + "type": "byte" + }, + "desc": "An arc4.Byte is essentially an alias for an 8-bit integer." + }, + { + "name": "arc4_address_properties", + "args": [ + { + "type": "address", + "name": "address" + } + ], + "returns": { + "type": "uint64" + } + }, + { + "name": "arc4_address_return", + "args": [ + { + "type": "address", + "name": "address" + } + ], + "returns": { + "type": "address" + } + } + ], + "networks": {} + }, + "bare_call_config": { + "no_op": "CREATE" + } +}""" +APP_SPEC = algokit_utils.ApplicationSpecification.from_json(_APP_SPEC_JSON) +_TReturn = typing.TypeVar("_TReturn") + + +class _ArgsBase(ABC, typing.Generic[_TReturn]): + @staticmethod + @abstractmethod + def method() -> str: + ... + + +_TArgs = typing.TypeVar("_TArgs", bound=_ArgsBase[typing.Any]) + + +@dataclasses.dataclass(kw_only=True) +class _TArgsHolder(typing.Generic[_TArgs]): + args: _TArgs + + +def _filter_none(value: dict | typing.Any) -> dict | typing.Any: + if isinstance(value, dict): + return {k: _filter_none(v) for k, v in value.items() if v is not None} + return value + + +def _as_dict(data: typing.Any, *, convert_all: bool = True) -> dict[str, typing.Any]: + if data is None: + return {} + if not dataclasses.is_dataclass(data): + raise TypeError(f"{data} must be a dataclass") + if convert_all: + result = dataclasses.asdict(data) # type: ignore[call-overload] + else: + result = {f.name: getattr(data, f.name) for f in dataclasses.fields(data)} + return _filter_none(result) + + +def _convert_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, +) -> algokit_utils.TransactionParametersDict: + return typing.cast(algokit_utils.TransactionParametersDict, _as_dict(transaction_parameters)) + + +def _convert_call_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, +) -> algokit_utils.OnCompleteCallParametersDict: + return typing.cast(algokit_utils.OnCompleteCallParametersDict, _as_dict(transaction_parameters)) + + +def _convert_create_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, + on_complete: algokit_utils.OnCompleteActionName, +) -> algokit_utils.CreateCallParametersDict: + result = typing.cast(algokit_utils.CreateCallParametersDict, _as_dict(transaction_parameters)) + on_complete_enum = on_complete.replace("_", " ").title().replace(" ", "") + "OC" + result["on_complete"] = getattr(algosdk.transaction.OnComplete, on_complete_enum) + return result + + +def _convert_deploy_args( + deploy_args: algokit_utils.DeployCallArgs | None, +) -> algokit_utils.ABICreateCallArgsDict | None: + if deploy_args is None: + return None + + deploy_args_dict = typing.cast(algokit_utils.ABICreateCallArgsDict, _as_dict(deploy_args)) + if isinstance(deploy_args, _TArgsHolder): + deploy_args_dict["args"] = _as_dict(deploy_args.args) + deploy_args_dict["method"] = deploy_args.args.method() + + return deploy_args_dict + + +@dataclasses.dataclass(kw_only=True) +class AddArc4Uint64Args(_ArgsBase[int]): + """Math operations (like a + b) are not supported on arc4.UInt64 types + since they are internally represented as byte arrays in the AVM. Use the .native property to perform arithmetic operations.""" + + a: int + b: int + + @staticmethod + def method() -> str: + return "add_arc4_uint64(uint64,uint64)uint64" + + +@dataclasses.dataclass(kw_only=True) +class AddArc4UintNArgs(_ArgsBase[int]): + """The encoding of arc4 integers will be smaller if it uses fewer bits. + Ultimately, they are all represented with native UInt64.""" + + a: int + b: int + c: int + d: int + + @staticmethod + def method() -> str: + return "add_arc4_uint_n(uint8,uint16,uint32,uint64)uint64" + + +@dataclasses.dataclass(kw_only=True) +class AddArc4BiguintNArgs(_ArgsBase[int]): + """Integers with larger bit size are supported up to 512 bits. + Ultimately, they are all represented with native BigUInt.""" + + a: int + b: int + c: int + + @staticmethod + def method() -> str: + return "add_arc4_biguint_n(uint128,uint256,uint512)uint512" + + +@dataclasses.dataclass(kw_only=True) +class Arc4ByteArgs(_ArgsBase[int]): + """An arc4.Byte is essentially an alias for an 8-bit integer.""" + + a: int + + @staticmethod + def method() -> str: + return "arc4_byte(byte)byte" + + +@dataclasses.dataclass(kw_only=True) +class Arc4AddressPropertiesArgs(_ArgsBase[int]): + address: str + + @staticmethod + def method() -> str: + return "arc4_address_properties(address)uint64" + + +@dataclasses.dataclass(kw_only=True) +class Arc4AddressReturnArgs(_ArgsBase[str]): + address: str + + @staticmethod + def method() -> str: + return "arc4_address_return(address)address" + + +@dataclasses.dataclass(kw_only=True) +class SimulateOptions: + allow_more_logs: bool = dataclasses.field(default=False) + allow_empty_signatures: bool = dataclasses.field(default=False) + extra_opcode_budget: int = dataclasses.field(default=0) + exec_trace_config: models.SimulateTraceConfig | None = dataclasses.field(default=None) + + +class Composer: + + def __init__(self, app_client: algokit_utils.ApplicationClient, atc: AtomicTransactionComposer): + self.app_client = app_client + self.atc = atc + + def build(self) -> AtomicTransactionComposer: + return self.atc + + def simulate(self, options: SimulateOptions | None = None) -> SimulateAtomicTransactionResponse: + request = models.SimulateRequest( + allow_more_logs=options.allow_more_logs, + allow_empty_signatures=options.allow_empty_signatures, + extra_opcode_budget=options.extra_opcode_budget, + exec_trace_config=options.exec_trace_config, + txn_groups=[] + ) if options else None + result = self.atc.simulate(self.app_client.algod_client, request) + return result + + def execute(self) -> AtomicTransactionResponse: + return self.app_client.execute_atc(self.atc) + + def add_arc4_uint64( + self, + *, + a: int, + b: int, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> "Composer": + """Math operations (like a + b) are not supported on arc4.UInt64 types + since they are internally represented as byte arrays in the AVM. Use the .native property to perform arithmetic operations. + + Adds a call to `add_arc4_uint64(uint64,uint64)uint64` ABI method + + :param int a: The `a` ABI parameter + :param int b: The `b` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + args = AddArc4Uint64Args( + a=a, + b=b, + ) + self.app_client.compose_call( + self.atc, + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return self + + def add_arc4_uint_n( + self, + *, + a: int, + b: int, + c: int, + d: int, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> "Composer": + """The encoding of arc4 integers will be smaller if it uses fewer bits. + Ultimately, they are all represented with native UInt64. + + Adds a call to `add_arc4_uint_n(uint8,uint16,uint32,uint64)uint64` ABI method + + :param int a: The `a` ABI parameter + :param int b: The `b` ABI parameter + :param int c: The `c` ABI parameter + :param int d: The `d` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + args = AddArc4UintNArgs( + a=a, + b=b, + c=c, + d=d, + ) + self.app_client.compose_call( + self.atc, + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return self + + def add_arc4_biguint_n( + self, + *, + a: int, + b: int, + c: int, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> "Composer": + """Integers with larger bit size are supported up to 512 bits. + Ultimately, they are all represented with native BigUInt. + + Adds a call to `add_arc4_biguint_n(uint128,uint256,uint512)uint512` ABI method + + :param int a: The `a` ABI parameter + :param int b: The `b` ABI parameter + :param int c: The `c` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + args = AddArc4BiguintNArgs( + a=a, + b=b, + c=c, + ) + self.app_client.compose_call( + self.atc, + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return self + + def arc4_byte( + self, + *, + a: int, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> "Composer": + """An arc4.Byte is essentially an alias for an 8-bit integer. + + Adds a call to `arc4_byte(byte)byte` ABI method + + :param int a: The `a` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + args = Arc4ByteArgs( + a=a, + ) + self.app_client.compose_call( + self.atc, + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return self + + def arc4_address_properties( + self, + *, + address: str, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> "Composer": + """Adds a call to `arc4_address_properties(address)uint64` ABI method + + :param str address: The `address` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + args = Arc4AddressPropertiesArgs( + address=address, + ) + self.app_client.compose_call( + self.atc, + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return self + + def arc4_address_return( + self, + *, + address: str, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> "Composer": + """Adds a call to `arc4_address_return(address)address` ABI method + + :param str address: The `address` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + args = Arc4AddressReturnArgs( + address=address, + ) + self.app_client.compose_call( + self.atc, + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return self + + def create_bare( + self, + *, + on_complete: typing.Literal["no_op"] = "no_op", + transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, + ) -> "Composer": + """Adds a call to create an application using the no_op bare method + + :param typing.Literal[no_op] on_complete: On completion type to use + :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + self.app_client.compose_create( + self.atc, + call_abi_method=False, + transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), + ) + return self + + def clear_state( + self, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + app_args: list[bytes] | None = None, + ) -> "Composer": + """Adds a call to the application with on completion set to ClearState + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :param list[bytes] | None app_args: (optional) Application args to pass""" + + self.app_client.compose_clear_state(self.atc, _convert_transaction_parameters(transaction_parameters), app_args) + return self + + +class Arc4TypesClient: + """A class for interacting with the Arc4Types app providing high productivity and + strongly typed methods to deploy and call the app""" + + @typing.overload + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + app_id: int = 0, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + ... + + @typing.overload + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + creator: str | algokit_utils.Account, + indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, + existing_deployments: algokit_utils.AppLookup | None = None, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + ... + + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + creator: str | algokit_utils.Account | None = None, + indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, + existing_deployments: algokit_utils.AppLookup | None = None, + app_id: int = 0, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + """ + Arc4TypesClient can be created with an app_id to interact with an existing application, alternatively + it can be created with a creator and indexer_client specified to find existing applications by name and creator. + + :param AlgodClient algod_client: AlgoSDK algod client + :param int app_id: The app_id of an existing application, to instead find the application by creator and name + use the creator and indexer_client parameters + :param str | Account creator: The address or Account of the app creator to resolve the app_id + :param IndexerClient indexer_client: AlgoSDK indexer client, only required if deploying or finding app_id by + creator and app name + :param AppLookup existing_deployments: + :param TransactionSigner | Account signer: Account or signer to use to sign transactions, if not specified and + creator was passed as an Account will use that. + :param str sender: Address to use as the sender for all transactions, will use the address associated with the + signer if not specified. + :param TemplateValueMapping template_values: Values to use for TMPL_* template variables, dictionary keys should + *NOT* include the TMPL_ prefix + :param str | None app_name: Name of application to use when deploying, defaults to name defined on the + Application Specification + """ + + self.app_spec = APP_SPEC + + # calling full __init__ signature, so ignoring mypy warning about overloads + self.app_client = algokit_utils.ApplicationClient( # type: ignore[call-overload, misc] + algod_client=algod_client, + app_spec=self.app_spec, + app_id=app_id, + creator=creator, + indexer_client=indexer_client, + existing_deployments=existing_deployments, + signer=signer, + sender=sender, + suggested_params=suggested_params, + template_values=template_values, + app_name=app_name, + ) + + @property + def algod_client(self) -> algosdk.v2client.algod.AlgodClient: + return self.app_client.algod_client + + @property + def app_id(self) -> int: + return self.app_client.app_id + + @app_id.setter + def app_id(self, value: int) -> None: + self.app_client.app_id = value + + @property + def app_address(self) -> str: + return self.app_client.app_address + + @property + def sender(self) -> str | None: + return self.app_client.sender + + @sender.setter + def sender(self, value: str) -> None: + self.app_client.sender = value + + @property + def signer(self) -> TransactionSigner | None: + return self.app_client.signer + + @signer.setter + def signer(self, value: TransactionSigner) -> None: + self.app_client.signer = value + + @property + def suggested_params(self) -> algosdk.transaction.SuggestedParams | None: + return self.app_client.suggested_params + + @suggested_params.setter + def suggested_params(self, value: algosdk.transaction.SuggestedParams | None) -> None: + self.app_client.suggested_params = value + + def add_arc4_uint64( + self, + *, + a: int, + b: int, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> algokit_utils.ABITransactionResponse[int]: + """Math operations (like a + b) are not supported on arc4.UInt64 types + since they are internally represented as byte arrays in the AVM. Use the .native property to perform arithmetic operations. + + Calls `add_arc4_uint64(uint64,uint64)uint64` ABI method + + :param int a: The `a` ABI parameter + :param int b: The `b` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.ABITransactionResponse[int]: The result of the transaction""" + + args = AddArc4Uint64Args( + a=a, + b=b, + ) + result = self.app_client.call( + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return result + + def add_arc4_uint_n( + self, + *, + a: int, + b: int, + c: int, + d: int, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> algokit_utils.ABITransactionResponse[int]: + """The encoding of arc4 integers will be smaller if it uses fewer bits. + Ultimately, they are all represented with native UInt64. + + Calls `add_arc4_uint_n(uint8,uint16,uint32,uint64)uint64` ABI method + + :param int a: The `a` ABI parameter + :param int b: The `b` ABI parameter + :param int c: The `c` ABI parameter + :param int d: The `d` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.ABITransactionResponse[int]: The result of the transaction""" + + args = AddArc4UintNArgs( + a=a, + b=b, + c=c, + d=d, + ) + result = self.app_client.call( + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return result + + def add_arc4_biguint_n( + self, + *, + a: int, + b: int, + c: int, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> algokit_utils.ABITransactionResponse[int]: + """Integers with larger bit size are supported up to 512 bits. + Ultimately, they are all represented with native BigUInt. + + Calls `add_arc4_biguint_n(uint128,uint256,uint512)uint512` ABI method + + :param int a: The `a` ABI parameter + :param int b: The `b` ABI parameter + :param int c: The `c` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.ABITransactionResponse[int]: The result of the transaction""" + + args = AddArc4BiguintNArgs( + a=a, + b=b, + c=c, + ) + result = self.app_client.call( + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return result + + def arc4_byte( + self, + *, + a: int, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> algokit_utils.ABITransactionResponse[int]: + """An arc4.Byte is essentially an alias for an 8-bit integer. + + Calls `arc4_byte(byte)byte` ABI method + + :param int a: The `a` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.ABITransactionResponse[int]: The result of the transaction""" + + args = Arc4ByteArgs( + a=a, + ) + result = self.app_client.call( + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return result + + def arc4_address_properties( + self, + *, + address: str, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> algokit_utils.ABITransactionResponse[int]: + """Calls `arc4_address_properties(address)uint64` ABI method + + :param str address: The `address` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.ABITransactionResponse[int]: The result of the transaction""" + + args = Arc4AddressPropertiesArgs( + address=address, + ) + result = self.app_client.call( + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return result + + def arc4_address_return( + self, + *, + address: str, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> algokit_utils.ABITransactionResponse[str]: + """Calls `arc4_address_return(address)address` ABI method + + :param str address: The `address` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.ABITransactionResponse[str]: The result of the transaction""" + + args = Arc4AddressReturnArgs( + address=address, + ) + result = self.app_client.call( + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return result + + def create_bare( + self, + *, + on_complete: typing.Literal["no_op"] = "no_op", + transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, + ) -> algokit_utils.TransactionResponse: + """Creates an application using the no_op bare method + + :param typing.Literal[no_op] on_complete: On completion type to use + :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.TransactionResponse: The result of the transaction""" + + result = self.app_client.create( + call_abi_method=False, + transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), + ) + return result + + def clear_state( + self, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + app_args: list[bytes] | None = None, + ) -> algokit_utils.TransactionResponse: + """Calls the application with on completion set to ClearState + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :param list[bytes] | None app_args: (optional) Application args to pass + :returns algokit_utils.TransactionResponse: The result of the transaction""" + + return self.app_client.clear_state(_convert_transaction_parameters(transaction_parameters), app_args) + + def deploy( + self, + version: str | None = None, + *, + signer: TransactionSigner | None = None, + sender: str | None = None, + allow_update: bool | None = None, + allow_delete: bool | None = None, + on_update: algokit_utils.OnUpdate = algokit_utils.OnUpdate.Fail, + on_schema_break: algokit_utils.OnSchemaBreak = algokit_utils.OnSchemaBreak.Fail, + template_values: algokit_utils.TemplateValueMapping | None = None, + create_args: algokit_utils.DeployCallArgs | None = None, + update_args: algokit_utils.DeployCallArgs | None = None, + delete_args: algokit_utils.DeployCallArgs | None = None, + ) -> algokit_utils.DeployResponse: + """Deploy an application and update client to reference it. + + Idempotently deploy (create, update/delete if changed) an app against the given name via the given creator + account, including deploy-time template placeholder substitutions. + To understand the architecture decisions behind this functionality please see + + + ```{note} + If there is a breaking state schema change to an existing app (and `on_schema_break` is set to + 'ReplaceApp' the existing app will be deleted and re-created. + ``` + + ```{note} + If there is an update (different TEAL code) to an existing app (and `on_update` is set to 'ReplaceApp') + the existing app will be deleted and re-created. + ``` + + :param str version: version to use when creating or updating app, if None version will be auto incremented + :param algosdk.atomic_transaction_composer.TransactionSigner signer: signer to use when deploying app + , if None uses self.signer + :param str sender: sender address to use when deploying app, if None uses self.sender + :param bool allow_delete: Used to set the `TMPL_DELETABLE` template variable to conditionally control if an app + can be deleted + :param bool allow_update: Used to set the `TMPL_UPDATABLE` template variable to conditionally control if an app + can be updated + :param OnUpdate on_update: Determines what action to take if an application update is required + :param OnSchemaBreak on_schema_break: Determines what action to take if an application schema requirements + has increased beyond the current allocation + :param dict[str, int|str|bytes] template_values: Values to use for `TMPL_*` template variables, dictionary keys + should *NOT* include the TMPL_ prefix + :param algokit_utils.DeployCallArgs | None create_args: Arguments used when creating an application + :param algokit_utils.DeployCallArgs | None update_args: Arguments used when updating an application + :param algokit_utils.DeployCallArgs | None delete_args: Arguments used when deleting an application + :return DeployResponse: details action taken and relevant transactions + :raises DeploymentError: If the deployment failed""" + + return self.app_client.deploy( + version, + signer=signer, + sender=sender, + allow_update=allow_update, + allow_delete=allow_delete, + on_update=on_update, + on_schema_break=on_schema_break, + template_values=template_values, + create_args=_convert_deploy_args(create_args), + update_args=_convert_deploy_args(update_args), + delete_args=_convert_deploy_args(delete_args), + ) + + def compose(self, atc: AtomicTransactionComposer | None = None) -> Composer: + return Composer(self.app_client, atc or AtomicTransactionComposer()) diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/transaction_types_client.py b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/transaction_types_client.py new file mode 100644 index 0000000..8771e4b --- /dev/null +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/transaction_types_client.py @@ -0,0 +1,563 @@ +# flake8: noqa +# fmt: off +# mypy: disable-error-code="no-any-return, no-untyped-call, misc, type-arg" +# This file was automatically generated by algokit-client-generator. +# DO NOT MODIFY IT BY HAND. +# requires: algokit-utils@^1.2.0 +import base64 +import dataclasses +import decimal +import typing +from abc import ABC, abstractmethod + +import algokit_utils +import algosdk +from algosdk.v2client import models +from algosdk.atomic_transaction_composer import ( + AtomicTransactionComposer, + AtomicTransactionResponse, + SimulateAtomicTransactionResponse, + TransactionSigner, + TransactionWithSigner +) + +_APP_SPEC_JSON = r"""{ + "hints": { + "payment_txn(pay)uint64": { + "call_config": { + "no_op": "CALL" + } + }, + "asset_transfer_txn(axfer)uint64": { + "call_config": { + "no_op": "CALL" + } + } + }, + "source": { + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5UcmFuc2FjdGlvblR5cGVzLmFwcHJvdmFsX3Byb2dyYW06CiAgICBjYWxsc3ViIF9fcHV5YV9hcmM0X3JvdXRlcl9fCiAgICByZXR1cm4KCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5UcmFuc2FjdGlvblR5cGVzLl9fcHV5YV9hcmM0X3JvdXRlcl9fKCkgLT4gdWludDY0OgpfX3B1eWFfYXJjNF9yb3V0ZXJfXzoKICAgIHByb3RvIDAgMQogICAgdHhuIE51bUFwcEFyZ3MKICAgIGJ6IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2CiAgICBtZXRob2QgInBheW1lbnRfdHhuKHBheSl1aW50NjQiCiAgICBtZXRob2QgImFzc2V0X3RyYW5zZmVyX3R4bihheGZlcil1aW50NjQiCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAwCiAgICBtYXRjaCBfX3B1eWFfYXJjNF9yb3V0ZXJfX19wYXltZW50X3R4bl9yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2Fzc2V0X3RyYW5zZmVyX3R4bl9yb3V0ZUAzCiAgICBpbnQgMAogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19wYXltZW50X3R4bl9yb3V0ZUAyOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuIEdyb3VwSW5kZXgKICAgIGludCAxCiAgICAtCiAgICBkdXAKICAgIGd0eG5zIFR5cGVFbnVtCiAgICBpbnQgcGF5CiAgICA9PQogICAgYXNzZXJ0IC8vIHRyYW5zYWN0aW9uIHR5cGUgaXMgcGF5CiAgICBjYWxsc3ViIHBheW1lbnRfdHhuCiAgICBpdG9iCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hc3NldF90cmFuc2Zlcl90eG5fcm91dGVAMzoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4biBHcm91cEluZGV4CiAgICBpbnQgMQogICAgLQogICAgZHVwCiAgICBndHhucyBUeXBlRW51bQogICAgaW50IGF4ZmVyCiAgICA9PQogICAgYXNzZXJ0IC8vIHRyYW5zYWN0aW9uIHR5cGUgaXMgYXhmZXIKICAgIGNhbGxzdWIgYXNzZXRfdHJhbnNmZXJfdHhuCiAgICBpdG9iCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgIGJueiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDEwCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgIQogICAgYXNzZXJ0IC8vIGlzIGNyZWF0aW5nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDEwOgogICAgaW50IDAKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LlRyYW5zYWN0aW9uVHlwZXMucGF5bWVudF90eG4ocGF5OiB1aW50NjQpIC0+IHVpbnQ2NDoKcGF5bWVudF90eG46CiAgICBwcm90byAxIDEKICAgIGZyYW1lX2RpZyAtMQogICAgZ3R4bnMgQW1vdW50CiAgICBkdXAKICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0xCiAgICBndHhucyBSZWNlaXZlcgogICAgZ2xvYmFsIEN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMQogICAgZ3R4bnMgU2VuZGVyCiAgICB0eG4gU2VuZGVyCiAgICA9PQogICAgYXNzZXJ0CiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5UcmFuc2FjdGlvblR5cGVzLmFzc2V0X3RyYW5zZmVyX3R4bihhc3NldF90cmFuc2ZlcjogdWludDY0KSAtPiB1aW50NjQ6CmFzc2V0X3RyYW5zZmVyX3R4bjoKICAgIHByb3RvIDEgMQogICAgZ2xvYmFsIEN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MKICAgIGZyYW1lX2RpZyAtMQogICAgZ3R4bnMgWGZlckFzc2V0CiAgICBhc3NldF9ob2xkaW5nX2dldCBBc3NldEJhbGFuY2UKICAgIGJ1cnkgMQogICAgYXNzZXJ0IC8vIEFzc2V0IG5vdCBvcHRlZCBpbgogICAgZnJhbWVfZGlnIC0xCiAgICBndHhucyBBc3NldEFtb3VudAogICAgZHVwCiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMQogICAgZ3R4bnMgQXNzZXRSZWNlaXZlcgogICAgZ2xvYmFsIEN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMQogICAgZ3R4bnMgU2VuZGVyCiAgICB0eG4gU2VuZGVyCiAgICA9PQogICAgYXNzZXJ0CiAgICByZXRzdWIK", + "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5UcmFuc2FjdGlvblR5cGVzLmNsZWFyX3N0YXRlX3Byb2dyYW06CiAgICBpbnQgMQogICAgcmV0dXJuCg==" + }, + "state": { + "global": { + "num_byte_slices": 0, + "num_uints": 0 + }, + "local": { + "num_byte_slices": 0, + "num_uints": 0 + } + }, + "schema": { + "global": { + "declared": {}, + "reserved": {} + }, + "local": { + "declared": {}, + "reserved": {} + } + }, + "contract": { + "name": "TransactionTypes", + "methods": [ + { + "name": "payment_txn", + "args": [ + { + "type": "pay", + "name": "pay" + } + ], + "returns": { + "type": "uint64" + } + }, + { + "name": "asset_transfer_txn", + "args": [ + { + "type": "axfer", + "name": "asset_transfer" + } + ], + "returns": { + "type": "uint64" + } + } + ], + "networks": {} + }, + "bare_call_config": { + "no_op": "CREATE" + } +}""" +APP_SPEC = algokit_utils.ApplicationSpecification.from_json(_APP_SPEC_JSON) +_TReturn = typing.TypeVar("_TReturn") + + +class _ArgsBase(ABC, typing.Generic[_TReturn]): + @staticmethod + @abstractmethod + def method() -> str: + ... + + +_TArgs = typing.TypeVar("_TArgs", bound=_ArgsBase[typing.Any]) + + +@dataclasses.dataclass(kw_only=True) +class _TArgsHolder(typing.Generic[_TArgs]): + args: _TArgs + + +def _filter_none(value: dict | typing.Any) -> dict | typing.Any: + if isinstance(value, dict): + return {k: _filter_none(v) for k, v in value.items() if v is not None} + return value + + +def _as_dict(data: typing.Any, *, convert_all: bool = True) -> dict[str, typing.Any]: + if data is None: + return {} + if not dataclasses.is_dataclass(data): + raise TypeError(f"{data} must be a dataclass") + if convert_all: + result = dataclasses.asdict(data) # type: ignore[call-overload] + else: + result = {f.name: getattr(data, f.name) for f in dataclasses.fields(data)} + return _filter_none(result) + + +def _convert_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, +) -> algokit_utils.TransactionParametersDict: + return typing.cast(algokit_utils.TransactionParametersDict, _as_dict(transaction_parameters)) + + +def _convert_call_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, +) -> algokit_utils.OnCompleteCallParametersDict: + return typing.cast(algokit_utils.OnCompleteCallParametersDict, _as_dict(transaction_parameters)) + + +def _convert_create_transaction_parameters( + transaction_parameters: algokit_utils.TransactionParameters | None, + on_complete: algokit_utils.OnCompleteActionName, +) -> algokit_utils.CreateCallParametersDict: + result = typing.cast(algokit_utils.CreateCallParametersDict, _as_dict(transaction_parameters)) + on_complete_enum = on_complete.replace("_", " ").title().replace(" ", "") + "OC" + result["on_complete"] = getattr(algosdk.transaction.OnComplete, on_complete_enum) + return result + + +def _convert_deploy_args( + deploy_args: algokit_utils.DeployCallArgs | None, +) -> algokit_utils.ABICreateCallArgsDict | None: + if deploy_args is None: + return None + + deploy_args_dict = typing.cast(algokit_utils.ABICreateCallArgsDict, _as_dict(deploy_args)) + if isinstance(deploy_args, _TArgsHolder): + deploy_args_dict["args"] = _as_dict(deploy_args.args) + deploy_args_dict["method"] = deploy_args.args.method() + + return deploy_args_dict + + +@dataclasses.dataclass(kw_only=True) +class PaymentTxnArgs(_ArgsBase[int]): + pay: TransactionWithSigner + + @staticmethod + def method() -> str: + return "payment_txn(pay)uint64" + + +@dataclasses.dataclass(kw_only=True) +class AssetTransferTxnArgs(_ArgsBase[int]): + asset_transfer: TransactionWithSigner + + @staticmethod + def method() -> str: + return "asset_transfer_txn(axfer)uint64" + + +@dataclasses.dataclass(kw_only=True) +class SimulateOptions: + allow_more_logs: bool = dataclasses.field(default=False) + allow_empty_signatures: bool = dataclasses.field(default=False) + extra_opcode_budget: int = dataclasses.field(default=0) + exec_trace_config: models.SimulateTraceConfig | None = dataclasses.field(default=None) + + +class Composer: + + def __init__(self, app_client: algokit_utils.ApplicationClient, atc: AtomicTransactionComposer): + self.app_client = app_client + self.atc = atc + + def build(self) -> AtomicTransactionComposer: + return self.atc + + def simulate(self, options: SimulateOptions | None = None) -> SimulateAtomicTransactionResponse: + request = models.SimulateRequest( + allow_more_logs=options.allow_more_logs, + allow_empty_signatures=options.allow_empty_signatures, + extra_opcode_budget=options.extra_opcode_budget, + exec_trace_config=options.exec_trace_config, + txn_groups=[] + ) if options else None + result = self.atc.simulate(self.app_client.algod_client, request) + return result + + def execute(self) -> AtomicTransactionResponse: + return self.app_client.execute_atc(self.atc) + + def payment_txn( + self, + *, + pay: TransactionWithSigner, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> "Composer": + """Adds a call to `payment_txn(pay)uint64` ABI method + + :param TransactionWithSigner pay: The `pay` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + args = PaymentTxnArgs( + pay=pay, + ) + self.app_client.compose_call( + self.atc, + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return self + + def asset_transfer_txn( + self, + *, + asset_transfer: TransactionWithSigner, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> "Composer": + """Adds a call to `asset_transfer_txn(axfer)uint64` ABI method + + :param TransactionWithSigner asset_transfer: The `asset_transfer` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + args = AssetTransferTxnArgs( + asset_transfer=asset_transfer, + ) + self.app_client.compose_call( + self.atc, + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return self + + def create_bare( + self, + *, + on_complete: typing.Literal["no_op"] = "no_op", + transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, + ) -> "Composer": + """Adds a call to create an application using the no_op bare method + + :param typing.Literal[no_op] on_complete: On completion type to use + :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns Composer: This Composer instance""" + + self.app_client.compose_create( + self.atc, + call_abi_method=False, + transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), + ) + return self + + def clear_state( + self, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + app_args: list[bytes] | None = None, + ) -> "Composer": + """Adds a call to the application with on completion set to ClearState + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :param list[bytes] | None app_args: (optional) Application args to pass""" + + self.app_client.compose_clear_state(self.atc, _convert_transaction_parameters(transaction_parameters), app_args) + return self + + +class TransactionTypesClient: + """A class for interacting with the TransactionTypes app providing high productivity and + strongly typed methods to deploy and call the app""" + + @typing.overload + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + app_id: int = 0, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + ... + + @typing.overload + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + creator: str | algokit_utils.Account, + indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, + existing_deployments: algokit_utils.AppLookup | None = None, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + ... + + def __init__( + self, + algod_client: algosdk.v2client.algod.AlgodClient, + *, + creator: str | algokit_utils.Account | None = None, + indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, + existing_deployments: algokit_utils.AppLookup | None = None, + app_id: int = 0, + signer: TransactionSigner | algokit_utils.Account | None = None, + sender: str | None = None, + suggested_params: algosdk.transaction.SuggestedParams | None = None, + template_values: algokit_utils.TemplateValueMapping | None = None, + app_name: str | None = None, + ) -> None: + """ + TransactionTypesClient can be created with an app_id to interact with an existing application, alternatively + it can be created with a creator and indexer_client specified to find existing applications by name and creator. + + :param AlgodClient algod_client: AlgoSDK algod client + :param int app_id: The app_id of an existing application, to instead find the application by creator and name + use the creator and indexer_client parameters + :param str | Account creator: The address or Account of the app creator to resolve the app_id + :param IndexerClient indexer_client: AlgoSDK indexer client, only required if deploying or finding app_id by + creator and app name + :param AppLookup existing_deployments: + :param TransactionSigner | Account signer: Account or signer to use to sign transactions, if not specified and + creator was passed as an Account will use that. + :param str sender: Address to use as the sender for all transactions, will use the address associated with the + signer if not specified. + :param TemplateValueMapping template_values: Values to use for TMPL_* template variables, dictionary keys should + *NOT* include the TMPL_ prefix + :param str | None app_name: Name of application to use when deploying, defaults to name defined on the + Application Specification + """ + + self.app_spec = APP_SPEC + + # calling full __init__ signature, so ignoring mypy warning about overloads + self.app_client = algokit_utils.ApplicationClient( # type: ignore[call-overload, misc] + algod_client=algod_client, + app_spec=self.app_spec, + app_id=app_id, + creator=creator, + indexer_client=indexer_client, + existing_deployments=existing_deployments, + signer=signer, + sender=sender, + suggested_params=suggested_params, + template_values=template_values, + app_name=app_name, + ) + + @property + def algod_client(self) -> algosdk.v2client.algod.AlgodClient: + return self.app_client.algod_client + + @property + def app_id(self) -> int: + return self.app_client.app_id + + @app_id.setter + def app_id(self, value: int) -> None: + self.app_client.app_id = value + + @property + def app_address(self) -> str: + return self.app_client.app_address + + @property + def sender(self) -> str | None: + return self.app_client.sender + + @sender.setter + def sender(self, value: str) -> None: + self.app_client.sender = value + + @property + def signer(self) -> TransactionSigner | None: + return self.app_client.signer + + @signer.setter + def signer(self, value: TransactionSigner) -> None: + self.app_client.signer = value + + @property + def suggested_params(self) -> algosdk.transaction.SuggestedParams | None: + return self.app_client.suggested_params + + @suggested_params.setter + def suggested_params(self, value: algosdk.transaction.SuggestedParams | None) -> None: + self.app_client.suggested_params = value + + def payment_txn( + self, + *, + pay: TransactionWithSigner, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> algokit_utils.ABITransactionResponse[int]: + """Calls `payment_txn(pay)uint64` ABI method + + :param TransactionWithSigner pay: The `pay` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.ABITransactionResponse[int]: The result of the transaction""" + + args = PaymentTxnArgs( + pay=pay, + ) + result = self.app_client.call( + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return result + + def asset_transfer_txn( + self, + *, + asset_transfer: TransactionWithSigner, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + ) -> algokit_utils.ABITransactionResponse[int]: + """Calls `asset_transfer_txn(axfer)uint64` ABI method + + :param TransactionWithSigner asset_transfer: The `asset_transfer` ABI parameter + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.ABITransactionResponse[int]: The result of the transaction""" + + args = AssetTransferTxnArgs( + asset_transfer=asset_transfer, + ) + result = self.app_client.call( + call_abi_method=args.method(), + transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), + **_as_dict(args, convert_all=True), + ) + return result + + def create_bare( + self, + *, + on_complete: typing.Literal["no_op"] = "no_op", + transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, + ) -> algokit_utils.TransactionResponse: + """Creates an application using the no_op bare method + + :param typing.Literal[no_op] on_complete: On completion type to use + :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters + :returns algokit_utils.TransactionResponse: The result of the transaction""" + + result = self.app_client.create( + call_abi_method=False, + transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), + ) + return result + + def clear_state( + self, + transaction_parameters: algokit_utils.TransactionParameters | None = None, + app_args: list[bytes] | None = None, + ) -> algokit_utils.TransactionResponse: + """Calls the application with on completion set to ClearState + + :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters + :param list[bytes] | None app_args: (optional) Application args to pass + :returns algokit_utils.TransactionResponse: The result of the transaction""" + + return self.app_client.clear_state(_convert_transaction_parameters(transaction_parameters), app_args) + + def deploy( + self, + version: str | None = None, + *, + signer: TransactionSigner | None = None, + sender: str | None = None, + allow_update: bool | None = None, + allow_delete: bool | None = None, + on_update: algokit_utils.OnUpdate = algokit_utils.OnUpdate.Fail, + on_schema_break: algokit_utils.OnSchemaBreak = algokit_utils.OnSchemaBreak.Fail, + template_values: algokit_utils.TemplateValueMapping | None = None, + create_args: algokit_utils.DeployCallArgs | None = None, + update_args: algokit_utils.DeployCallArgs | None = None, + delete_args: algokit_utils.DeployCallArgs | None = None, + ) -> algokit_utils.DeployResponse: + """Deploy an application and update client to reference it. + + Idempotently deploy (create, update/delete if changed) an app against the given name via the given creator + account, including deploy-time template placeholder substitutions. + To understand the architecture decisions behind this functionality please see + + + ```{note} + If there is a breaking state schema change to an existing app (and `on_schema_break` is set to + 'ReplaceApp' the existing app will be deleted and re-created. + ``` + + ```{note} + If there is an update (different TEAL code) to an existing app (and `on_update` is set to 'ReplaceApp') + the existing app will be deleted and re-created. + ``` + + :param str version: version to use when creating or updating app, if None version will be auto incremented + :param algosdk.atomic_transaction_composer.TransactionSigner signer: signer to use when deploying app + , if None uses self.signer + :param str sender: sender address to use when deploying app, if None uses self.sender + :param bool allow_delete: Used to set the `TMPL_DELETABLE` template variable to conditionally control if an app + can be deleted + :param bool allow_update: Used to set the `TMPL_UPDATABLE` template variable to conditionally control if an app + can be updated + :param OnUpdate on_update: Determines what action to take if an application update is required + :param OnSchemaBreak on_schema_break: Determines what action to take if an application schema requirements + has increased beyond the current allocation + :param dict[str, int|str|bytes] template_values: Values to use for `TMPL_*` template variables, dictionary keys + should *NOT* include the TMPL_ prefix + :param algokit_utils.DeployCallArgs | None create_args: Arguments used when creating an application + :param algokit_utils.DeployCallArgs | None update_args: Arguments used when updating an application + :param algokit_utils.DeployCallArgs | None delete_args: Arguments used when deleting an application + :return DeployResponse: details action taken and relevant transactions + :raises DeploymentError: If the deployment failed""" + + return self.app_client.deploy( + version, + signer=signer, + sender=sender, + allow_update=allow_update, + allow_delete=allow_delete, + on_update=on_update, + on_schema_break=on_schema_break, + template_values=template_values, + create_args=_convert_deploy_args(create_args), + update_args=_convert_deploy_args(update_args), + delete_args=_convert_deploy_args(delete_args), + ) + + def compose(self, atc: AtomicTransactionComposer | None = None) -> Composer: + return Composer(self.app_client, atc or AtomicTransactionComposer()) From 44d81f9cbc185f7767f9ce7a9e4f859ae39bf497 Mon Sep 17 00:00:00 2001 From: "Chris Kim (Hyunggun)" Date: Wed, 20 Nov 2024 13:55:22 -0800 Subject: [PATCH 17/23] minor tuple example change --- .../smart_contracts/arc4_types/contract.py | 5 +++-- .../artifacts/arc4_types/Arc4Tuple.approval.teal | 4 ++-- .../artifacts/arc4_types/Arc4Tuple.arc32.json | 2 +- .../artifacts/arc4_types/arc4_tuple_client.py | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py index ff026e5..895c463 100644 --- a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py +++ b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py @@ -251,6 +251,7 @@ def return_todo(self, task: arc4.String) -> Todo: class Arc4Tuple(ARC4Contract): + def __init__(self) -> None: self.contact_info = GlobalState( @@ -262,8 +263,8 @@ def add_contact_info(self, contact: contact_info_tuple) -> UInt64: """An arc4.Tuple is a heterogeneous collection of arc4 types.""" name, email, phone = contact.native - assert name.native == "John Woods" - assert email.native == "john@something.com" + assert name.native == "Alice" + assert email.native == "alice@something.com" assert phone == arc4.UInt64(555_555_555) self.contact_info.value = contact diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.approval.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.approval.teal index 62aadc4..e678928 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.approval.teal +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.approval.teal @@ -90,11 +90,11 @@ add_contact_info: extract 4 8 // on error: Index access is out of bounds cover 2 extract 2 0 - byte "John Woods" + byte "Alice" == assert extract 2 0 - byte "john@something.com" + byte "alice@something.com" == assert dup diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.arc32.json b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.arc32.json index 8b437fd..ae63afa 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.arc32.json +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4Tuple.arc32.json @@ -12,7 +12,7 @@ } }, "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHVwbGUuYXBwcm92YWxfcHJvZ3JhbToKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBibnogbWFpbl9lbnRyeXBvaW50QDIKICAgIGNhbGxzdWIgX19pbml0X18KCm1haW5fZW50cnlwb2ludEAyOgogICAgY2FsbHN1YiBfX3B1eWFfYXJjNF9yb3V0ZXJfXwogICAgcmV0dXJuCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLl9fcHV5YV9hcmM0X3JvdXRlcl9fKCkgLT4gdWludDY0OgpfX3B1eWFfYXJjNF9yb3V0ZXJfXzoKICAgIHByb3RvIDAgMQogICAgdHhuIE51bUFwcEFyZ3MKICAgIGJ6IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2CiAgICBtZXRob2QgImFkZF9jb250YWN0X2luZm8oKHN0cmluZyxzdHJpbmcsdWludDY0KSl1aW50NjQiCiAgICBtZXRob2QgInJldHVybl9jb250YWN0KCkoc3RyaW5nLHN0cmluZyx1aW50NjQpIgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAogICAgbWF0Y2ggX19wdXlhX2FyYzRfcm91dGVyX19fYWRkX2NvbnRhY3RfaW5mb19yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX3JldHVybl9jb250YWN0X3JvdXRlQDMKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FkZF9jb250YWN0X2luZm9fcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYWRkX2NvbnRhY3RfaW5mbwogICAgaXRvYgogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fcmV0dXJuX2NvbnRhY3Rfcm91dGVAMzoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIGNhbGxzdWIgcmV0dXJuX2NvbnRhY3QKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgYm56IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTAKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICAhCiAgICBhc3NlcnQgLy8gaXMgY3JlYXRpbmcKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTA6CiAgICBpbnQgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLmFkZF9jb250YWN0X2luZm8oY29udGFjdDogYnl0ZXMpIC0+IHVpbnQ2NDoKYWRkX2NvbnRhY3RfaW5mbzoKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDIKICAgIGV4dHJhY3RfdWludDE2CiAgICBmcmFtZV9kaWcgLTEKICAgIHVuY292ZXIgMgogICAgZGlnIDIKICAgIHN1YnN0cmluZzMKICAgIHN3YXAKICAgIGZyYW1lX2RpZyAtMQogICAgbGVuCiAgICBmcmFtZV9kaWcgLTEKICAgIGNvdmVyIDIKICAgIHN1YnN0cmluZzMKICAgIHN3YXAKICAgIGZyYW1lX2RpZyAtMQogICAgZXh0cmFjdCA0IDggLy8gb24gZXJyb3I6IEluZGV4IGFjY2VzcyBpcyBvdXQgb2YgYm91bmRzCiAgICBjb3ZlciAyCiAgICBleHRyYWN0IDIgMAogICAgYnl0ZSAiSm9obiBXb29kcyIKICAgID09CiAgICBhc3NlcnQKICAgIGV4dHJhY3QgMiAwCiAgICBieXRlICJqb2huQHNvbWV0aGluZy5jb20iCiAgICA9PQogICAgYXNzZXJ0CiAgICBkdXAKICAgIGJ5dGUgMHgwMDAwMDAwMDIxMWQxYWUzCiAgICBiPT0KICAgIGFzc2VydAogICAgYnl0ZSAiY29udGFjdF9pbmZvIgogICAgZnJhbWVfZGlnIC0xCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgYnRvaQogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLnJldHVybl9jb250YWN0KCkgLT4gYnl0ZXM6CnJldHVybl9jb250YWN0OgogICAgcHJvdG8gMCAxCiAgICBpbnQgMAogICAgYnl0ZSAiY29udGFjdF9pbmZvIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBzZWxmLmNvbnRhY3RfaW5mbyBleGlzdHMKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUdXBsZS5fX2luaXRfXygpIC0+IHZvaWQ6Cl9faW5pdF9fOgogICAgcHJvdG8gMCAwCiAgICBieXRlICJjb250YWN0X2luZm8iCiAgICBieXRlIDB4MDAwYzAwMGUwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAKICAgIGFwcF9nbG9iYWxfcHV0CiAgICByZXRzdWIK", + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHVwbGUuYXBwcm92YWxfcHJvZ3JhbToKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBibnogbWFpbl9lbnRyeXBvaW50QDIKICAgIGNhbGxzdWIgX19pbml0X18KCm1haW5fZW50cnlwb2ludEAyOgogICAgY2FsbHN1YiBfX3B1eWFfYXJjNF9yb3V0ZXJfXwogICAgcmV0dXJuCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLl9fcHV5YV9hcmM0X3JvdXRlcl9fKCkgLT4gdWludDY0OgpfX3B1eWFfYXJjNF9yb3V0ZXJfXzoKICAgIHByb3RvIDAgMQogICAgdHhuIE51bUFwcEFyZ3MKICAgIGJ6IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2CiAgICBtZXRob2QgImFkZF9jb250YWN0X2luZm8oKHN0cmluZyxzdHJpbmcsdWludDY0KSl1aW50NjQiCiAgICBtZXRob2QgInJldHVybl9jb250YWN0KCkoc3RyaW5nLHN0cmluZyx1aW50NjQpIgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAogICAgbWF0Y2ggX19wdXlhX2FyYzRfcm91dGVyX19fYWRkX2NvbnRhY3RfaW5mb19yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX3JldHVybl9jb250YWN0X3JvdXRlQDMKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FkZF9jb250YWN0X2luZm9fcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYWRkX2NvbnRhY3RfaW5mbwogICAgaXRvYgogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fcmV0dXJuX2NvbnRhY3Rfcm91dGVAMzoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIGNhbGxzdWIgcmV0dXJuX2NvbnRhY3QKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgYm56IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTAKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICAhCiAgICBhc3NlcnQgLy8gaXMgY3JlYXRpbmcKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTA6CiAgICBpbnQgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLmFkZF9jb250YWN0X2luZm8oY29udGFjdDogYnl0ZXMpIC0+IHVpbnQ2NDoKYWRkX2NvbnRhY3RfaW5mbzoKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDIKICAgIGV4dHJhY3RfdWludDE2CiAgICBmcmFtZV9kaWcgLTEKICAgIHVuY292ZXIgMgogICAgZGlnIDIKICAgIHN1YnN0cmluZzMKICAgIHN3YXAKICAgIGZyYW1lX2RpZyAtMQogICAgbGVuCiAgICBmcmFtZV9kaWcgLTEKICAgIGNvdmVyIDIKICAgIHN1YnN0cmluZzMKICAgIHN3YXAKICAgIGZyYW1lX2RpZyAtMQogICAgZXh0cmFjdCA0IDggLy8gb24gZXJyb3I6IEluZGV4IGFjY2VzcyBpcyBvdXQgb2YgYm91bmRzCiAgICBjb3ZlciAyCiAgICBleHRyYWN0IDIgMAogICAgYnl0ZSAiQWxpY2UiCiAgICA9PQogICAgYXNzZXJ0CiAgICBleHRyYWN0IDIgMAogICAgYnl0ZSAiYWxpY2VAc29tZXRoaW5nLmNvbSIKICAgID09CiAgICBhc3NlcnQKICAgIGR1cAogICAgYnl0ZSAweDAwMDAwMDAwMjExZDFhZTMKICAgIGI9PQogICAgYXNzZXJ0CiAgICBieXRlICJjb250YWN0X2luZm8iCiAgICBmcmFtZV9kaWcgLTEKICAgIGFwcF9nbG9iYWxfcHV0CiAgICBidG9pCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHVwbGUucmV0dXJuX2NvbnRhY3QoKSAtPiBieXRlczoKcmV0dXJuX2NvbnRhY3Q6CiAgICBwcm90byAwIDEKICAgIGludCAwCiAgICBieXRlICJjb250YWN0X2luZm8iCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIHNlbGYuY29udGFjdF9pbmZvIGV4aXN0cwogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLl9faW5pdF9fKCkgLT4gdm9pZDoKX19pbml0X186CiAgICBwcm90byAwIDAKICAgIGJ5dGUgImNvbnRhY3RfaW5mbyIKICAgIGJ5dGUgMHgwMDBjMDAwZTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAogICAgYXBwX2dsb2JhbF9wdXQKICAgIHJldHN1Ygo=", "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHVwbGUuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" }, "state": { diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_tuple_client.py b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_tuple_client.py index 20dfa26..cd995d4 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_tuple_client.py +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_tuple_client.py @@ -35,7 +35,7 @@ } }, "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHVwbGUuYXBwcm92YWxfcHJvZ3JhbToKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBibnogbWFpbl9lbnRyeXBvaW50QDIKICAgIGNhbGxzdWIgX19pbml0X18KCm1haW5fZW50cnlwb2ludEAyOgogICAgY2FsbHN1YiBfX3B1eWFfYXJjNF9yb3V0ZXJfXwogICAgcmV0dXJuCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLl9fcHV5YV9hcmM0X3JvdXRlcl9fKCkgLT4gdWludDY0OgpfX3B1eWFfYXJjNF9yb3V0ZXJfXzoKICAgIHByb3RvIDAgMQogICAgdHhuIE51bUFwcEFyZ3MKICAgIGJ6IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2CiAgICBtZXRob2QgImFkZF9jb250YWN0X2luZm8oKHN0cmluZyxzdHJpbmcsdWludDY0KSl1aW50NjQiCiAgICBtZXRob2QgInJldHVybl9jb250YWN0KCkoc3RyaW5nLHN0cmluZyx1aW50NjQpIgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAogICAgbWF0Y2ggX19wdXlhX2FyYzRfcm91dGVyX19fYWRkX2NvbnRhY3RfaW5mb19yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX3JldHVybl9jb250YWN0X3JvdXRlQDMKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FkZF9jb250YWN0X2luZm9fcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYWRkX2NvbnRhY3RfaW5mbwogICAgaXRvYgogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fcmV0dXJuX2NvbnRhY3Rfcm91dGVAMzoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIGNhbGxzdWIgcmV0dXJuX2NvbnRhY3QKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgYm56IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTAKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICAhCiAgICBhc3NlcnQgLy8gaXMgY3JlYXRpbmcKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTA6CiAgICBpbnQgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLmFkZF9jb250YWN0X2luZm8oY29udGFjdDogYnl0ZXMpIC0+IHVpbnQ2NDoKYWRkX2NvbnRhY3RfaW5mbzoKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDIKICAgIGV4dHJhY3RfdWludDE2CiAgICBmcmFtZV9kaWcgLTEKICAgIHVuY292ZXIgMgogICAgZGlnIDIKICAgIHN1YnN0cmluZzMKICAgIHN3YXAKICAgIGZyYW1lX2RpZyAtMQogICAgbGVuCiAgICBmcmFtZV9kaWcgLTEKICAgIGNvdmVyIDIKICAgIHN1YnN0cmluZzMKICAgIHN3YXAKICAgIGZyYW1lX2RpZyAtMQogICAgZXh0cmFjdCA0IDggLy8gb24gZXJyb3I6IEluZGV4IGFjY2VzcyBpcyBvdXQgb2YgYm91bmRzCiAgICBjb3ZlciAyCiAgICBleHRyYWN0IDIgMAogICAgYnl0ZSAiSm9obiBXb29kcyIKICAgID09CiAgICBhc3NlcnQKICAgIGV4dHJhY3QgMiAwCiAgICBieXRlICJqb2huQHNvbWV0aGluZy5jb20iCiAgICA9PQogICAgYXNzZXJ0CiAgICBkdXAKICAgIGJ5dGUgMHgwMDAwMDAwMDIxMWQxYWUzCiAgICBiPT0KICAgIGFzc2VydAogICAgYnl0ZSAiY29udGFjdF9pbmZvIgogICAgZnJhbWVfZGlnIC0xCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgYnRvaQogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLnJldHVybl9jb250YWN0KCkgLT4gYnl0ZXM6CnJldHVybl9jb250YWN0OgogICAgcHJvdG8gMCAxCiAgICBpbnQgMAogICAgYnl0ZSAiY29udGFjdF9pbmZvIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBzZWxmLmNvbnRhY3RfaW5mbyBleGlzdHMKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LkFyYzRUdXBsZS5fX2luaXRfXygpIC0+IHZvaWQ6Cl9faW5pdF9fOgogICAgcHJvdG8gMCAwCiAgICBieXRlICJjb250YWN0X2luZm8iCiAgICBieXRlIDB4MDAwYzAwMGUwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAKICAgIGFwcF9nbG9iYWxfcHV0CiAgICByZXRzdWIK", + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHVwbGUuYXBwcm92YWxfcHJvZ3JhbToKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBibnogbWFpbl9lbnRyeXBvaW50QDIKICAgIGNhbGxzdWIgX19pbml0X18KCm1haW5fZW50cnlwb2ludEAyOgogICAgY2FsbHN1YiBfX3B1eWFfYXJjNF9yb3V0ZXJfXwogICAgcmV0dXJuCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLl9fcHV5YV9hcmM0X3JvdXRlcl9fKCkgLT4gdWludDY0OgpfX3B1eWFfYXJjNF9yb3V0ZXJfXzoKICAgIHByb3RvIDAgMQogICAgdHhuIE51bUFwcEFyZ3MKICAgIGJ6IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2CiAgICBtZXRob2QgImFkZF9jb250YWN0X2luZm8oKHN0cmluZyxzdHJpbmcsdWludDY0KSl1aW50NjQiCiAgICBtZXRob2QgInJldHVybl9jb250YWN0KCkoc3RyaW5nLHN0cmluZyx1aW50NjQpIgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAogICAgbWF0Y2ggX19wdXlhX2FyYzRfcm91dGVyX19fYWRkX2NvbnRhY3RfaW5mb19yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX3JldHVybl9jb250YWN0X3JvdXRlQDMKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FkZF9jb250YWN0X2luZm9fcm91dGVAMjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGNhbGxzdWIgYWRkX2NvbnRhY3RfaW5mbwogICAgaXRvYgogICAgYnl0ZSAweDE1MWY3Yzc1CiAgICBzd2FwCiAgICBjb25jYXQKICAgIGxvZwogICAgaW50IDEKICAgIHJldHN1YgoKX19wdXlhX2FyYzRfcm91dGVyX19fcmV0dXJuX2NvbnRhY3Rfcm91dGVAMzoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIGNhbGxzdWIgcmV0dXJuX2NvbnRhY3QKICAgIGJ5dGUgMHgxNTFmN2M3NQogICAgc3dhcAogICAgY29uY2F0CiAgICBsb2cKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2OgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgYm56IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTAKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICAhCiAgICBhc3NlcnQgLy8gaXMgY3JlYXRpbmcKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2FmdGVyX2lmX2Vsc2VAMTA6CiAgICBpbnQgMAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLmFkZF9jb250YWN0X2luZm8oY29udGFjdDogYnl0ZXMpIC0+IHVpbnQ2NDoKYWRkX2NvbnRhY3RfaW5mbzoKICAgIHByb3RvIDEgMQogICAgZnJhbWVfZGlnIC0xCiAgICBpbnQgMAogICAgZXh0cmFjdF91aW50MTYKICAgIGZyYW1lX2RpZyAtMQogICAgaW50IDIKICAgIGV4dHJhY3RfdWludDE2CiAgICBmcmFtZV9kaWcgLTEKICAgIHVuY292ZXIgMgogICAgZGlnIDIKICAgIHN1YnN0cmluZzMKICAgIHN3YXAKICAgIGZyYW1lX2RpZyAtMQogICAgbGVuCiAgICBmcmFtZV9kaWcgLTEKICAgIGNvdmVyIDIKICAgIHN1YnN0cmluZzMKICAgIHN3YXAKICAgIGZyYW1lX2RpZyAtMQogICAgZXh0cmFjdCA0IDggLy8gb24gZXJyb3I6IEluZGV4IGFjY2VzcyBpcyBvdXQgb2YgYm91bmRzCiAgICBjb3ZlciAyCiAgICBleHRyYWN0IDIgMAogICAgYnl0ZSAiQWxpY2UiCiAgICA9PQogICAgYXNzZXJ0CiAgICBleHRyYWN0IDIgMAogICAgYnl0ZSAiYWxpY2VAc29tZXRoaW5nLmNvbSIKICAgID09CiAgICBhc3NlcnQKICAgIGR1cAogICAgYnl0ZSAweDAwMDAwMDAwMjExZDFhZTMKICAgIGI9PQogICAgYXNzZXJ0CiAgICBieXRlICJjb250YWN0X2luZm8iCiAgICBmcmFtZV9kaWcgLTEKICAgIGFwcF9nbG9iYWxfcHV0CiAgICBidG9pCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHVwbGUucmV0dXJuX2NvbnRhY3QoKSAtPiBieXRlczoKcmV0dXJuX2NvbnRhY3Q6CiAgICBwcm90byAwIDEKICAgIGludCAwCiAgICBieXRlICJjb250YWN0X2luZm8iCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIHNlbGYuY29udGFjdF9pbmZvIGV4aXN0cwogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLmFyYzRfdHlwZXMuY29udHJhY3QuQXJjNFR1cGxlLl9faW5pdF9fKCkgLT4gdm9pZDoKX19pbml0X186CiAgICBwcm90byAwIDAKICAgIGJ5dGUgImNvbnRhY3RfaW5mbyIKICAgIGJ5dGUgMHgwMDBjMDAwZTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAogICAgYXBwX2dsb2JhbF9wdXQKICAgIHJldHN1Ygo=", "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5BcmM0VHVwbGUuY2xlYXJfc3RhdGVfcHJvZ3JhbToKICAgIGludCAxCiAgICByZXR1cm4K" }, "state": { From 11ea6295834f319bf962b5c1d0e724719f19d714 Mon Sep 17 00:00:00 2001 From: "Chris Kim (Hyunggun)" Date: Fri, 22 Nov 2024 14:55:13 -0800 Subject: [PATCH 18/23] chore: add dev portal import comments, update test --- .../smart_contracts/arc4_types/contract.py | 49 +- .../arc4_types/TransactionTypes.approval.teal | 123 ---- .../arc4_types/TransactionTypes.arc32.json | 73 --- .../arc4_types/TransactionTypes.clear.teal | 5 - .../arc4_types/transaction_types_client.py | 563 ------------------ .../tests/arc4_types_integration_test.py | 28 +- 6 files changed, 34 insertions(+), 807 deletions(-) delete mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/TransactionTypes.approval.teal delete mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/TransactionTypes.arc32.json delete mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/TransactionTypes.clear.teal delete mode 100644 projects/python-contract-examples/smart_contracts/artifacts/arc4_types/transaction_types_client.py diff --git a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py index 895c463..b50b312 100644 --- a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py +++ b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py @@ -17,6 +17,7 @@ class Arc4Types(ARC4Contract): + # example: ARC4_UINT64 @abimethod() def add_arc4_uint64(self, a: arc4.UInt64, b: arc4.UInt64) -> arc4.UInt64: """ @@ -29,7 +30,9 @@ def add_arc4_uint64(self, a: arc4.UInt64, b: arc4.UInt64) -> arc4.UInt64: c = a.native + b.native return arc4.UInt64(c) + # example: ARC4_UINT64 + # example: ARC4_UINTN @abimethod() def add_arc4_uint_n( self, a: arc4.UInt8, b: arc4.UInt16, c: arc4.UInt32, d: arc4.UInt64 @@ -46,7 +49,9 @@ def add_arc4_uint_n( total = a.native + b.native + c.native + d.native return arc4.UInt64(total) + # example: ARC4_UINTN + # example: ARC4_BIGUINT @abimethod() def add_arc4_biguint_n( self, a: arc4.UInt128, b: arc4.UInt256, c: arc4.UInt512 @@ -62,14 +67,18 @@ def add_arc4_biguint_n( total = a.native + b.native + c.native return arc4.UInt512(total) + # example: ARC4_BIGUINT + # example: ARC4_BYTES @abimethod() def arc4_byte(self, a: arc4.Byte) -> arc4.Byte: """ An arc4.Byte is essentially an alias for an 8-bit integer. """ return arc4.Byte(a.native + 1) + # example: ARC4_BYTES + # example: ARC4_ADDRESS @abimethod() def arc4_address_properties(self, address: arc4.Address) -> UInt64: underlying_bytes = ( # noqa: F841 @@ -103,8 +112,9 @@ def arc4_address_return(self, address: arc4.Address) -> arc4.Address: assert converted_address == address return converted_address + # example: ARC4_ADDRESS - +# example: ARC4_STATIC_ARRAY AliasedStaticArray: t.TypeAlias = arc4.StaticArray[arc4.UInt8, t.Literal[1]] @@ -143,8 +153,9 @@ def arc4_static_array(self) -> None: so this won't compile: aliased_static.pop() """ +# example: ARC4_STATIC_ARRAY - +# example: ARC4_DYNAMIC_ARRAY goodbye: t.TypeAlias = arc4.DynamicArray[arc4.String] @@ -177,7 +188,9 @@ def hello(self, name: arc4.String) -> String: greeting += x.native return greeting +# example: ARC4_DYNAMIC_ARRAY + # example: ARC4_DYNAMIC_BYTES @abimethod() def arc4_dynamic_bytes(self) -> arc4.DynamicBytes: """arc4.DynamicBytes are essentially an arc4.DynamicArray[arc4.Bytes] and some convenience methods.""" @@ -195,8 +208,9 @@ def arc4_dynamic_bytes(self) -> arc4.DynamicBytes: dynamic_bytes.append(arc4.Byte(255)) return dynamic_bytes + # example: ARC4_DYNAMIC_BYTES - +# example: ARC4_STRUCT class Todo(arc4.Struct): task: arc4.String completed: arc4.Bool @@ -243,8 +257,9 @@ def return_todo(self, task: arc4.String) -> Todo: assert exist return todo_to_return +# example: ARC4_STRUCT - +# example: ARC4_TUPLE contact_info_tuple = arc4.Tuple[ arc4.String, arc4.String, arc4.UInt64 ] # name, email, phone @@ -276,28 +291,4 @@ def return_contact(self) -> arc4.Tuple[arc4.String, arc4.String, arc4.UInt64]: """An arc4.Tuple can be returned when more than one return value is needed.""" return self.contact_info.value - - -class TransactionTypes(ARC4Contract): - - @abimethod - def payment_txn(self, pay: gtxn.PaymentTransaction) -> UInt64: - assert pay.amount > 0 - assert pay.receiver == Global.current_application_address - assert pay.sender == Txn.sender - - return pay.amount - - @abimethod - def asset_transfer_txn( - self, asset_transfer: gtxn.AssetTransferTransaction - ) -> UInt64: - assert Global.current_application_address.is_opted_in( - asset_transfer.xfer_asset - ), "Asset not opted in" - - assert asset_transfer.asset_amount > 0 - assert asset_transfer.asset_receiver == Global.current_application_address - assert asset_transfer.sender == Txn.sender - - return asset_transfer.asset_amount +# example: ARC4_TUPLE diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/TransactionTypes.approval.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/TransactionTypes.approval.teal deleted file mode 100644 index 3cad3aa..0000000 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/TransactionTypes.approval.teal +++ /dev/null @@ -1,123 +0,0 @@ -#pragma version 10 - -smart_contracts.arc4_types.contract.TransactionTypes.approval_program: - callsub __puya_arc4_router__ - return - - -// smart_contracts.arc4_types.contract.TransactionTypes.__puya_arc4_router__() -> uint64: -__puya_arc4_router__: - proto 0 1 - txn NumAppArgs - bz __puya_arc4_router___bare_routing@6 - method "payment_txn(pay)uint64" - method "asset_transfer_txn(axfer)uint64" - txna ApplicationArgs 0 - match __puya_arc4_router___payment_txn_route@2 __puya_arc4_router___asset_transfer_txn_route@3 - int 0 - retsub - -__puya_arc4_router___payment_txn_route@2: - txn OnCompletion - ! - assert // OnCompletion is NoOp - txn ApplicationID - assert // is not creating - txn GroupIndex - int 1 - - - dup - gtxns TypeEnum - int pay - == - assert // transaction type is pay - callsub payment_txn - itob - byte 0x151f7c75 - swap - concat - log - int 1 - retsub - -__puya_arc4_router___asset_transfer_txn_route@3: - txn OnCompletion - ! - assert // OnCompletion is NoOp - txn ApplicationID - assert // is not creating - txn GroupIndex - int 1 - - - dup - gtxns TypeEnum - int axfer - == - assert // transaction type is axfer - callsub asset_transfer_txn - itob - byte 0x151f7c75 - swap - concat - log - int 1 - retsub - -__puya_arc4_router___bare_routing@6: - txn OnCompletion - bnz __puya_arc4_router___after_if_else@10 - txn ApplicationID - ! - assert // is creating - int 1 - retsub - -__puya_arc4_router___after_if_else@10: - int 0 - retsub - - -// smart_contracts.arc4_types.contract.TransactionTypes.payment_txn(pay: uint64) -> uint64: -payment_txn: - proto 1 1 - frame_dig -1 - gtxns Amount - dup - assert - frame_dig -1 - gtxns Receiver - global CurrentApplicationAddress - == - assert - frame_dig -1 - gtxns Sender - txn Sender - == - assert - retsub - - -// smart_contracts.arc4_types.contract.TransactionTypes.asset_transfer_txn(asset_transfer: uint64) -> uint64: -asset_transfer_txn: - proto 1 1 - global CurrentApplicationAddress - frame_dig -1 - gtxns XferAsset - asset_holding_get AssetBalance - bury 1 - assert // Asset not opted in - frame_dig -1 - gtxns AssetAmount - dup - assert - frame_dig -1 - gtxns AssetReceiver - global CurrentApplicationAddress - == - assert - frame_dig -1 - gtxns Sender - txn Sender - == - assert - retsub diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/TransactionTypes.arc32.json b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/TransactionTypes.arc32.json deleted file mode 100644 index 047ca0c..0000000 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/TransactionTypes.arc32.json +++ /dev/null @@ -1,73 +0,0 @@ -{ - "hints": { - "payment_txn(pay)uint64": { - "call_config": { - "no_op": "CALL" - } - }, - "asset_transfer_txn(axfer)uint64": { - "call_config": { - "no_op": "CALL" - } - } - }, - "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5UcmFuc2FjdGlvblR5cGVzLmFwcHJvdmFsX3Byb2dyYW06CiAgICBjYWxsc3ViIF9fcHV5YV9hcmM0X3JvdXRlcl9fCiAgICByZXR1cm4KCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5UcmFuc2FjdGlvblR5cGVzLl9fcHV5YV9hcmM0X3JvdXRlcl9fKCkgLT4gdWludDY0OgpfX3B1eWFfYXJjNF9yb3V0ZXJfXzoKICAgIHByb3RvIDAgMQogICAgdHhuIE51bUFwcEFyZ3MKICAgIGJ6IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2CiAgICBtZXRob2QgInBheW1lbnRfdHhuKHBheSl1aW50NjQiCiAgICBtZXRob2QgImFzc2V0X3RyYW5zZmVyX3R4bihheGZlcil1aW50NjQiCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAwCiAgICBtYXRjaCBfX3B1eWFfYXJjNF9yb3V0ZXJfX19wYXltZW50X3R4bl9yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2Fzc2V0X3RyYW5zZmVyX3R4bl9yb3V0ZUAzCiAgICBpbnQgMAogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19wYXltZW50X3R4bl9yb3V0ZUAyOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuIEdyb3VwSW5kZXgKICAgIGludCAxCiAgICAtCiAgICBkdXAKICAgIGd0eG5zIFR5cGVFbnVtCiAgICBpbnQgcGF5CiAgICA9PQogICAgYXNzZXJ0IC8vIHRyYW5zYWN0aW9uIHR5cGUgaXMgcGF5CiAgICBjYWxsc3ViIHBheW1lbnRfdHhuCiAgICBpdG9iCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hc3NldF90cmFuc2Zlcl90eG5fcm91dGVAMzoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4biBHcm91cEluZGV4CiAgICBpbnQgMQogICAgLQogICAgZHVwCiAgICBndHhucyBUeXBlRW51bQogICAgaW50IGF4ZmVyCiAgICA9PQogICAgYXNzZXJ0IC8vIHRyYW5zYWN0aW9uIHR5cGUgaXMgYXhmZXIKICAgIGNhbGxzdWIgYXNzZXRfdHJhbnNmZXJfdHhuCiAgICBpdG9iCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgIGJueiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDEwCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgIQogICAgYXNzZXJ0IC8vIGlzIGNyZWF0aW5nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDEwOgogICAgaW50IDAKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LlRyYW5zYWN0aW9uVHlwZXMucGF5bWVudF90eG4ocGF5OiB1aW50NjQpIC0+IHVpbnQ2NDoKcGF5bWVudF90eG46CiAgICBwcm90byAxIDEKICAgIGZyYW1lX2RpZyAtMQogICAgZ3R4bnMgQW1vdW50CiAgICBkdXAKICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0xCiAgICBndHhucyBSZWNlaXZlcgogICAgZ2xvYmFsIEN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMQogICAgZ3R4bnMgU2VuZGVyCiAgICB0eG4gU2VuZGVyCiAgICA9PQogICAgYXNzZXJ0CiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5UcmFuc2FjdGlvblR5cGVzLmFzc2V0X3RyYW5zZmVyX3R4bihhc3NldF90cmFuc2ZlcjogdWludDY0KSAtPiB1aW50NjQ6CmFzc2V0X3RyYW5zZmVyX3R4bjoKICAgIHByb3RvIDEgMQogICAgZ2xvYmFsIEN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MKICAgIGZyYW1lX2RpZyAtMQogICAgZ3R4bnMgWGZlckFzc2V0CiAgICBhc3NldF9ob2xkaW5nX2dldCBBc3NldEJhbGFuY2UKICAgIGJ1cnkgMQogICAgYXNzZXJ0IC8vIEFzc2V0IG5vdCBvcHRlZCBpbgogICAgZnJhbWVfZGlnIC0xCiAgICBndHhucyBBc3NldEFtb3VudAogICAgZHVwCiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMQogICAgZ3R4bnMgQXNzZXRSZWNlaXZlcgogICAgZ2xvYmFsIEN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMQogICAgZ3R4bnMgU2VuZGVyCiAgICB0eG4gU2VuZGVyCiAgICA9PQogICAgYXNzZXJ0CiAgICByZXRzdWIK", - "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5UcmFuc2FjdGlvblR5cGVzLmNsZWFyX3N0YXRlX3Byb2dyYW06CiAgICBpbnQgMQogICAgcmV0dXJuCg==" - }, - "state": { - "global": { - "num_byte_slices": 0, - "num_uints": 0 - }, - "local": { - "num_byte_slices": 0, - "num_uints": 0 - } - }, - "schema": { - "global": { - "declared": {}, - "reserved": {} - }, - "local": { - "declared": {}, - "reserved": {} - } - }, - "contract": { - "name": "TransactionTypes", - "methods": [ - { - "name": "payment_txn", - "args": [ - { - "type": "pay", - "name": "pay" - } - ], - "readonly": false, - "returns": { - "type": "uint64" - } - }, - { - "name": "asset_transfer_txn", - "args": [ - { - "type": "axfer", - "name": "asset_transfer" - } - ], - "readonly": false, - "returns": { - "type": "uint64" - } - } - ], - "networks": {} - }, - "bare_call_config": { - "no_op": "CREATE" - } -} \ No newline at end of file diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/TransactionTypes.clear.teal b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/TransactionTypes.clear.teal deleted file mode 100644 index fc120bb..0000000 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/TransactionTypes.clear.teal +++ /dev/null @@ -1,5 +0,0 @@ -#pragma version 10 - -smart_contracts.arc4_types.contract.TransactionTypes.clear_state_program: - int 1 - return diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/transaction_types_client.py b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/transaction_types_client.py deleted file mode 100644 index 8771e4b..0000000 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/transaction_types_client.py +++ /dev/null @@ -1,563 +0,0 @@ -# flake8: noqa -# fmt: off -# mypy: disable-error-code="no-any-return, no-untyped-call, misc, type-arg" -# This file was automatically generated by algokit-client-generator. -# DO NOT MODIFY IT BY HAND. -# requires: algokit-utils@^1.2.0 -import base64 -import dataclasses -import decimal -import typing -from abc import ABC, abstractmethod - -import algokit_utils -import algosdk -from algosdk.v2client import models -from algosdk.atomic_transaction_composer import ( - AtomicTransactionComposer, - AtomicTransactionResponse, - SimulateAtomicTransactionResponse, - TransactionSigner, - TransactionWithSigner -) - -_APP_SPEC_JSON = r"""{ - "hints": { - "payment_txn(pay)uint64": { - "call_config": { - "no_op": "CALL" - } - }, - "asset_transfer_txn(axfer)uint64": { - "call_config": { - "no_op": "CALL" - } - } - }, - "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5UcmFuc2FjdGlvblR5cGVzLmFwcHJvdmFsX3Byb2dyYW06CiAgICBjYWxsc3ViIF9fcHV5YV9hcmM0X3JvdXRlcl9fCiAgICByZXR1cm4KCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5UcmFuc2FjdGlvblR5cGVzLl9fcHV5YV9hcmM0X3JvdXRlcl9fKCkgLT4gdWludDY0OgpfX3B1eWFfYXJjNF9yb3V0ZXJfXzoKICAgIHByb3RvIDAgMQogICAgdHhuIE51bUFwcEFyZ3MKICAgIGJ6IF9fcHV5YV9hcmM0X3JvdXRlcl9fX2JhcmVfcm91dGluZ0A2CiAgICBtZXRob2QgInBheW1lbnRfdHhuKHBheSl1aW50NjQiCiAgICBtZXRob2QgImFzc2V0X3RyYW5zZmVyX3R4bihheGZlcil1aW50NjQiCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAwCiAgICBtYXRjaCBfX3B1eWFfYXJjNF9yb3V0ZXJfX19wYXltZW50X3R4bl9yb3V0ZUAyIF9fcHV5YV9hcmM0X3JvdXRlcl9fX2Fzc2V0X3RyYW5zZmVyX3R4bl9yb3V0ZUAzCiAgICBpbnQgMAogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19wYXltZW50X3R4bl9yb3V0ZUAyOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgdHhuIEdyb3VwSW5kZXgKICAgIGludCAxCiAgICAtCiAgICBkdXAKICAgIGd0eG5zIFR5cGVFbnVtCiAgICBpbnQgcGF5CiAgICA9PQogICAgYXNzZXJ0IC8vIHRyYW5zYWN0aW9uIHR5cGUgaXMgcGF5CiAgICBjYWxsc3ViIHBheW1lbnRfdHhuCiAgICBpdG9iCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hc3NldF90cmFuc2Zlcl90eG5fcm91dGVAMzoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgICEKICAgIGFzc2VydCAvLyBPbkNvbXBsZXRpb24gaXMgTm9PcAogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgIGFzc2VydCAvLyBpcyBub3QgY3JlYXRpbmcKICAgIHR4biBHcm91cEluZGV4CiAgICBpbnQgMQogICAgLQogICAgZHVwCiAgICBndHhucyBUeXBlRW51bQogICAgaW50IGF4ZmVyCiAgICA9PQogICAgYXNzZXJ0IC8vIHRyYW5zYWN0aW9uIHR5cGUgaXMgYXhmZXIKICAgIGNhbGxzdWIgYXNzZXRfdHJhbnNmZXJfdHhuCiAgICBpdG9iCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19iYXJlX3JvdXRpbmdANjoKICAgIHR4biBPbkNvbXBsZXRpb24KICAgIGJueiBfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDEwCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgIQogICAgYXNzZXJ0IC8vIGlzIGNyZWF0aW5nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDEwOgogICAgaW50IDAKICAgIHJldHN1YgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5hcmM0X3R5cGVzLmNvbnRyYWN0LlRyYW5zYWN0aW9uVHlwZXMucGF5bWVudF90eG4ocGF5OiB1aW50NjQpIC0+IHVpbnQ2NDoKcGF5bWVudF90eG46CiAgICBwcm90byAxIDEKICAgIGZyYW1lX2RpZyAtMQogICAgZ3R4bnMgQW1vdW50CiAgICBkdXAKICAgIGFzc2VydAogICAgZnJhbWVfZGlnIC0xCiAgICBndHhucyBSZWNlaXZlcgogICAgZ2xvYmFsIEN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMQogICAgZ3R4bnMgU2VuZGVyCiAgICB0eG4gU2VuZGVyCiAgICA9PQogICAgYXNzZXJ0CiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5UcmFuc2FjdGlvblR5cGVzLmFzc2V0X3RyYW5zZmVyX3R4bihhc3NldF90cmFuc2ZlcjogdWludDY0KSAtPiB1aW50NjQ6CmFzc2V0X3RyYW5zZmVyX3R4bjoKICAgIHByb3RvIDEgMQogICAgZ2xvYmFsIEN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MKICAgIGZyYW1lX2RpZyAtMQogICAgZ3R4bnMgWGZlckFzc2V0CiAgICBhc3NldF9ob2xkaW5nX2dldCBBc3NldEJhbGFuY2UKICAgIGJ1cnkgMQogICAgYXNzZXJ0IC8vIEFzc2V0IG5vdCBvcHRlZCBpbgogICAgZnJhbWVfZGlnIC0xCiAgICBndHhucyBBc3NldEFtb3VudAogICAgZHVwCiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMQogICAgZ3R4bnMgQXNzZXRSZWNlaXZlcgogICAgZ2xvYmFsIEN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MKICAgID09CiAgICBhc3NlcnQKICAgIGZyYW1lX2RpZyAtMQogICAgZ3R4bnMgU2VuZGVyCiAgICB0eG4gU2VuZGVyCiAgICA9PQogICAgYXNzZXJ0CiAgICByZXRzdWIK", - "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMuYXJjNF90eXBlcy5jb250cmFjdC5UcmFuc2FjdGlvblR5cGVzLmNsZWFyX3N0YXRlX3Byb2dyYW06CiAgICBpbnQgMQogICAgcmV0dXJuCg==" - }, - "state": { - "global": { - "num_byte_slices": 0, - "num_uints": 0 - }, - "local": { - "num_byte_slices": 0, - "num_uints": 0 - } - }, - "schema": { - "global": { - "declared": {}, - "reserved": {} - }, - "local": { - "declared": {}, - "reserved": {} - } - }, - "contract": { - "name": "TransactionTypes", - "methods": [ - { - "name": "payment_txn", - "args": [ - { - "type": "pay", - "name": "pay" - } - ], - "returns": { - "type": "uint64" - } - }, - { - "name": "asset_transfer_txn", - "args": [ - { - "type": "axfer", - "name": "asset_transfer" - } - ], - "returns": { - "type": "uint64" - } - } - ], - "networks": {} - }, - "bare_call_config": { - "no_op": "CREATE" - } -}""" -APP_SPEC = algokit_utils.ApplicationSpecification.from_json(_APP_SPEC_JSON) -_TReturn = typing.TypeVar("_TReturn") - - -class _ArgsBase(ABC, typing.Generic[_TReturn]): - @staticmethod - @abstractmethod - def method() -> str: - ... - - -_TArgs = typing.TypeVar("_TArgs", bound=_ArgsBase[typing.Any]) - - -@dataclasses.dataclass(kw_only=True) -class _TArgsHolder(typing.Generic[_TArgs]): - args: _TArgs - - -def _filter_none(value: dict | typing.Any) -> dict | typing.Any: - if isinstance(value, dict): - return {k: _filter_none(v) for k, v in value.items() if v is not None} - return value - - -def _as_dict(data: typing.Any, *, convert_all: bool = True) -> dict[str, typing.Any]: - if data is None: - return {} - if not dataclasses.is_dataclass(data): - raise TypeError(f"{data} must be a dataclass") - if convert_all: - result = dataclasses.asdict(data) # type: ignore[call-overload] - else: - result = {f.name: getattr(data, f.name) for f in dataclasses.fields(data)} - return _filter_none(result) - - -def _convert_transaction_parameters( - transaction_parameters: algokit_utils.TransactionParameters | None, -) -> algokit_utils.TransactionParametersDict: - return typing.cast(algokit_utils.TransactionParametersDict, _as_dict(transaction_parameters)) - - -def _convert_call_transaction_parameters( - transaction_parameters: algokit_utils.TransactionParameters | None, -) -> algokit_utils.OnCompleteCallParametersDict: - return typing.cast(algokit_utils.OnCompleteCallParametersDict, _as_dict(transaction_parameters)) - - -def _convert_create_transaction_parameters( - transaction_parameters: algokit_utils.TransactionParameters | None, - on_complete: algokit_utils.OnCompleteActionName, -) -> algokit_utils.CreateCallParametersDict: - result = typing.cast(algokit_utils.CreateCallParametersDict, _as_dict(transaction_parameters)) - on_complete_enum = on_complete.replace("_", " ").title().replace(" ", "") + "OC" - result["on_complete"] = getattr(algosdk.transaction.OnComplete, on_complete_enum) - return result - - -def _convert_deploy_args( - deploy_args: algokit_utils.DeployCallArgs | None, -) -> algokit_utils.ABICreateCallArgsDict | None: - if deploy_args is None: - return None - - deploy_args_dict = typing.cast(algokit_utils.ABICreateCallArgsDict, _as_dict(deploy_args)) - if isinstance(deploy_args, _TArgsHolder): - deploy_args_dict["args"] = _as_dict(deploy_args.args) - deploy_args_dict["method"] = deploy_args.args.method() - - return deploy_args_dict - - -@dataclasses.dataclass(kw_only=True) -class PaymentTxnArgs(_ArgsBase[int]): - pay: TransactionWithSigner - - @staticmethod - def method() -> str: - return "payment_txn(pay)uint64" - - -@dataclasses.dataclass(kw_only=True) -class AssetTransferTxnArgs(_ArgsBase[int]): - asset_transfer: TransactionWithSigner - - @staticmethod - def method() -> str: - return "asset_transfer_txn(axfer)uint64" - - -@dataclasses.dataclass(kw_only=True) -class SimulateOptions: - allow_more_logs: bool = dataclasses.field(default=False) - allow_empty_signatures: bool = dataclasses.field(default=False) - extra_opcode_budget: int = dataclasses.field(default=0) - exec_trace_config: models.SimulateTraceConfig | None = dataclasses.field(default=None) - - -class Composer: - - def __init__(self, app_client: algokit_utils.ApplicationClient, atc: AtomicTransactionComposer): - self.app_client = app_client - self.atc = atc - - def build(self) -> AtomicTransactionComposer: - return self.atc - - def simulate(self, options: SimulateOptions | None = None) -> SimulateAtomicTransactionResponse: - request = models.SimulateRequest( - allow_more_logs=options.allow_more_logs, - allow_empty_signatures=options.allow_empty_signatures, - extra_opcode_budget=options.extra_opcode_budget, - exec_trace_config=options.exec_trace_config, - txn_groups=[] - ) if options else None - result = self.atc.simulate(self.app_client.algod_client, request) - return result - - def execute(self) -> AtomicTransactionResponse: - return self.app_client.execute_atc(self.atc) - - def payment_txn( - self, - *, - pay: TransactionWithSigner, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> "Composer": - """Adds a call to `payment_txn(pay)uint64` ABI method - - :param TransactionWithSigner pay: The `pay` ABI parameter - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns Composer: This Composer instance""" - - args = PaymentTxnArgs( - pay=pay, - ) - self.app_client.compose_call( - self.atc, - call_abi_method=args.method(), - transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), - **_as_dict(args, convert_all=True), - ) - return self - - def asset_transfer_txn( - self, - *, - asset_transfer: TransactionWithSigner, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> "Composer": - """Adds a call to `asset_transfer_txn(axfer)uint64` ABI method - - :param TransactionWithSigner asset_transfer: The `asset_transfer` ABI parameter - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns Composer: This Composer instance""" - - args = AssetTransferTxnArgs( - asset_transfer=asset_transfer, - ) - self.app_client.compose_call( - self.atc, - call_abi_method=args.method(), - transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), - **_as_dict(args, convert_all=True), - ) - return self - - def create_bare( - self, - *, - on_complete: typing.Literal["no_op"] = "no_op", - transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, - ) -> "Composer": - """Adds a call to create an application using the no_op bare method - - :param typing.Literal[no_op] on_complete: On completion type to use - :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns Composer: This Composer instance""" - - self.app_client.compose_create( - self.atc, - call_abi_method=False, - transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), - ) - return self - - def clear_state( - self, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - app_args: list[bytes] | None = None, - ) -> "Composer": - """Adds a call to the application with on completion set to ClearState - - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :param list[bytes] | None app_args: (optional) Application args to pass""" - - self.app_client.compose_clear_state(self.atc, _convert_transaction_parameters(transaction_parameters), app_args) - return self - - -class TransactionTypesClient: - """A class for interacting with the TransactionTypes app providing high productivity and - strongly typed methods to deploy and call the app""" - - @typing.overload - def __init__( - self, - algod_client: algosdk.v2client.algod.AlgodClient, - *, - app_id: int = 0, - signer: TransactionSigner | algokit_utils.Account | None = None, - sender: str | None = None, - suggested_params: algosdk.transaction.SuggestedParams | None = None, - template_values: algokit_utils.TemplateValueMapping | None = None, - app_name: str | None = None, - ) -> None: - ... - - @typing.overload - def __init__( - self, - algod_client: algosdk.v2client.algod.AlgodClient, - *, - creator: str | algokit_utils.Account, - indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, - existing_deployments: algokit_utils.AppLookup | None = None, - signer: TransactionSigner | algokit_utils.Account | None = None, - sender: str | None = None, - suggested_params: algosdk.transaction.SuggestedParams | None = None, - template_values: algokit_utils.TemplateValueMapping | None = None, - app_name: str | None = None, - ) -> None: - ... - - def __init__( - self, - algod_client: algosdk.v2client.algod.AlgodClient, - *, - creator: str | algokit_utils.Account | None = None, - indexer_client: algosdk.v2client.indexer.IndexerClient | None = None, - existing_deployments: algokit_utils.AppLookup | None = None, - app_id: int = 0, - signer: TransactionSigner | algokit_utils.Account | None = None, - sender: str | None = None, - suggested_params: algosdk.transaction.SuggestedParams | None = None, - template_values: algokit_utils.TemplateValueMapping | None = None, - app_name: str | None = None, - ) -> None: - """ - TransactionTypesClient can be created with an app_id to interact with an existing application, alternatively - it can be created with a creator and indexer_client specified to find existing applications by name and creator. - - :param AlgodClient algod_client: AlgoSDK algod client - :param int app_id: The app_id of an existing application, to instead find the application by creator and name - use the creator and indexer_client parameters - :param str | Account creator: The address or Account of the app creator to resolve the app_id - :param IndexerClient indexer_client: AlgoSDK indexer client, only required if deploying or finding app_id by - creator and app name - :param AppLookup existing_deployments: - :param TransactionSigner | Account signer: Account or signer to use to sign transactions, if not specified and - creator was passed as an Account will use that. - :param str sender: Address to use as the sender for all transactions, will use the address associated with the - signer if not specified. - :param TemplateValueMapping template_values: Values to use for TMPL_* template variables, dictionary keys should - *NOT* include the TMPL_ prefix - :param str | None app_name: Name of application to use when deploying, defaults to name defined on the - Application Specification - """ - - self.app_spec = APP_SPEC - - # calling full __init__ signature, so ignoring mypy warning about overloads - self.app_client = algokit_utils.ApplicationClient( # type: ignore[call-overload, misc] - algod_client=algod_client, - app_spec=self.app_spec, - app_id=app_id, - creator=creator, - indexer_client=indexer_client, - existing_deployments=existing_deployments, - signer=signer, - sender=sender, - suggested_params=suggested_params, - template_values=template_values, - app_name=app_name, - ) - - @property - def algod_client(self) -> algosdk.v2client.algod.AlgodClient: - return self.app_client.algod_client - - @property - def app_id(self) -> int: - return self.app_client.app_id - - @app_id.setter - def app_id(self, value: int) -> None: - self.app_client.app_id = value - - @property - def app_address(self) -> str: - return self.app_client.app_address - - @property - def sender(self) -> str | None: - return self.app_client.sender - - @sender.setter - def sender(self, value: str) -> None: - self.app_client.sender = value - - @property - def signer(self) -> TransactionSigner | None: - return self.app_client.signer - - @signer.setter - def signer(self, value: TransactionSigner) -> None: - self.app_client.signer = value - - @property - def suggested_params(self) -> algosdk.transaction.SuggestedParams | None: - return self.app_client.suggested_params - - @suggested_params.setter - def suggested_params(self, value: algosdk.transaction.SuggestedParams | None) -> None: - self.app_client.suggested_params = value - - def payment_txn( - self, - *, - pay: TransactionWithSigner, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> algokit_utils.ABITransactionResponse[int]: - """Calls `payment_txn(pay)uint64` ABI method - - :param TransactionWithSigner pay: The `pay` ABI parameter - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns algokit_utils.ABITransactionResponse[int]: The result of the transaction""" - - args = PaymentTxnArgs( - pay=pay, - ) - result = self.app_client.call( - call_abi_method=args.method(), - transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), - **_as_dict(args, convert_all=True), - ) - return result - - def asset_transfer_txn( - self, - *, - asset_transfer: TransactionWithSigner, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - ) -> algokit_utils.ABITransactionResponse[int]: - """Calls `asset_transfer_txn(axfer)uint64` ABI method - - :param TransactionWithSigner asset_transfer: The `asset_transfer` ABI parameter - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns algokit_utils.ABITransactionResponse[int]: The result of the transaction""" - - args = AssetTransferTxnArgs( - asset_transfer=asset_transfer, - ) - result = self.app_client.call( - call_abi_method=args.method(), - transaction_parameters=_convert_call_transaction_parameters(transaction_parameters), - **_as_dict(args, convert_all=True), - ) - return result - - def create_bare( - self, - *, - on_complete: typing.Literal["no_op"] = "no_op", - transaction_parameters: algokit_utils.CreateTransactionParameters | None = None, - ) -> algokit_utils.TransactionResponse: - """Creates an application using the no_op bare method - - :param typing.Literal[no_op] on_complete: On completion type to use - :param algokit_utils.CreateTransactionParameters transaction_parameters: (optional) Additional transaction parameters - :returns algokit_utils.TransactionResponse: The result of the transaction""" - - result = self.app_client.create( - call_abi_method=False, - transaction_parameters=_convert_create_transaction_parameters(transaction_parameters, on_complete), - ) - return result - - def clear_state( - self, - transaction_parameters: algokit_utils.TransactionParameters | None = None, - app_args: list[bytes] | None = None, - ) -> algokit_utils.TransactionResponse: - """Calls the application with on completion set to ClearState - - :param algokit_utils.TransactionParameters transaction_parameters: (optional) Additional transaction parameters - :param list[bytes] | None app_args: (optional) Application args to pass - :returns algokit_utils.TransactionResponse: The result of the transaction""" - - return self.app_client.clear_state(_convert_transaction_parameters(transaction_parameters), app_args) - - def deploy( - self, - version: str | None = None, - *, - signer: TransactionSigner | None = None, - sender: str | None = None, - allow_update: bool | None = None, - allow_delete: bool | None = None, - on_update: algokit_utils.OnUpdate = algokit_utils.OnUpdate.Fail, - on_schema_break: algokit_utils.OnSchemaBreak = algokit_utils.OnSchemaBreak.Fail, - template_values: algokit_utils.TemplateValueMapping | None = None, - create_args: algokit_utils.DeployCallArgs | None = None, - update_args: algokit_utils.DeployCallArgs | None = None, - delete_args: algokit_utils.DeployCallArgs | None = None, - ) -> algokit_utils.DeployResponse: - """Deploy an application and update client to reference it. - - Idempotently deploy (create, update/delete if changed) an app against the given name via the given creator - account, including deploy-time template placeholder substitutions. - To understand the architecture decisions behind this functionality please see - - - ```{note} - If there is a breaking state schema change to an existing app (and `on_schema_break` is set to - 'ReplaceApp' the existing app will be deleted and re-created. - ``` - - ```{note} - If there is an update (different TEAL code) to an existing app (and `on_update` is set to 'ReplaceApp') - the existing app will be deleted and re-created. - ``` - - :param str version: version to use when creating or updating app, if None version will be auto incremented - :param algosdk.atomic_transaction_composer.TransactionSigner signer: signer to use when deploying app - , if None uses self.signer - :param str sender: sender address to use when deploying app, if None uses self.sender - :param bool allow_delete: Used to set the `TMPL_DELETABLE` template variable to conditionally control if an app - can be deleted - :param bool allow_update: Used to set the `TMPL_UPDATABLE` template variable to conditionally control if an app - can be updated - :param OnUpdate on_update: Determines what action to take if an application update is required - :param OnSchemaBreak on_schema_break: Determines what action to take if an application schema requirements - has increased beyond the current allocation - :param dict[str, int|str|bytes] template_values: Values to use for `TMPL_*` template variables, dictionary keys - should *NOT* include the TMPL_ prefix - :param algokit_utils.DeployCallArgs | None create_args: Arguments used when creating an application - :param algokit_utils.DeployCallArgs | None update_args: Arguments used when updating an application - :param algokit_utils.DeployCallArgs | None delete_args: Arguments used when deleting an application - :return DeployResponse: details action taken and relevant transactions - :raises DeploymentError: If the deployment failed""" - - return self.app_client.deploy( - version, - signer=signer, - sender=sender, - allow_update=allow_update, - allow_delete=allow_delete, - on_update=on_update, - on_schema_break=on_schema_break, - template_values=template_values, - create_args=_convert_deploy_args(create_args), - update_args=_convert_deploy_args(update_args), - delete_args=_convert_deploy_args(delete_args), - ) - - def compose(self, atc: AtomicTransactionComposer | None = None) -> Composer: - return Composer(self.app_client, atc or AtomicTransactionComposer()) diff --git a/projects/python-contract-examples/tests/arc4_types_integration_test.py b/projects/python-contract-examples/tests/arc4_types_integration_test.py index 475f865..0aee786 100644 --- a/projects/python-contract-examples/tests/arc4_types_integration_test.py +++ b/projects/python-contract-examples/tests/arc4_types_integration_test.py @@ -216,7 +216,7 @@ def test_arc4_uint64( """Test the arc4_uint64 method""" # Call the arc4_uint64 method - result = arc4_types_app_client.arc4_uint64(a=1, b=2) + result = arc4_types_app_client.add_arc4_uint64(a=1, b=2) # Check the result assert result.return_value == 3 @@ -227,7 +227,7 @@ def test_arc4_uint_n( ) -> None: """Test the arc4_uint_n method""" - result = arc4_types_app_client.arc4_uint_n(a=100, b=1_000, c=100_000, d=100_000) + result = arc4_types_app_client.add_arc4_uint_n(a=100, b=1_000, c=100_000, d=100_000) assert result.return_value == 201_100 @@ -237,7 +237,7 @@ def test_arc4_biguint_n( ) -> None: """Test the arc4_uint_n method""" - result = arc4_types_app_client.arc4_biguint_n(a=2**65, b=2**129, c=2**257) + result = arc4_types_app_client.add_arc4_biguint_n(a=2**65, b=2**129, c=2**257) assert result.return_value == 2**65 + 2**129 + 2**257 @@ -294,11 +294,11 @@ def test_arc4_dynamic_array( # Call the arc4_static_array method with simulate to avoid opcode budget constraints. result = ( arc4_dynamic_array_app_client.compose() - .arc4_dynamic_array(name="John") + .hello(name="John") .simulate(SimulateOptions(extra_opcode_budget=700)) ) - assert result.abi_results[0].return_value == "Hello world, John" + assert result.abi_results[0].return_value == "Hello John!" def test_arc4_dynamic_bytes( @@ -347,23 +347,23 @@ def test_arc4_struct_complete_and_return_todo( assert result.return_value.completed is True -def test_arc4_tuple_argument( +def test_tuple_add_contact_info( arc4_tuple_app_client: Arc4TupleClient, ) -> None: - """Test the arc4_tuple_argument method""" + """Test the add_contact_info method""" - result = arc4_tuple_app_client.arc4_tuple_argument( - a=(4, "This is a good string.", 100, [1, 2, 3]) + result = arc4_tuple_app_client.add_contact_info( + contact=("Alice", "alice@something.com", 555_555_555) ) - assert result.return_value == "This is a good string." + assert result.return_value == 555_555_555 -def test_arc4_tuple_return( +def test_tuple_return_contact( arc4_tuple_app_client: Arc4TupleClient, ) -> None: - """Test the arc4_tuple_return method""" + """Test the return_contact method""" - result = arc4_tuple_app_client.arc4_tuple_return() + result = arc4_tuple_app_client.return_contact() - assert result.return_value == [42, "hello, world!"] + assert result.return_value == ["Alice", "alice@something.com", 555_555_555] From 2671ac6f22ca244e9956499eae1ecf42ba3cbf73 Mon Sep 17 00:00:00 2001 From: "Chris Kim (Hyunggun)" Date: Fri, 22 Nov 2024 14:58:09 -0800 Subject: [PATCH 19/23] chore: linting fix --- .../smart_contracts/arc4_types/contract.py | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py index b50b312..6b03fc7 100644 --- a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py +++ b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py @@ -3,13 +3,10 @@ from algopy import ( ARC4Contract, - Global, GlobalState, String, - Txn, UInt64, arc4, - gtxn, urange, ) from algopy.arc4 import abimethod @@ -30,6 +27,7 @@ def add_arc4_uint64(self, a: arc4.UInt64, b: arc4.UInt64) -> arc4.UInt64: c = a.native + b.native return arc4.UInt64(c) + # example: ARC4_UINT64 # example: ARC4_UINTN @@ -49,6 +47,7 @@ def add_arc4_uint_n( total = a.native + b.native + c.native + d.native return arc4.UInt64(total) + # example: ARC4_UINTN # example: ARC4_BIGUINT @@ -67,6 +66,7 @@ def add_arc4_biguint_n( total = a.native + b.native + c.native return arc4.UInt512(total) + # example: ARC4_BIGUINT # example: ARC4_BYTES @@ -76,6 +76,7 @@ def arc4_byte(self, a: arc4.Byte) -> arc4.Byte: An arc4.Byte is essentially an alias for an 8-bit integer. """ return arc4.Byte(a.native + 1) + # example: ARC4_BYTES # example: ARC4_ADDRESS @@ -112,8 +113,10 @@ def arc4_address_return(self, address: arc4.Address) -> arc4.Address: assert converted_address == address return converted_address + # example: ARC4_ADDRESS + # example: ARC4_STATIC_ARRAY AliasedStaticArray: t.TypeAlias = arc4.StaticArray[arc4.UInt8, t.Literal[1]] @@ -153,6 +156,8 @@ def arc4_static_array(self) -> None: so this won't compile: aliased_static.pop() """ + + # example: ARC4_STATIC_ARRAY # example: ARC4_DYNAMIC_ARRAY @@ -188,9 +193,10 @@ def hello(self, name: arc4.String) -> String: greeting += x.native return greeting -# example: ARC4_DYNAMIC_ARRAY - # example: ARC4_DYNAMIC_BYTES + # example: ARC4_DYNAMIC_ARRAY + + # example: ARC4_DYNAMIC_BYTES @abimethod() def arc4_dynamic_bytes(self) -> arc4.DynamicBytes: """arc4.DynamicBytes are essentially an arc4.DynamicArray[arc4.Bytes] and some convenience methods.""" @@ -208,8 +214,10 @@ def arc4_dynamic_bytes(self) -> arc4.DynamicBytes: dynamic_bytes.append(arc4.Byte(255)) return dynamic_bytes + # example: ARC4_DYNAMIC_BYTES + # example: ARC4_STRUCT class Todo(arc4.Struct): task: arc4.String @@ -257,6 +265,8 @@ def return_todo(self, task: arc4.String) -> Todo: assert exist return todo_to_return + + # example: ARC4_STRUCT # example: ARC4_TUPLE @@ -266,7 +276,6 @@ def return_todo(self, task: arc4.String) -> Todo: class Arc4Tuple(ARC4Contract): - def __init__(self) -> None: self.contact_info = GlobalState( @@ -291,4 +300,6 @@ def return_contact(self) -> arc4.Tuple[arc4.String, arc4.String, arc4.UInt64]: """An arc4.Tuple can be returned when more than one return value is needed.""" return self.contact_info.value + + # example: ARC4_TUPLE From 9de26026e9cd572ccfec0752b1d26c6201548054 Mon Sep 17 00:00:00 2001 From: "Chris Kim (Hyunggun)" <52557585+iskysun96@users.noreply.github.com> Date: Fri, 6 Dec 2024 17:18:27 +0900 Subject: [PATCH 20/23] Update projects/python-contract-examples/smart_contracts/arc4_types/contract.py Co-authored-by: Gabriel Kuettel --- .../smart_contracts/arc4_types/contract.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py index 6b03fc7..3f41b46 100644 --- a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py +++ b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py @@ -199,7 +199,7 @@ def hello(self, name: arc4.String) -> String: # example: ARC4_DYNAMIC_BYTES @abimethod() def arc4_dynamic_bytes(self) -> arc4.DynamicBytes: - """arc4.DynamicBytes are essentially an arc4.DynamicArray[arc4.Bytes] and some convenience methods.""" + """arc4.DynamicBytes is essentially an arc4.DynamicArray[arc4.Byte] with additional convenience methods""" dynamic_bytes = arc4.DynamicBytes(b"\xFF\xFF\xFF") # arc4.DynamicBytes can return the native bytearray instead of accessing every single index of the array. From 1c40a597dbacba1af672b28513615548d023bc71 Mon Sep 17 00:00:00 2001 From: "Chris Kim (Hyunggun)" <52557585+iskysun96@users.noreply.github.com> Date: Fri, 6 Dec 2024 17:18:38 +0900 Subject: [PATCH 21/23] Update projects/python-contract-examples/smart_contracts/arc4_types/contract.py Co-authored-by: Gabriel Kuettel --- .../smart_contracts/arc4_types/contract.py | 1 + 1 file changed, 1 insertion(+) diff --git a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py index 3f41b46..6c623d7 100644 --- a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py +++ b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py @@ -26,6 +26,7 @@ def add_arc4_uint64(self, a: arc4.UInt64, b: arc4.UInt64) -> arc4.UInt64: # Use the native integers to perform arithmetic c = a.native + b.native + # Convert back to arc4.UInt64 for ABI compatability before returning return arc4.UInt64(c) # example: ARC4_UINT64 From 4fe077402040ef2aa0e53badd2a151225e4f206e Mon Sep 17 00:00:00 2001 From: "Chris Kim (Hyunggun)" <52557585+iskysun96@users.noreply.github.com> Date: Fri, 6 Dec 2024 17:18:45 +0900 Subject: [PATCH 22/23] Update projects/python-contract-examples/smart_contracts/arc4_types/contract.py Co-authored-by: Gabriel Kuettel --- .../smart_contracts/arc4_types/contract.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py index 6c623d7..c5e0c5f 100644 --- a/projects/python-contract-examples/smart_contracts/arc4_types/contract.py +++ b/projects/python-contract-examples/smart_contracts/arc4_types/contract.py @@ -40,10 +40,10 @@ def add_arc4_uint_n( The encoding of arc4 integers will be smaller if it uses fewer bits. Ultimately, they are all represented with native UInt64. """ - assert a.bytes.length == 1 - assert b.bytes.length == 2 - assert c.bytes.length == 4 - assert d.bytes.length == 8 + assert a.bytes.length == 1 # UInt8 = 1 byte + assert b.bytes.length == 2 # UInt16 = 2 bytes + assert c.bytes.length == 4 # UInt32 = 4 bytes + assert d.bytes.length == 8 # UInt64 = 8 bytes total = a.native + b.native + c.native + d.native From f8952aeb8f90a58895fd1824f97ac12ce6f1aa6f Mon Sep 17 00:00:00 2001 From: "Chris Kim (Hyunggun)" Date: Fri, 6 Dec 2024 17:25:58 +0900 Subject: [PATCH 23/23] chore: rebuild the contract --- .../artifacts/arc4_types/Arc4DynamicArray.arc32.json | 2 +- .../artifacts/arc4_types/arc4_dynamic_array_client.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.arc32.json b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.arc32.json index 6b5c000..e945b34 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.arc32.json +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/Arc4DynamicArray.arc32.json @@ -77,7 +77,7 @@ "returns": { "type": "byte[]" }, - "desc": "arc4.DynamicBytes are essentially an arc4.DynamicArray[arc4.Bytes] and some convenience methods." + "desc": "arc4.DynamicBytes is essentially an arc4.DynamicArray[arc4.Byte] with additional convenience methods" } ], "networks": {} diff --git a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_dynamic_array_client.py b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_dynamic_array_client.py index 4e88aab..b91c169 100644 --- a/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_dynamic_array_client.py +++ b/projects/python-contract-examples/smart_contracts/artifacts/arc4_types/arc4_dynamic_array_client.py @@ -97,7 +97,7 @@ "returns": { "type": "byte[]" }, - "desc": "arc4.DynamicBytes are essentially an arc4.DynamicArray[arc4.Bytes] and some convenience methods." + "desc": "arc4.DynamicBytes is essentially an arc4.DynamicArray[arc4.Byte] with additional convenience methods" } ], "networks": {} @@ -202,7 +202,7 @@ def method() -> str: @dataclasses.dataclass(kw_only=True) class Arc4DynamicBytesArgs(_ArgsBase[bytes | bytearray]): - """arc4.DynamicBytes are essentially an arc4.DynamicArray[arc4.Bytes] and some convenience methods.""" + """arc4.DynamicBytes is essentially an arc4.DynamicArray[arc4.Byte] with additional convenience methods""" @staticmethod def method() -> str: @@ -294,7 +294,7 @@ def arc4_dynamic_bytes( *, transaction_parameters: algokit_utils.TransactionParameters | None = None, ) -> "Composer": - """arc4.DynamicBytes are essentially an arc4.DynamicArray[arc4.Bytes] and some convenience methods. + """arc4.DynamicBytes is essentially an arc4.DynamicArray[arc4.Byte] with additional convenience methods Adds a call to `arc4_dynamic_bytes()byte[]` ABI method @@ -521,7 +521,7 @@ def arc4_dynamic_bytes( *, transaction_parameters: algokit_utils.TransactionParameters | None = None, ) -> algokit_utils.ABITransactionResponse[bytes | bytearray]: - """arc4.DynamicBytes are essentially an arc4.DynamicArray[arc4.Bytes] and some convenience methods. + """arc4.DynamicBytes is essentially an arc4.DynamicArray[arc4.Byte] with additional convenience methods Calls `arc4_dynamic_bytes()byte[]` ABI method