App Client
Application client that works with ARC-0032 application spec defined smart contracts. ARC-0032 is a standard for defining smart contracts on Algorand that provides descriptive metadata about the smart contract to clients, including state docsSchema, default method arguments, and custom data types.
By generating an app client, you are provided with a high-productivity client that enables you to easily and safely create, update, delete, deploy, and call a smart contract and access state data for it.
Design
The design for the app client is based on a wrapper for parsing an ARC-0032 application spec and wrapping the App deployment functionality and corresponding design.
App Client Generation
Follow the steps below to generate an app client:
-
Prerequisites
To be able to consume the generated file you need to include it in a Python project that has, at a minimum, the
algokit-utils
package installed.Terminal window poetry add algokit-utils@^2.2.0 -
Installation
Terminal window pipx install algokit-client-generator -
Client Generation
Terminal window algokit generate client path/to/application.json --output path/to/output/client_generated.pyFor example, and assuming that you used the AlgoKit CLI to bootstrap your python smart contract project and you named your app “hello_world”, you would run the following command:
Terminal window algokit generate client smart_contracts/artifacts/hello_world/HelloWorld.arc32.json--output smart_contracts/artifacts/hello_world/HelloWorld_generated.py
Usage
There are two key ways of instantiating an ApplicationClient
:
-
Using App ID - When needing to call an existing app by app ID or unconditionally create a new app. The function
ApplicationClient(algod_client, app_spec, app_id)
requires:algod_client
: AnAlgodClient
objectapp_spec
: AnApplicationSpecification
objectapp_id
: The app_id of an existing application, or 0 if creating a new app
-
Using Creator and App Name - When needing to deploy or find an app associated with a specific creator account and app name. The function
ApplicationClient(algod_client, app_spec, creator, indexer, app_lookup)
requires:algod_client
: AnAlgodClient
app_spec
: AnApplicationSpecification
creator
: The address orAccount
of the creator of the app for which to search for the deployed app underindexer
:app_lookup
: Optional if an indexer is provided,app_name
: An overridden name to identify the contract with, otherwisecontract.name
is used from the app spec
Both approaches also allow specifying the following parameters that will be used as defaults for all
application calls: - signer
: TransactionSigner
to sign transactions with - sender
: Address to use for transaction signing, will be derived from the signer if not provided - suggested_params
: Default SuggestedParams
to use; will use the current network suggested params by default
The above approaches also allow specifying a mapping of template values via the template_values
parameter. This
will be used before compiling the application to replace any TMPL_
variables that may be in the TEAL.
The TMPL_UPDATABLE
and TMPL_DELETABLE
variables used in some AlgoKit templates are handled by the deploy
method, but should be included if using create
or update
directly.
Example usage:
1# TODO - USAGE EXAMPLE (Use HelloWorldClient)
App Method Calls
There are various methods available on ApplicationClient
that can be used to call an app:
call
: Used to call methods with an on complete action ofno_op
create
: Used to create an instance of the app, by using anapp_id
of 0, includes the approval and clear programs in the callupdate
: Used to update an existing app, includes the approval and clear programs in the call, and is called with an on complete action ofupdate_application
delete
: Used to remove an existing app, is called with an on complete action ofdelete_application
opt_in
: Used to opt in to an existing app, is called with an on complete action ofopt_in
close_out
: Used to close out of an existing app, is called with an on complete action ofopt_in
clear_state
: Used to unconditionally close out from an app, calls the clear program of an app
Example usage:
1# TODO - USAGE EXAMPLE
ABI Method Calls
All methods for calling an app that support ABI methods (everything except clear_state
) take a parameter
call_abi_method
which can be used to specify which method to call. The method selected can be specified
explicitly, or allow the client to infer the method where possible.
Supported values are:
None
: The default value, whenNone
is passed the client will attempt to find any ABI method or bare method that is compatible with the provided argumentsFalse
: Indicates that an ABI method should not be used, and instead a bare method call is madeTrue
: Indicates that an ABI method should be used, and the client will attempt to find an ABI method that is compatible with the provided argumentsstr
: If a string is provided, it will be interpreted as either an ABI signature specifying a method, or as an ABI method namealgosdk.abi.Method
: The specified ABI method will be calledABIReturnSubroutine
: Any type that has amethod_spec
function that returns analgosd.abi.Method
Example usage:
1# TODO - USAGE EXAMPLE
ABI Arguments
ABI arguments are passed as python keyword arguments e.g., to pass the ABI parameter name
for the ABI method
hello
the following syntax is used:
client.call("hello", name="world")
Transaction Parameters
All methods for calling an app take an optional transaction_parameters
argument, with the following
supported parameters:
signer
: TheTransactionSigner
to use on the call. This overrides any signer specified on the clientsender
: The address of the sender to use on the call, must be able to be signed for by thesigner
. This overrides any sender specified on the clientsuggested_params
:SuggestedParams
to use on the call. This overrides any suggested_params specified on the clientnote
: Note to include in the transactionlease
: Lease parameter for the transactionboxes
: A sequence of boxes to use in the transaction, this is a list of (app_index, box_name) tuples[(0, "box_name"), (0, ...)]
accounts
: Account references to include in the transactionforeign_apps
: Foreign apps to include in the transactionforeign_assets
: Foreign assets to include in the transactionon_complete
: The on complete action to use for the transaction, only available when usingcall
orcreate
extra_pages
: Additional pages to allocate when callingcreate
, by default a sufficient amount will be calculated based on the current approval and clear. This can be overridden, if more is required for a future update
Parameters can be passed as one of the dataclasses CommonCallParameters
, OnCompleteCallParameters
, or
CreateCallParameters
(exact type depends on method used):
client.call("hello", transaction_parameters=algokit_utils.OnCompleteCallParameters(signer=...))
Alternatively, parameters can be passed as a dictionary e.g.
client.call("hello", transaction_parameters={"signer":...})
Transaction Composition
If multiple calls need to be made in a single transaction, the compose_
method variants can be used. All
these methods take an AtomicTransactionComposer
as their first argument. Once all the calls have been added
to the Atomic Transaction Composer (ATC), it can then be executed.
Example usage:
1from algokit_utils import ApplicationClient2from algosdk.atomic_transaction_composer import AtomicTransactionComposer3
4client = ApplicationClient(...)5atc = AtomicTransactionComposer()6client.compose_call(atc, "hello", name="world")7... # additional compose calls8
9response = client.execute_atc(atc)
State Reading
There are various methods defined that let you read state from the smart contract app:
get_global_state
- Gets the current global state of the appget_local_state
- Gets the current local state for the given account address
Error Handling
Often when calling a smart contract during development you will get logic errors that cause an exception to throw. This may be because of a failing assertion, a lack of fees, exhaustion of opcode budget, or any number of other reasons.
When this occurs, you will generally get an error that looks something like the following:
TransactionPool.Remember: transaction {TRANSACTION_ID}: logic eval error: {ERROR_MESSAGE}. Details: pc={PROGRAM_COUNTER_VALUE}, opcodes={LIST_OF_OP_CODES}
The information in that error message can be parsed and when combined with the source map from compilation you can expose debugging information that makes it much easier to understand what’s happening.
When an error is thrown then the resulting error that is re-thrown will be a LogicError
, which has the
following fields:
logic_error
: Original exceptionprogram
: Program source (if available)source_map
: Source map used (if available)transaction_id
: Transaction ID of failing transactionmessage
: The error messageline_no
: The line number in the TEAL program thattraces
: A list of Trace objects providing additional insights on simulation when debug mode is active
The function trace()
will provide a formatted output of the surrounding TEAL where the error occurred.
Extended Error Information
The extended information will only show if the Application Client has a source map. This will occur if:
- The
ApplicationClient
instance has already called (create
,update
, ordeploy
) template_values
are provided when creating theApplicationClient
, so a SourceMap can be obtained automaticallyapproval_source_map
onApplicationClient
has been set from a previously compiled approval program- A source map has been exported/imported using
export_source_map
/import_source_map
Debug Mode and Traces Field
When debug mode is active, the LogicError
will contain a field named traces
. This field will include raw
simulate execution traces, providing a detailed account of the transaction simulation. These traces are
crucial for diagnosing complex issues and are automatically included in all application client calls when
debug mode is active.