#
tokens: 34967/50000 1/942 files (page 67/93)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 67 of 93. Use http://codebase.md/goplausible/algorand-mcp?lines=true&page={x} to view the full context.

# Directory Structure

```
├── .gitignore
├── CONTRIBUTING.md
├── LICENSE
├── llms-install.md
├── llms.txt
├── package.json
├── packages
│   ├── client
│   │   ├── .env.example
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── env.ts
│   │   │   ├── index.ts
│   │   │   └── LocalWallet.ts
│   │   └── tsconfig.json
│   └── server
│       ├── .env.example
│       ├── API specs
│       │   ├── algod_api.json
│       │   ├── indexer_api.json
│       │   ├── mcp.json
│       │   ├── nfd_api.json
│       │   ├── ultrade_api.json
│       │   ├── vestige_api.json
│       │   └── vestige_free_api.json
│       ├── Dockerfile
│       ├── jest.config.js
│       ├── package.json
│       ├── README.md
│       ├── smithery.yaml
│       ├── src
│       │   ├── algorand-client.ts
│       │   ├── env.ts
│       │   ├── index.ts
│       │   ├── resources
│       │   │   ├── index.ts
│       │   │   ├── knowledge
│       │   │   │   ├── ARCs.txt
│       │   │   │   ├── developers-algokit-architecture-decisions.txt
│       │   │   │   ├── developers-algokit-cli.txt
│       │   │   │   ├── developers-algokit-utils-python.txt
│       │   │   │   ├── developers-algokit-utils-typescript.txt
│       │   │   │   ├── developers-clis.txt
│       │   │   │   ├── developers-details.txt
│       │   │   │   ├── developers-liquid-auth.txt
│       │   │   │   ├── developers-nodes.txt
│       │   │   │   ├── developers-puya.txt
│       │   │   │   ├── developers-python.txt
│       │   │   │   ├── developers-sdks-js.txt
│       │   │   │   ├── developers-sdks-python.txt
│       │   │   │   ├── developers-tealscript.txt
│       │   │   │   ├── developers.txt
│       │   │   │   ├── index.ts
│       │   │   │   ├── taxonomy
│       │   │   │   │   ├── algokit-cli:README.md
│       │   │   │   │   ├── algokit:cli:algokit.md
│       │   │   │   │   ├── algokit:cli:architecture-decisions:2022-11-14_sandbox-approach.md
│       │   │   │   │   ├── algokit:cli:architecture-decisions:2022-11-22_beaker-testing-strategy.md
│       │   │   │   │   ├── algokit:cli:architecture-decisions:2023-01-11_beaker_productionisation_review.md
│       │   │   │   │   ├── algokit:cli:architecture-decisions:2023-01-11_brew_install.md
│       │   │   │   │   ├── algokit:cli:architecture-decisions:2023-01-12_smart-contract-deployment.md
│       │   │   │   │   ├── algokit:cli:architecture-decisions:2023-06-06_frontend-templates.md
│       │   │   │   │   ├── algokit:cli:architecture-decisions:2023-07-19_advanced_generate_command.md
│       │   │   │   │   ├── algokit:cli:architecture-decisions:2024-01-13_native_binaries.md
│       │   │   │   │   ├── algokit:cli:architecture-decisions:2024-01-23_init-wizard-v2.md
│       │   │   │   │   ├── algokit:cli:architecture-decisions:2024-01-31_binary_distribution.md
│       │   │   │   │   ├── algokit:cli:architecture-decisions:2024-03-06_local_dev_ui_packaging.md
│       │   │   │   │   ├── algokit:cli:articles:output_stability.md
│       │   │   │   │   ├── algokit:cli:cli:index.md
│       │   │   │   │   ├── algokit:cli:features:compile.md
│       │   │   │   │   ├── algokit:cli:features:completions.md
│       │   │   │   │   ├── algokit:cli:features:config.md
│       │   │   │   │   ├── algokit:cli:features:dispenser.md
│       │   │   │   │   ├── algokit:cli:features:doctor.md
│       │   │   │   │   ├── algokit:cli:features:explore.md
│       │   │   │   │   ├── algokit:cli:features:generate.md
│       │   │   │   │   ├── algokit:cli:features:goal.md
│       │   │   │   │   ├── algokit:cli:features:init.md
│       │   │   │   │   ├── algokit:cli:features:localnet.md
│       │   │   │   │   ├── algokit:cli:features:project:bootstrap.md
│       │   │   │   │   ├── algokit:cli:features:project:deploy.md
│       │   │   │   │   ├── algokit:cli:features:project:link.md
│       │   │   │   │   ├── algokit:cli:features:project:list.md
│       │   │   │   │   ├── algokit:cli:features:project:run.md
│       │   │   │   │   ├── algokit:cli:features:project.md
│       │   │   │   │   ├── algokit:cli:features:tasks:analyze.md
│       │   │   │   │   ├── algokit:cli:features:tasks:ipfs.md
│       │   │   │   │   ├── algokit:cli:features:tasks:mint.md
│       │   │   │   │   ├── algokit:cli:features:tasks:nfd.md
│       │   │   │   │   ├── algokit:cli:features:tasks:opt.md
│       │   │   │   │   ├── algokit:cli:features:tasks:send.md
│       │   │   │   │   ├── algokit:cli:features:tasks:sign.md
│       │   │   │   │   ├── algokit:cli:features:tasks:transfer.md
│       │   │   │   │   ├── algokit:cli:features:tasks:vanity_address.md
│       │   │   │   │   ├── algokit:cli:features:tasks:wallet.md
│       │   │   │   │   ├── algokit:cli:features:tasks.md
│       │   │   │   │   ├── algokit:cli:tutorials:algokit-template.md
│       │   │   │   │   ├── algokit:cli:tutorials:intro.md
│       │   │   │   │   ├── algokit:cli:tutorials:smart-contracts.md
│       │   │   │   │   ├── algokit:docs:testnet_api.md
│       │   │   │   │   ├── algokit:lora:README.md
│       │   │   │   │   ├── algokit:README.md
│       │   │   │   │   ├── algokit:utils:python:markdown:apidocs:algokit_utils:algokit_utils.md
│       │   │   │   │   ├── algokit:utils:python:markdown:capabilities:account.md
│       │   │   │   │   ├── algokit:utils:python:markdown:capabilities:app-client.md
│       │   │   │   │   ├── algokit:utils:python:markdown:capabilities:app-deploy.md
│       │   │   │   │   ├── algokit:utils:python:markdown:capabilities:client.md
│       │   │   │   │   ├── algokit:utils:python:markdown:capabilities:debugger.md
│       │   │   │   │   ├── algokit:utils:python:markdown:capabilities:dispenser-client.md
│       │   │   │   │   ├── algokit:utils:python:markdown:capabilities:transfer.md
│       │   │   │   │   ├── algokit:utils:python:markdown:index.md
│       │   │   │   │   ├── algokit:utils:python:README.md
│       │   │   │   │   ├── algokit:utils:python:source:capabilities:account.md
│       │   │   │   │   ├── algokit:utils:python:source:capabilities:app-client.md
│       │   │   │   │   ├── algokit:utils:python:source:capabilities:app-deploy.md
│       │   │   │   │   ├── algokit:utils:python:source:capabilities:client.md
│       │   │   │   │   ├── algokit:utils:python:source:capabilities:debugger.md
│       │   │   │   │   ├── algokit:utils:python:source:capabilities:dispenser-client.md
│       │   │   │   │   ├── algokit:utils:python:source:capabilities:transfer.md
│       │   │   │   │   ├── algokit:utils:python:source:index.md
│       │   │   │   │   ├── algokit:utils:typescript:capabilities:account.md
│       │   │   │   │   ├── algokit:utils:typescript:capabilities:algorand-client.md
│       │   │   │   │   ├── algokit:utils:typescript:capabilities:amount.md
│       │   │   │   │   ├── algokit:utils:typescript:capabilities:app-client.md
│       │   │   │   │   ├── algokit:utils:typescript:capabilities:app-deploy.md
│       │   │   │   │   ├── algokit:utils:typescript:capabilities:app.md
│       │   │   │   │   ├── algokit:utils:typescript:capabilities:asset.md
│       │   │   │   │   ├── algokit:utils:typescript:capabilities:client.md
│       │   │   │   │   ├── algokit:utils:typescript:capabilities:debugging.md
│       │   │   │   │   ├── algokit:utils:typescript:capabilities:dispenser-client.md
│       │   │   │   │   ├── algokit:utils:typescript:capabilities:event-emitter.md
│       │   │   │   │   ├── algokit:utils:typescript:capabilities:indexer.md
│       │   │   │   │   ├── algokit:utils:typescript:capabilities:testing.md
│       │   │   │   │   ├── algokit:utils:typescript:capabilities:transaction-composer.md
│       │   │   │   │   ├── algokit:utils:typescript:capabilities:transaction.md
│       │   │   │   │   ├── algokit:utils:typescript:capabilities:transfer.md
│       │   │   │   │   ├── algokit:utils:typescript:capabilities:typed-app-clients.md
│       │   │   │   │   ├── algokit:utils:typescript:code:classes:testing.TestLogger.md
│       │   │   │   │   ├── algokit:utils:typescript:code:classes:testing.TransactionLogger.md
│       │   │   │   │   ├── algokit:utils:typescript:code:classes:types_account_manager.AccountManager.md
│       │   │   │   │   ├── algokit:utils:typescript:code:classes:types_account.MultisigAccount.md
│       │   │   │   │   ├── algokit:utils:typescript:code:classes:types_account.SigningAccount.md
│       │   │   │   │   ├── algokit:utils:typescript:code:classes:types_algo_http_client_with_retry.AlgoHttpClientWithRetry.md
│       │   │   │   │   ├── algokit:utils:typescript:code:classes:types_algorand_client_transaction_creator.AlgorandClientTransactionCreator.md
│       │   │   │   │   ├── algokit:utils:typescript:code:classes:types_algorand_client_transaction_sender.AlgorandClientTransactionSender.md
│       │   │   │   │   ├── algokit:utils:typescript:code:classes:types_algorand_client.AlgorandClient.md
│       │   │   │   │   ├── algokit:utils:typescript:code:classes:types_amount.AlgoAmount.md
│       │   │   │   │   ├── algokit:utils:typescript:code:classes:types_app_arc56.Arc56Method.md
│       │   │   │   │   ├── algokit:utils:typescript:code:classes:types_app_client.AppClient.md
│       │   │   │   │   ├── algokit:utils:typescript:code:classes:types_app_client.ApplicationClient.md
│       │   │   │   │   ├── algokit:utils:typescript:code:classes:types_app_deployer.AppDeployer.md
│       │   │   │   │   ├── algokit:utils:typescript:code:classes:types_app_factory.AppFactory.md
│       │   │   │   │   ├── algokit:utils:typescript:code:classes:types_app_manager.AppManager.md
│       │   │   │   │   ├── algokit:utils:typescript:code:classes:types_asset_manager.AssetManager.md
│       │   │   │   │   ├── algokit:utils:typescript:code:classes:types_async_event_emitter.AsyncEventEmitter.md
│       │   │   │   │   ├── algokit:utils:typescript:code:classes:types_client_manager.ClientManager.md
│       │   │   │   │   ├── algokit:utils:typescript:code:classes:types_composer.TransactionComposer.md
│       │   │   │   │   ├── algokit:utils:typescript:code:classes:types_config.UpdatableConfig.md
│       │   │   │   │   ├── algokit:utils:typescript:code:classes:types_dispenser_client.TestNetDispenserApiClient.md
│       │   │   │   │   ├── algokit:utils:typescript:code:classes:types_kmd_account_manager.KmdAccountManager.md
│       │   │   │   │   ├── algokit:utils:typescript:code:classes:types_logic_error.LogicError.md
│       │   │   │   │   ├── algokit:utils:typescript:code:enums:types_app.OnSchemaBreak.md
│       │   │   │   │   ├── algokit:utils:typescript:code:enums:types_app.OnUpdate.md
│       │   │   │   │   ├── algokit:utils:typescript:code:enums:types_indexer.AccountStatus.md
│       │   │   │   │   ├── algokit:utils:typescript:code:enums:types_indexer.ApplicationOnComplete.md
│       │   │   │   │   ├── algokit:utils:typescript:code:enums:types_indexer.SignatureType.md
│       │   │   │   │   ├── algokit:utils:typescript:code:enums:types_lifecycle_events.EventType.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_account_manager.EnsureFundedResult.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_account.AccountConfig.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_account.TransactionSignerAccount.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_algorand_client_interface.AlgorandClientInterface.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_arc56.Arc56Contract.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_arc56.Event.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_arc56.Method.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_arc56.ProgramSourceInfo.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_arc56.StorageKey.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_arc56.StorageMap.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_arc56.StructField.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_client.AppClientCallABIArgs.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_client.AppClientCallCoreParams.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_client.AppClientCompilationParams.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_client.AppClientCompilationResult.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_client.AppClientDeployCallInterfaceParams.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_client.AppClientDeployCoreParams.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_client.AppClientDeployParams.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_client.AppClientParams.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_client.AppSourceMaps.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_client.FundAppAccountParams.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_client.ResolveAppById.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_client.ResolveAppByIdBase.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_client.SourceMapExport.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_deployer.AppLookup.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_deployer.AppMetadata.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_factory.AppFactoryParams.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_manager.AppInformation.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_manager.BoxReference.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_manager.BoxValueRequestParams.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_manager.BoxValuesRequestParams.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_spec.AppSources.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_spec.AppSpec.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_spec.CallConfig.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_spec.DeclaredSchemaValueSpec.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_spec.Hint.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_spec.ReservedSchemaValueSpec.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_spec.Schema.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_spec.SchemaSpec.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_spec.StateSchemaSpec.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app_spec.Struct.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app.AppCallParams.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app.AppCallTransactionResultOfType.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app.AppCompilationResult.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app.AppDeploymentParams.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app.AppDeployMetadata.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app.AppLookup.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app.AppMetadata.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app.AppReference.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app.AppState.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app.AppStorageSchema.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app.BoxName.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app.BoxReference.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app.BoxValueRequestParams.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app.BoxValuesRequestParams.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app.CompiledTeal.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app.CoreAppCallArgs.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app.CreateAppParams.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app.RawAppCallArgs.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app.TealTemplateParams.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_app.UpdateAppParams.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_asset_manager.AssetInformation.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_asset_manager.BulkAssetOptInOutResult.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_asset.AssetBulkOptInOutParams.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_asset.AssetOptInParams.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_asset.AssetOptOutParams.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_asset.CreateAssetParams.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_client_manager.AlgoSdkClients.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_client_manager.TypedAppClient.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_client_manager.TypedAppFactory.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_composer.BuiltTransactions.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_config.Config.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_debugging.AVMTracesEventData.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_debugging.TealSourceDebugEventData.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_debugging.TealSourcesDebugEventData.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_dispenser_client.DispenserFundResponse.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_dispenser_client.DispenserLimitResponse.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_dispenser_client.TestNetDispenserApiClientParams.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_indexer.LookupAssetHoldingsOptions.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_logic_error.LogicErrorDetails.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_network_client.AlgoClientConfig.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_network_client.AlgoConfig.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_network_client.NetworkDetails.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_testing.AlgoKitLogCaptureFixture.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_testing.AlgorandFixture.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_testing.AlgorandFixtureConfig.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_testing.AlgorandTestAutomationContext.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_testing.GetTestAccountParams.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_testing.LogSnapshotConfig.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_transaction.AtomicTransactionComposerToSend.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_transaction.ConfirmedTransactionResult.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_transaction.ConfirmedTransactionResults.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_transaction.SendAtomicTransactionComposerResults.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_transaction.SendParams.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_transaction.SendTransactionParams.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_transaction.SendTransactionResult.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_transaction.SendTransactionResults.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_transaction.TransactionGroupToSend.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_transaction.TransactionToSign.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_transfer.AlgoRekeyParams.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_transfer.AlgoTransferParams.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_transfer.EnsureFundedParams.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_transfer.EnsureFundedReturnType.md
│       │   │   │   │   ├── algokit:utils:typescript:code:interfaces:types_transfer.TransferAssetParams.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:index.indexer.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:index.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:testing.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_account_manager_spec.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_account_manager.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_account.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_algo_http_client_with_retry.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_algorand_client_asset_spec.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_algorand_client_interface.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_algorand_client_spec.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_algorand_client_transaction_creator.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_algorand_client_transaction_sender.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_algorand_client_transfer_spec.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_algorand_client.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_amount_spec.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_amount.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_app_arc56.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_app_client_spec.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_app_client.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_app_deployer.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_app_factory_and_client_spec.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_app_factory.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_app_manager.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_app_spec.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_app.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_asset_manager.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_asset.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_async_event_emitter_spec.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_async_event_emitter.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_client_manager_spec.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_client_manager.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_composer.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_config.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_debugging.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_dispenser_client_spec.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_dispenser_client.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_expand.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_indexer.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_kmd_account_manager.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_lifecycle_events.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_logging.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_logic_error.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_network_client.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_testing.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_transaction.md
│       │   │   │   │   ├── algokit:utils:typescript:code:modules:types_transfer.md
│       │   │   │   │   ├── algokit:utils:typescript:code:README.md
│       │   │   │   │   ├── algokit:utils:typescript:README.md
│       │   │   │   │   ├── algokit:utils:typescript:v7-migration.md
│       │   │   │   │   ├── algokit:utils:typescript:v8-migration.md
│       │   │   │   │   ├── ARCs:ARC-template.md
│       │   │   │   │   ├── ARCs:assets:arc-0012:README.md
│       │   │   │   │   ├── ARCs:assets:arc-0034:TemplateForm.md
│       │   │   │   │   ├── ARCs:assets:arc-0062:README.md
│       │   │   │   │   ├── ARCs:pages:nfts.md
│       │   │   │   │   ├── ARCs:pages:wallets.md
│       │   │   │   │   ├── ARCs:README.md
│       │   │   │   │   ├── ARCs:specs:arc-0000.md
│       │   │   │   │   ├── ARCs:specs:arc-0001.md
│       │   │   │   │   ├── ARCs:specs:arc-0002.md
│       │   │   │   │   ├── ARCs:specs:arc-0003.md
│       │   │   │   │   ├── ARCs:specs:arc-0004.md
│       │   │   │   │   ├── ARCs:specs:arc-0005.md
│       │   │   │   │   ├── ARCs:specs:arc-0006.md
│       │   │   │   │   ├── ARCs:specs:arc-0007.md
│       │   │   │   │   ├── ARCs:specs:arc-0008.md
│       │   │   │   │   ├── ARCs:specs:arc-0009.md
│       │   │   │   │   ├── ARCs:specs:arc-0010.md
│       │   │   │   │   ├── ARCs:specs:arc-0011.md
│       │   │   │   │   ├── ARCs:specs:arc-0012.md
│       │   │   │   │   ├── ARCs:specs:arc-0015.md
│       │   │   │   │   ├── ARCs:specs:arc-0016.md
│       │   │   │   │   ├── ARCs:specs:arc-0018.md
│       │   │   │   │   ├── ARCs:specs:arc-0019.md
│       │   │   │   │   ├── ARCs:specs:arc-0020.md
│       │   │   │   │   ├── ARCs:specs:arc-0021.md
│       │   │   │   │   ├── ARCs:specs:arc-0022.md
│       │   │   │   │   ├── ARCs:specs:arc-0023.md
│       │   │   │   │   ├── ARCs:specs:arc-0025.md
│       │   │   │   │   ├── ARCs:specs:arc-0026.md
│       │   │   │   │   ├── ARCs:specs:arc-0028.md
│       │   │   │   │   ├── ARCs:specs:arc-0032.md
│       │   │   │   │   ├── ARCs:specs:arc-0033.md
│       │   │   │   │   ├── ARCs:specs:arc-0034.md
│       │   │   │   │   ├── ARCs:specs:arc-0035.md
│       │   │   │   │   ├── ARCs:specs:arc-0036.md
│       │   │   │   │   ├── ARCs:specs:arc-0042.md
│       │   │   │   │   ├── ARCs:specs:arc-0047.md
│       │   │   │   │   ├── ARCs:specs:arc-0048.md
│       │   │   │   │   ├── ARCs:specs:arc-0049.md
│       │   │   │   │   ├── ARCs:specs:arc-0054.md
│       │   │   │   │   ├── ARCs:specs:arc-0055.md
│       │   │   │   │   ├── ARCs:specs:arc-0056.md
│       │   │   │   │   ├── ARCs:specs:arc-0059.md
│       │   │   │   │   ├── ARCs:specs:arc-0062.md
│       │   │   │   │   ├── ARCs:specs:arc-0065.md
│       │   │   │   │   ├── ARCs:specs:arc-0069.md
│       │   │   │   │   ├── ARCs:specs:arc-0072.md
│       │   │   │   │   ├── ARCs:specs:arc-0073.md
│       │   │   │   │   ├── ARCs:specs:arc-0074.md
│       │   │   │   │   ├── ARCs:specs:arc-0076.md
│       │   │   │   │   ├── ARCs:specs:arc-0078.md
│       │   │   │   │   ├── ARCs:specs:arc-0079.md
│       │   │   │   │   ├── ARCs:specs:arc-0200.md
│       │   │   │   │   ├── clis_index.md
│       │   │   │   │   ├── developer:docs:about.md
│       │   │   │   │   ├── developer:docs:clis:algokey:algokey.md
│       │   │   │   │   ├── developer:docs:clis:algokey:generate.md
│       │   │   │   │   ├── developer:docs:clis:algokey:import.md
│       │   │   │   │   ├── developer:docs:clis:algokey:multisig:append-auth-addr.md
│       │   │   │   │   ├── developer:docs:clis:algokey:multisig:multisig.md
│       │   │   │   │   ├── developer:docs:clis:algokey:part:info.md
│       │   │   │   │   ├── developer:docs:clis:algokey:part:part.md
│       │   │   │   │   ├── developer:docs:clis:algokey:part:reparent.md
│       │   │   │   │   ├── developer:docs:clis:algokey:sign.md
│       │   │   │   │   ├── developer:docs:clis:conduit:conduit.md
│       │   │   │   │   ├── developer:docs:clis:conduit:init.md
│       │   │   │   │   ├── developer:docs:clis:conduit:list:exporters.md
│       │   │   │   │   ├── developer:docs:clis:conduit:list:importers.md
│       │   │   │   │   ├── developer:docs:clis:conduit:list:list.md
│       │   │   │   │   ├── developer:docs:clis:conduit:list:processors.md
│       │   │   │   │   ├── developer:docs:clis:diagcfg:diagcfg.md
│       │   │   │   │   ├── developer:docs:clis:diagcfg:metric:disable.md
│       │   │   │   │   ├── developer:docs:clis:diagcfg:metric:enable.md
│       │   │   │   │   ├── developer:docs:clis:diagcfg:metric:metric.md
│       │   │   │   │   ├── developer:docs:clis:diagcfg:metric:status.md
│       │   │   │   │   ├── developer:docs:clis:diagcfg:telemetry:disable.md
│       │   │   │   │   ├── developer:docs:clis:diagcfg:telemetry:enable.md
│       │   │   │   │   ├── developer:docs:clis:diagcfg:telemetry:endpoint.md
│       │   │   │   │   ├── developer:docs:clis:diagcfg:telemetry:name.md
│       │   │   │   │   ├── developer:docs:clis:diagcfg:telemetry:status.md
│       │   │   │   │   ├── developer:docs:clis:diagcfg:telemetry:telemetry.md
│       │   │   │   │   ├── developer:docs:clis:goal:node:restart.md
│       │   │   │   │   ├── developer:docs:clis:goal:node:start.md
│       │   │   │   │   ├── developer:docs:clis:goal:node:status.md
│       │   │   │   │   ├── developer:docs:clis:goal:node:stop.md
│       │   │   │   │   ├── developer:docs:clis:goal:node:wait.md
│       │   │   │   │   ├── developer:docs:clis:goal:protocols.md
│       │   │   │   │   ├── developer:docs:clis:goal:report.md
│       │   │   │   │   ├── developer:docs:clis:goal:version.md
│       │   │   │   │   ├── developer:docs:clis:goal:wallet:list.md
│       │   │   │   │   ├── developer:docs:clis:goal:wallet:new.md
│       │   │   │   │   ├── developer:docs:clis:goal:wallet:wallet.md
│       │   │   │   │   ├── developer:docs:clis:indexer:api-config.md
│       │   │   │   │   ├── developer:docs:clis:indexer:daemon.md
│       │   │   │   │   ├── developer:docs:clis:indexer:indexer.md
│       │   │   │   │   ├── developer:docs:clis:indexer:util:util.md
│       │   │   │   │   ├── developer:docs:clis:indexer:util:validator.md
│       │   │   │   │   ├── developer:docs:clis:kmd.md
│       │   │   │   │   ├── developer:docs:clis:tealdbg:debug.md
│       │   │   │   │   ├── developer:docs:clis:tealdbg:remote.md
│       │   │   │   │   ├── developer:docs:clis:tealdbg:tealdbg.md
│       │   │   │   │   ├── developer:docs:details:accounts:create.md
│       │   │   │   │   ├── developer:docs:details:accounts:index.md
│       │   │   │   │   ├── developer:docs:details:accounts:rekey.md
│       │   │   │   │   ├── developer:docs:details:algorand_consensus.md
│       │   │   │   │   ├── developer:docs:details:algorand-networks:betanet.md
│       │   │   │   │   ├── developer:docs:details:algorand-networks:index.md
│       │   │   │   │   ├── developer:docs:details:algorand-networks:mainnet.md
│       │   │   │   │   ├── developer:docs:details:algorand-networks:testnet.md
│       │   │   │   │   ├── developer:docs:details:asa.md
│       │   │   │   │   ├── developer:docs:details:atc.md
│       │   │   │   │   ├── developer:docs:details:atomic_transfers.md
│       │   │   │   │   ├── developer:docs:details:conduit.md
│       │   │   │   │   ├── developer:docs:details:crust.md
│       │   │   │   │   ├── developer:docs:details:dapps:avm:index.md
│       │   │   │   │   ├── developer:docs:details:dapps:avm:teal:guidelines.md
│       │   │   │   │   ├── developer:docs:details:dapps:avm:teal:index.md
│       │   │   │   │   ├── developer:docs:details:dapps:avm:teal:jsonspec.md
│       │   │   │   │   ├── developer:docs:details:dapps:avm:teal:opcodes:index.md
│       │   │   │   │   ├── developer:docs:details:dapps:avm:teal:opcodes:v1.md
│       │   │   │   │   ├── developer:docs:details:dapps:avm:teal:opcodes:v10.md
│       │   │   │   │   ├── developer:docs:details:dapps:avm:teal:opcodes:v2.md
│       │   │   │   │   ├── developer:docs:details:dapps:avm:teal:opcodes:v3.md
│       │   │   │   │   ├── developer:docs:details:dapps:avm:teal:opcodes:v4.md
│       │   │   │   │   ├── developer:docs:details:dapps:avm:teal:opcodes:v5.md
│       │   │   │   │   ├── developer:docs:details:dapps:avm:teal:opcodes:v6.md
│       │   │   │   │   ├── developer:docs:details:dapps:avm:teal:opcodes:v7.md
│       │   │   │   │   ├── developer:docs:details:dapps:avm:teal:opcodes:v8.md
│       │   │   │   │   ├── developer:docs:details:dapps:avm:teal:opcodes:v9.md
│       │   │   │   │   ├── developer:docs:details:dapps:avm:teal:specification.md
│       │   │   │   │   ├── developer:docs:details:dapps:smart-contracts:ABI:index.md
│       │   │   │   │   ├── developer:docs:details:dapps:smart-contracts:apps:create.md
│       │   │   │   │   ├── developer:docs:details:dapps:smart-contracts:apps:index.md
│       │   │   │   │   ├── developer:docs:details:dapps:smart-contracts:apps:innertx.md
│       │   │   │   │   ├── developer:docs:details:dapps:smart-contracts:apps:state.md
│       │   │   │   │   ├── developer:docs:details:dapps:smart-contracts:apps:txs.md
│       │   │   │   │   ├── developer:docs:details:dapps:smart-contracts:debugging.md
│       │   │   │   │   ├── developer:docs:details:dapps:smart-contracts:frontend:apps.md
│       │   │   │   │   ├── developer:docs:details:dapps:smart-contracts:frontend:smartsigs.md
│       │   │   │   │   ├── developer:docs:details:dapps:smart-contracts:guidelines.md
│       │   │   │   │   ├── developer:docs:details:dapps:smart-contracts:index.md
│       │   │   │   │   ├── developer:docs:details:dapps:smart-contracts:smartsigs:index.md
│       │   │   │   │   ├── developer:docs:details:dapps:smart-contracts:smartsigs:modes.md
│       │   │   │   │   ├── developer:docs:details:dapps:smart-contracts:smartsigs:walkthrough.md
│       │   │   │   │   ├── developer:docs:details:dapps:writing-contracts:beaker.md
│       │   │   │   │   ├── developer:docs:details:dapps:writing-contracts:pyteal.md
│       │   │   │   │   ├── developer:docs:details:dapps:writing-contracts:python.md
│       │   │   │   │   ├── developer:docs:details:encoding.md
│       │   │   │   │   ├── developer:docs:details:ethereum_to_algorand.md
│       │   │   │   │   ├── developer:docs:details:index.md
│       │   │   │   │   ├── developer:docs:details:indexer.md
│       │   │   │   │   ├── developer:docs:details:parameter_tables.md
│       │   │   │   │   ├── developer:docs:details:stateproofs:index.md
│       │   │   │   │   ├── developer:docs:details:stateproofs:light_client.md
│       │   │   │   │   ├── developer:docs:details:technical_faq.md
│       │   │   │   │   ├── developer:docs:details:transactions:index.md
│       │   │   │   │   ├── developer:docs:details:transactions:offline_transactions.md
│       │   │   │   │   ├── developer:docs:details:transactions:payment_prompts.md
│       │   │   │   │   ├── developer:docs:details:transactions:signatures.md
│       │   │   │   │   ├── developer:docs:details:transactions:transactions.md
│       │   │   │   │   ├── developer:docs:details:useful_resources.md
│       │   │   │   │   ├── developer:docs:get-started:algokit.md
│       │   │   │   │   ├── developer:docs:get-started:basics:what_is_blockchain.md
│       │   │   │   │   ├── developer:docs:get-started:basics:whats_a_dapp.md
│       │   │   │   │   ├── developer:docs:get-started:basics:where_to_start.md
│       │   │   │   │   ├── developer:docs:get-started:basics:why_algorand.md
│       │   │   │   │   ├── developer:docs:get-started:tokenization:ft.md
│       │   │   │   │   ├── developer:docs:get-started:tokenization:nft.md
│       │   │   │   │   ├── developer:docs:index.md
│       │   │   │   │   ├── developer:docs:rest-apis:algod.md
│       │   │   │   │   ├── developer:docs:rest-apis:indexer.md
│       │   │   │   │   ├── developer:docs:rest-apis:kmd.md
│       │   │   │   │   ├── developer:docs:rest-apis:restendpoints.md
│       │   │   │   │   ├── developer:docs:run-a-node:operations:catchup.md
│       │   │   │   │   ├── developer:docs:run-a-node:operations:switch_networks.md
│       │   │   │   │   ├── developer:docs:run-a-node:participate:generate_keys.md
│       │   │   │   │   ├── developer:docs:run-a-node:participate:index.md
│       │   │   │   │   ├── developer:docs:run-a-node:participate:offline.md
│       │   │   │   │   ├── developer:docs:run-a-node:participate:online.md
│       │   │   │   │   ├── developer:docs:run-a-node:participate:renew.md
│       │   │   │   │   ├── developer:docs:run-a-node:reference:artifacts.md
│       │   │   │   │   ├── developer:docs:run-a-node:reference:config.md
│       │   │   │   │   ├── developer:docs:run-a-node:reference:relay.md
│       │   │   │   │   ├── developer:docs:run-a-node:reference:telemetry-config.md
│       │   │   │   │   ├── developer:docs:run-a-node:setup:indexer.md
│       │   │   │   │   ├── developer:docs:run-a-node:setup:install.md
│       │   │   │   │   ├── developer:docs:run-a-node:setup:node-troubleshooting.md
│       │   │   │   │   ├── developer:docs:run-a-node:setup:types.md
│       │   │   │   │   ├── developer:docs:sdks:go:index.md
│       │   │   │   │   ├── developer:docs:sdks:index.md
│       │   │   │   │   ├── developer:docs:sdks:java:index.md
│       │   │   │   │   ├── developer:docs:sdks:javascript:index.md
│       │   │   │   │   ├── developer:docs:sdks:python:index.md
│       │   │   │   │   ├── developer:python:code:example:accounts.md
│       │   │   │   │   ├── developer:python:code:example:arc4_types.md
│       │   │   │   │   ├── developer:python:code:example:assets.md
│       │   │   │   │   ├── developer:python:code:example:box_storage.md
│       │   │   │   │   ├── developer:python:code:example:control_flow.md
│       │   │   │   │   ├── developer:python:code:example:crypto:merkle_tree.md
│       │   │   │   │   ├── developer:python:code:example:defi:amm.md
│       │   │   │   │   ├── developer:python:code:example:defi:auction.md
│       │   │   │   │   ├── developer:python:code:example:defi:htlc_logicsig.md
│       │   │   │   │   ├── developer:python:code:example:defi:marketplace.md
│       │   │   │   │   ├── developer:python:code:example:events:arc28_events.md
│       │   │   │   │   ├── developer:python:code:example:global_storage.md
│       │   │   │   │   ├── developer:python:code:example:governance:simple_voting.md
│       │   │   │   │   ├── developer:python:code:example:hello_world.md
│       │   │   │   │   ├── developer:python:code:example:inner_transactions.md
│       │   │   │   │   ├── developer:python:code:example:local_storage.md
│       │   │   │   │   ├── developer:python:code:example:nft:proof_of_attendance.md
│       │   │   │   │   ├── developer:python:code:example:privacy:zk_whitelist.md
│       │   │   │   │   ├── developer:python:code:example:scratch_storage.md
│       │   │   │   │   ├── developer:python:code:example:self_payment.md
│       │   │   │   │   ├── developer:python:code:example:struct_in_box.md
│       │   │   │   │   ├── developer:python:code:example:subsidize_app_call.md
│       │   │   │   │   ├── developer:python:code:example:transactions.md
│       │   │   │   │   ├── developer:python:code:example:utility:calculator.md
│       │   │   │   │   ├── devportal-code-examples:projects:python-contract-examples:README.md
│       │   │   │   │   ├── devportal-code-examples:README.md
│       │   │   │   │   ├── docs:.walletconnect:index.md
│       │   │   │   │   ├── docs:.walletconnect:walletconnect-schema.md
│       │   │   │   │   ├── docs:README.md
│       │   │   │   │   ├── docs:scripts:example_tracker:example_list.md
│       │   │   │   │   ├── docs:scripts:README.md
│       │   │   │   │   ├── index.md
│       │   │   │   │   ├── liquid_auth_index.md
│       │   │   │   │   ├── liquid-auth:ARCHITECTURE.md
│       │   │   │   │   ├── liquid-auth:decisions:1-Service-Authentication.md
│       │   │   │   │   ├── liquid-auth:decisions:2-Bidirectional-Communication.md
│       │   │   │   │   ├── liquid-auth:decisions:3-Peer-to-Peer-Signaling.md
│       │   │   │   │   ├── liquid-auth:decisions:4-Fido-Extension.md
│       │   │   │   │   ├── liquid-auth:decisions:README.md
│       │   │   │   │   ├── liquid-auth:docs:architecture.md
│       │   │   │   │   ├── liquid-auth:docs:clients:android:provider-service:authenticate.md
│       │   │   │   │   ├── liquid-auth:docs:clients:android:provider-service:register.md
│       │   │   │   │   ├── liquid-auth:docs:clients:browser:authentication.md
│       │   │   │   │   ├── liquid-auth:docs:clients:browser:example.md
│       │   │   │   │   ├── liquid-auth:docs:introduction.md
│       │   │   │   │   ├── liquid-auth:docs:README.md
│       │   │   │   │   ├── liquid-auth:docs:server:environment-variables.md
│       │   │   │   │   ├── liquid-auth:docs:server:integrations.md
│       │   │   │   │   ├── liquid-auth:docs:server:introduction.md
│       │   │   │   │   ├── liquid-auth:docs:server:running-locally.md
│       │   │   │   │   ├── liquid-auth:README.md
│       │   │   │   │   ├── liquid-auth:SEQUENCE.md
│       │   │   │   │   ├── liquid-auth:services:liquid-auth-api-js:src:assertion:assertion.controller.post.request.md
│       │   │   │   │   ├── liquid-auth:services:liquid-auth-api-js:src:assertion:assertion.controller.post.response.md
│       │   │   │   │   ├── liquid-auth:services:liquid-auth-api-js:src:attestation:attestation.controller.post.request.md
│       │   │   │   │   ├── liquid-auth:services:liquid-auth-api-js:src:auth:auth.controller.get.user.md
│       │   │   │   │   ├── liquid-auth:sites:express-dapp:README.md
│       │   │   │   │   ├── liquid-auth:VISION.md
│       │   │   │   │   ├── puya_index.md
│       │   │   │   │   ├── puya:docs:algopy_testing:index.md
│       │   │   │   │   ├── puya:docs:api-algopy.arc4.md
│       │   │   │   │   ├── puya:docs:api-algopy.gtxn.md
│       │   │   │   │   ├── puya:docs:api-algopy.itxn.md
│       │   │   │   │   ├── puya:docs:api-algopy.md
│       │   │   │   │   ├── puya:docs:api-algopy.op.md
│       │   │   │   │   ├── puya:docs:api.md
│       │   │   │   │   ├── puya:docs:compiler.md
│       │   │   │   │   ├── puya:docs:index.md
│       │   │   │   │   ├── puya:docs:language-guide.md
│       │   │   │   │   ├── puya:docs:lg-arc28.md
│       │   │   │   │   ├── puya:docs:lg-arc4.md
│       │   │   │   │   ├── puya:docs:lg-builtins.md
│       │   │   │   │   ├── puya:docs:lg-calling-apps.md
│       │   │   │   │   ├── puya:docs:lg-compile.md
│       │   │   │   │   ├── puya:docs:lg-control.md
│       │   │   │   │   ├── puya:docs:lg-errors.md
│       │   │   │   │   ├── puya:docs:lg-logs.md
│       │   │   │   │   ├── puya:docs:lg-modules.md
│       │   │   │   │   ├── puya:docs:lg-opcode-budget.md
│       │   │   │   │   ├── puya:docs:lg-ops.md
│       │   │   │   │   ├── puya:docs:lg-storage.md
│       │   │   │   │   ├── puya:docs:lg-structure.md
│       │   │   │   │   ├── puya:docs:lg-transactions.md
│       │   │   │   │   ├── puya:docs:lg-types.md
│       │   │   │   │   ├── puya:docs:lg-unsupported-python-features.md
│       │   │   │   │   ├── puya:docs:principles.md
│       │   │   │   │   ├── puya:examples:auction:README.md
│       │   │   │   │   ├── puya:python:testing:docs:algopy.md
│       │   │   │   │   ├── puya:python:testing:docs:api.md
│       │   │   │   │   ├── puya:python:testing:docs:coverage.md
│       │   │   │   │   ├── puya:python:testing:docs:examples.md
│       │   │   │   │   ├── puya:python:testing:docs:faq.md
│       │   │   │   │   ├── puya:python:testing:docs:index.md
│       │   │   │   │   ├── puya:python:testing:docs:testing-guide:arc4-types.md
│       │   │   │   │   ├── puya:python:testing:docs:testing-guide:avm-types.md
│       │   │   │   │   ├── puya:python:testing:docs:testing-guide:concepts.md
│       │   │   │   │   ├── puya:python:testing:docs:testing-guide:contract-testing.md
│       │   │   │   │   ├── puya:python:testing:docs:testing-guide:index.md
│       │   │   │   │   ├── puya:python:testing:docs:testing-guide:opcodes.md
│       │   │   │   │   ├── puya:python:testing:docs:testing-guide:signature-testing.md
│       │   │   │   │   ├── puya:python:testing:docs:testing-guide:state-management.md
│       │   │   │   │   ├── puya:python:testing:docs:testing-guide:subroutines.md
│       │   │   │   │   ├── puya:python:testing:docs:testing-guide:transactions.md
│       │   │   │   │   ├── puya:python:testing:examples:README.md
│       │   │   │   │   ├── puya:python:testing:README.md
│       │   │   │   │   ├── puya:README.md
│       │   │   │   │   ├── puya:src:puya:ARCHITECTURE.md
│       │   │   │   │   ├── puya:src:puyapy:_typeshed:README.md
│       │   │   │   │   ├── puya:src:puyapy:_vendor:mypy:typeshed:stdlib:_typeshed:README.md
│       │   │   │   │   ├── puya:src:puyapy:awst_build:README.md
│       │   │   │   │   ├── puya:stubs:README.md
│       │   │   │   │   ├── puya:tests:test_expected_output:README.md
│       │   │   │   │   ├── puya:typescript:docs:architecture-decisions:2024-05-21_primitive-bytes-and-strings.md
│       │   │   │   │   ├── puya:typescript:docs:architecture-decisions:2024-05-21_primitive-integer-types.md
│       │   │   │   │   ├── puya:typescript:docs:README.md
│       │   │   │   │   ├── puya:typescript:packages:algo-ts:readme.md
│       │   │   │   │   ├── puya:typescript:README.md
│       │   │   │   │   ├── SDKs:javascript:classes:ABIAddressType.md
│       │   │   │   │   ├── SDKs:javascript:classes:ABIArrayDynamicType.md
│       │   │   │   │   ├── SDKs:javascript:classes:ABIArrayStaticType.md
│       │   │   │   │   ├── SDKs:javascript:classes:ABIBoolType.md
│       │   │   │   │   ├── SDKs:javascript:classes:ABIByteType.md
│       │   │   │   │   ├── SDKs:javascript:classes:ABIContract.md
│       │   │   │   │   ├── SDKs:javascript:classes:ABIInterface.md
│       │   │   │   │   ├── SDKs:javascript:classes:ABIMethod.md
│       │   │   │   │   ├── SDKs:javascript:classes:ABIStringType.md
│       │   │   │   │   ├── SDKs:javascript:classes:ABITupleType.md
│       │   │   │   │   ├── SDKs:javascript:classes:ABIType.md
│       │   │   │   │   ├── SDKs:javascript:classes:ABIUfixedType.md
│       │   │   │   │   ├── SDKs:javascript:classes:ABIUintType.md
│       │   │   │   │   ├── SDKs:javascript:classes:Algodv2.md
│       │   │   │   │   ├── SDKs:javascript:classes:AtomicTransactionComposer.md
│       │   │   │   │   ├── SDKs:javascript:classes:DryrunResult.md
│       │   │   │   │   ├── SDKs:javascript:classes:Indexer.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.Account.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.AccountParticipation.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.AccountResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.AccountsResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.AccountStateDelta.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.Application.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.ApplicationLocalState.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.ApplicationLocalStatesResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.ApplicationLogData.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.ApplicationLogsResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.ApplicationParams.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.ApplicationResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.ApplicationsResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.ApplicationStateSchema.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.Asset.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.AssetBalancesResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.AssetHolding.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.AssetHoldingsResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.AssetParams.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.AssetResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.AssetsResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.Block.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.BlockRewards.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.BlockUpgradeState.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.BlockUpgradeVote.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.Box.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.BoxDescriptor.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.BoxesResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.ErrorResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.EvalDelta.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.EvalDeltaKeyValue.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.HashFactory.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.HealthCheck.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.IndexerStateProofMessage.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.MerkleArrayProof.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.MiniAssetHolding.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.ParticipationUpdates.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.StateProofFields.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.StateProofParticipant.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.StateProofReveal.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.StateProofSignature.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.StateProofSigSlot.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.StateProofTracking.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.StateProofVerifier.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.StateSchema.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.TealKeyValue.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.TealValue.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.Transaction.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.TransactionApplication.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.TransactionAssetConfig.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.TransactionAssetFreeze.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.TransactionAssetTransfer.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.TransactionKeyreg.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.TransactionPayment.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.TransactionResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.TransactionSignature.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.TransactionSignatureLogicsig.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.TransactionSignatureMultisig.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.TransactionSignatureMultisigSubsignature.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.TransactionsResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:indexerModels.TransactionStateProof.md
│       │   │   │   │   ├── SDKs:javascript:classes:Kmd.md
│       │   │   │   │   ├── SDKs:javascript:classes:LogicSig.md
│       │   │   │   │   ├── SDKs:javascript:classes:LogicSigAccount.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.Account.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.AccountApplicationResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.AccountAssetHolding.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.AccountAssetResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.AccountAssetsInformationResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.AccountParticipation.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.AccountStateDelta.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.AppCallLogs.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.Application.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.ApplicationInitialStates.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.ApplicationKVStorage.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.ApplicationLocalReference.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.ApplicationLocalState.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.ApplicationParams.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.ApplicationStateOperation.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.ApplicationStateSchema.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.Asset.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.AssetHolding.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.AssetHoldingReference.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.AssetParams.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.AvmKeyValue.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.AvmValue.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.BlockHashResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.BlockLogsResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.BlockResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.BlockTxidsResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.Box.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.BoxDescriptor.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.BoxesResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.BoxReference.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.BuildVersion.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.CompileResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.DisassembleResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.DryrunRequest.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.DryrunResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.DryrunSource.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.DryrunState.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.DryrunTxnResult.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.ErrorResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.EvalDelta.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.EvalDeltaKeyValue.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.GetBlockTimeStampOffsetResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.GetSyncRoundResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.KvDelta.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.LedgerStateDeltaForTransactionGroup.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.LightBlockHeaderProof.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.NodeStatusResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.PendingTransactionResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.PendingTransactionsResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.PostTransactionsResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.ScratchChange.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.SimulateInitialStates.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.SimulateRequest.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.SimulateRequestTransactionGroup.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.SimulateResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.SimulateTraceConfig.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.SimulateTransactionGroupResult.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.SimulateTransactionResult.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.SimulateUnnamedResourcesAccessed.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.SimulationEvalOverrides.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.SimulationOpcodeTraceUnit.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.SimulationTransactionExecTrace.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.StateProof.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.StateProofMessage.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.SupplyResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.TealKeyValue.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.TealValue.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.TransactionGroupLedgerStateDeltasForRoundResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.TransactionParametersResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.TransactionProofResponse.md
│       │   │   │   │   ├── SDKs:javascript:classes:modelsv2.Version.md
│       │   │   │   │   ├── SDKs:javascript:classes:SourceMap.md
│       │   │   │   │   ├── SDKs:javascript:classes:Transaction.md
│       │   │   │   │   ├── SDKs:javascript:enums:ABIReferenceType.md
│       │   │   │   │   ├── SDKs:javascript:enums:ABITransactionType.md
│       │   │   │   │   ├── SDKs:javascript:enums:AtomicTransactionComposerStatus.md
│       │   │   │   │   ├── SDKs:javascript:enums:IntDecoding.md
│       │   │   │   │   ├── SDKs:javascript:enums:OnApplicationComplete.md
│       │   │   │   │   ├── SDKs:javascript:enums:TransactionType.md
│       │   │   │   │   ├── SDKs:javascript:examples:README.md
│       │   │   │   │   ├── SDKs:javascript:FAQ.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:ABIContractNetworkInfo.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:ABIContractNetworks.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:ABIContractParams.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:ABIInterfaceParams.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:ABIMethodArgParams.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:ABIMethodParams.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:ABIMethodReturnParams.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:ABIResult.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:Account.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:Address.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:AlgodTokenHeader.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:BaseHTTPClient.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:BaseHTTPClientError.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:BaseHTTPClientResponse.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:BoxReference.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:CustomTokenHeader.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:EncodedAssetParams.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:EncodedBoxReference.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:EncodedGlobalStateSchema.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:EncodedLocalStateSchema.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:EncodedLogicSig.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:EncodedLogicSigAccount.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:EncodedMultisig.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:EncodedSignedTransaction.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:EncodedSubsig.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:EncodedTransaction.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:IndexerTokenHeader.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:KMDTokenHeader.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:MultisigMetadata.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:SignedTransaction.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:SuggestedParams.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:TransactionParams.md
│       │   │   │   │   ├── SDKs:javascript:interfaces:TransactionWithSigner.md
│       │   │   │   │   ├── SDKs:javascript:modules:indexerModels.md
│       │   │   │   │   ├── SDKs:javascript:modules:modelsv2.md
│       │   │   │   │   ├── SDKs:javascript:modules.md
│       │   │   │   │   ├── SDKs:javascript:README.md
│       │   │   │   │   ├── SDKs:python:algosdk:v2client:harness:README.md
│       │   │   │   │   ├── SDKs:python:examples:README.md
│       │   │   │   │   ├── SDKs:python:README.md
│       │   │   │   │   ├── tealscript:examples_amm_README.md
│       │   │   │   │   ├── tealscript:examples_auction_README.md
│       │   │   │   │   ├── tealscript:examples_big_box_README.md
│       │   │   │   │   ├── tealscript:examples_itxns_README.md
│       │   │   │   │   ├── tealscript:examples_lsig_with_app_README.md
│       │   │   │   │   ├── tealscript:examples_reti_README.md
│       │   │   │   │   ├── tealscript:FEATURES.md
│       │   │   │   │   ├── tealscript:guides_atomic_txn.md
│       │   │   │   │   ├── tealscript:guides_features.md
│       │   │   │   │   ├── tealscript:guides_getting_started.md
│       │   │   │   │   ├── tealscript:guides_inner_transactions.md
│       │   │   │   │   ├── tealscript:guides_lifecycle.md
│       │   │   │   │   ├── tealscript:guides_math.md
│       │   │   │   │   ├── tealscript:guides_methods.md
│       │   │   │   │   ├── tealscript:guides_multiple_contracts.md
│       │   │   │   │   ├── tealscript:guides_pyteal.md
│       │   │   │   │   ├── tealscript:guides_storage.md
│       │   │   │   │   ├── tealscript:guides_Supported Types_arrays.md
│       │   │   │   │   ├── tealscript:guides_Supported Types_numbers.md
│       │   │   │   │   ├── TEALScript:README.md
│       │   │   │   │   ├── tealscript:tests_test_package_README.md
│       │   │   │   │   ├── tealscript:tutorials_Hello World_0001-intro.md
│       │   │   │   │   ├── tealscript:tutorials_Hello World_0002-init.md
│       │   │   │   │   ├── tealscript:tutorials_Hello World_0003-contract.md
│       │   │   │   │   ├── tealscript:tutorials_Hello World_0004-artifacts.md
│       │   │   │   │   ├── tealscript:tutorials_Hello World_0005-hello.md
│       │   │   │   │   └── tealscript:tutorials_Hello World_0006-test.md
│       │   │   │   └── taxonomy-categories
│       │   │   │       ├── algokit-utils.json
│       │   │   │       ├── algokit.json
│       │   │   │       ├── arcs.json
│       │   │   │       ├── clis.json
│       │   │   │       ├── details.json
│       │   │   │       ├── developers.json
│       │   │   │       ├── liquid-auth.json
│       │   │   │       ├── nodes.json
│       │   │   │       ├── puya.json
│       │   │   │       ├── python.json
│       │   │   │       ├── sdks.json
│       │   │   │       └── tealscript.json
│       │   │   └── wallet
│       │   │       └── index.ts
│       │   ├── tools
│       │   │   ├── accountManager.ts
│       │   │   ├── algodManager.ts
│       │   │   ├── apiManager
│       │   │   │   ├── algod
│       │   │   │   │   ├── account.ts
│       │   │   │   │   ├── application.ts
│       │   │   │   │   ├── asset.ts
│       │   │   │   │   ├── index.ts
│       │   │   │   │   └── transaction.ts
│       │   │   │   ├── example
│       │   │   │   │   ├── get-balance.ts
│       │   │   │   │   └── index.ts
│       │   │   │   ├── index.ts
│       │   │   │   ├── indexer
│       │   │   │   │   ├── account.ts
│       │   │   │   │   ├── application.ts
│       │   │   │   │   ├── asset.ts
│       │   │   │   │   ├── index.ts
│       │   │   │   │   └── transaction.ts
│       │   │   │   ├── nfd
│       │   │   │   │   └── index.ts
│       │   │   │   ├── tinyman
│       │   │   │   │   ├── analytics.ts
│       │   │   │   │   ├── bootstrap.ts
│       │   │   │   │   ├── index.ts
│       │   │   │   │   ├── liquidity.ts
│       │   │   │   │   ├── opt_in.ts
│       │   │   │   │   ├── pool.ts
│       │   │   │   │   ├── remove_liquidity.ts
│       │   │   │   │   └── swap.ts
│       │   │   │   ├── ultrade
│       │   │   │   │   ├── index.ts
│       │   │   │   │   ├── market.ts
│       │   │   │   │   ├── system.ts
│       │   │   │   │   └── wallet.ts
│       │   │   │   └── vestige
│       │   │   │       ├── assets.ts
│       │   │   │       ├── balances.ts
│       │   │   │       ├── index.ts
│       │   │   │       ├── networks.ts
│       │   │   │       ├── notes.ts
│       │   │   │       ├── pools.ts
│       │   │   │       ├── protocols.ts
│       │   │   │       ├── swaps.ts
│       │   │   │       └── vaults.ts
│       │   │   ├── arc26Manager.ts
│       │   │   ├── index.ts
│       │   │   ├── knowledgeManager.ts
│       │   │   ├── transactionManager
│       │   │   │   ├── accountTransactions.ts
│       │   │   │   ├── appTransactions
│       │   │   │   │   ├── callTxn.ts
│       │   │   │   │   ├── clearTxn.ts
│       │   │   │   │   ├── closeOutTxn.ts
│       │   │   │   │   ├── createTxn.ts
│       │   │   │   │   ├── deleteTxn.ts
│       │   │   │   │   ├── index.ts
│       │   │   │   │   ├── optInTxn.ts
│       │   │   │   │   ├── test
│       │   │   │   │   │   ├── counter_approval.teal
│       │   │   │   │   │   ├── counter_clear.teal
│       │   │   │   │   │   ├── storage_test_approval_v2.teal
│       │   │   │   │   │   ├── storage_test_approval.teal
│       │   │   │   │   │   └── storage_test_clear.teal
│       │   │   │   │   ├── types.ts
│       │   │   │   │   └── updateTxn.ts
│       │   │   │   ├── assetTransactions.ts
│       │   │   │   ├── generalTransaction.ts
│       │   │   │   └── index.ts
│       │   │   └── utilityManager.ts
│       │   ├── types.ts
│       │   └── utils
│       │       └── responseProcessor.ts
│       ├── tests
│       │   ├── resources
│       │   │   ├── algod
│       │   │   │   ├── account.test.ts
│       │   │   │   ├── application.test.ts
│       │   │   │   ├── asset.test.ts
│       │   │   │   └── transaction.test.ts
│       │   │   └── indexer
│       │   │       ├── account.test.ts
│       │   │       ├── application.test.ts
│       │   │       ├── asset.test.ts
│       │   │       └── transaction.test.ts
│       │   └── tools
│       │       ├── accountManager.test.ts
│       │       ├── algodManager.test.ts
│       │       ├── apiManager
│       │       │   └── example
│       │       │       └── get-balance.test.ts
│       │       ├── transactionManager
│       │       │   ├── accountTransactionManager.test.ts
│       │       │   ├── appTransactionManager.test.ts
│       │       │   ├── assetTransactionManager.test.ts
│       │       │   ├── generalTransactionManager.test.ts
│       │       │   └── transactionManager.test.ts
│       │       └── utilityManager.test.ts
│       └── tsconfig.json
├── README.md
├── rename_files.sh
└── tsconfig.json
```

