This is page 27 of 74. Use http://codebase.md/goplausible/algorand-mcp?lines=false&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/ARCs:specs:arc-0025.md:
--------------------------------------------------------------------------------
```markdown
---
arc: 25
title: Algorand WalletConnect v1 API
description: API for communication between Dapps and wallets using WalletConnect
author: JasonPaulos (@jasonpaulos)
discussions-to: https://github.com/algorandfoundation/ARCs/issues/104
status: Final
type: Standards Track
category: Interface
sub-category: Wallet
created: 2022-05-12
---
# Algorand WalletConnect v1 API
This document specifies a standard API for communication between Algorand decentralized applications and wallets using the WalletConnect v1 protocol.
## Abstract
WalletConnect https://walletconnect.com/ is an open protocol to communicate securely between mobile wallets and decentralized applications (dApps) using QR code scanning (desktop) or deep linking (mobile). It’s main use case allows users to sign transactions on web apps using a mobile wallet.
This document aims to establish a standard API for using the WalletConnect v1 protocol on Algorand, leveraging the existing transaction signing APIs defined in [ARC-1](./arc-0001.md).
## Specification
The key words "**MUST**", "**MUST NOT**", "**REQUIRED**", "**SHALL**", "**SHALL NOT**", "**SHOULD**", "**SHOULD NOT**", "**RECOMMENDED**", "**MAY**", and "**OPTIONAL**" in this document are to be interpreted as described in <a href="https://www.ietf.org/rfc/rfc2119.txt">RFC-2119</a>.
> Comments like this are non-normative.
It is strongly recommended to read and understand the entirety of [ARC-1](./arc-0001.md) before reading this ARC.
### Overview
This overview section is non-normative. It offers a brief overview of the WalletConnect v1 lifecycle. A more in-depth description can be found in the WalletConnect v1 documentation https://docs.walletconnect.com/tech-spec .
In order for a dApp and wallet to communicate using WalletConnect, a WalletConnect session must be established between them. The dApp is responsible for initiating this session and producing a session URI, which it will communicate to the wallet, typically in the form of a QR code or a deep link. This processed is described in the [Session Creation](#session-creation) section.
Once a session is established between a dApp and a wallet, the dApp is able to send requests to the wallet. The wallet is responsible for listening for requests, performing the appropriate actions to fulfill requests, and sending responses back to the dApp with the results of requests. This process is described in the [Message Schema](#message-schema) section.
### Session Creation
The dApp is responsible for initializing a WalletConnect session and producing a WalletConnect URI that communicates the necessary session information to the wallet. This process is as described in the WalletConnect documentation https://docs.walletconnect.com/tech-spec#requesting-connection, with one addition. In order for wallets to be able to easily and immediately recognize an Algorand WalletConnect session, dApps **SHOULD** add an additional URI query parameter to the WalletConnect URI. If present, the name of this parameter **MUST** be `algorand` and its value **MUST** be `true`. This query parameter can appear in any order relative to the other query parameters in the URI.
> For example, here is a standard WalletConnect URI:
> ```
> wc:4015f93f-b88d-48fc-8bfe-8b063cc325b6@1?bridge=https%3A%2F%2F9.bridge.walletconnect.org&key=b0576e0880e17f8400bfff92d4caaf2158cccc0f493dcf455ba76d448c9b5655
> ```
> And here is that same URI with the Algorand-specific query parameter:
> ```
> wc:4015f93f-b88d-48fc-8bfe-8b063cc325b6@1?bridge=https%3A%2F%2F9.bridge.walletconnect.org&key=b0576e0880e17f8400bfff92d4caaf2158cccc0f493dcf455ba76d448c9b5655&algorand=true
> ```
It is **RECOMMENDED** that dApps include this query parameter, but it is not **REQUIRED**. Wallets **MAY** reject sessions if the session URI does not contain this query parameter.
#### Chain IDs
WalletConnect v1 sessions are associated with a numeric chain ID. Since Algorand chains do not have numeric identifiers (instead, the genesis hash or ID is used for this purpose), this document defines the following chain IDs for the Algorand ecosystem:
* MainNet (genesis hash `wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=`): 416001
* TestNet (genesis hash `SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=`): 416002
* BetaNet (genesis hash `mFgazF+2uRS1tMiL9dsj01hJGySEmPN28B/TjjvpVW0=`): 416003
At the time of writing, these chain IDs do not conflict with any known chain that also uses WalletConnect. In the unfortunate event that this were to happen, the `algorand` query parameter discussed above would be used to differentiate Algorand chains from others.
Future Algorand chains, if introduced, **MUST** be assigned new chain IDs.
Wallets and dApps **MAY** support all of the above chain IDs or only a subset of them. If a chain ID is presented to a wallet or dApp that does not support that chain ID, they **MUST** terminate the session.
For compatibility with WalletConnect usage prior to this ARC, the following catch-all chain ID is also defined:
* All Algorand Chains (legacy value): 4160
Wallets and dApps **SHOULD** support this chain ID as well for backwards compatibility. Unfortunately this ID alone is not enough to identify which Algorand chain is being used, so extra fields in message requests (i.e. the genesis hash field in a transaction to sign) **SHOULD** be consulted as well to determine this.
### Message Schema
Note: interfaces are defined in TypeScript. These interfaces are designed to be serializable to and from valid JSON objects.
The WalletConnect message schema is a set of JSON-RPC 2.0 https://www.jsonrpc.org/specification requests and responses. Decentralized applications will send requests to the wallets and will receive responses as JSON-RPC messages. All requests **MUST** adhere to the following structure:
```typescript
interface JsonRpcRequest {
/**
* An identifier established by the Client. Numbers SHOULD NOT contain fractional parts.
*/
id: number;
/**
* A String specifying the version of the JSON-RPC protocol. MUST be exactly "2.0".
*/
jsonrpc: "2.0";
/**
* A String containing the name of the RPC method to be invoked.
*/
method: string;
/**
* A Structured value that holds the parameter values to be used during the invocation of the method.
*/
params: any[];
}
```
The Algorand WalletConnect schema consists of a single RPC method, `algo_signTxn`, as described in the following section.
All responses, whether successful or unsuccessful, **MUST** adhere to the following structure:
```typescript
interface JsonRpcResponse {
/**
* This member is REQUIRED.
* It MUST be the same as the value of the id member in the Request Object.
* If there was an error in detecting the id in the Request object (e.g. Parse error/Invalid Request), it MUST be Null.
*/
id: number;
/**
* A String specifying the version of the JSON-RPC protocol. MUST be exactly "2.0".
*/
jsonrpc: "2.0";
/**
* This member is REQUIRED on success.
* This member MUST NOT exist if there was an error invoking the method.
* The value of this member is determined by the method invoked on the Server.
*/
result?: any;
/**
* This member is REQUIRED on error.
* This member MUST NOT exist if the requested method was invoked successfully.
*/
error?: JsonRpcError;
}
interface JsonRpcError {
/**
* A Number that indicates the error type that occurred.
* This MUST be an integer.
*/
code: number;
/**
* A String providing a short description of the error.
* The message SHOULD be limited to a concise single sentence.
*/
message: string;
/**
* A Primitive or Structured value that contains additional information about the error.
* This may be omitted.
* The value of this member is defined by the Server (e.g. detailed error information, nested errors etc.).
*/
data?: any;
}
```
#### `algo_signTxn`
This request is used to ask a wallet to sign one or more transactions in one or more atomic groups.
##### Request
This request **MUST** adhere to the following structure:
```typescript
interface AlgoSignTxnRequest {
/**
* As described in JsonRpcRequest.
*/
id: number;
/**
* As described in JsonRpcRequest.
*/
jsonrpc: "2.0";
/**
* The method to invoke, MUST be "algo_signTxn".
*/
method: "algo_signTxn";
/**
* Parameters for the transaction signing request.
*/
params: SignTxnParams;
}
/**
* The first element is an array of `WalletTransaction` objects which contain the transaction(s) to be signed.
* If transactions from an atomic transaction group are being signed, then all transactions in the group (even the ones not being signed by the wallet) MUST appear in this array.
*
* The second element, if present, contains addition options specified with the `SignTxnOpts` structure.
*/
type SignTxnParams = [WalletTransaction[], SignTxnOpts?];
```
> `SignTxnParams` is a tuple with an optional element https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html#optional-elements-in-tuple-types, meaning its length can be 1 or 2.
The [`WalletTransaction`](./arc-0001.md#interface-wallettransaction) and [`SignTxnOpts`](./arc-0001.md#interface-signtxnsopts) types are defined in [ARC-1](./arc-0001.md).
All specifications, restrictions, and guidelines declared in ARC-1 for these types apply to their usage here as well. Additionally, all security requirements and restrictions for processing transaction signing requests from ARC-1 apply to this request as well.
> For more information, see [ARC-1 - Syntax and Interfaces](./arc-0001.md#syntax-and-interfaces) and [ARC-1 - Semantic and Security Requirements](./arc-0001.md#semantic-and-security-requirements).
##### Response
To respond to a request, the wallet **MUST** send back the following response object:
```typescript
interface AlgoSignTxnResponse {
/**
* As described in JsonRpcResponse.
*/
id: number;
/**
* As described in JsonRpcResponse.
*/
jsonrpc: "2.0";
/**
* An array containing signed transactions at specific indexes.
*/
result?: Array<SignedTxnStr | null>;
/**
* As described in JsonRpcResponse.
*/
error?: JsonRpcError;
}
```
[`SignedTxnStr`](./arc-0001.md#interface-signedtxnstr) type is defined in [ARC-1](./arc-0001.md).
In this response, `result` **MUST** be an array with the same length as the number of `WalletTransaction`s in the request (i.e. `<AlgoSignTxnRequest instance>.params[0].length`). For every integer `i` such that `0 <= i < result.length`:
* If the transaction at index `i` in the group should be signed by the wallet (i.e. `<AlgoSignTxnRequest instance>.params[0][i].signers` is not an empty array): `result[i]` **MUST** be a base64-encoded string containing the msgpack-encoded signed transaction `params[0][i].txn`.
* Otherwise: `result[i]` **MUST** be `null`, since the wallet was not requested to sign this transaction.
If the wallet does not approve signing every transaction whose signature is being requested, the request **MUST** fail.
All request failures **MUST** use the error codes defined in [ARC-1 - Error Standards](./arc-0001.md#error-standards).
## Rationale
## Security Considerations
None.
## Copyright
Copyright and related rights waived via <a href="https://creativecommons.org/publicdomain/zero/1.0/">CCO</a>.
```
--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/ARCs:specs:arc-0062.md:
--------------------------------------------------------------------------------
```markdown
---
arc: 62
title: ASA Circulating Supply
description: Getter method for ASA circulating supply
author: Cosimo Bassi (@cusma)
discussions-to: https://github.com/algorandfoundation/ARCs/issues/302
status: Final
type: Standards Track
category: Interface
sub-category: Asa
created: 2024-06-12
requires: 2, 4, 22
---
## Abstract
This ARC introduces a standard for the definition of circulating supply for Algorand
Standard Assets (ASA) and its client-side retrieval. A reference implementation is
suggested.
## Motivation
Algorand Standard Asset (ASA) `total` supply is _defined_ upon ASA creation.
Creating an ASA on the ledger _does not_ imply its `total` supply is immediately
“minted” or “circulating”. In fact, the semantic of token “minting” on Algorand is
slightly different from other blockchains: it is not coincident with the token units
creation on the ledger.
The Reserve Address, one of the 4 addresses of ASA Role-Based-Access-Control (RBAC),
is conventionally used to identify the portion of `total` supply not yet in circulation.
The Reserve Address has no “privilege” over the token: it is just a “logical” label
used (client-side) to classify an existing amount of ASA as “not in circulation”.
According to this convention, “minting” an amount of ASA units is equivalent to
_moving that amount out of the Reserve Address_.
> ASA may have the Reserve Address assigned to a Smart Contract to enforce specific
> “minting” policies, if needed.
This convention led to a simple and unsophisticated semantic of ASA circulating
supply, widely adopted by clients (wallets, explorers, etc.) to provide standard
information:
```text
circulating_supply = total - reserve_balance
```
Where `reserve_balance` is the ASA balance hold by the Reserve Address.
However, the simplicity of such convention, who fostered adoption across the Algorand
ecosystem, poses some limitations. Complex and sophisticated use-cases of ASA, such
as regulated stable-coins and tokenized securities among others, require more
detailed and expressive definitions of circulating supply.
As an example, an ASA could have “burned”, “locked” or “pre-minted” amounts of token,
not held in the Reserve Address, which _should not_ be considered as “circulating”
supply. This is not possible with the basic ASA protocol convention.
This ARC proposes a standard ABI _read-only_ method (getter) to provide the circulating
supply of an ASA.
## Specification
The keywords "**MUST**", "**MUST NOT**", "**REQUIRED**", "**SHALL**", "**SHALL NOT**",
"**SHOULD**", "**SHOULD NOT**", "**RECOMMENDED**", "**MAY**", and "**OPTIONAL**"
in this document are to be interpreted as described in <a href="https://datatracker.ietf.org/doc/html/rfc2119">RFC 2119</a>.
> Notes like this are non-normative.
### ABI Method
A compliant ASA, whose circulating supply definition conforms to this ARC, **MUST**
implement the following method on an Application (referred as _Circulating Supply
App_ in this specification):
```json
{
"name": "arc62_get_circulating_supply",
"readonly": true,
"args": [
{
"type": "uint64",
"name": "asset_id",
"desc": "ASA ID of the circulating supply"
}
],
"returns": {
"type": "uint64",
"desc": "ASA circulating supply"
},
"desc": "Get ASA circulating supply"
}
```
The `arc62_get_circulating_supply` **MUST** be a _read-only_ ([ARC-22](./arc-0022.md))
method (getter).
### Usage
Getter calls **SHOULD** be _simulated_.
Any external resources used by the implementation **SHOULD** be discovered and
auto-populated by the simulated getter call.
#### Example 1
> Let the ASA have `total` supply and a Reserve Address (i.e. not set to `ZeroAddress`).
>
> Let the Reserve Address be assigned to an account different from the Circulating
> Supply App Account.
>
> Let `burned` be an external Burned Address dedicated to ASA burned supply.
>
> Let `locked` be an external Locked Address dedicated to ASA locked supply.
>
> The ASA issuer defines the _circulating supply_ as:
>
> ```text
> circulating_supply = total - reserve_balance - burned_balance - locked_balance
> ```
>
> In this case the simulated read-only method call would auto-populate 1 external
> reference for the ASA and 3 external reference accounts (Reserve, Burned and Locked).
#### Example 2
> Let the ASA have `total` supply and _no_ Reserve Address (i.e. set to `ZeroAddress`).
>
> Let `non_circulating_amount` be a UInt64 Global Var defined by the implementation
> of the Circulating Supply App.
>
> The ASA issuer defines the _circulating supply_ as:
>
> ```text
> circulating_supply = total - non_circulating_amount
> ```
>
> In this case the simulated read-only method call would auto-populate just 1 external
> reference for the ASA.
### Circulating Supply Application discovery
> Given an ASA ID, clients (wallet, explorer, etc.) need to discover the related
> Circulating Supply App.
An ASA conforming to this ARC **MUST** specify the Circulating Supply App ID.
> To avoid ecosystem fragmentation this ARC does not propose any new method to specify
> the metadata of an ASA. Instead, it only extends already existing standards.
If the ASA also conforms to any ARC that supports additional `properties` ([ARC-3](./arc-0003.md),
[ARC-19](./arc-0019.md), [ARC-69](./arc-0069.md)),
then it **MUST** include a `arc-62` key and set the corresponding value to a map,
including the ID of the Circulating Supply App as a value for the key `application-id`.
#### Example
```json
{
//...
"properties": {
//...
"arc-62": {
"application-id": 123
}
}
//...
}
```
## Rationale
The definition of _circulating supply_ for sophisticated use-cases is usually ASA-specific.
It could involve, for example, complex math or external accounts’ balances, variables
stored in boxes or in global state, etc..
For this reason, the proposed method’s signature does not require any reference
to external resources, a part form the `asset_id` of the ASA for which the circulating
supply is defined.
Eventual external resources can be discovered and auto-populated directly by the
simulated method call.
The rational of this design choice is avoiding fragmentation and integration overhead
for clients (wallets, explorers, etc.).
Clients just need to know:
1. The ASA ID;
1. The Circulating Supply App ID implementing the `arc62_get_circulating_supply`
method for that ASA.
## Backwards Compatibility
Existing ASA willing to conform to this ARC **MUST** specify the Circulating Supply
App ID as [ARC-2](./arc-0002.md) `AssetConfig` transaction note field, as follows:
- The `<arc-number>` **MUST** be equal to `62`;
- The **RECOMMENDED** `<data-format>` are <a href="https://msgpack.org/">MsgPack</a>
(`m`) or <a href="https://www.json.org/json-en.html">JSON</a> (`j`);
- The `<data>` **MUST** specify `application-id` equal to the Circulating Supply
App ID.
> **WARNING**: To preserve the existing ASA RBAC (e.g. Manager Address, Freeze Address,
> etc.) it is necessary to **include all the existing role addresses** in the `AssetConfig`.
> Not doing so would irreversibly disable the RBAC roles!
### Example - JSON without version
```text
arc62:j{"application-id":123}
```
## Reference Implementation
> This section is non-normative.
This section suggests a reference implementation of the Circulating Supply App.
An Algorand-Python example is available [here](../assets/arc-0062).
### Recommendations
An ASA using the reference implementation **SHOULD NOT** assign the Reserve Address
to the Circulating Supply App Account.
A reference implementation **SHOULD** target a version of the AVM that supports
foreign resources pooling (version 9 or greater).
A reference implementation **SHOULD** use 3 external addresses, in addition to the
Reserve Address, to define the not circulating supply.
The **RECOMMENDED** labels for not-circulating balances are: `burned`, `locked`
and `generic`.
> To change the labels of not circulating addresses is sufficient to rename the
> following constants just in `smart_contracts/circulating_supply/config.py`:
> ```python
> NOT_CIRCULATING_LABEL_1: Final[str] = "burned"
> NOT_CIRCULATING_LABEL_2: Final[str] = "locked"
> NOT_CIRCULATING_LABEL_3: Final[str] = "generic"
> ```
### State Schema
A reference implementation **SHOULD** allocate, at least, the following Global State
variables:
- `asset_id` as UInt64, initialized to `0` and set **only once** by the ASA Manager
Address;
- Not circulating address 1 (`burned`) as Bytes, initialized to the Global `Zero Address`
and set by the ASA Manager Address;
- Not circulating address 2 (`locked`) as Bytes, initialized to the Global `Zero Address`
and set by the ASA Manager Address;
- Not circulating address 3 (`generic`) as Bytes, initialized to the Global `Zero Address`
and set by the ASA Manager Address.
A reference implementation **SHOULD** enforce that, upon setting `burned`, `locked`
and `generic` addresses, the latter already opted-in the `asset_id`.
```json
"state": {
"global": {
"num_byte_slices": 3,
"num_uints": 1
},
"local": {
"num_byte_slices": 0,
"num_uints": 0
}
},
"schema": {
"global": {
"declared": {
"asset_id": {
"type": "uint64",
"key": "asset_id"
},
"not_circulating_label_1": {
"type": "bytes",
"key": "burned"
},
"not_circulating_label_2": {
"type": "bytes",
"key": "locked"
},
"not_circulating_label_3": {
"type": "bytes",
"key": "generic"
}
},
"reserved": {}
},
"local": {
"declared": {},
"reserved": {}
}
},
```
### Circulating Supply Getter
A reference implementation **SHOULD** enforce that the `asset_id` Global Variable
is equal to the `asset_id` argument of the `arc62_get_circulating_supply` getter
method.
> Alternatively the reference implementation could ignore the `asset_id` argument
> and use directly the `asset_id` Global Variable.
A reference implementation **SHOULD** return the ASA _circulating supply_ as:
```text
circulating_supply = total - reserve_balance - burned_balance - locked_balance - generic_balance
```
Where:
- `total` is the total supply of the ASA (`asset_id`);
- `reserve_balance` is the ASA balance hold by the Reserve Address or `0` if the
address is set to the Global `ZeroAddress` or not opted-in `asset_id`;
- `burned_balance` is the ASA balance hold by the Burned Address or `0` if the address
is set to the Global `ZeroAddress` or is not opted-in `asset_id`;
- `locked_balance` is the ASA balance hold by the Locked Address or `0` if the address
is set to the Global `ZeroAddress` or not opted-in `asset_id`;
- `generic_balance` is the ASA balance hold by a Generic Address or `0` if the address
is set to the Global `ZeroAddress` or not opted-in `asset_id`.
## Security Considerations
Permissions over the Circulating Supply App setting and update **SHOULD** be granted
to the ASA Manager Address.
> The ASA trust-model (i.e. who sets the Reserve Address) is extended to the generalized
> ASA circulating supply definition.
## Copyright
Copyright and related rights waived via <a href="https://creativecommons.org/publicdomain/zero/1.0/">CCO</a>.
```
--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/developer:docs:run-a-node:setup:node-troubleshooting.md:
--------------------------------------------------------------------------------
```markdown
title: Node Troubleshooting
# Do you want to run a node yourself?
If you are a developer, running a private network using [AlgoKit](/docs/get-started/algokit) is simpler and provide more flexibility.
Running a production node for MainNet is very beneficial for decentralization.
However, as any unmanaged system (and any blockchain node/indexer), to achieve high SLA, running a production node has many requirements: appropriate redundancy (some upgrades create downtime on nodes), 24/7 monitoring, regular maintenance, use of a staging environment for testing updates, ...
!!! tip
Subscribe to notifications on [Forum](https://forum.algorand.org/c/announcements/5) to be aware of new releases. Read carefully all release notes as some updates may create downtimes or may require some configuration changes. It is recommended to systematically update to new releases after testing in a non-production environment.
You can consider using [third-party API services](https://developer.algorand.org/ecosystem-projects/?tags=api-services) or a third-party provider to help setting/maintaining a node.
# First steps
Be sure to have your `$PATH` and `$ALGORAND_DATA` environment variables set properly and that your node is running. In particular:
```bash
goal node status
```
should return something like:
```
Last committed block: 23119736
Time since last block: 0.1s
Sync Time: 2.7s
Last consensus protocol: https://github.com/algorandfoundation/specs/tree/d5ac876d7ede07367dbaa26e149aa42589aac1f7
Next consensus protocol: https://github.com/algorandfoundation/specs/tree/d5ac876d7ede07367dbaa26e149aa42589aac1f7
Round for next consensus protocol: 23119737
Next consensus protocol supported: true
Last Catchpoint:
Genesis ID: testnet-v1.0
Genesis hash: SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=
```
Read [Install a Node](../install) to set these variables properly.
If you see:
* `Data directory not specified. Please use -d or set $ALGORAND_DATA in your environment. Exiting.`: `$ALGORAND_DATA` is not properly set up.
* `command not found: goal`: `$PATH` is not properly set up.
* `Cannot contact Algorand node: open ...: no such file or directory`: the node is not started. Starting a node is done differently depending on the installation method. See sections "Start the node" from [Install a Node](/docs/run-a-node/setup/install).
# Common Issues for algod
## Most common issues: wrong version, wrong network, not caught up
One of the most common issues are that the node is on the wrong network, has the wrong algod version, or is not fully synced.
* **Check that the node is synced/caught up** following [Catchup and Status](/docs/run-a-node/operations/catchup). See below if the node is not syncing.
* **Check that the node is on the right network**: when running `goal node status`, `Genesis ID` must be `mainnet-v1.0` for MainNet, `testnet-v1.0` for TestNet, `betanet-v1.0` for BetaNet. See [Switch Networks](/docs/run-a-node/operations/switch_networks) to solve this issue.
* **Check that the version** reported of `algod -v` and `goal version -v` are the latest stable release (if using MainNet or TestNet) or the latest beta release (if using BetaNet). See the [official repo](https://github.com/algorand/go-algorand/releases) for the list of all releases. Beta releases are clearly marked as such.
## My node is not syncing/catching up at all (Last Committed Block is 0)
As soon as the node is started, the `Last Committed Block` from `goal node status` should be increasing.
If it stays 0, the node is not syncing/catching up at all.
This is usually due to a connectivity issue or a DNS restriction imposed by the ISP.
### No connectivity
First, check that the node has proper internet access.
To check it with the command line, you may use `curl https://example.com`.
### DNS restrictions
By default, a node gets the list of relays it needs to connect to by reading DNS SRV records.
To ensure those records are not tampered with, the node uses DNSSec.
The node will first try to use the system DNS. If it fails, it will use the fallback DNS from `config.json` (if provided). If this fails again, it will try hardcoded DNS from [tools/network/dnssec/config.go](https://github.com/algorand/go-algorand/blob/master/tools/network/dnssec/config.go).
Some ISP, enterprise networks, or public networks only allows DNS queries to their own DNS server that may not support DNSSec.
In that case, you will need to set `"DNSSecurityFlags": 0` inside `$ALGORAND_DATA/config.json`.
!!! warning
Setting `DNSSecurityFlags` to `0` lowers the security of the node and may allow attackers to make your node connect to untrustworthy relays. While untrustworthy relays cannot make your node accept invalid blocks or create invalid transactions, they may censor all transactions from your nodes or may prevent your node from syncing by not providing the latest blocks. It is strongly recommended to enable DNSSec in production.
!!! tip
Do not forget to restart `algod` after any change to the configuration.
To check if your node's DNS access is correct, run the following commands in the terminal:
```
dig -t SRV _algobootstrap._tcp.mainnet.algorand.network +dnssec
dig -t SRV _algobootstrap._tcp.mainnet.algorand.network @8.8.8.8 +dnssec
```
at least one of them must return a list of relays without any error nor warning.
(The first command uses the system DNS while the second one uses Google DNS.)
### Other issues
Here are other less common reasons for a node not being able to catch up at all.
* Check the presence of the right `genesis.json` file in `$ALGORAND_DATA`. See the documentation on how to [switch networks](/docs/run-a-node/operations/switch_networks/).
* If using BetaNet, check that `$ALGORAND_DATA/config.json` contains the right `DNSBootstrapID`. See the [configuration for BetaNet](/docs/run-a-node/operations/switch_networks/#dns-configuration-for-betanet).
## My node is syncing/catching up very slowly (without fast catchup)
Syncing without fast catchup is expecting to take a 2 to 4 weeks in November 2022, due to the amount of data on the Algorand blockchain.
In addition, syncing will slow down as rounds increases, as newer blocks usually contain many more transactions than older blocks.
!!! tip
Remember that non-archival node can be synced faster using [fast catchup](/docs/run-a-node/setup/install#sync-node-network-using-fast-catchup). Archival nodes cannot use fast catchup but algonode.io, a third-party service, provides [snapshots of archival nodes](https://algonode.io/extras/). This tip is NOT an endorsement of these snapshots and using these snapshots require careful weighting of associated risks: `algod` cannot verify that these snapshots are valid. In particular, `algod` cannot verify that these snapshots do not contain invalid data that would allow for double spending.
If it looks like your node will take much longer than 4 weeks for syncing, then:
1. Check that your node has the right [hardware requirements](/docs/run-a-node/setup/install/#hardware-requirements). In particular, if your node has less than 4GB (or ideally 8GB) of RAM and/or an HDD/slow-SATA-SSD/SD, then you will not be able to catch up on MainNet.
2. Check that your node is not overused:
1. Check RAM and CPU use using `top` or `htop`
2. Check free disk using `df -h`
3. Check that your Internet connection is fast enough using a speed test. You need to have at least a 100Mbps connection and low enough latency (below 100ms is most likely needed).
4. While there are relays all over the world, some regions may have a few number of relays which may slow down catching up. Check latency to the best relays using [algonode.io](https://algonode.io/extras/) scripts (in the folder `utils` of https://snap.algonode.cloud/ --- copied below for completeness):
```
#!/bin/bash
# needs dig from dnsutils
N=$(dig +short srv _algobootstrap._tcp.mainnet.algorand.network @1.1.1.1 |wc -l)
echo "Querying $N nodes, be patient..."
echo "" > report.txt
for relay in $(dig +short srv _algobootstrap._tcp.mainnet.algorand.network @1.1.1.1|awk '{print $4 ":" $3}');
do
echo -n .
curl -s -o /dev/null --max-time 1 "http://$relay/v1/urtho/ledger/0"
echo -ne '\bo'
curl -s -o /dev/null --max-time 1 "http://$relay/v1/urtho/ledger/0" -w %{time_total} >> report.txt
echo -ne '\b+'
echo "s;$relay" >> report.txt
done
echo "Top 20 nodes"
sort -n report.txt | head -20
```
Latency above 100ms to the top 20 relays may most likely cause issues.
5. Check that `$ALGORAND_DATA/config.json` is either absent or only contain the non-default parameters you actually need to change. Only change parameters if you understand the consequences, some parameter changes may significantly slow down syncing.
## My node is not syncing/catching up with fast catchup
See [troubleshooting for fast catchup](/docs/run-a-node/setup/install#troubleshooting-for-fast-catchup).
## Other issues
### I get an `overspend` error when sending a transaction
If sending a transaction results in an `overspend` error (i.e., the word `overspend` appears in the error):
1. Check that the account has enough Algos on a [block explorer](https://developer.algorand.org/ecosystem-projects/?tags=block-explorers).
2. Check that your node is [synced and on the right network](#Most-common-issues-wrong-version-wrong-network-not-caught-up).
3. Do not forget to take into account:
1. The [minimum balance requirement](/docs/get-details/parameter_tables/#minimum-balance) of 0.1 Algo for a basic account (more if ASA or applications are created or used).
2. The [fee](/docs/get-details/transactions/#fees) paid by the sender of the transaction.
## None of the above works
If none of the above works, you can look for additional information on the [third-party algonode.io FAQ](https://algonode.io/faq/#algorand-faq).
If this still does not solve your issue, please open a new post on [Forum](https://forum.algorand.org) with the following information:
* what you are trying to do and what fails (with full command lines tried and outputs written in triple backquotes)
* OS version
* machine specs: number of CPU, size of RAM, disk type (NVMe SSD, SATA SSD, ...)
* actual use: memory available, disk available, ...
* algod version: `algod -v`
* goal version: `goal version -v`
* goal status: `goal node status`
* content of `config.json` (in the data folder `$ALGORAND_DATA`)
* link to the files `algod-out.log`, `algod-err.log`, `node.log` (in the data folder `$ALGORAND_DATA`) uploaded in a Github gist or equivalent system
!!! tip
Always write code/long outputs between triple backquotes or use the "code" button to facilitate the user reading
```
$ goal node status
Last committed block: 23119736
Time since last block: 0.1s
Sync Time: 2.7s
Last consensus protocol: https://github.com/algorandfoundation/specs/tree/d5ac876d7ede07367dbaa26e149aa42589aac1f7
Next consensus protocol: https://github.com/algorandfoundation/specs/tree/d5ac876d7ede07367dbaa26e149aa42589aac1f7
Round for next consensus protocol: 23119737
Next consensus protocol supported: true
Last Catchpoint:
Genesis ID: testnet-v1.0
Genesis hash: SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=
```
```
--------------------------------------------------------------------------------
/packages/server/src/tools/algodManager.ts:
--------------------------------------------------------------------------------
```typescript
import algosdk, { modelsv2 } from 'algosdk';
import type { EncodedSignedTransaction } from 'algosdk';
import type {
SimulateResponse,
CompileResponse,
DisassembleResponse,
SimulateTraceConfig,
PostTransactionsResponse
} from 'algosdk/dist/types/client/v2/algod/models/types';
import { algodClient } from '../algorand-client.js';
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
// Tool schemas
export const algodToolSchemas = {
compileTeal: {
type: 'object',
properties: {
source: { type: 'string', description: 'Logic that executes when the app is called (compiled TEAL as base64)' }
},
required: ['source']
},
disassembleTeal: {
type: 'object',
properties: {
bytecode: { type: 'string', description: 'TEAL bytecode to disassemble into source code' }
},
required: ['bytecode']
},
sendRawTransaction: {
type: 'object',
properties: {
signedTxns: {
type: 'array',
items: { type: 'string', description: 'Base64-encoded signed transaction' },
description: 'Array of signed transactions to submit to the network'
}
},
required: ['signedTxns']
},
simulateRawTransactions: {
type: 'object',
properties: {
txns: {
type: 'array',
items: { type: 'string', description: 'Base64-encoded transaction' },
description: 'Array of transactions to simulate'
}
},
required: ['txns']
},
simulateTransactions: {
type: 'object',
properties: {
txnGroups: {
type: 'array',
items: {
type: 'object',
properties: {
txns: {
type: 'array',
items: { type: 'object', description: 'Transaction object to simulate' },
description: 'Array of transactions in this group'
}
},
required: ['txns'],
description: 'Group of transactions to simulate together'
},
description: 'Array of transaction groups to simulate'
},
allowEmptySignatures: { type: 'boolean', optional: true, description: 'Allow transactions without signatures' },
allowMoreLogging: { type: 'boolean', optional: true, description: 'Enable additional logging during simulation' },
allowUnnamedResources: { type: 'boolean', optional: true, description: 'Allow access to resources not listed in transaction' },
execTraceConfig: { type: 'object', optional: true, description: 'Configuration for execution trace output' },
extraOpcodeBudget: { type: 'integer', optional: true, description: 'Additional budget for TEAL program execution' },
round: { type: 'integer', optional: true, description: 'Round at which to simulate the transactions' }
},
required: ['txnGroups']
}
};
export class AlgodManager {
static readonly algodTools = [
{
name: 'compile_teal',
description: 'Compile TEAL source code',
inputSchema: algodToolSchemas.compileTeal,
},
{
name: 'disassemble_teal',
description: 'Disassemble TEAL bytecode back to source',
inputSchema: algodToolSchemas.disassembleTeal,
},
{
name: 'send_raw_transaction',
description: 'Submit signed transactions to the Algorand network',
inputSchema: algodToolSchemas.sendRawTransaction,
},
{
name: 'simulate_raw_transactions',
description: 'Simulate raw transactions',
inputSchema: algodToolSchemas.simulateRawTransactions,
},
{
name: 'simulate_transactions',
description: 'Simulate transactions with detailed configuration',
inputSchema: algodToolSchemas.simulateTransactions,
}
];
// Tool handlers
static async handleTool(name: string, args: Record<string, unknown>) {
try {
switch (name) {
case 'compile_teal':
if (!args.source || typeof args.source !== 'string') {
throw new McpError(ErrorCode.InvalidParams, 'TEAL source code is required');
}
const result = await AlgodManager.compile(args.source);
return {
content: [{
type: 'text',
text: JSON.stringify(result, null, 2),
}],
};
case 'disassemble_teal':
if (!args.bytecode || typeof args.bytecode !== 'string') {
throw new McpError(ErrorCode.InvalidParams, 'TEAL bytecode is required');
}
const disassembled = await AlgodManager.disassemble(args.bytecode);
return {
content: [{
type: 'text',
text: JSON.stringify(disassembled, null, 2),
}],
};
case 'send_raw_transaction':
if (!args.signedTxns || !Array.isArray(args.signedTxns)) {
throw new McpError(ErrorCode.InvalidParams, 'Signed transactions array is required');
}
const txns = args.signedTxns.map(txn => {
if (typeof txn !== 'string') {
throw new McpError(ErrorCode.InvalidParams, 'Each transaction must be a base64 string');
}
return Buffer.from(txn, 'base64');
});
const sent = await AlgodManager.sendRawTransaction(txns);
return {
content: [{
type: 'text',
text: JSON.stringify(sent, null, 2),
}],
};
case 'simulate_raw_transactions':
if (!args.txns || !Array.isArray(args.txns)) {
throw new McpError(ErrorCode.InvalidParams, 'Transactions array is required');
}
const rawTxns = args.txns.map(txn => {
if (typeof txn !== 'string') {
throw new McpError(ErrorCode.InvalidParams, 'Each transaction must be a base64 string');
}
return Buffer.from(txn, 'base64');
});
const simulated = await AlgodManager.simulateRawTransactions(rawTxns);
return {
content: [{
type: 'text',
text: JSON.stringify(simulated, null, 2),
}],
};
case 'simulate_transactions':
if (!args.txnGroups || !Array.isArray(args.txnGroups)) {
throw new McpError(ErrorCode.InvalidParams, 'Transaction groups array is required');
}
const simulateResult = await AlgodManager.simulateTransactions(args as any);
return {
content: [{
type: 'text',
text: JSON.stringify(simulateResult, null, 2),
}],
};
default:
console.error(`[MCP Error] Unknown tool requested: ${name}`);
throw new McpError(
ErrorCode.MethodNotFound,
`Unknown tool: ${name}`
);
}
} catch (error) {
if (error instanceof McpError) {
console.error(`[MCP Error] ${error.code}: ${error.message}`);
throw error;
}
console.error('[MCP Error] Unexpected error:', error);
throw new McpError(
ErrorCode.InternalError,
`Operation failed: ${error instanceof Error ? error.message : 'Unknown error'}`
);
}
}
/**
* Compiles TEAL source code to binary
* @param source TEAL source code as string or bytes
* @returns Compilation result with hash and bytecode
*/
static async compile(source: string | Uint8Array): Promise<CompileResponse> {
try {
// Convert string source to Buffer
if (typeof source === 'string') {
// Ensure proper line endings and add final newline
source = source.replace(/\r\n/g, '\n');
if (!source.endsWith('\n')) {
source += '\n';
}
source = new TextEncoder().encode(source);
}
const response = await algodClient.compile(source).do() as CompileResponse;
return response;
} catch (error) {
console.error('[MCP Error] Failed to compile TEAL:', error);
throw new McpError(
ErrorCode.InternalError,
`Failed to compile TEAL: ${error instanceof Error ? error.message : String(error)}`
);
}
}
/**
* Disassembles TEAL bytecode back to source
* @param bytecode TEAL bytecode as string or bytes
* @returns Disassembled TEAL source code
*/
static async disassemble(bytecode: string | Uint8Array): Promise<DisassembleResponse> {
try {
const response = await algodClient.disassemble(bytecode).do() as DisassembleResponse;
return response;
} catch (error) {
console.error('[MCP Error] Failed to disassemble TEAL:', error);
throw new McpError(
ErrorCode.InternalError,
`Failed to disassemble TEAL: ${error instanceof Error ? error.message : String(error)}`
);
}
}
/**
* Broadcasts signed transactions to the network
* @param signedTxns Single signed transaction or array of signed transactions
* @returns Transaction ID of the submission
*/
static async sendRawTransaction(signedTxns: Uint8Array | Uint8Array[]): Promise<PostTransactionsResponse> {
try {
const response = await algodClient.sendRawTransaction(signedTxns).do() as PostTransactionsResponse;
return response;
} catch (error) {
console.error('[MCP Error] Failed to send transaction:', error);
throw new McpError(
ErrorCode.InternalError,
`Failed to send transaction: ${error instanceof Error ? error.message : String(error)}`
);
}
}
/**
* Simulates raw transactions
* @param txns Single transaction or array of transactions to simulate
* @returns Simulation results
*/
static async simulateRawTransactions(txns: Uint8Array | Uint8Array[]): Promise<SimulateResponse> {
try {
const response = await algodClient.simulateRawTransactions(txns).do() as SimulateResponse;
return response;
} catch (error) {
console.error('[MCP Error] Failed to simulate raw transactions:', error);
throw new McpError(
ErrorCode.InternalError,
`Failed to simulate raw transactions: ${error instanceof Error ? error.message : String(error)}`
);
}
}
/**
* Simulates transactions with detailed configuration
* @param request Simulation request with transaction groups and configuration
* @returns Simulation results
*/
static async simulateTransactions(request: {
txnGroups: { txns: EncodedSignedTransaction[] }[];
allowEmptySignatures?: boolean;
allowMoreLogging?: boolean;
allowUnnamedResources?: boolean;
execTraceConfig?: SimulateTraceConfig;
extraOpcodeBudget?: number;
round?: number;
}): Promise<SimulateResponse> {
try {
const simulateRequest = new modelsv2.SimulateRequest({
txnGroups: request.txnGroups.map(group =>
new modelsv2.SimulateRequestTransactionGroup({ txns: group.txns })
),
allowEmptySignatures: request.allowEmptySignatures,
allowMoreLogging: request.allowMoreLogging,
allowUnnamedResources: request.allowUnnamedResources,
execTraceConfig: request.execTraceConfig,
extraOpcodeBudget: request.extraOpcodeBudget,
round: request.round,
});
const response = await algodClient.simulateTransactions(simulateRequest).do() as SimulateResponse;
return response;
} catch (error) {
console.error('[MCP Error] Failed to simulate transactions:', error);
throw new McpError(
ErrorCode.InternalError,
`Failed to simulate transactions: ${error instanceof Error ? error.message : String(error)}`
);
}
}
}
```
--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/puya:python:testing:docs:testing-guide:opcodes.md:
--------------------------------------------------------------------------------
```markdown
# AVM Opcodes
The [coverage](coverage.md) file provides a comprehensive list of all opcodes and their respective types, categorized as _Mockable_, _Emulated_, or _Native_ within the `algorand-python-testing` package. This section highlights a **subset** of opcodes and types that typically require interaction with the test context manager.
`Native` opcodes are assumed to function as they do in the Algorand Virtual Machine, given their stateless nature. If you encounter issues with any `Native` opcodes, please raise an issue in the [`algorand-python-testing` repo](https://github.com/algorandfoundation/algorand-python-testing/issues/new/choose) or contribute a PR following the [Contributing](https://github.com/algorandfoundation/algorand-python-testing/blob/main/CONTRIBUTING.md) guide.
```{testsetup}
import algopy
from algopy_testing import algopy_testing_context
# Create the context manager for snippets below
ctx_manager = algopy_testing_context()
# Enter the context
context = ctx_manager.__enter__()
```
## Implemented Types
These types are fully implemented in Python and behave identically to their AVM counterparts:
### 1. Cryptographic Operations
The following opcodes are demonstrated:
- `op.sha256`
- `op.keccak256`
- `op.ecdsa_verify`
```{testcode}
from algopy import op
# SHA256 hash
data = algopy.Bytes(b"Hello, World!")
hashed = op.sha256(data)
# Keccak256 hash
keccak_hashed = op.keccak256(data)
# ECDSA verification
message_hash = bytes.fromhex("f809fd0aa0bb0f20b354c6b2f86ea751957a4e262a546bd716f34f69b9516ae1")
sig_r = bytes.fromhex("18d96c7cda4bc14d06277534681ded8a94828eb731d8b842e0da8105408c83cf")
sig_s = bytes.fromhex("7d33c61acf39cbb7a1d51c7126f1718116179adebd31618c4604a1f03b5c274a")
pubkey_x = bytes.fromhex("f8140e3b2b92f7cbdc8196bc6baa9ce86cf15c18e8ad0145d50824e6fa890264")
pubkey_y = bytes.fromhex("bd437b75d6f1db67155a95a0da4b41f2b6b3dc5d42f7db56238449e404a6c0a3")
result = op.ecdsa_verify(op.ECDSA.Secp256r1, message_hash, sig_r, sig_s, pubkey_x, pubkey_y)
assert result
```
### 2. Arithmetic and Bitwise Operations
The following opcodes are demonstrated:
- `op.addw`
- `op.bitlen`
- `op.getbit`
- `op.setbit_uint64`
```{testcode}
from algopy import op
# Addition with carry
result, carry = op.addw(algopy.UInt64(2**63), algopy.UInt64(2**63))
# Bitwise operations
value = algopy.UInt64(42)
bit_length = op.bitlen(value)
is_bit_set = op.getbit(value, 3)
new_value = op.setbit_uint64(value, 2, 1)
```
For a comprehensive list of all opcodes and types, refer to the [coverage](../coverage.md) page.
## Emulated Types Requiring Transaction Context
These types necessitate interaction with the transaction context:
### algopy.op.Global
```{testcode}
from algopy import op
class MyContract(algopy.ARC4Contract):
@algopy.arc4.abimethod
def check_globals(self) -> algopy.UInt64:
return op.Global.min_txn_fee + op.Global.min_balance
... # setup context (below assumes available under 'ctx' variable)
context.ledger.patch_global_fields(
min_txn_fee=algopy.UInt64(1000),
min_balance=algopy.UInt64(100000)
)
contract = MyContract()
result = contract.check_globals()
assert result == algopy.UInt64(101000)
```
### algopy.op.Txn
```{testcode}
from algopy import op
class MyContract(algopy.ARC4Contract):
@algopy.arc4.abimethod
def check_txn_fields(self) -> algopy.arc4.Address:
return algopy.arc4.Address(op.Txn.sender)
... # setup context (below assumes available under 'ctx' variable)
contract = MyContract()
custom_sender = context.any.account()
with context.txn.create_group(active_txn_overrides={"sender": custom_sender}):
result = contract.check_txn_fields()
assert result == custom_sender
```
### algopy.op.AssetHoldingGet
```{testcode}
from algopy import op
class AssetContract(algopy.ARC4Contract):
@algopy.arc4.abimethod
def check_asset_holding(self, account: algopy.Account, asset: algopy.Asset) -> algopy.UInt64:
balance, _ = op.AssetHoldingGet.asset_balance(account, asset)
return balance
... # setup context (below assumes available under 'ctx' variable)
asset = context.any.asset(total=algopy.UInt64(1000000))
account = context.any.account(opted_asset_balances={asset.id: algopy.UInt64(5000)})
contract = AssetContract()
result = contract.check_asset_holding(account, asset)
assert result == algopy.UInt64(5000)
```
### algopy.op.AppGlobal
```{testcode}
from algopy import op
class StateContract(algopy.ARC4Contract):
@algopy.arc4.abimethod
def set_and_get_state(self, key: algopy.Bytes, value: algopy.UInt64) -> algopy.UInt64:
op.AppGlobal.put(key, value)
return op.AppGlobal.get_uint64(key)
... # setup context (below assumes available under 'ctx' variable)
contract = StateContract()
key, value = algopy.Bytes(b"test_key"), algopy.UInt64(42)
result = contract.set_and_get_state(key, value)
assert result == value
stored_value = context.ledger.get_global_state(contract, key)
assert stored_value == 42
```
### algopy.op.Block
```{testcode}
from algopy import op
class BlockInfoContract(algopy.ARC4Contract):
@algopy.arc4.abimethod
def get_block_seed(self) -> algopy.Bytes:
return op.Block.blk_seed(1000)
... # setup context (below assumes available under 'ctx' variable)
context.ledger.set_block(1000, seed=123456, timestamp=1625097600)
contract = BlockInfoContract()
seed = contract.get_block_seed()
assert seed == algopy.op.itob(123456)
```
### algopy.op.AcctParamsGet
```{testcode}
from algopy import op
class AccountParamsContract(algopy.ARC4Contract):
@algopy.arc4.abimethod
def get_account_balance(self, account: algopy.Account) -> algopy.UInt64:
balance, exists = op.AcctParamsGet.acct_balance(account)
assert exists
return balance
... # setup context (below assumes available under 'ctx' variable)
account = context.any.account(balance=algopy.UInt64(1000000))
contract = AccountParamsContract()
balance = contract.get_account_balance(account)
assert balance == algopy.UInt64(1000000)
```
### algopy.op.AppParamsGet
```{testcode}
class AppParamsContract(algopy.ARC4Contract):
@algopy.arc4.abimethod
def get_app_creator(self, app_id: algopy.Application) -> algopy.arc4.Address:
creator, exists = algopy.op.AppParamsGet.app_creator(app_id)
assert exists
return algopy.arc4.Address(creator)
... # setup context (below assumes available under 'ctx' variable)
contract = AppParamsContract()
app = context.any.application()
creator = contract.get_app_creator(app)
assert creator == context.default_sender
```
### algopy.op.AssetParamsGet
```{testcode}
from algopy import op
class AssetParamsContract(algopy.ARC4Contract):
@algopy.arc4.abimethod
def get_asset_total(self, asset_id: algopy.UInt64) -> algopy.UInt64:
total, exists = op.AssetParamsGet.asset_total(asset_id)
assert exists
return total
... # setup context (below assumes available under 'ctx' variable)
asset = context.any.asset(total=algopy.UInt64(1000000), decimals=algopy.UInt64(6))
contract = AssetParamsContract()
total = contract.get_asset_total(asset.id)
assert total == algopy.UInt64(1000000)
```
### algopy.op.Box
```{testcode}
from algopy import op
class BoxStorageContract(algopy.ARC4Contract):
@algopy.arc4.abimethod
def store_and_retrieve(self, key: algopy.Bytes, value: algopy.Bytes) -> algopy.Bytes:
op.Box.put(key, value)
retrieved_value, exists = op.Box.get(key)
assert exists
return retrieved_value
... # setup context (below assumes available under 'ctx' variable)
contract = BoxStorageContract()
key, value = algopy.Bytes(b"test_key"), algopy.Bytes(b"test_value")
result = contract.store_and_retrieve(key, value)
assert result == value
stored_value = context.ledger.get_box(contract, key)
assert stored_value == value.value
```
## Mockable Opcodes
These opcodes are mockable in `algorand-python-testing`, allowing for controlled testing of complex operations:
### algopy.compile_contract
```{testcode}
from unittest.mock import patch, MagicMock
import algopy
mocked_response = MagicMock()
mocked_response.local_bytes = algopy.UInt64(4)
class MockContract(algopy.Contract):
...
class ContractFactory(algopy.ARC4Contract):
...
@algopy.arc4.abimethod
def compile_and_get_bytes(self) -> algopy.UInt64:
contract_response = algopy.compile_contract(MockContract)
return contract_response.local_bytes
... # setup context (below assumes available under 'ctx' variable)
contract = ContractFactory()
with patch('algopy.compile_contract', return_value=mocked_response):
assert contract.compile_and_get_bytes() == 4
```
### algopy.arc4.abi_call
```{testcode}
import unittest
from unittest.mock import patch, MagicMock
import algopy
import typing
class MockAbiCall:
def __call__(
self, *args: typing.Any, **_kwargs: typing.Any
) -> tuple[typing.Any, typing.Any]:
return (
algopy.arc4.UInt64(11),
MagicMock(),
)
def __getitem__(self, _item: object) -> typing.Self:
return self
class MyContract(algopy.ARC4Contract):
@algopy.arc4.abimethod
def my_method(self, arg1: algopy.UInt64, arg2: algopy.UInt64) -> algopy.UInt64:
return algopy.arc4.abi_call[algopy.arc4.UInt64]("my_other_method", arg1, arg2)[0].native
... # setup context (below assumes available under 'ctx' variable)
contract = MyContract()
with patch('algopy.arc4.abi_call', MockAbiCall()):
result = contract.my_method(algopy.UInt64(10), algopy.UInt64(1))
assert result == 11
```
### algopy.op.vrf_verify
```{testcode}
from unittest.mock import patch, MagicMock
import algopy
def test_mock_vrf_verify():
mock_result = (algopy.Bytes(b'mock_output'), True)
with patch('algopy.op.vrf_verify', return_value=mock_result) as mock_vrf_verify:
result = algopy.op.vrf_verify(
algopy.op.VrfVerify.VrfAlgorand,
algopy.Bytes(b'proof'),
algopy.Bytes(b'message'),
algopy.Bytes(b'public_key')
)
assert result == mock_result
mock_vrf_verify.assert_called_once_with(
algopy.op.VrfVerify.VrfAlgorand,
algopy.Bytes(b'proof'),
algopy.Bytes(b'message'),
algopy.Bytes(b'public_key')
)
test_mock_vrf_verify()
```
### algopy.op.EllipticCurve
```{testcode}
from unittest.mock import patch, MagicMock
import algopy
def test_mock_elliptic_curve_decompress():
mock_result = (algopy.Bytes(b'x_coord'), algopy.Bytes(b'y_coord'))
with patch('algopy.op.EllipticCurve.decompress', return_value=mock_result) as mock_decompress:
result = algopy.op.EllipticCurve.decompress(
algopy.op.EC.BN254g1,
algopy.Bytes(b'compressed_point')
)
assert result == mock_result
mock_decompress.assert_called_once_with(
algopy.op.EC.BN254g1,
algopy.Bytes(b'compressed_point')
)
test_mock_elliptic_curve_decompress()
```
These examples demonstrate how to mock key mockable opcodes in `algorand-python-testing`. Use similar techniques (in your preferred testing framework) for other mockable opcodes like `algopy.compile_logicsig`, `algopy.arc4.arc4_create`, and `algopy.arc4.arc4_update`.
Mocking these opcodes allows you to:
1. Control complex operations' behavior not covered by _implemented_ and _emulated_ types.
2. Test edge cases and error conditions.
3. Isolate contract logic from external dependencies.
```{testcleanup}
ctx_manager.__exit__(None, None, None)
```
```
--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/ARCs:specs:arc-0032.md:
--------------------------------------------------------------------------------
```markdown
---
arc: 32
title: Application Specification
description: A specification for fully describing an Application, useful for Application clients.
author: Benjamin Guidarelli (@barnjamin)
discussions-to: https://github.com/algorandfoundation/ARCs/issues/150
status: Final
type: Standards Track
category: ARC
sub-category: Application
created: 2022-12-01
requires: 4, 21
---
## Abstract
> [!NOTE]
> This specification will be eventually deprecated by the <a href="https://github.com/algorandfoundation/ARCs/pull/258">`ARC-56`</a> specification.
An Application is partially defined by it's [methods](./arc-0004.md) but further information about the Application should be available. Other descriptive elements of an application may include it's State Schema, the original TEAL source programs, default method arguments, and custom data types. This specification defines the descriptive elements of an Application that should be available to clients to provide useful information for an Application Client.
## Motivation
As more complex Applications are created and deployed, some consistent way to specify the details of the application and how to interact with it becomes more important. A specification to allow a consistent and complete definition of an application will help developers attempting to integrate an application they've never worked with before.
## Specification
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in <a href="https://www.ietf.org/rfc/rfc822.txt">RFC 822</a>..
### Definitions
- [Application Specification](#application-specification): The object containing the elements describing the Application.
- [Source Specification](#source-specification): The object containing a description of the TEAL source programs that are evaluated when this Application is called.
- [Schema Specification](#schema-specification): The object containing a description of the schema required by the Application.
- [Bare Call Specification](#bare-call-specification): The object containing a map of on completion actions to allowable calls for bare methods
- [Hints Specification](#hints-specification): The object containing a map of method signatures to meta data about each method
### Application Specification
The Application Specification is composed of a number of elements that serve to fully describe the Application.
```ts
type AppSpec = {
// embedded contract fields, see ARC-0004 for more
contract: ARC4Contract;
// the original teal source, containing annotations, base64 encoded
source?: SourceSpec;
// the schema this application requires/provides
schema?: SchemaSpec;
// supplemental information for calling bare methods
bare_call_config?: CallConfigSpec;
// supplemental information for calling ARC-0004 ABI methods
hints: HintsSpec;
// storage requirements
state?: StateSpec;
}
```
### Source Specification
Contains the source TEAL files including comments and other annotations.
```ts
// Object containing the original TEAL source files
type SourceSpec = {
// b64 encoded approval program
approval: string;
// b64 encoded clear state program
clear: string;
}
```
### Schema Specification
The schema of an application is critical to know prior to creation since it is immutable after create. It also helps clients of the application understand the data that is available to be queried from off chain. Individual fields can be referenced from the [default argument](#default-argument) to provide input data to a given ABI method.
While some fields are possible to know ahead of time, others may be keyed dynamically. In both cases the data type being stored MUST be known and declared ahead of time.
```ts
// The complete schema for this application
type SchemaSpec = {
local: Schema;
global: Schema;
}
// Schema fields may be declared explicitly or reserved
type Schema = {
declared: Record<string, DeclaredSchemaValueSpec>;
reserved: Record<string, ReservedSchemaValueSpec>;
}
// Types supported for encoding/decoding
enum AVMType { uint64, bytes }
// string encoded datatype name defined in arc-4
type ABIType = string;
// Fields that have an explicit key
type DeclaredSchemaValueSpec = {
type: AVMType | ABIType;
key: string;
descr: string;
}
// Fields that have an undetermined key
type ReservedSchemaValueSpec = {
type: AVMType | ABIType;
descr: string;
max_keys: number;
}
```
### Bare call specification
Describes the supported OnComplete actions for bare calls on the contract.
```ts
// describes under what conditions an associated OnCompletion type can be used with a particular method
// NEVER: Never handle the specified on completion type
// CALL: Only handle the specified on completion type for application calls
// CREATE: Only handle the specified on completion type for application create calls
// ALL: Handle the specified on completion type for both create and normal application calls
type CallConfig = 'NEVER' | 'CALL' | 'CREATE' | 'ALL'
type CallConfigSpec = {
// lists the supported CallConfig for each on completion type, if not specified a CallConfig of NEVER is assumed
no_op?: CallConfig
opt_in?: CallConfig
close_out?: CallConfig
update_application?: CallConfig
delete_application?: CallConfig
}
```
### Hints specification
Contains supplemental information about [ARC-0004](./arc-0004.md) ABI methods, each record represents a single method in the [ARC-0004](./arc-0004.md) contract. The record key should be the corresponding ABI signature.
NOTE: Ideally this information would be part of the [ARC-0004](./arc-0004.md) ABI specification.
```ts
type HintSpec = {
// indicates the method has no side-effects and can be call via dry-run/simulate
read_only?: bool;
// describes the structure of arguments, key represents the argument name
structs?: Record<string, StructSpec>;
// describes source of default values for arguments, key represents the argument name
default_arguments?: Record<string, DefaultArgumentSpec>;
// describes which OnCompletion types are supported
call_config: CallConfigSpec;
}
// key represents the method signature for an ABI method defined in 'contracts'
type HintsSpec = Record<string, HintSpec>
```
#### Readonly Specification
Indicates the method has no side-effects and can be called via dry-run/simulate
NOTE: This property is made obsolete by [ARC-0022](./arc-0022.md) but is included as it is currently
used by existing reference implementations such as Beaker
#### Struct Specification
Each defined type is specified as an array of `StructElement`s.
The ABI encoding is exactly as if an ABI Tuple type defined the same element types in the same order.
It is important to encode the struct elements as an array since it preserves the order of fields which is critical to encoding/decoding the data properly.
```ts
// Type aliases for readability
type FieldName = string
// string encoded datatype name defined in ARC-0004
type ABIType = string
// Each field in the struct contains a name and ABI type
type StructElement = [FieldName, ABIType]
// Type aliases for readability
type ContractDefinedType = StructElement[]
type ContractDefinedTypeName = string;
// represents a input/output structure
type StructSpec = {
name: ContractDefinedTypeName
elements: ContractDefinedType
}
```
For example a `ContractDefinedType` that should provide an array of `StructElement`s
Given the PyTeal:
```py
from pyteal import abi
class Thing(abi.NamedTuple):
addr: abi.Field[abi.address]
balance: abi.Field[abi.Uint64]
```
the equivalent ABI type is `(address,uint64)` and an element in the TypeSpec is:
```js
{
// ...
"Thing":[["addr", "address"]["balance","uint64"]],
// ...
}
```
#### Default Argument
Defines how default argument values can be obtained. The `source` field defines how a default value is obtained, the `data` field
contains additional information based on the `source` value.
Valid values for `source` are:
* "constant" - `data` is the value to use
* "global-state" - `data` is the global state key.
* "local-state" - `data` is the local state key
* "abi-method" - `data` is a reference to the ABI method to call. Method should be read only and return a value of the appropriate type
Two scenarios where providing default arguments can be useful:
1. Providing a default value for optional arguments
2. Providing a value for required arguments such as foreign asset or application references without requiring the client to explicitly determine these values when calling the contract
```ts
// ARC-0004 ABI method definition
type ABIMethod = {};
type DefaultArgumentSpec = {
// Where to look for the default arg value
source: "constant" | "global-state" | "local-state" | "abi-method"
// extra data to include when looking up the value
data: string | bigint | number | ABIMethod
}
```
### State Specifications
Describes the total storage requirements for both global and local storage, this should include both declared and reserved described in SchemaSpec.
NOTE: If the Schema specification contained additional information such that the size could be calculated, then this specification would not be required.
```ts
type StateSchema = {
// how many byte slices are required
num_byte_slices: number
// how many uints are required
num_uints: number
}
type StateSpec = {
// schema specification for global storage
global: StateSchema
// schema specification for local storage
local: StateSchema
}
```
### Reference schema
A full JSON schema for application.json can be found in [here](../assets/arc-0032/application.schema.json).
## Rationale
The rationale fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work, e.g. how the feature is supported in other languages.
## Backwards Compatibility
All ARCs that introduce backwards incompatibilities must include a section describing these incompatibilities and their severity. The ARC must explain how the author proposes to deal with these incompatibilities. ARC submissions without a sufficient backwards compatibility treatise may be rejected outright.
## Test Cases
Test cases for an implementation are mandatory for ARCs that are affecting consensus changes. If the test suite is too large to reasonably be included inline, then consider adding it as one or more files in `../assets/arc-####/`.
## Reference Implementation
`algokit-utils-py` and `algokit-utils-ts` both provide reference implementations for the specification structure and using the data in an `ApplicationClient`
`Beaker` provides a reference implementation for creating an application.json from a smart contract.
## Security Considerations
All ARCs must contain a section that discusses the security implications/considerations relevant to the proposed change. Include information that might be important for security discussions, surfaces risks and can be used throughout the life cycle of the proposal. E.g. include security-relevant design decisions, concerns, important discussions, implementation-specific guidance and pitfalls, an outline of threats and risks and how they are being addressed. ARC submissions missing the "Security Considerations" section will be rejected. An ARC cannot proceed to status "Final" without a Security Considerations discussion deemed sufficient by the reviewers.
## Copyright
Copyright and related rights waived via <a href="https://creativecommons.org/publicdomain/zero/1.0/">CCO</a>.
```
--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/developer:docs:details:dapps:smart-contracts:apps:txs.md:
--------------------------------------------------------------------------------
```markdown
title: Evaluating transactions
# Checking the transaction type in a smart contract
The `ApplicationCall` transaction types defined in [The Lifecycle of a Smart Contract](#the-lifecycle-of-a-smart-contract) can be checked within the TEAL code by examining the `OnCompletion` transaction property.
=== "PyTeal"
<!-- ===PYTEAL_TXN_ONCOMPLETE=== -->
```python
program = OnComplete.NoOp == Txn.on_completion()
print(compileTeal(program, Mode.Application))
```
[Snippet Source](https://github.com/barnjamin/pyteal/blob/examples-for-docs/_examples/txn.py#L20-L22)
<!-- ===PYTEAL_TXN_ONCOMPLETE=== -->
=== "TEAL"
<!-- ===TEAL_TXN_ONCOMPLETE=== -->
```teal
txn OnCompletion
int NoOp // OptIn, CloseOut, UpdateApplication, or DeleteApplication
==
```
[Snippet Source](https://github.com/nullun/algorand-teal-examples/blob/main/_examples/oncomplete/approval.teal#L3-L6)
<!-- ===TEAL_TXN_ONCOMPLETE=== -->
# Global values in smart contracts
Smart contracts have access to many global variables. These variables are set for the blockchain, like the minimum transaction fee (MinTxnFee). As another example of Global variable use, in the [Atomic Transfers and Transaction Properties](#atomic-transfers-and-transaction-properties) section of this guide, `GroupSize` is used to show how to get the number of transactions that are grouped within a smart contract call. Smart contracts also have access to the `LatestTimestamp` global which represents the latest confirmed block's Unix timestamp. This is not the current time, but the time when the last block was confirmed. This can be used to set times on when the contract is allowed to do certain things. For example, a contract may only allow accounts to opt in after a start date, which is set when the contract is created and stored in global storage.
=== "PyTeal"
<!-- ===PYTEAL_GLOBAL_LATEST_TIMESTAMP=== -->
```python
program = Global.latest_timestamp() >= App.globalGet(Bytes("StartDate"))
print(compileTeal(program, Mode.Application))
```
[Snippet Source](https://github.com/barnjamin/pyteal/blob/examples-for-docs/_examples/application.py#L25-L27)
<!-- ===PYTEAL_GLOBAL_LATEST_TIMESTAMP=== -->
=== "TEAL"
<!-- ===TEAL_GLOBAL_LATEST_TIMESTAMP=== -->
```teal
global LatestTimestamp
byte "StateDate"
app_global_get
>=
```
[Snippet Source](https://github.com/nullun/algorand-teal-examples/blob/main/_examples/misc/global.teal#L3-L7)
<!-- ===TEAL_GLOBAL_LATEST_TIMESTAMP=== -->
# Atomic transfers and transaction properties
The [TEAL opcodes](../../avm/teal/opcodes) documentation describes all transaction properties that are available within a TEAL program. These properties can be retrieved using the following contract code.
=== "PyTeal"
<!-- ===PYTEAL_TXN_AMOUNT=== -->
```python
program = Txn.amount()
print(compileTeal(program, Mode.Application))
```
[Snippet Source](https://github.com/barnjamin/pyteal/blob/examples-for-docs/_examples/txn.py#L48-L50)
<!-- ===PYTEAL_TXN_AMOUNT=== -->
=== "TEAL"
<!-- ===TEAL_TXN_AMOUNT=== -->
```teal
txn Amount
```
[Snippet Source](https://github.com/nullun/algorand-teal-examples/blob/main/_examples/misc/global.teal#L13-L14)
<!-- ===TEAL_TXN_AMOUNT=== -->
In many common patterns, the smart contract will be combined with other Algorand technologies such as assets, atomic transfers, or smart signatures to build a complete application. In the case of atomic transfers, more than one transaction’s properties can be checked within the smart contract. The number of transactions can be checked using the `GroupSize` global property. If the value is greater than 1, then the call to the smart contract is grouped with more than one transaction.
=== "PyTeal"
<!-- ===PYTEAL_TXN_GROUP_SIZE=== -->
```python
program = Global.group_size() == Int(2)
print(compileTeal(program, Mode.Application))
```
[Snippet Source](https://github.com/barnjamin/pyteal/blob/examples-for-docs/_examples/txn.py#L55-L57)
<!-- ===PYTEAL_TXN_GROUP_SIZE=== -->
=== "TEAL"
<!-- ===TEAL_TXN_GROUP_SIZE=== -->
```teal
global GroupSize
int 2
==
```
[Snippet Source](https://github.com/nullun/algorand-teal-examples/blob/main/_examples/misc/global.teal#L18-L21)
<!-- ===TEAL_TXN_GROUP_SIZE=== -->
The above contract code will be true if there are two transactions submitted at once using an atomic transfer. To access the properties of a specific transaction in the atomic group use the `gtxn` opcode.
=== "PyTeal"
<!-- ===PYTEAL_GTXN_TYPE_ENUM=== -->
```python
program = Gtxn[1].type_enum() == TxnType.Payment
print(compileTeal(program, Mode.Application))
```
[Snippet Source](https://github.com/barnjamin/pyteal/blob/examples-for-docs/_examples/txn.py#L62-L64)
<!-- ===PYTEAL_GTXN_TYPE_ENUM=== -->
=== "TEAL"
<!-- ===TEAL_GTXN_TYPE_ENUM=== -->
```teal
gtxn 1 TypeEnum
int pay
==
```
[Snippet Source](https://github.com/nullun/algorand-teal-examples/blob/main/_examples/misc/global.teal#L25-L28)
<!-- ===TEAL_GTXN_TYPE_ENUM=== -->
In the above example, the second transaction’s type is checked, where the `int pay` references a payment transaction. See the [opcodes](../../avm/teal/opcodes) documentation for all transaction types. Note that the `gtxn` call is a zero-based index into the atomic group of transactions. The `gtxns` opcode could also have been used to retrieve the index into the atomic group from the top of the stack instead of hard coding the index. If the TEAL program fails, all transactions in the group will fail.
If any transaction in a group of transactions is a call to a smart contract, the opcodes `gtxna` and `gtxnsa` can be used to access any of the transactions array values.
=== "PyTeal"
<!-- ===PYTEAL_GTXN_APP_ARGS=== -->
```python
program = Gtxn[Txn.group_index() - Int(1)].application_args[0]
print(compileTeal(program, Mode.Application))
```
[Snippet Source](https://github.com/barnjamin/pyteal/blob/examples-for-docs/_examples/txn.py#L69-L71)
<!-- ===PYTEAL_GTXN_APP_ARGS=== -->
=== "TEAL"
<!-- ===TEAL_GTXN_APP_ARGS=== -->
```teal
txn GroupIndex
int 1
-
gtxnsa ApplicationArgs 0
```
[Snippet Source](https://github.com/nullun/algorand-teal-examples/blob/main/_examples/misc/global.teal#L32-L36)
<!-- ===TEAL_GTXN_APP_ARGS=== -->
# Using assets in smart contracts
Smart contract applications can work in conjunction with assets. In addition to normal asset transaction properties, such as asset amount, sender, and receiver, TEAL provides an opcode to interrogate an account’s asset balance and whether the asset is frozen. This opcode `asset_holding_get` can be used to retrieve an asset balance or check whether the asset is frozen for any account in the transaction accounts array. The asset must also be in the assets array. See [Reference arrays](index.md#reference-arrays) for more details.
=== "PyTeal"
```python
asset_balance = AssetHolding.balance(Txn.sender(), Int(123456))
program = Seq(
asset_balance, If(asset_balance.hasValue(), Return(Int(1)), Return(Int(0)))
)
print(compileTeal(program, Mode.Application))
```
=== "TEAL"
```teal
txn Sender
int 123456
asset_holding_get AssetBalance
bnz has_balance
// Reject transaction if no asset balance
int 0
return
has_balance:
//balance value is now on top of the stack
```
This opcode takes two parameters. The first parameter represents the account to check. The second parameter is the Asset ID of the asset to examine. The asset must be in the assets array and the account in the accounts array for the call to be successful. See [Reference arrays](index.md#reference-arrays) for more details.
This opcode supports getting the asset balance and the frozen state of the asset for the specific account. To get the frozen state, replace `AssetBalance` above with `AssetFrozen`. This opcode also returns two values to the top of the stack. The first is a 0 or 1, where 0 means the asset balance was not found and 1 means an asset balance was found in the accounts balance record.
It is also possible to get an Asset’s configuration information within a smart contract if the asset ID is passed with the transaction in the assets array. To read the configuration, the `asset_params_get` opcode must be used. This opcode should be supplied with one parameter, which is the index into the assets array or the actual asset ID.
=== "PyTEAL"
```python
program = AssetParam.total(Int(123456))
print(compileTeal(program, Mode.Application))
```
=== "TEAL"
<!-- ===TEAL_APPL_ASSET_PARAM=== -->
```teal
int 123456
asset_params_get AssetTotal
```
This call returns two values. The first is a 0 or 1 indicating if the parameter was found and the second contains the value of the parameter. See the [opcodes](../../avm/teal/opcodes) documentation for more details on what additional parameters can be read.
# Creating an asset or contract within a group of transactions
The Algorand Protocol assigns an identifier (ID) when creating an asset (ASA) or a smart contract. These IDs are used to refer to the asset or the contract later when either is used in a transaction or a call to the smart contract. Because these IDs are assigned when the asset or the contract is created, the ID is not available until after the creation transaction is fully executed. In an atomic group, TEAL can retrieve the ID of a previous group transaction which created an asset or contract, enabling a smart contract to store the asset ID or another smart contract ID in its state for later usage.
The ID retrieval operation can be performed by using one of two opcodes (`gaid` and `gaids`). With the `gaid` opcode, the specific transaction to read must be passed to the command. The `gaids` opcode will use the last value on the stack as the transaction index.
=== "TEAL"
<!-- ===TEAL_APPL_CREATED_ASSET_ID=== -->
```teal
// Get the created id of the asset created in the first tx
gaid 0
// Get the created id of the asset created in the second tx
int 1
gaids
```
[Snippet Source](https://github.com/nullun/algorand-teal-examples/blob/main/_examples/appl_asset/approval.teal#L25-L30)
<!-- ===TEAL_APPL_CREATED_ASSET_ID=== -->
# Sharing data between contracts
In addition to reading another contract's state, data can be passed between contracts. Algorand’s AVM gives smart contracts access to scratch space that can be used to temporarily store values, while the contract is executing. TEAL allows other contracts to read this scratch space. Scratch space can only be read by other transactions that the specific transaction is grouped with atomically. Grouped transactions execute in the order they are grouped, contracts can not read scratch space for transactions that occur after the current contract transaction.
This operation can be performed by using one of two opcodes (`gload` and `gloads`). With the `gload` opcode, the specific transaction to read and the slot number must be passed to the command. The `gloads` opcode will use the last value on the stack as the transaction index and must be passed the slot number to read.
For example, with two grouped smart contracts the following code can be used.
Store an integer in scratch space in the first transaction.
=== "TEAL"
<!-- ===TEAL_APPL_GLOAD_T1=== -->
```teal
int 777
store 10
```
[Snippet Source](https://github.com/nullun/algorand-teal-examples/blob/main/_examples/misc/scratch_t1.teal#L3-L5)
<!-- ===TEAL_APPL_GLOAD_T1=== -->
In the second transaction read the stored value.
=== "TEAL"
<!-- ===TEAL_APPL_GLOAD_T2=== -->
```teal
// read the first
// transaction's 10th
// slot of scratch space
gload 0 10
```
[Snippet Source](https://github.com/nullun/algorand-teal-examples/blob/main/_examples/misc/scratch_t2.teal#L3-L7)
<!-- ===TEAL_APPL_GLOAD_T2=== -->
```
--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/SDKs:javascript:classes:AtomicTransactionComposer.md:
--------------------------------------------------------------------------------
```markdown
[algosdk](../README.md) / [Exports](../modules.md) / AtomicTransactionComposer
# Class: AtomicTransactionComposer
A class used to construct and execute atomic transaction groups
## Table of contents
### Constructors
- [constructor](AtomicTransactionComposer.md#constructor)
### Properties
- [methodCalls](AtomicTransactionComposer.md#methodcalls)
- [signedTxns](AtomicTransactionComposer.md#signedtxns)
- [status](AtomicTransactionComposer.md#status)
- [transactions](AtomicTransactionComposer.md#transactions)
- [txIDs](AtomicTransactionComposer.md#txids)
- [MAX\_GROUP\_SIZE](AtomicTransactionComposer.md#max_group_size)
### Methods
- [addMethodCall](AtomicTransactionComposer.md#addmethodcall)
- [addTransaction](AtomicTransactionComposer.md#addtransaction)
- [buildGroup](AtomicTransactionComposer.md#buildgroup)
- [clone](AtomicTransactionComposer.md#clone)
- [count](AtomicTransactionComposer.md#count)
- [execute](AtomicTransactionComposer.md#execute)
- [gatherSignatures](AtomicTransactionComposer.md#gathersignatures)
- [getStatus](AtomicTransactionComposer.md#getstatus)
- [simulate](AtomicTransactionComposer.md#simulate)
- [submit](AtomicTransactionComposer.md#submit)
- [parseMethodResponse](AtomicTransactionComposer.md#parsemethodresponse)
## Constructors
### constructor
• **new AtomicTransactionComposer**()
## Properties
### methodCalls
• `Private` **methodCalls**: `Map`\<`number`, [`ABIMethod`](ABIMethod.md)\>
#### Defined in
composer.ts:127
___
### signedTxns
• `Private` **signedTxns**: `Uint8Array`[] = `[]`
#### Defined in
composer.ts:128
___
### status
• `Private` **status**: [`AtomicTransactionComposerStatus`](../enums/AtomicTransactionComposerStatus.md) = `AtomicTransactionComposerStatus.BUILDING`
#### Defined in
composer.ts:125
___
### transactions
• `Private` **transactions**: [`TransactionWithSigner`](../interfaces/TransactionWithSigner.md)[] = `[]`
#### Defined in
composer.ts:126
___
### txIDs
• `Private` **txIDs**: `string`[] = `[]`
#### Defined in
composer.ts:129
___
### MAX\_GROUP\_SIZE
▪ `Static` **MAX\_GROUP\_SIZE**: `number` = `16`
The maximum size of an atomic transaction group.
#### Defined in
composer.ts:123
## Methods
### addMethodCall
▸ **addMethodCall**(`«destructured»`): `void`
Add a smart contract method call to this atomic group.
An error will be thrown if the composer's status is not BUILDING, if adding this transaction
causes the current group to exceed MAX_GROUP_SIZE, or if the provided arguments are invalid
for the given method.
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `«destructured»` | `Object` | - |
| › `appAccounts?` | `string`[] | Array of Address strings that represent external accounts supplied to this application. If accounts are provided here, the accounts specified in the method args will appear after these. |
| › `appForeignApps?` | `number`[] | Array of App ID numbers that represent external apps supplied to this application. If apps are provided here, the apps specified in the method args will appear after these. |
| › `appForeignAssets?` | `number`[] | Array of Asset ID numbers that represent external assets supplied to this application. If assets are provided here, the assets specified in the method args will appear after these. |
| › `appID` | `number` | The ID of the smart contract to call. Set this to 0 to indicate an application creation call. |
| › `approvalProgram?` | `Uint8Array` | The approval program for this application call. Only set this if this is an application creation call, or if onComplete is OnApplicationComplete.UpdateApplicationOC |
| › `boxes?` | [`BoxReference`](../interfaces/BoxReference.md)[] | The box references for this application call |
| › `clearProgram?` | `Uint8Array` | The clear program for this application call. Only set this if this is an application creation call, or if onComplete is OnApplicationComplete.UpdateApplicationOC |
| › `extraPages?` | `number` | The number of extra pages to allocate for the application's programs. Only set this if this is an application creation call. If omitted, defaults to 0. |
| › `lease?` | `Uint8Array` | The lease value for this application call |
| › `method` | [`ABIMethod`](ABIMethod.md) | The method to call on the smart contract |
| › `methodArgs?` | [`ABIArgument`](../modules.md#abiargument)[] | The arguments to include in the method call. If omitted, no arguments will be passed to the method. |
| › `note?` | `Uint8Array` | The note value for this application call |
| › `numGlobalByteSlices?` | `number` | The global byte slice schema size. Only set this if this is an application creation call. |
| › `numGlobalInts?` | `number` | The global integer schema size. Only set this if this is an application creation call. |
| › `numLocalByteSlices?` | `number` | The local byte slice schema size. Only set this if this is an application creation call. |
| › `numLocalInts?` | `number` | The local integer schema size. Only set this if this is an application creation call. |
| › `onComplete?` | [`OnApplicationComplete`](../enums/OnApplicationComplete.md) | The OnComplete action to take for this application call. If omitted, OnApplicationComplete.NoOpOC will be used. |
| › `rekeyTo?` | `string` | If provided, the address that the sender will be rekeyed to at the conclusion of this application call |
| › `sender` | `string` | The address of the sender of this application call |
| › `signer` | [`TransactionSigner`](../modules.md#transactionsigner) | A transaction signer that can authorize this application call from sender |
| › `suggestedParams` | [`SuggestedParams`](../interfaces/SuggestedParams.md) | Transactions params to use for this application call |
#### Returns
`void`
#### Defined in
composer.ts:199
___
### addTransaction
▸ **addTransaction**(`txnAndSigner`): `void`
Add a transaction to this atomic group.
An error will be thrown if the transaction has a nonzero group ID, the composer's status is
not BUILDING, or if adding this transaction causes the current group to exceed MAX_GROUP_SIZE.
#### Parameters
| Name | Type |
| :------ | :------ |
| `txnAndSigner` | [`TransactionWithSigner`](../interfaces/TransactionWithSigner.md) |
#### Returns
`void`
#### Defined in
composer.ts:172
___
### buildGroup
▸ **buildGroup**(): [`TransactionWithSigner`](../interfaces/TransactionWithSigner.md)[]
Finalize the transaction group and returned the finalized transactions.
The composer's status will be at least BUILT after executing this method.
#### Returns
[`TransactionWithSigner`](../interfaces/TransactionWithSigner.md)[]
#### Defined in
composer.ts:493
___
### clone
▸ **clone**(): [`AtomicTransactionComposer`](AtomicTransactionComposer.md)
Create a new composer with the same underlying transactions. The new composer's status will be
BUILDING, so additional transactions may be added to it.
#### Returns
[`AtomicTransactionComposer`](AtomicTransactionComposer.md)
#### Defined in
composer.ts:149
___
### count
▸ **count**(): `number`
Get the number of transactions currently in this atomic group.
#### Returns
`number`
#### Defined in
composer.ts:141
___
### execute
▸ **execute**(`client`, `waitRounds`): `Promise`\<\{ `confirmedRound`: `number` ; `methodResults`: [`ABIResult`](../interfaces/ABIResult.md)[] ; `txIDs`: `string`[] }\>
Send the transaction group to the network and wait until it's committed to a block. An error
will be thrown if submission or execution fails.
The composer's status must be SUBMITTED or lower before calling this method, since execution is
only allowed once. If submission is successful, this composer's status will update to SUBMITTED.
If the execution is also successful, this composer's status will update to COMMITTED.
Note: a group can only be submitted again if it fails.
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `client` | [`Algodv2`](Algodv2.md) | An Algodv2 client |
| `waitRounds` | `number` | The maximum number of rounds to wait for transaction confirmation |
#### Returns
`Promise`\<\{ `confirmedRound`: `number` ; `methodResults`: [`ABIResult`](../interfaces/ABIResult.md)[] ; `txIDs`: `string`[] }\>
A promise that, upon success, resolves to an object containing the confirmed round for
this transaction, the txIDs of the submitted transactions, and an array of results containing
one element for each method call transaction in this group.
#### Defined in
composer.ts:699
___
### gatherSignatures
▸ **gatherSignatures**(): `Promise`\<`Uint8Array`[]\>
Obtain signatures for each transaction in this group. If signatures have already been obtained,
this method will return cached versions of the signatures.
The composer's status will be at least SIGNED after executing this method.
An error will be thrown if signing any of the transactions fails.
#### Returns
`Promise`\<`Uint8Array`[]\>
A promise that resolves to an array of signed transactions.
#### Defined in
composer.ts:518
___
### getStatus
▸ **getStatus**(): [`AtomicTransactionComposerStatus`](../enums/AtomicTransactionComposerStatus.md)
Get the status of this composer's transaction group.
#### Returns
[`AtomicTransactionComposerStatus`](../enums/AtomicTransactionComposerStatus.md)
#### Defined in
composer.ts:134
___
### simulate
▸ **simulate**(`client`, `request?`): `Promise`\<\{ `methodResults`: [`ABIResult`](../interfaces/ABIResult.md)[] ; `simulateResponse`: [`SimulateResponse`](modelsv2.SimulateResponse.md) }\>
Simulates the transaction group in the network.
The composer will try to sign any transactions in the group, then simulate
the results.
Simulating the group will not change the composer's status.
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `client` | [`Algodv2`](Algodv2.md) | An Algodv2 client |
| `request?` | [`SimulateRequest`](modelsv2.SimulateRequest.md) | SimulateRequest with options in simulation. If provided, the request's transaction group will be overrwritten by the composer's group, only simulation related options will be used. |
#### Returns
`Promise`\<\{ `methodResults`: [`ABIResult`](../interfaces/ABIResult.md)[] ; `simulateResponse`: [`SimulateResponse`](modelsv2.SimulateResponse.md) }\>
A promise that, upon success, resolves to an object containing an
array of results containing one element for each method call transaction
in this group (ABIResult[]) and the SimulateResponse object.
#### Defined in
composer.ts:626
___
### submit
▸ **submit**(`client`): `Promise`\<`string`[]\>
Send the transaction group to the network, but don't wait for it to be committed to a block. An
error will be thrown if submission fails.
The composer's status must be SUBMITTED or lower before calling this method. If submission is
successful, this composer's status will update to SUBMITTED.
Note: a group can only be submitted again if it fails.
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `client` | [`Algodv2`](Algodv2.md) | An Algodv2 client |
#### Returns
`Promise`\<`string`[]\>
A promise that, upon success, resolves to a list of TxIDs of the submitted transactions.
#### Defined in
composer.ts:596
___
### parseMethodResponse
▸ `Static` **parseMethodResponse**(`method`, `methodResult`, `pendingInfo`): [`ABIResult`](../interfaces/ABIResult.md)
Parses a single ABI Method transaction log into a ABI result object.
#### Parameters
| Name | Type |
| :------ | :------ |
| `method` | [`ABIMethod`](ABIMethod.md) |
| `methodResult` | [`ABIResult`](../interfaces/ABIResult.md) |
| `pendingInfo` | `Record`\<`string`, `any`\> |
#### Returns
[`ABIResult`](../interfaces/ABIResult.md)
An ABIResult object
#### Defined in
composer.ts:775
```
--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/puya:docs:lg-types.md:
--------------------------------------------------------------------------------
```markdown
# Types
Algorand Python exposes a number of types that provide a statically typed representation of the behaviour that is possible on the Algorand Virtual Machine.
```{contents} Types
:local:
:depth: 3
:class: this-will-duplicate-information-and-it-is-still-useful-here
```
## AVM types
The most basic [types on the AVM](https://developer.algorand.org/docs/get-details/dapps/avm/teal/specification/#stack-types)
are `uint64` and `bytes[]`, representing unsigned 64-bit integers and byte arrays respectively.
These are represented by [`UInt64`](./#uint64) and [`Bytes`](./#bytes) in Algorand Python.
There are further "bounded" types supported by the AVM, which are backed by these two simple primitives.
For example, `bigint` represents a variably sized (up to 512-bits), unsigned integer, but is actually
backed by a `bytes[]`. This is represented by [`BigUInt`](./#biguint) in Algorand Python.
### UInt64
[`algopy.UInt64`](#algopy.UInt64) represents the underlying AVM `uint64` type.
It supports all the same operators as `int`, except for `/`, you must use `//` for truncating
division instead.
```python
# you can instantiate with an integer literal
num = algopy.UInt64(1)
# no arguments default to the zero value
zero = algopy.UInt64()
# zero is False, any other value is True
assert not zero
assert num
# Like Python's `int`, `UInt64` is immutable, so augmented assignment operators return new values
one = num
num += 1
assert one == 1
assert num == 2
# note that once you have a variable of type UInt64, you don't need to type any variables
# derived from that or wrap int literals
num2 = num + 200 // 3
```
[Further examples available here](https://github.com/algorandfoundation/puya/blob/main/test_cases/stubs/uint64.py).
### Bytes
[`algopy.Bytes`](#algopy.Bytes) represents the underlying AVM `bytes[]` type. It is intended
to represent binary data, for UTF-8 it might be preferable to use [String](#string).
```python
# you can instantiate with a bytes literal
data = algopy.Bytes(b"abc")
# no arguments defaults to an empty value
empty = algopy.Bytes()
# empty is False, non-empty is True
assert data
assert not empty
# Like Python's `bytes`, `Bytes` is immutable, augmented assignment operators return new values
abc = data
data += b"def"
assert abc == b"abc"
assert data == b"abcdef"
# indexing and slicing are supported, and both return a Bytes
assert abc[0] == b"a"
assert data[:3] == abc
# check if a bytes sequence occurs within another
assert abc in data
```
```{hint}
Indexing a `Bytes` returning a `Bytes` differs from the behaviour of Python's bytes type, which
returns an `int`.
```
```python
# you can iterate
for i in abc:
...
# construct from encoded values
base32_seq = algopy.Bytes.from_base32('74======')
base64_seq = algopy.Bytes.from_base64('RkY=')
hex_seq = algopy.Bytes.from_hex('FF')
# binary manipulations ^, &, |, and ~ are supported
data ^= ~((base32_seq & base64_seq) | hex_seq)
# access the length via the .length property
assert abc.length == 3
```
```{note}
See [Python builtins](lg-builtins.md#len---length) for an explanation of why `len()` isn't supported.
```
[See a full example](https://github.com/algorandfoundation/puya/blob/main/test_cases/stubs/bytes.py).
### String
[`String`](#algopy.String) is a special Algorand Python type that represents a UTF8 encoded string.
It's backed by `Bytes`, which can be accessed through the `.bytes`.
It works similarly to `Bytes`, except that it works with `str` literals rather than `bytes`
literals. Additionally, due to a lack of AVM support for unicode data, indexing and length
operations are not currently supported (simply getting the length of a UTF8 string is an `O(N)`
operation, which would be quite costly in a smart contract). If you are happy using the length as
the number of bytes, then you can call `.bytes.length`.
```python
# you can instantiate with a string literal
data = algopy.String("abc")
# no arguments defaults to an empty value
empty = algopy.String()
# empty is False, non-empty is True
assert data
assert not empty
# Like Python's `str`, `String` is immutable, augmented assignment operators return new values
abc = data
data += "def"
assert abc == "abc"
assert data == "abcdef"
# whilst indexing and slicing are not supported, the following tests are:
assert abc.startswith("ab")
assert abc.endswith("bc")
assert abc in data
# you can also join multiple Strings together with a seperator:
assert algopy.String(", ").join((abc, abc)) == "abc, abc"
# access the underlying bytes
assert abc.bytes == b"abc"
```
[See a full example](https://github.com/algorandfoundation/puya/blob/main/test_cases/stubs/string.py).
### BigUInt
[`algopy.BigUInt`](#algopy.BigUInt) represents a variable length (max 512-bit) unsigned integer stored
as `bytes[]` in the AVM.
It supports all the same operators as `int`, except for power (`**`), left and right shift (`<<`
and `>>`) and `/` (as with `UInt64`, you must use `//` for truncating division instead).
Note that the op code costs for `bigint` math are an order of magnitude higher than those for
`uint64` math. If you just need to handle overflow, take a look at the wide ops such as `addw`,
`mulw`, etc - all of which are exposed through the [`algopy.op`](#algopy.op) module.
Another contrast between `bigint` and `uint64` math is that `bigint` math ops don't immediately
error on overflow - if the result exceeds 512-bits, then you can still access the value via
`.bytes`, but any further math operations will fail.
```python
# you can instantiate with an integer literal
num = algopy.BigUInt(1)
# no arguments default to the zero value
zero = algopy.BigUInt()
# zero is False, any other value is True
assert not zero
assert num
# Like Python's `int`, `BigUInt` is immutable, so augmented assignment operators return new values
one = num
num += 1
assert one == 1
assert num == UInt64(2)
# note that once you have a variable of type BigUInt, you don't need to type any variables
# derived from that or wrap int literals
num2 = num + 200 // 3
```
[Further examples available here](https://github.com/algorandfoundation/puya/blob/main/test_cases/stubs/biguint.py).
### bool
The semantics of the AVM `bool` bounded type exactly match the semantics of Python's built-in `bool` type
and thus Algorand Python uses the in-built `bool` type from Python.
Per the behaviour in normal Python, Algorand Python automatically converts various types to `bool` when they
appear in statements that expect a `bool` e.g. `if`/`while`/`assert` statements, appear in Boolean expressions
(e.g. next to `and` or `or` keywords) or are explicitly casted to a bool.
The semantics of `not`, `and` and `or` are special [per how these keywords work in Python](https://docs.python.org/3/reference/expressions.html#boolean-operations)
(e.g. short circuiting).
```python
a = UInt64(1)
b = UInt64(2)
c = a or b
d = b and a
e = self.expensive_op(UInt64(0)) or self.side_effecting_op(UInt64(1))
f = self.expensive_op(UInt64(3)) or self.side_effecting_op(UInt64(42))
g = self.side_effecting_op(UInt64(0)) and self.expensive_op(UInt64(42))
h = self.side_effecting_op(UInt64(2)) and self.expensive_op(UInt64(3))
i = a if b < c else d + e
if a:
log("a is True")
```
[Further examples available here](https://github.com/algorandfoundation/puya/blob/main/test_cases/stubs/uint64.py).
### Account
[`Account`](#algopy.Account) represents a logical Account, backed by a `bytes[32]` representing the
bytes of the public key (without the checksum). It has various account related methods that can be called from the type.
Also see [`algopy.arc4.Address`](#algopy.arc4.Address) if needing to represent the address as a distinct type.
### Asset
[`Asset`](#algopy.Asset) represents a logical Asset, backed by a `uint64` ID.
It has various asset related methods that can be called from the type.
### Application
[`Application`](#algopy.Application) represents a logical Application, backed by a `uint64` ID.
It has various application related methods that can be called from the type.
## Python built-in types
Unfortunately, the [AVM types](#avm-types) don't map to standard Python primitives. For instance,
in Python, an `int` is unsigned, and effectively unbounded. A `bytes` similarly is limited only by
the memory available, whereas an AVM `bytes[]` has a maximum length of 4096. In order to both maintain
semantic compatibility and allow for a framework implementation in plain Python that will fail under the
same conditions as when deployed to the AVM, support for Python primitives is limited.
In saying that, there are many places where built-in Python types can be used and over time the places these types can be used are expected to increase.
### bool
[Per above](#bool) Algorand Python has full support for `bool`.
### tuple
Python tuples are supported as arguments to subroutines, local variables, return types.
### typing.NamedTuple
Python named tuples are also supported using [`typing.NamedTuple`](https://docs.python.org/3/library/typing.html#typing.NamedTuple).
```{note}
Default field values and subclassing a NamedTuple are not supported
```
```python
import typing
import algopy
class Pair(typing.NamedTuple):
foo: algopy.Bytes
bar: algopy.Bytes
```
### None
`None` is not supported as a value, but is supported as a type annotation to indicate a function or subroutine
returns no value.
### int, str, bytes, float
The `int`, `str` and `bytes` built-in types are currently only supported as [module-level constants](./lg-modules.md) or literals.
They can be passed as arguments to various Algorand Python methods that support them or
when interacting with certain [AVM types](#avm-types) e.g. adding a number to a `UInt64`.
`float` is not supported.
## Template variables
Template variables can be used to represent a placeholder for a deploy-time provided
value. This can be declared using the `TemplateVar[TYPE]` type where `TYPE` is the
Algorand Python type that it will be interpreted as.
```python
from algopy import BigUInt, Bytes, TemplateVar, UInt64, arc4
from algopy.arc4 import UInt512
class TemplateVariablesContract(arc4.ARC4Contract):
@arc4.abimethod()
def get_bytes(self) -> Bytes:
return TemplateVar[Bytes]("SOME_BYTES")
@arc4.abimethod()
def get_big_uint(self) -> UInt512:
x = TemplateVar[BigUInt]("SOME_BIG_UINT")
return UInt512(x)
@arc4.baremethod(allow_actions=["UpdateApplication"])
def on_update(self) -> None:
assert TemplateVar[bool]("UPDATABLE")
@arc4.baremethod(allow_actions=["DeleteApplication"])
def on_delete(self) -> None:
assert TemplateVar[UInt64]("DELETABLE")
```
The resulting TEAL code that PuyaPy emits has placeholders with `TMPL_{template variable name}`
that expects either an integer value or an encoded bytes value. This behaviour exactly
matches what
[AlgoKit Utils expects](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/docs/capabilities/app-deploy.md#compilation-and-template-substitution).
For more information look at the API reference for [`TemplateVar`](./api-algopy.md#algopy.TemplateVar).
## ARC-4 types
ARC-4 data types are a first class concept in Algorand Python. They can be passed into ARC-4
methods (which will translate to the relevant ARC-4 method signature), passed into subroutines, or
instantiated into local variables. A limited set of operations are exposed on some ARC-4 types, but
often it may make sense to convert the ARC-4 value to a native AVM type, in which case you can use
the `native` property to retrieve the value. Most of the ARC-4 types also allow for mutation e.g.
you can edit values in arrays by index.
Please see the [reference documentation](./api-algopy.arc4.md) for the different classes that can
be used to represent ARC-4 values or the [ARC-4 documentation](./lg-arc4.md) for more information
about ARC-4.
```