# Files

--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/developer:docs:details:dapps:writing-contracts:pyteal.md:
--------------------------------------------------------------------------------

```markdown
  1 | title: PyTeal
  2 | 
  3 | !!! note
  4 | For a native Python experience, checkout our [Algorand Python](https://algorandfoundation.github.io/puya/) docs.
  5 | 
  6 | [PyTeal](https://github.com/algorand/pyteal) is a python library for generating [TEAL](/docs/get-details/dapps/avm/teal/) programs that provides a convenient and familiar syntax. 
  7 | 
  8 | Complete installation instructions and developer guides are available in the [PyTeal documentation](https://pyteal.readthedocs.io/en/latest/).
  9 | 
 10 | 
 11 | 
 12 | # Quick start videos
 13 | 
 14 | If you prefer videos, take a look at this playlist to learn about PyTeal. Most of the videos in the list are under 7 minutes each.
 15 | 
 16 | <iframe width="100%" style="aspect-ratio:16/9" src="https://www.youtube-nocookie.com/embed/yEFUv760I8A" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
 17 | 
 18 | # PyTeal overview
 19 | 
 20 | This section assumes the reader is familiar with [Smart Contracts](/docs/get-details/dapps/smart-contracts/#smart-contracts) and [Smart Signatures](/docs/get-details/dapps/smart-contracts/#smart-signatures).
 21 | 
 22 | When building a dApp that makes use of smart contracts or smart signatures (smartsigs), PyTeal makes implementation of more complex logic much simpler than writing the TEAL manually. 
 23 | 
 24 | Generally, developers install PyTeal, write the contract in Python using their preferred editor, and then use PyTeal’s `compileProgram` method to produce the TEAL code. The TEAL source can be compiled into bytecode and deployed to the blockchain.
 25 | 
 26 | For most applications, these contracts will only be a portion of the dApp’s architecture. Typically, developers will build functionality in the dApp that resides on the blockchain and some front end to interact with the smart contracts. 
 27 | 
 28 | The PyTeal contracts can be pre-compiled into TEAL and used directly or the logic to generate TEAL dynamically may be integrated into the dApp front end workflow. For example, a front end may provide something like an exchange that allows limit orders to be created based on a template and then deployed once a user opens an order. In this case, the complete limit order may be implemented as part of a smart contract that is deployed when the order is opened by the dApp. 
 29 | 
 30 | # Building PyTeal smart contracts
 31 | 
 32 | On Algorand, smart contracts are small programs that are evaluated when the contract is deployed or called. These contracts make use of a set of functions [(opcodes)](../avm/teal/opcodes) to be evaluated against the context it was called with. This context includes the current state of its storage values, the transactions in the group, any arguments and references to accounts, assets, or other applications.
 33 | 
 34 | Besides evaluating the logic to approve or reject a transaction, the contracts may cause side effects. Side effects a contract may produce include changes to an Applications global or local state, or producing their own [transactions](../../transactions/transactions.md). These transactions are [atomic](../../atomic_transfers.md) with the outer group the application was invoked with.  The transactions produced during contract evaluation are by default sent from the Applications associated account.
 35 | 
 36 | For more information on smart contracts, see the [smart contract documentation](../smart-contracts/apps/index.md).
 37 | 
 38 | 
 39 | ## Hello PyTeal
 40 | 
 41 | When building smart contracts in PyTeal it is important to realize that a smart contract actually consists of two programs. These are called the approval and the clear programs. In PyTeal both of these programs are generally created in the same Python file. So the beginning of a PyTeal program will contain logic similar to the following:
 42 | 
 43 | <!-- ===PYTEAL_APP_EMPTY_LOGIC=== -->
 44 | ```python
 45 |     def approval_program():
 46 |         program = Return(Int(1))
 47 |         # Mode.Application specifies that this is a smart contract
 48 |         return compileTeal(program, Mode.Application, version=5)
 49 | 
 50 |     def clear_state_program():
 51 |         program = Return(Int(1))
 52 |         # Mode.Application specifies that this is a smart contract
 53 |         return compileTeal(program, Mode.Application, version=5)
 54 | 
 55 |     print(approval_program())
 56 |     print(clear_state_program())
 57 | ```
 58 | [Snippet Source](https://github.com/barnjamin/pyteal/blob/examples-for-docs/_examples/app_walkthrough.py#L27-L39)
 59 | <!-- ===PYTEAL_APP_EMPTY_LOGIC=== -->
 60 | 
 61 | In the above example, a function is defined to return each of the two programs. The `compileTeal` function compiles the program set to the `program` variable. In this case, we are just returning the integer 1 for both programs. The other arguments passed to `compileTeal` set the mode (Application or Signature) and version of TEAL to produce. The output from calling the `compileTeal` method is a string representing the compiled TEAL source.
 62 | 
 63 | Running the program, the output should look something like:
 64 | ```teal
 65 | #pragma version 5
 66 | int 1
 67 | return
 68 | ```
 69 | 
 70 | This output represents the TEAL source for the program. The TEAL source must be compiled to bytecode in order to make use of it on-chain.  This can be done using [goal](../../../clis/goal/clerk/compile.md) or one of the SDKs through the [REST](../../../rest-apis/algod.md#post-v2tealcompile) interface.
 71 | 
 72 | 
 73 | ## A note about PyTeal Expressions
 74 | 
 75 | Before going further, it is important to have the right mental model for thinking about PyTeal contracts.
 76 | 
 77 |     A PyTeal program is a PyTeal Expression composed of other PyTeal Expressions. 
 78 |     
 79 | Reread that sentence.
 80 | 
 81 | When first starting to write contracts using PyTeal, the most common point of confusion comes from trying to include _Python_ native expressions in the the _PyTeal_ Expression tree.  In the above example the entire program was `Return(Int(1))`.  Here `Return` is a PyTeal Expression that takes as an argument another PyTeal Expression. The argument we pass it is the PyTeal Expression `Int(1)`. 
 82 | 
 83 | If we were to call `print(program)` we'd see our tiny Expression tree:
 84 | ```
 85 | (Return (Int: 1))
 86 | ```
 87 | 
 88 | As a counter example, if instead of passing `Int(1)`, we make the program `Return(1)`, PyTeal would throw an error complaining that `1` is not a valid PyTeal Expression.  
 89 | 
 90 | !!! note
 91 |     If you ever see any python error like `...has no attribute 'type_of'` PyTeal is probably trying to tell you you included something that is _not_ a valid PyTeal Expression
 92 | 
 93 | While _only_ PyTeal Expressions may be included in the Expression tree representing the program, the Expressions may be generated as part of running the Python program. This allows the author to make use of Python scripting logic to generate a PyTeal Expression tree based on more complex logic. 
 94 | 
 95 | 
 96 | ## Writing a simple PyTeal Contract
 97 | 
 98 | Here we'll start updating our example to allow a more complex logical flow, showing how to build up a PyTeal contract using PyTeal Expressions.
 99 | 
100 | Below is a simple logical switch statement used to route evaluation to different set of logic based on a Transaction's [`OnComplete`](../../transactions/transactions.md#application-call-transaction) value.  
101 | 
102 | <!-- ===PYTEAL_APP_MANUAL_ROUTER=== -->
103 | ```python
104 |     def approval_program():
105 | 
106 |         handle_creation = Approve()
107 |         handle_optin = Reject()
108 |         handle_closeout = Reject()
109 |         handle_update = Reject()
110 |         handle_delete = Reject()
111 |         handle_noop = Reject()
112 | 
113 |         program = Cond(
114 |             [Txn.application_id() == Int(0), handle_creation],
115 |             [Txn.on_completion() == OnComplete.OptIn, handle_optin],
116 |             [Txn.on_completion() == OnComplete.CloseOut, handle_closeout],
117 |             [Txn.on_completion() == OnComplete.UpdateApplication, handle_update],
118 |             [Txn.on_completion() == OnComplete.DeleteApplication, handle_delete],
119 |             [Txn.on_completion() == OnComplete.NoOp, handle_noop],
120 |         )
121 |         return program
122 | 
123 |     return compileTeal(approval_program(), Mode.Application, version=5)
124 | ```
125 | [Snippet Source](https://github.com/barnjamin/pyteal/blob/examples-for-docs/_examples/app_walkthrough.py#L44-L64)
126 | <!-- ===PYTEAL_APP_MANUAL_ROUTER=== -->
127 | 
128 | The `program` variable is set to a [PyTeal `Cond` Expression](https://pyteal.readthedocs.io/en/latest/control_structures.html?highlight=Cond#chaining-tests-cond) which is an example of a Control Flow statement. Other Control flow statements are documented in the [PyTeal documentation](https://pyteal.readthedocs.io/en/latest/control_structures.html?highlight=seq#).
129 | 
130 | A `Cond` expression allows several conditions to be evaluated in order, taking a number of arguments as [`Condition Expression`, `Body Expression`].  The `Condition Expression` must evaluate to True or False. For a given invocation, the first Condition that evaluates True will pass flow of the program to its corresponding `Body Expression`.  If none of the conditions are true the smart contract will return an `err` and fail.  The body for each condition here should reference some other variable or method defined in your PyTeal contract.
131 | 
132 | !!! note
133 |     For control flow statements like `Cond`, the Body Expression of each condition _MUST_ evaluate to the same type. The current types that are allowed are `none`, `any`, `uint64` or `bytes`
134 | 
135 | In the above example, most of the conditions check the transaction type using the `on_completion` transaction field. The result of a statement like `Txn.on_completion() == OnComplete.NoOp` is itself a PyTeal Expression, in this case evaluating to True or False.  
136 | 
137 | !!! note
138 |     Using `Txn` is shorthand for `The transaction that invoked this contract` and should be used inspect transaction fields. Other transactions in the group including the one referenced by `Txn` are available using `Gtxn[n]` where n is the index of the Transaction in the group.  All other transaction fields can be examined using these transaction references, see the [PyTeal documentation](https://pyteal.readthedocs.io/en/latest/accessing_transaction_field.html) for a complete list.
139 | 
140 | The only condition above that does _not_ check the `on_completion` field is the first one, which only checks the `application_id` field. An `application_id` of `0` on the `Txn` tells us that this is meant to Create the Application. If the program succeeds, it will be assigned an application ID and further invocations will use that ID to call it. In this example the `handle_creation` Expression should handle any initialization necessary for this contract.
141 | 
142 | ### First Router 
143 | 
144 | While the above method of constructing distinct Expression trees for both the approval and clear state programs works, it is often preferable to use the [Router](https://pyteal.readthedocs.io/en/stable/abi.html#registering-methods) class provided in `PyTeal`. The `Router` class abstracts much of the handling for method routing when constructing ABI compliant applications. This is especially useful for encoding and decoding ABI types and returning ABI types.
145 | 
146 | <!-- ===PYTEAL_APP_ROUTER_BASIC=== -->
147 | ```python
148 | ## Contract logic
149 | count_key = Bytes("Count")
150 | 
151 | # Create an expression to store 0 in the `Count` global variable and return 1
152 | handle_creation = Seq(App.globalPut(count_key, Int(0)), Approve())
153 | 
154 | # Main router class
155 | router = Router(
156 |     # Name of the contract
157 |     "my-first-router",
158 |     # What to do for each on-complete type when no arguments are passed (bare call)
159 |     BareCallActions(
160 |         # On create only, just approve
161 |         no_op=OnCompleteAction.create_only(handle_creation),
162 |         # Always let creator update/delete but only by the creator of this contract
163 |         update_application=OnCompleteAction.always(Reject()),
164 |         delete_application=OnCompleteAction.always(Reject()),
165 |         # No local state, don't bother handling it.
166 |         close_out=OnCompleteAction.never(),
167 |         opt_in=OnCompleteAction.never(),
168 |     ),
169 | )
170 | ```
171 | [Snippet Source](https://github.com/barnjamin/pyteal/blob/examples-for-docs/_examples/simple_router.py#L81-L103)
172 | <!-- ===PYTEAL_APP_ROUTER_BASIC=== -->
173 | 
174 | Here we defined the `handle_creation` variable to be a Sequence of Expressions using [`Seq`](https://pyteal.readthedocs.io/en/latest/control_structures.html?highlight=seq#chaining-expressions-seq).
175 | 
176 | The first expression stores a global variable named Count, and its value is set to 0. More information about storing state variables is available in the [PyTeal documentation](https://pyteal.readthedocs.io/en/latest/control_structures.html?highlight=seq#chaining-expressions-seq).
177 | 
178 | This second expression is just `Approve()` which is an alias for `Return(Int(1))` that gets passed back to the caller. 
179 | 
180 | The Router class is initialized with a string name (will be important below in [abi.json](#abi-specification)) and a set of BareCallActions. A Bare Call is an application call transaction with 0 application arguments.
181 | 
182 | Each OnComplete type may have an associated OnCompleteAction, the options are:
183 | 
184 |     - `create_only`: Only triggered on the initial creation of the application (Txn.application_id() == Int(0))
185 |     - `call_only`: Triggered for any application calls that are not the initial creation (Txn.application_id() != Int(0))
186 |     - `always`: Triggered any time this on complete is used Or(Txn.application_id() == Int(0), Txn.application_id() != Int(0))
187 |     - `never`: Never triggered, application should reject the transaction if this OnComplete is specified in the transaction. 
188 | 
189 | The OnCompleteAction is passed an Expression to evaluate when it is triggered and it should `Return` something. 
190 | 
191 | In the first case we `Return` the result of the `handle_creation` expression. For update and delete we `Reject`, this is an alias for `Return(Int(0))`
192 | 
193 | To summarize, when this specific smart contract is first deployed it will store a global variable named Count with a value of 0 and return success. 
194 | 
195 | ### Handle Method Calls 
196 | 
197 | Typically the OnCompletion value is set to `NoOp` to make calls to any application. Different logic handling is often achieved by inspecting other transaction fields, especially `application_args`.
198 | 
199 | Since our example will be an ARC4 contract, the application_args first argument will be the method selector but the router handles that for us.
200 | 
201 | Our example requires an increment function and a decrement function to be handle incrementing and decrementing the counter. 
202 | 
203 | <!-- ===PYTEAL_APP_ROUTER_METHODS=== -->
204 | ```python
205 | @router.method
206 | def increment():
207 |     # Declare the ScratchVar as a Python variable _outside_ the expression tree
208 |     scratchCount = ScratchVar(TealType.uint64)
209 |     return Seq(
210 |         Assert(Global.group_size() == Int(1)),
211 |         # The initial `store` for the scratch var sets the value to
212 |         # whatever is in the `Count` global state variable
213 |         scratchCount.store(App.globalGet(count_key)),
214 |         # Increment the value stored in the scratch var
215 |         # and update the global state variable
216 |         App.globalPut(count_key, scratchCount.load() + Int(1)),
217 |     )
218 | 
219 | 
220 | @router.method
221 | def decrement():
222 |     # Declare the ScratchVar as a Python variable _outside_ the expression tree
223 |     scratchCount = ScratchVar(TealType.uint64)
224 |     return Seq(
225 |         Assert(Global.group_size() == Int(1)),
226 |         # The initial `store` for the scratch var sets the value to
227 |         # whatever is in the `Count` global state variable
228 |         scratchCount.store(App.globalGet(count_key)),
229 |         # Check if the value would be negative by decrementing
230 |         If(
231 |             scratchCount.load() > Int(0),
232 |             # If the value is > 0, decrement the value stored
233 |             # in the scratch var and update the global state variable
234 |             App.globalPut(count_key, scratchCount.load() - Int(1)),
235 |         ),
236 |     )
237 | 
238 | 
239 | ```
240 | [Snippet Source](https://github.com/barnjamin/pyteal/blob/examples-for-docs/_examples/simple_router.py#L117-L151)
241 | <!-- ===PYTEAL_APP_ROUTER_METHODS=== -->
242 | 
243 | In the example, we've implemented the `increment` and `decrement` methods as python methods that return a PyTeal `Expression`. They are attached to the router using the `@router.method` decorator which handles determining the method selector that should be used for routing when an application call is made.
244 | 
245 | The first line of both handlers creates a ScratchVar to be used later. Critically, the declaration of this `ScratchVar` happens _outside_ the Expression tree since the statement `scratchCount = ScratchVar()` is _not_ a valid PyTeal Expression. Smart contracts can hold up to 256 temporary variables in scratch space.  The scratch variable in this example happens to be an integer, byte arrays can also be stored. 
246 | 
247 | !!! note
248 |     The `walrus operator` is very handy for these types of things. The above could have been `Seq( (sv := ScratchVar()).store(Int(0)), ...)` but would have complicated the example.
249 | 
250 | The first expression in the Sequence for both handlers is an `Assert` that will immediately Reject the Transaction if, in this case, the number of transactions in the group is not exactly 1. The `Global.group_size()` illustrates the use of a PyTeal global variables. See the [PyTeal documentation](https://pyteal.readthedocs.io/en/latest/accessing_transaction_field.html?highlight=global#global-parameters) for other global variables available.
251 | 
252 | 
253 | Next, the current value of the global variable Count is read for the contract and placed in scratch space. 
254 | 
255 | Then, the contract either increments this number or decrements and then stores the result into the contract’s global variable. 
256 | 
257 | In the `decrement` method, an additional `If` expression is used to verify the current global variable is above 0. 
258 | 
259 | Finally, both methods exit the smart contract call. Assuming no errors were thrown, the `Router` will return 1, indicating success.
260 | 
261 | ### Final product
262 | 
263 | Because no opt-in is allowed, a clear program need not do anything so we simply return 1, indicating success. The `Router` can now be used to compile our application to the `TEAL` programs and provide a `Contract` object to allow clients to call the `ABI` methods.
264 | 
265 | <!-- ===PYTEAL_APP_ROUTER_COMPILE=== -->
266 | ```python
267 | # Compile the program
268 | approval_program, clear_program, contract = router.compile_program(version=6)
269 | 
270 | # print out the results
271 | print(approval_program)
272 | print(clear_program)
273 | 
274 | print(json.dumps(contract.dictify()))
275 | ```
276 | [Snippet Source](https://github.com/barnjamin/pyteal/blob/examples-for-docs/_examples/simple_router.py#L106-L114)
277 | <!-- ===PYTEAL_APP_ROUTER_COMPILE=== -->
278 | 
279 | The last bit to add is the `router.compile_program` which compiles the PyTeal into TEAL and returns the `approval` program, the `clear` program, and even the Python SDK `contract` object that can be used to make method calls or written to a file and shared.
280 | 
281 | ### ABI specification
282 | 
283 | The contract as json can be be shared with callers and loaded into the SDKs, see the [abi](/docs/get-details/dapps/smart-contracts/ABI/) page for more. 
284 | 
285 | It will look line this:
286 | ```json
287 | {
288 |   "name": "my-first-router",
289 |   "methods": [
290 |     { "name": "increment", "args": [], "returns": { "type": "void" } },
291 |     { "name": "decrement", "args": [], "returns": { "type": "void" } }
292 |   ],
293 |   "desc": null,
294 |   "networks": {}
295 | }
296 | ```
297 | 
298 | This program can be executed to illustrate compiling the PyTeal and printing out the resultant TEAL code.
299 | 
300 | ```bash
301 | python3 samplecontract.py
302 | ```
303 | 
304 | This example of a smart contract is very simple. Using PyTeal, more sophisticated contracts can be created. To learn more about what can be done in smart contracts, see the [smart contract documentation](../smart-contracts/apps/index.md). The documentation also contains many PyTeal code snippets that can be used within smart contracts.
305 | 
306 | # Deploying and calling the smart contract
307 | 
308 | This section explains how to deploy and call the smart contract developed in the previous section.
309 | 
310 | ## Deploying the contract
311 | 
312 | In the previous section, the development of a simple smart contract was explained. This smart contract can be deployed in many different ways, but generally, this will be done using one of the Algorand SDKs ([Python](../../../sdks/python/index.md), [JavaScript](../../../sdks/javascript/index.md), [Go](../../../sdks/go/index.md), and [Java](../../../sdks/java/index.md)). This section will add additional code to the previous section’s example using the Python SDK to illustrate deploying the example contract.
313 | 
314 | !!!note
315 |     This example expects the developer to use the sandbox install. Additionally, one account should be set up and funded. See the [Python SDK](../../../sdks/python/index.md) getting started guide for more details.
316 | 
317 | Before getting into the details of deploying the contract, a couple of global variables must be added to the PyTeal Python example.
318 | 
319 | <!-- ===PYTEAL_APP_ROUTER_SETUP=== -->
320 | ```python
321 | # user declared account mnemonics
322 | creator_mnemonic = "TODO: Add your mnemonic"
323 | # user declared algod connection parameters. Node must have EnableDeveloperAPI set to true in its config
324 | algod_address = "http://localhost:4001"
325 | algod_token = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
326 | ```
327 | [Snippet Source](https://github.com/barnjamin/pyteal/blob/examples-for-docs/_examples/simple_router.py#L28-L33)
328 | <!-- ===PYTEAL_APP_ROUTER_SETUP=== -->
329 | 
330 | The first is a creator mnemonic. This mnemonic is used to recover the private key for the funded account that will own and create the smart contract. 
331 | 
332 | !!!warning
333 |     Placing a mnemonic like this in code should never be done in production. Typically applications will link to some protected wallet to sign transactions. Some examples of wallets are Pera wallet (mobile and web) and Exodus (web extension). Pera, along with some other wallets in the ecosystem, allow transcations be signed using the Wallet Connect API. The mnemonic is used here for learning purposes only.
334 | 
335 | The algod_address and algod_token values are the default values to connect to a sandbox installed node. Also note that in this example, the sandbox node is connected to the Algorand TestNet network (eg `./sandbox up testnet`).
336 | 
337 | In this example, the TEAL for the smart contract will be compiled programmatically by the node. The `EnableDeveloperAPI` configuration parameter must be set to `true` in the node’s configuration to allow this operation. For more information on changing node configuration parameters, see the [developer documentation](../../../run-a-node/reference/config.md). When using the sandbox install, this value is automatically set to true.
338 | 
339 | Next, a few helper functions need to be added to the sample.
340 | 
341 | <!-- ===PYTEAL_APP_ROUTER_HELPERS=== -->
342 | ```python
343 | # helper function to compile program source
344 | def compile_program(client: algod.AlgodClient, source_code: str):
345 |     compile_response = client.compile(source_code)
346 |     return base64.b64decode(compile_response["result"])
347 | 
348 | 
349 | # helper function that converts a mnemonic passphrase into a private signing key
350 | def get_private_key_from_mnemonic(mn: str):
351 |     private_key = mnemonic.to_private_key(mn)
352 |     return private_key
353 | 
354 | 
355 | # helper function that formats global state for printing
356 | def format_state(state: List[Dict[str, Any]]):
357 |     formatted = {}
358 |     for item in state:
359 |         key = item["key"]
360 |         value = item["value"]
361 |         formatted_key = base64.b64decode(key).decode("utf-8")
362 |         if value["type"] == 1:
363 |             # byte string
364 |             if formatted_key == "voted":
365 |                 formatted_value = base64.b64decode(value["bytes"]).decode("utf-8")
366 |             else:
367 |                 formatted_value = value["bytes"]
368 |             formatted[formatted_key] = formatted_value
369 |         else:
370 |             # integer
371 |             formatted[formatted_key] = value["uint"]
372 |     return formatted
373 | 
374 | 
375 | # helper function to read app global state
376 | def read_global_state(client: algod.AlgodClient, app_id: int):
377 |     app = client.application_info(app_id)
378 |     global_state = (
379 |         app["params"]["global-state"] if "global-state" in app["params"] else []
380 |     )
381 |     return format_state(global_state)
382 | 
383 | 
384 | ```
385 | [Snippet Source](https://github.com/barnjamin/pyteal/blob/examples-for-docs/_examples/simple_router.py#L36-L77)
386 | <!-- ===PYTEAL_APP_ROUTER_HELPERS=== -->
387 | 
388 | The `compile_program` function is a utility function that allows passing the generated TEAL code to a node that will compile and return the byte code. This returned byte code will be used with the application creation transaction (deploying the contract) later.
389 | 
390 | The `get_private_key_from_mnemonic` function is a utility function that takes a mnemonic (account backup phrase) and returns the private key of the specific account. This will be used in this sample to recover the private key of the funded account of the smart contract creator.
391 | 
392 | The `wait_for_confirmation` SDK function is a utility function that when called will wait until a specific transaction is confirmed on the Algorand blockchain. This will be used to confirm that the application creation transaction is successful and the smart contract is actively deployed.
393 | 
394 | As the sample smart contract manipulates global variables, a couple of helper functions are needed to display the contents of these values.
395 | 
396 | 
397 | Global variables for smart contracts are actually stored in the creator account’s ledger entry on the blockchain. The location is referred to as global state and the SDKs provide a function to retrieve the application data including the global state. In this example, the function `read_global_state` uses the Python SDK function `application_info` to connect to the Algorand node and retrieve the application information. The function then extracts the global state values if they exist, otherwise returns an empty array. The `format_state` function takes the application data and formats the values for display. For more information on global and local state see the [smart contract documentation](../smart-contracts/apps/index.md).
398 | 
399 | As covered earlier in this guide, to deploy the contract an application creation transaction must be created and submitted to the blockchain. The SDKs provide a method for creating this transaction. The following code illustrates creating and submitting this transaction.
400 | 
401 | <!-- ===PYTEAL_APP_ROUTER_CREATOR=== -->
402 | ```python
403 | # create new application
404 | def create_app(
405 |     client: algod.AlgodClient,
406 |     private_key: str,
407 |     approval_program: bytes,
408 |     clear_program: bytes,
409 |     global_schema: transaction.StateSchema,
410 |     local_schema: transaction.StateSchema,
411 | ) -> int:
412 |     # define sender as creator
413 |     sender = account.address_from_private_key(private_key)
414 | 
415 |     # declare on_complete as NoOp
416 |     on_complete = transaction.OnComplete.NoOpOC.real
417 | 
418 |     # get node suggested parameters
419 |     params = client.suggested_params()
420 | 
421 |     # create unsigned transaction
422 |     txn = transaction.ApplicationCreateTxn(
423 |         sender,
424 |         params,
425 |         on_complete,
426 |         approval_program,
427 |         clear_program,
428 |         global_schema,
429 |         local_schema,
430 |     )
431 | 
432 |     # sign transaction
433 |     signed_txn = txn.sign(private_key)
434 |     tx_id = signed_txn.transaction.get_txid()
435 | 
436 |     # send transaction
437 |     client.send_transactions([signed_txn])
438 | 
439 |     # wait for confirmation
440 |     try:
441 |         transaction_response = transaction.wait_for_confirmation(client, tx_id, 5)
442 |         print("TXID: ", tx_id)
443 |         print(
444 |             "Result confirmed in round: {}".format(
445 |                 transaction_response["confirmed-round"]
446 |             )
447 |         )
448 |     except Exception as err:
449 |         print(err)
450 |         return 0
451 | 
452 |     # display results
453 |     transaction_response = client.pending_transaction_info(tx_id)
454 |     app_id = transaction_response["application-index"]
455 |     print("Created new app-id:", app_id)
456 | 
457 |     return app_id
458 | 
459 | 
460 | ```
461 | [Snippet Source](https://github.com/barnjamin/pyteal/blob/examples-for-docs/_examples/simple_router.py#L155-L212)
462 | <!-- ===PYTEAL_APP_ROUTER_CREATOR=== -->
463 | 
464 | This function is a simple example of creating an application creation transaction, which when submitted will deploy a smart contract. This example is very generic and can be used to deploy any smart contract. First, the creator’s address is resolved from the private key passed to the function, the transaction type is set to a NoOp application transaction, and the blockchain suggested parameters are retrieved from the connected node. These suggested parameters provide the default values that are required to submit a transaction, such as the expected fee for the transaction.
465 | 
466 | The Python SDK’s `ApplicationCreateTxn` function is called to create the transaction. This function takes the creator’s address, the approval and clear programs byte code, and a declaration of how much global and local state the smart contract will reserve. When creating a smart contract, the creation transaction has to specify how much state will be reserved. A contract can store up to 64 key-value pairs in global state and up to 16 key-value pairs per user who opts into the contract. Once these values are set, they can never be changed. The key is limited to 64 bytes. The key plus the value is limited to 128 bytes total. Using smaller keys to have more storage available for the value is possible. The keys are stored as byte slices (byte-array value) and the values are stored as either byte slices (byte-array value) or uint64s. More information on state values can be found in the [smart contract documentation](../smart-contracts/apps/index.md#modifying-state-in-smart-contract).
467 | 
468 | The passed-in private key is then used to sign the transaction and the ID of the transaction is retrieved. This ID is unique and can be used to look up the transaction later.
469 | 
470 | The transaction is then submitted to the connected node and the `wait_for_confirmation` SDK function is called to wait for the blockchain to process the transaction. Once the blockchain processes the transaction, a unique ID, called application ID, is returned for the smart contract. This can be used later to issue calls against the smart contract.
471 | 
472 | Now that all required functions are implemented, the main function can be created to deploy the contract.
473 | 
474 | <!-- ===PYTEAL_APP_ROUTER_DEPLOY=== -->
475 | ```python
476 |     # initialize an algodClient
477 |     algod_client = algod.AlgodClient(algod_token, algod_address)
478 | 
479 |     # define private keys
480 |     creator_private_key = get_private_key_from_mnemonic(creator_mnemonic)
481 | 
482 |     # declare application state storage (immutable)
483 |     local_ints = 0
484 |     local_bytes = 0
485 |     global_ints = 1
486 |     global_bytes = 0
487 |     global_schema = transaction.StateSchema(global_ints, global_bytes)
488 |     local_schema = transaction.StateSchema(local_ints, local_bytes)
489 | 
490 |     # Compile the program
491 |     approval_program, clear_program, contract = router.compile_program(version=6)
492 | 
493 |     with open("./approval.teal", "w") as f:
494 |         f.write(approval_program)
495 | 
496 |     with open("./clear.teal", "w") as f:
497 |         f.write(clear_program)
498 | 
499 |     with open("./contract.json", "w") as f:
500 |         import json
501 | 
502 |         f.write(json.dumps(contract.dictify()))
503 | 
504 |     # compile program to binary
505 |     approval_program_compiled = compile_program(algod_client, approval_program)
506 | 
507 |     # compile program to binary
508 |     clear_state_program_compiled = compile_program(algod_client, clear_program)
509 | 
510 |     print("Deploying Counter application......")
511 | 
512 |     # create new application
513 |     app_id = create_app(
514 |         algod_client,
515 |         creator_private_key,
516 |         approval_program_compiled,
517 |         clear_state_program_compiled,
518 |         global_schema,
519 |         local_schema,
520 |     )
521 | 
522 |     # read global state of application
523 |     print("Global state:", read_global_state(algod_client, app_id))
524 | ```
525 | [Snippet Source](https://github.com/barnjamin/pyteal/blob/examples-for-docs/_examples/simple_router.py#L250-L298)
526 | <!-- ===PYTEAL_APP_ROUTER_DEPLOY=== -->
527 | 
528 | First, a connection to the sandbox node is established. This is followed by recovering the account of the creator. Next, the amount of state to be used is defined. In this example, only one global integer is specified.
529 | 
530 | The SDK is then used to first convert the approval and clear programs to TEAL using the PyTeal library and both are written to local files. Each is then complied to byte code by the connected node. Finally, the smart contract is deployed using the `create_app` function created earlier and the current global state is then printed out for the contract. On deployment, this value will be set to 0.
531 | 
532 | ## Calling the deployed smart contract
533 | 
534 | Now that the contract is deployed, the Add or Deduct functions can be called using a standard NoOp application transaction. The example created throughout this guide can be further modified to illustrate making a call to the smart contract.
535 | 
536 | To begin with, a function can be added to support calling the smart contract.
537 | 
538 | <!-- ===PYTEAL_APP_ROUTER_CALLER=== -->
539 | ```python
540 | # call application
541 | def call_app(client, private_key, index, contract):
542 |     # get sender address
543 |     sender = account.address_from_private_key(private_key)
544 |     # create a Signer object
545 |     signer = AccountTransactionSigner(private_key)
546 | 
547 |     # get node suggested parameters
548 |     sp = client.suggested_params()
549 | 
550 |     # Create an instance of AtomicTransactionComposer
551 |     atc = AtomicTransactionComposer()
552 |     atc.add_method_call(
553 |         app_id=index,
554 |         method=contract.get_method_by_name("increment"),
555 |         sender=sender,
556 |         sp=sp,
557 |         signer=signer,
558 |         method_args=[],  # No method args needed here
559 |     )
560 | 
561 |     # send transaction
562 |     results = atc.execute(client, 2)
563 | 
564 |     # wait for confirmation
565 |     print("TXID: ", results.tx_ids[0])
566 |     print("Result confirmed in round: {}".format(results.confirmed_round))
567 | 
568 | 
569 | ```
570 | [Snippet Source](https://github.com/barnjamin/pyteal/blob/examples-for-docs/_examples/simple_router.py#L216-L245)
571 | <!-- ===PYTEAL_APP_ROUTER_CALLER=== -->
572 | 
573 | This function constructs an AtomicTransactionComposer to handle adding the appropriate arguments. The only argument we need to pass in this case is the method selector for the method we wish to call (`increment`) but it is added automatically to the application args of the created transaction. Any arguments that the method specifies in the contract would be passed to the `method_args` array.
574 | 
575 | The `main` function can then be modified to call the smart contract after deploying by adding the following to the bottom of the `main` function.
576 | 
577 | <!-- ===PYTEAL_APP_ROUTER_CALL=== -->
578 | ```python
579 |     print("Calling Counter application......")
580 |     call_app(algod_client, creator_private_key, app_id, contract)
581 | 
582 |     # read global state of application
583 |     print("Global state:", read_global_state(algod_client, app_id))
584 | ```
585 | [Snippet Source](https://github.com/barnjamin/pyteal/blob/examples-for-docs/_examples/simple_router.py#L301-L306)
586 | <!-- ===PYTEAL_APP_CALL=== -->
587 | 
588 | In this example, the Add string is added to the application arguments array and the smart contract is called. The updated global state is then printed out. The value should now be set to 1.
589 | 
590 | For more information on using the SDKs to deploy and interact with smart contracts see the [developer documentation](../smart-contracts/frontend/smartsigs.md).
591 | 
592 | # Building PyTeal smart signatures
593 | 
594 | Smart signatures are small programs that are submitted as part of a transaction and evaluated at submission time. These types of signatures can be used as an escrow-type of account or can be used to delegate a portion of the authority for a specific account.
595 | 
596 | When used as an escrow, they can hold Algos or Algorand assets (ASAs). When used this way any transaction can send Algos or ASAs to the escrow but the logic in the signature determines when value leaves the escrow. In this respect, they act very similarly to smart contracts, but the logic must be supplied with every transaction.
597 | 
598 | When used as a delegate, the logic can be signed by a specific account. The logic is then evaluated when a transaction is submitted from the signing account that is signed by the logic and not the private key of the sender. This is often used to allow restricted access to an account. For example, a mortgage company may provide logic to an account to remove a certain number of Algos from the account once a month. The user then signs this logic and once a month the mortgage company can submit a transaction from the signing account, but the transaction is signed by the smart signature and not the private key of the account.
599 | 
600 | Any time a smart signature is used the complete logic must be submitted as part of the transaction where the logic is used. The logic is recorded as part of the transaction but this is after the fact.
601 | 
602 | PyTeal supports building smart signatures in Python. For example, assume an escrow account is needed. This escrow can be funded by anyone but only a specific account is the beneficiary of the escrow and that account can withdraw funds at any time.
603 | 
604 | <!-- ===PYTEAL_LSIG_SIMPLE_ESCROW=== -->
605 | ```python
606 | def donation_escrow(benefactor):
607 |     Fee = Int(1000)
608 | 
609 |     # Only the benefactor account can withdraw from this escrow
610 |     program = And(
611 |         Txn.type_enum() == TxnType.Payment,
612 |         Txn.fee() <= Fee,
613 |         Txn.receiver() == Addr(benefactor),
614 |         Global.group_size() == Int(1),
615 |         Txn.rekey_to() == Global.zero_address(),
616 |     )
617 | 
618 |     # Mode.Signature specifies that this is a smart signature
619 |     return compileTeal(program, Mode.Signature, version=5)
620 | 
621 | 
622 | ```
623 | [Snippet Source](https://github.com/barnjamin/pyteal/blob/examples-for-docs/_examples/lsig.py#L7-L23)
624 | <!-- ===PYTEAL_LSIG_SIMPLE_ESCROW=== -->
625 | 
626 | This is a very simplistic smart signature. The code for the complete signature is defined in the `donation_escrow` function. This function takes an Algorand address as a parameter. This address represents the beneficiary of the escrow. The entire program is a set of conditions anded together using the [`And` logical expression](https://pyteal.readthedocs.io/en/latest/api.html#pyteal.And). This expression takes two or more arguments that are logically anded and produces a 0 (logically false) or 1 (logically true). In this sample, a set of transaction fields are compared to expected values. The transaction type is first verified to be a payment transaction, the transaction fee is compared to make sure it is less than 1000 microAlgos, the transaction receiver is compared to the benefactor’s address, the group size is verified to guarantee that this transaction is not submitted with other transactions in a group, and the rekey field of the transaction is verified to be the zero address. The zero address is used to verify that the rekey field is not set. This prevents the escrow from being rekeyed to another account. This sample uses transaction fields and global properties. See the PyTeal documentation for additional [transaction fields](https://pyteal.readthedocs.io/en/latest/accessing_transaction_field.html?highlight=global#id1) and [global properties](https://pyteal.readthedocs.io/en/latest/accessing_transaction_field.html?highlight=global#global-parameters). The entire program is compiled to TEAL using the `compileTeal` PyTeal function. This function compiles the program as defined by the program variable. The `compileTeal` method also sets the Mode.Signature. This lets PyTeal know this is for a smart signature and not a smart contract. The version parameter instructs PyTeal on which version of program version to produce when compiling. 
627 | 
628 | To test this sample, a sample address can be defined and a print command calling the `donation_escrow` function can be added to the sample.
629 | 
630 | <!-- ===PYTEAL_LSIG_SIMPLE_ESCROW_INIT=== -->
631 | ```python
632 | rando_addr, _ = account.generate_account()
633 | teal_program = donation_escrow(rando_addr)
634 | ```
635 | [Snippet Source](https://github.com/barnjamin/pyteal/blob/examples-for-docs/_examples/lsig.py#L26-L28)
636 | <!-- ===PYTEAL_LSIG_SIMPLE_ESCROW_INIT=== -->
637 | 
638 | 
639 | This will print out the compiled TEAL. The Algorand address of the escrow can be retrieved by first saving the produced TEAL to a file and then compiled to byte code using the `goal` command-line tool. In the next section, using this smart signature with a transaction will be demonstrated.
640 | 
641 | ```bash
642 | $ python3 smart_sig.py > test.teal
643 | $ ./goal clerk compile test.teal
644 | test.teal: ZNJNTBMZKTCSO2RF4AJ3TLVFCZ5ZTHKAUBGR5AHJ23IHRFGK6GRIUVH2MU
645 | ```
646 | 
647 | # Deploying the smart signature
648 | 
649 | As stated in the previous section, smart signatures are used in conjunction with a transaction submission. In the previous section, a sample escrow was created. With escrows, any account can fund these accounts. These funds can not leave the escrow unless the logic evaluates to true. Once you have the escrow address, simple payment transactions can be used to fund it. To remove funds, a payment transaction can also be used but the transaction needs to be signed with the logic, not a private key. The following example illustrates:
650 | 
651 | - Compiling the escrow
652 | - Funding the escrow with a simple payment transaction
653 | - Dispensing funds using a payment transaction to the beneficiary signed with the logic
654 | 
655 | A few global variables are created and some utility functions are added to the previous section’s sample. The `benefactor_mnemonic` is the backup phrase for the address of the benefactor and the `sender_mnemonic` represents the account that will fund the escrow. Mnemonics should never be included in the source of a production environment. It is done here for learning purposes only. Key management should be handled by a proper wallet.
656 | 
657 | <!-- ===PYTEAL_LSIG_SIMPLE_SETUP=== -->
658 | ```python
659 | # user declared account mnemonics
660 | benefactor_mnemonic = "REPLACE WITH YOUR OWN MNEMONIC"
661 | sender_mnemonic = "REPLACE WITH YOUR OWN MNEMONIC"
662 | 
663 | 
664 | # user declared algod connection parameters. Node must have EnableDeveloperAPI set to true in its config
665 | algod_address = "http://localhost:4001"
666 | algod_token = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
667 | ```
668 | [Snippet Source](https://github.com/barnjamin/pyteal/blob/examples-for-docs/_examples/lsig.py#L32-L40)
669 | <!-- ===PYTEAL_LSIG_SIMPLE_SETUP=== -->
670 | 
671 | <!-- ===PYTEAL_LSIG_SIMPLE_HELPERS=== -->
672 | ```python
673 | # helper function to compile program source
674 | def compile_smart_signature(
675 |     client: algod.AlgodClient, source_code: str
676 | ) -> Tuple[str, str]:
677 |     compile_response = client.compile(source_code)
678 |     return compile_response["result"], compile_response["hash"]
679 | 
680 | 
681 | ```
682 | [Snippet Source](https://github.com/barnjamin/pyteal/blob/examples-for-docs/_examples/lsig.py#L43-L51)
683 | <!-- ===PYTEAL_LSIG_SIMPLE_HELPERS=== -->
684 | 
685 | 
686 | The `compile_smart_contract` and `get_private_key_from_mnemonic` functions are explained in [Deploying and calling a smart contract](#deploying-the-contract).
687 | 
688 | A utility function is then added to create and submit a simple payment transaction.
689 | 
690 | <!-- ===PYTEAL_LSIG_SIMPLE_SEED_PAYMENT=== -->
691 | ```python
692 | def payment_transaction(
693 |     creator_mnemonic: str, amt: int, rcv: str, algod_client: algod.AlgodClient
694 | ) -> dict:
695 |     creator_pk = mnemonic.to_private_key(creator_mnemonic)
696 |     creator_address = account.address_from_private_key(creator_pk)
697 | 
698 |     params = algod_client.suggested_params()
699 |     unsigned_txn = transaction.PaymentTxn(creator_address, params, rcv, amt)
700 |     signed = unsigned_txn.sign(creator_pk)
701 | 
702 |     txid = algod_client.send_transaction(signed)
703 |     pmtx = transaction.wait_for_confirmation(algod_client, txid, 5)
704 |     return pmtx
705 | 
706 | 
707 | ```
708 | [Snippet Source](https://github.com/barnjamin/pyteal/blob/examples-for-docs/_examples/lsig.py#L55-L70)
709 | <!-- ===PYTEAL_LSIG_SIMPLE_SEED_PAYMENT=== -->
710 | 
711 | This function takes a creator mnemonic of the address that is creating the payment transaction as the first parameter. The amount to send and the receiver of the payment transaction are the next two parameters. The final parameter is a connection to a valid Algorand node. In this example, the sandbox installed node is used.
712 | 
713 | In this function, the blockchain suggested parameters are retrieved from the connected node. These suggested parameters provide the default values that are required to submit a transaction, such as the expected fee for the transaction. The creator of the transaction’s address and private key are resolved from the mnemonic. The unsigned payment transaction is created using the Python SDK’s `PaymentTxn` method. This transaction is then signed with the recovered private key. As noted earlier, in a production application, the transaction should be signed by a valid wallet provider. The signed transaction is submitted to the node and the `wait_for_confirmation` SDK utility function is called, which will return when the transaction is finalized on the blockchain.
714 | 
715 | Another utility function is also added to create a payment transaction that is signed by the escrow logic. This function is very similar to the previous function.
716 | 
717 | <!-- ===PYTEAL_LSIG_SIMPLE_WITHDRAW=== -->
718 | ```python
719 | def lsig_payment_txn(
720 |     encoded_program: str, amt: int, rcv: str, algod_client: algod.AlgodClient
721 | ):
722 |     # Create an lsig object using the compiled, b64 encoded program
723 |     program = base64.b64decode(encoded_program)
724 |     lsig = transaction.LogicSigAccount(program)
725 | 
726 |     # Create transaction with the lsig address as the sender
727 |     params = algod_client.suggested_params()
728 |     unsigned_txn = transaction.PaymentTxn(lsig.address(), params, rcv, amt)
729 | 
730 |     # sign the transaction using the logic
731 |     stxn = transaction.LogicSigTransaction(unsigned_txn, lsig)
732 |     tx_id = algod_client.send_transaction(stxn)
733 |     pmtx = transaction.wait_for_confirmation(algod_client, tx_id, 10)
734 |     return pmtx
735 | 
736 | 
737 | ```
738 | [Snippet Source](https://github.com/barnjamin/pyteal/blob/examples-for-docs/_examples/lsig.py#L74-L92)
739 | <!-- ===PYTEAL_LSIG_SIMPLE_WITHDRAW=== -->
740 | 
741 | The primary difference is that the function is passed the base64 encoded string of the compiled bytecode for the smart signature and the escrow’s Algorand address. The program is then converted to a byte array and the Python SDK’s `LogicSigAccount` function is used to create a logic signature from the program bytes. The payment transaction is then signed with the logic using the SDKs `LogicSigTransaction` function. For more information on Logic Signatures and smart signatures see the [smart signatures documentation](../smart-contracts/smartsigs/index.md).
742 | 
743 | The solution can be completed by adding a main function to put the utility functions to use.
744 | 
745 | <!-- ===PYTEAL_LSIG_SIMPLE_USAGE=== -->
746 | ```python
747 | def main():
748 |     # initialize an algodClient
749 |     algod_client = algod.AlgodClient(algod_token, algod_address)
750 | 
751 |     # define private keys
752 |     private_key = mnemonic.to_private_key(benefactor_mnemonic)
753 |     receiver_public_key = account.address_from_private_key(private_key)
754 | 
755 |     print("Compiling Donation Smart Signature......")
756 | 
757 |     stateless_program_teal = donation_escrow(receiver_public_key)
758 |     escrow_result, escrow_address = compile_smart_signature(
759 |         algod_client, stateless_program_teal
760 |     )
761 | 
762 |     print("Program:", escrow_result)
763 |     print("LSig Address: ", escrow_address)
764 | 
765 |     print("Activating Donation Smart Signature......")
766 | 
767 |     # Activate escrow contract by sending 2 algo and 1000 microalgo for transaction fee from creator
768 |     amt = 2001000
769 |     payment_transaction(sender_mnemonic, amt, escrow_address, algod_client)
770 | 
771 |     print("Withdraw from Donation Smart Signature......")
772 | 
773 |     # Withdraws 1 ALGO from smart signature using logic signature.
774 |     withdrawal_amt = 1000000
775 |     lsig_payment_txn(escrow_result, withdrawal_amt, receiver_public_key, algod_client)
776 | 
777 | 
778 | ```
779 | [Snippet Source](https://github.com/barnjamin/pyteal/blob/examples-for-docs/_examples/lsig.py#L96-L127)
780 | <!-- ===PYTEAL_LSIG_SIMPLE_USAGE=== -->
781 | 
782 | The main function first makes a connection to the sandbox installed node, then the benefactor’s address is recovered. The `donation_escrow` built in the previous section is called to produce the TEAL for the smart signature. This TEAL is then compiled, returning both the base64 encoded bytes of the program and the address of the escrow.
783 | 
784 | A simple payment transaction is then created to fund the escrow with a little over 2 Algos. Finally, 1 Algo is dispensed from the escrow to the benefactor using a payment transaction signed by the smart signature. 
785 | 
786 | For more information on smart signatures, see the [developer documentation](../smart-contracts/smartsigs/index.md).
```
Page 67/93FirstPrevNextLast