This is page 33 of 93. Use http://codebase.md/goplausible/algorand-mcp?lines=true&page={x} to view the full context.
# Directory Structure
```
├── .gitignore
├── CONTRIBUTING.md
├── LICENSE
├── llms-install.md
├── llms.txt
├── package.json
├── packages
│ ├── client
│ │ ├── .env.example
│ │ ├── package.json
│ │ ├── README.md
│ │ ├── src
│ │ │ ├── env.ts
│ │ │ ├── index.ts
│ │ │ └── LocalWallet.ts
│ │ └── tsconfig.json
│ └── server
│ ├── .env.example
│ ├── API specs
│ │ ├── algod_api.json
│ │ ├── indexer_api.json
│ │ ├── mcp.json
│ │ ├── nfd_api.json
│ │ ├── ultrade_api.json
│ │ ├── vestige_api.json
│ │ └── vestige_free_api.json
│ ├── Dockerfile
│ ├── jest.config.js
│ ├── package.json
│ ├── README.md
│ ├── smithery.yaml
│ ├── src
│ │ ├── algorand-client.ts
│ │ ├── env.ts
│ │ ├── index.ts
│ │ ├── resources
│ │ │ ├── index.ts
│ │ │ ├── knowledge
│ │ │ │ ├── ARCs.txt
│ │ │ │ ├── developers-algokit-architecture-decisions.txt
│ │ │ │ ├── developers-algokit-cli.txt
│ │ │ │ ├── developers-algokit-utils-python.txt
│ │ │ │ ├── developers-algokit-utils-typescript.txt
│ │ │ │ ├── developers-clis.txt
│ │ │ │ ├── developers-details.txt
│ │ │ │ ├── developers-liquid-auth.txt
│ │ │ │ ├── developers-nodes.txt
│ │ │ │ ├── developers-puya.txt
│ │ │ │ ├── developers-python.txt
│ │ │ │ ├── developers-sdks-js.txt
│ │ │ │ ├── developers-sdks-python.txt
│ │ │ │ ├── developers-tealscript.txt
│ │ │ │ ├── developers.txt
│ │ │ │ ├── index.ts
│ │ │ │ ├── taxonomy
│ │ │ │ │ ├── algokit-cli:README.md
│ │ │ │ │ ├── algokit:cli:algokit.md
│ │ │ │ │ ├── algokit:cli:architecture-decisions:2022-11-14_sandbox-approach.md
│ │ │ │ │ ├── algokit:cli:architecture-decisions:2022-11-22_beaker-testing-strategy.md
│ │ │ │ │ ├── algokit:cli:architecture-decisions:2023-01-11_beaker_productionisation_review.md
│ │ │ │ │ ├── algokit:cli:architecture-decisions:2023-01-11_brew_install.md
│ │ │ │ │ ├── algokit:cli:architecture-decisions:2023-01-12_smart-contract-deployment.md
│ │ │ │ │ ├── algokit:cli:architecture-decisions:2023-06-06_frontend-templates.md
│ │ │ │ │ ├── algokit:cli:architecture-decisions:2023-07-19_advanced_generate_command.md
│ │ │ │ │ ├── algokit:cli:architecture-decisions:2024-01-13_native_binaries.md
│ │ │ │ │ ├── algokit:cli:architecture-decisions:2024-01-23_init-wizard-v2.md
│ │ │ │ │ ├── algokit:cli:architecture-decisions:2024-01-31_binary_distribution.md
│ │ │ │ │ ├── algokit:cli:architecture-decisions:2024-03-06_local_dev_ui_packaging.md
│ │ │ │ │ ├── algokit:cli:articles:output_stability.md
│ │ │ │ │ ├── algokit:cli:cli:index.md
│ │ │ │ │ ├── algokit:cli:features:compile.md
│ │ │ │ │ ├── algokit:cli:features:completions.md
│ │ │ │ │ ├── algokit:cli:features:config.md
│ │ │ │ │ ├── algokit:cli:features:dispenser.md
│ │ │ │ │ ├── algokit:cli:features:doctor.md
│ │ │ │ │ ├── algokit:cli:features:explore.md
│ │ │ │ │ ├── algokit:cli:features:generate.md
│ │ │ │ │ ├── algokit:cli:features:goal.md
│ │ │ │ │ ├── algokit:cli:features:init.md
│ │ │ │ │ ├── algokit:cli:features:localnet.md
│ │ │ │ │ ├── algokit:cli:features:project:bootstrap.md
│ │ │ │ │ ├── algokit:cli:features:project:deploy.md
│ │ │ │ │ ├── algokit:cli:features:project:link.md
│ │ │ │ │ ├── algokit:cli:features:project:list.md
│ │ │ │ │ ├── algokit:cli:features:project:run.md
│ │ │ │ │ ├── algokit:cli:features:project.md
│ │ │ │ │ ├── algokit:cli:features:tasks:analyze.md
│ │ │ │ │ ├── algokit:cli:features:tasks:ipfs.md
│ │ │ │ │ ├── algokit:cli:features:tasks:mint.md
│ │ │ │ │ ├── algokit:cli:features:tasks:nfd.md
│ │ │ │ │ ├── algokit:cli:features:tasks:opt.md
│ │ │ │ │ ├── algokit:cli:features:tasks:send.md
│ │ │ │ │ ├── algokit:cli:features:tasks:sign.md
│ │ │ │ │ ├── algokit:cli:features:tasks:transfer.md
│ │ │ │ │ ├── algokit:cli:features:tasks:vanity_address.md
│ │ │ │ │ ├── algokit:cli:features:tasks:wallet.md
│ │ │ │ │ ├── algokit:cli:features:tasks.md
│ │ │ │ │ ├── algokit:cli:tutorials:algokit-template.md
│ │ │ │ │ ├── algokit:cli:tutorials:intro.md
│ │ │ │ │ ├── algokit:cli:tutorials:smart-contracts.md
│ │ │ │ │ ├── algokit:docs:testnet_api.md
│ │ │ │ │ ├── algokit:lora:README.md
│ │ │ │ │ ├── algokit:README.md
│ │ │ │ │ ├── algokit:utils:python:markdown:apidocs:algokit_utils:algokit_utils.md
│ │ │ │ │ ├── algokit:utils:python:markdown:capabilities:account.md
│ │ │ │ │ ├── algokit:utils:python:markdown:capabilities:app-client.md
│ │ │ │ │ ├── algokit:utils:python:markdown:capabilities:app-deploy.md
│ │ │ │ │ ├── algokit:utils:python:markdown:capabilities:client.md
│ │ │ │ │ ├── algokit:utils:python:markdown:capabilities:debugger.md
│ │ │ │ │ ├── algokit:utils:python:markdown:capabilities:dispenser-client.md
│ │ │ │ │ ├── algokit:utils:python:markdown:capabilities:transfer.md
│ │ │ │ │ ├── algokit:utils:python:markdown:index.md
│ │ │ │ │ ├── algokit:utils:python:README.md
│ │ │ │ │ ├── algokit:utils:python:source:capabilities:account.md
│ │ │ │ │ ├── algokit:utils:python:source:capabilities:app-client.md
│ │ │ │ │ ├── algokit:utils:python:source:capabilities:app-deploy.md
│ │ │ │ │ ├── algokit:utils:python:source:capabilities:client.md
│ │ │ │ │ ├── algokit:utils:python:source:capabilities:debugger.md
│ │ │ │ │ ├── algokit:utils:python:source:capabilities:dispenser-client.md
│ │ │ │ │ ├── algokit:utils:python:source:capabilities:transfer.md
│ │ │ │ │ ├── algokit:utils:python:source:index.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:account.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:algorand-client.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:amount.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:app-client.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:app-deploy.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:app.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:asset.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:client.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:debugging.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:dispenser-client.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:event-emitter.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:indexer.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:testing.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:transaction-composer.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:transaction.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:transfer.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:typed-app-clients.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:testing.TestLogger.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:testing.TransactionLogger.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_account_manager.AccountManager.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_account.MultisigAccount.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_account.SigningAccount.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_algo_http_client_with_retry.AlgoHttpClientWithRetry.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_algorand_client_transaction_creator.AlgorandClientTransactionCreator.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_algorand_client_transaction_sender.AlgorandClientTransactionSender.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_algorand_client.AlgorandClient.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_amount.AlgoAmount.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_app_arc56.Arc56Method.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_app_client.AppClient.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_app_client.ApplicationClient.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_app_deployer.AppDeployer.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_app_factory.AppFactory.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_app_manager.AppManager.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_asset_manager.AssetManager.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_async_event_emitter.AsyncEventEmitter.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_client_manager.ClientManager.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_composer.TransactionComposer.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_config.UpdatableConfig.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_dispenser_client.TestNetDispenserApiClient.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_kmd_account_manager.KmdAccountManager.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_logic_error.LogicError.md
│ │ │ │ │ ├── algokit:utils:typescript:code:enums:types_app.OnSchemaBreak.md
│ │ │ │ │ ├── algokit:utils:typescript:code:enums:types_app.OnUpdate.md
│ │ │ │ │ ├── algokit:utils:typescript:code:enums:types_indexer.AccountStatus.md
│ │ │ │ │ ├── algokit:utils:typescript:code:enums:types_indexer.ApplicationOnComplete.md
│ │ │ │ │ ├── algokit:utils:typescript:code:enums:types_indexer.SignatureType.md
│ │ │ │ │ ├── algokit:utils:typescript:code:enums:types_lifecycle_events.EventType.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_account_manager.EnsureFundedResult.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_account.AccountConfig.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_account.TransactionSignerAccount.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_algorand_client_interface.AlgorandClientInterface.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_arc56.Arc56Contract.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_arc56.Event.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_arc56.Method.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_arc56.ProgramSourceInfo.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_arc56.StorageKey.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_arc56.StorageMap.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_arc56.StructField.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_client.AppClientCallABIArgs.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_client.AppClientCallCoreParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_client.AppClientCompilationParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_client.AppClientCompilationResult.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_client.AppClientDeployCallInterfaceParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_client.AppClientDeployCoreParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_client.AppClientDeployParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_client.AppClientParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_client.AppSourceMaps.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_client.FundAppAccountParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_client.ResolveAppById.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_client.ResolveAppByIdBase.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_client.SourceMapExport.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_deployer.AppLookup.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_deployer.AppMetadata.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_factory.AppFactoryParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_manager.AppInformation.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_manager.BoxReference.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_manager.BoxValueRequestParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_manager.BoxValuesRequestParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_spec.AppSources.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_spec.AppSpec.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_spec.CallConfig.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_spec.DeclaredSchemaValueSpec.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_spec.Hint.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_spec.ReservedSchemaValueSpec.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_spec.Schema.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_spec.SchemaSpec.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_spec.StateSchemaSpec.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_spec.Struct.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.AppCallParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.AppCallTransactionResultOfType.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.AppCompilationResult.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.AppDeploymentParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.AppDeployMetadata.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.AppLookup.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.AppMetadata.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.AppReference.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.AppState.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.AppStorageSchema.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.BoxName.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.BoxReference.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.BoxValueRequestParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.BoxValuesRequestParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.CompiledTeal.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.CoreAppCallArgs.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.CreateAppParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.RawAppCallArgs.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.TealTemplateParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.UpdateAppParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_asset_manager.AssetInformation.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_asset_manager.BulkAssetOptInOutResult.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_asset.AssetBulkOptInOutParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_asset.AssetOptInParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_asset.AssetOptOutParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_asset.CreateAssetParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_client_manager.AlgoSdkClients.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_client_manager.TypedAppClient.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_client_manager.TypedAppFactory.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_composer.BuiltTransactions.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_config.Config.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_debugging.AVMTracesEventData.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_debugging.TealSourceDebugEventData.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_debugging.TealSourcesDebugEventData.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_dispenser_client.DispenserFundResponse.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_dispenser_client.DispenserLimitResponse.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_dispenser_client.TestNetDispenserApiClientParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_indexer.LookupAssetHoldingsOptions.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_logic_error.LogicErrorDetails.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_network_client.AlgoClientConfig.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_network_client.AlgoConfig.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_network_client.NetworkDetails.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_testing.AlgoKitLogCaptureFixture.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_testing.AlgorandFixture.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_testing.AlgorandFixtureConfig.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_testing.AlgorandTestAutomationContext.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_testing.GetTestAccountParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_testing.LogSnapshotConfig.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_transaction.AtomicTransactionComposerToSend.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_transaction.ConfirmedTransactionResult.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_transaction.ConfirmedTransactionResults.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_transaction.SendAtomicTransactionComposerResults.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_transaction.SendParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_transaction.SendTransactionParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_transaction.SendTransactionResult.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_transaction.SendTransactionResults.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_transaction.TransactionGroupToSend.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_transaction.TransactionToSign.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_transfer.AlgoRekeyParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_transfer.AlgoTransferParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_transfer.EnsureFundedParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_transfer.EnsureFundedReturnType.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_transfer.TransferAssetParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:index.indexer.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:index.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:testing.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_account_manager_spec.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_account_manager.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_account.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_algo_http_client_with_retry.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_algorand_client_asset_spec.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_algorand_client_interface.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_algorand_client_spec.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_algorand_client_transaction_creator.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_algorand_client_transaction_sender.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_algorand_client_transfer_spec.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_algorand_client.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_amount_spec.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_amount.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_app_arc56.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_app_client_spec.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_app_client.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_app_deployer.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_app_factory_and_client_spec.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_app_factory.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_app_manager.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_app_spec.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_app.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_asset_manager.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_asset.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_async_event_emitter_spec.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_async_event_emitter.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_client_manager_spec.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_client_manager.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_composer.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_config.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_debugging.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_dispenser_client_spec.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_dispenser_client.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_expand.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_indexer.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_kmd_account_manager.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_lifecycle_events.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_logging.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_logic_error.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_network_client.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_testing.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_transaction.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_transfer.md
│ │ │ │ │ ├── algokit:utils:typescript:code:README.md
│ │ │ │ │ ├── algokit:utils:typescript:README.md
│ │ │ │ │ ├── algokit:utils:typescript:v7-migration.md
│ │ │ │ │ ├── algokit:utils:typescript:v8-migration.md
│ │ │ │ │ ├── ARCs:ARC-template.md
│ │ │ │ │ ├── ARCs:assets:arc-0012:README.md
│ │ │ │ │ ├── ARCs:assets:arc-0034:TemplateForm.md
│ │ │ │ │ ├── ARCs:assets:arc-0062:README.md
│ │ │ │ │ ├── ARCs:pages:nfts.md
│ │ │ │ │ ├── ARCs:pages:wallets.md
│ │ │ │ │ ├── ARCs:README.md
│ │ │ │ │ ├── ARCs:specs:arc-0000.md
│ │ │ │ │ ├── ARCs:specs:arc-0001.md
│ │ │ │ │ ├── ARCs:specs:arc-0002.md
│ │ │ │ │ ├── ARCs:specs:arc-0003.md
│ │ │ │ │ ├── ARCs:specs:arc-0004.md
│ │ │ │ │ ├── ARCs:specs:arc-0005.md
│ │ │ │ │ ├── ARCs:specs:arc-0006.md
│ │ │ │ │ ├── ARCs:specs:arc-0007.md
│ │ │ │ │ ├── ARCs:specs:arc-0008.md
│ │ │ │ │ ├── ARCs:specs:arc-0009.md
│ │ │ │ │ ├── ARCs:specs:arc-0010.md
│ │ │ │ │ ├── ARCs:specs:arc-0011.md
│ │ │ │ │ ├── ARCs:specs:arc-0012.md
│ │ │ │ │ ├── ARCs:specs:arc-0015.md
│ │ │ │ │ ├── ARCs:specs:arc-0016.md
│ │ │ │ │ ├── ARCs:specs:arc-0018.md
│ │ │ │ │ ├── ARCs:specs:arc-0019.md
│ │ │ │ │ ├── ARCs:specs:arc-0020.md
│ │ │ │ │ ├── ARCs:specs:arc-0021.md
│ │ │ │ │ ├── ARCs:specs:arc-0022.md
│ │ │ │ │ ├── ARCs:specs:arc-0023.md
│ │ │ │ │ ├── ARCs:specs:arc-0025.md
│ │ │ │ │ ├── ARCs:specs:arc-0026.md
│ │ │ │ │ ├── ARCs:specs:arc-0028.md
│ │ │ │ │ ├── ARCs:specs:arc-0032.md
│ │ │ │ │ ├── ARCs:specs:arc-0033.md
│ │ │ │ │ ├── ARCs:specs:arc-0034.md
│ │ │ │ │ ├── ARCs:specs:arc-0035.md
│ │ │ │ │ ├── ARCs:specs:arc-0036.md
│ │ │ │ │ ├── ARCs:specs:arc-0042.md
│ │ │ │ │ ├── ARCs:specs:arc-0047.md
│ │ │ │ │ ├── ARCs:specs:arc-0048.md
│ │ │ │ │ ├── ARCs:specs:arc-0049.md
│ │ │ │ │ ├── ARCs:specs:arc-0054.md
│ │ │ │ │ ├── ARCs:specs:arc-0055.md
│ │ │ │ │ ├── ARCs:specs:arc-0056.md
│ │ │ │ │ ├── ARCs:specs:arc-0059.md
│ │ │ │ │ ├── ARCs:specs:arc-0062.md
│ │ │ │ │ ├── ARCs:specs:arc-0065.md
│ │ │ │ │ ├── ARCs:specs:arc-0069.md
│ │ │ │ │ ├── ARCs:specs:arc-0072.md
│ │ │ │ │ ├── ARCs:specs:arc-0073.md
│ │ │ │ │ ├── ARCs:specs:arc-0074.md
│ │ │ │ │ ├── ARCs:specs:arc-0076.md
│ │ │ │ │ ├── ARCs:specs:arc-0078.md
│ │ │ │ │ ├── ARCs:specs:arc-0079.md
│ │ │ │ │ ├── ARCs:specs:arc-0200.md
│ │ │ │ │ ├── clis_index.md
│ │ │ │ │ ├── developer:docs:about.md
│ │ │ │ │ ├── developer:docs:clis:algokey:algokey.md
│ │ │ │ │ ├── developer:docs:clis:algokey:generate.md
│ │ │ │ │ ├── developer:docs:clis:algokey:import.md
│ │ │ │ │ ├── developer:docs:clis:algokey:multisig:append-auth-addr.md
│ │ │ │ │ ├── developer:docs:clis:algokey:multisig:multisig.md
│ │ │ │ │ ├── developer:docs:clis:algokey:part:info.md
│ │ │ │ │ ├── developer:docs:clis:algokey:part:part.md
│ │ │ │ │ ├── developer:docs:clis:algokey:part:reparent.md
│ │ │ │ │ ├── developer:docs:clis:algokey:sign.md
│ │ │ │ │ ├── developer:docs:clis:conduit:conduit.md
│ │ │ │ │ ├── developer:docs:clis:conduit:init.md
│ │ │ │ │ ├── developer:docs:clis:conduit:list:exporters.md
│ │ │ │ │ ├── developer:docs:clis:conduit:list:importers.md
│ │ │ │ │ ├── developer:docs:clis:conduit:list:list.md
│ │ │ │ │ ├── developer:docs:clis:conduit:list:processors.md
│ │ │ │ │ ├── developer:docs:clis:diagcfg:diagcfg.md
│ │ │ │ │ ├── developer:docs:clis:diagcfg:metric:disable.md
│ │ │ │ │ ├── developer:docs:clis:diagcfg:metric:enable.md
│ │ │ │ │ ├── developer:docs:clis:diagcfg:metric:metric.md
│ │ │ │ │ ├── developer:docs:clis:diagcfg:metric:status.md
│ │ │ │ │ ├── developer:docs:clis:diagcfg:telemetry:disable.md
│ │ │ │ │ ├── developer:docs:clis:diagcfg:telemetry:enable.md
│ │ │ │ │ ├── developer:docs:clis:diagcfg:telemetry:endpoint.md
│ │ │ │ │ ├── developer:docs:clis:diagcfg:telemetry:name.md
│ │ │ │ │ ├── developer:docs:clis:diagcfg:telemetry:status.md
│ │ │ │ │ ├── developer:docs:clis:diagcfg:telemetry:telemetry.md
│ │ │ │ │ ├── developer:docs:clis:goal:node:restart.md
│ │ │ │ │ ├── developer:docs:clis:goal:node:start.md
│ │ │ │ │ ├── developer:docs:clis:goal:node:status.md
│ │ │ │ │ ├── developer:docs:clis:goal:node:stop.md
│ │ │ │ │ ├── developer:docs:clis:goal:node:wait.md
│ │ │ │ │ ├── developer:docs:clis:goal:protocols.md
│ │ │ │ │ ├── developer:docs:clis:goal:report.md
│ │ │ │ │ ├── developer:docs:clis:goal:version.md
│ │ │ │ │ ├── developer:docs:clis:goal:wallet:list.md
│ │ │ │ │ ├── developer:docs:clis:goal:wallet:new.md
│ │ │ │ │ ├── developer:docs:clis:goal:wallet:wallet.md
│ │ │ │ │ ├── developer:docs:clis:indexer:api-config.md
│ │ │ │ │ ├── developer:docs:clis:indexer:daemon.md
│ │ │ │ │ ├── developer:docs:clis:indexer:indexer.md
│ │ │ │ │ ├── developer:docs:clis:indexer:util:util.md
│ │ │ │ │ ├── developer:docs:clis:indexer:util:validator.md
│ │ │ │ │ ├── developer:docs:clis:kmd.md
│ │ │ │ │ ├── developer:docs:clis:tealdbg:debug.md
│ │ │ │ │ ├── developer:docs:clis:tealdbg:remote.md
│ │ │ │ │ ├── developer:docs:clis:tealdbg:tealdbg.md
│ │ │ │ │ ├── developer:docs:details:accounts:create.md
│ │ │ │ │ ├── developer:docs:details:accounts:index.md
│ │ │ │ │ ├── developer:docs:details:accounts:rekey.md
│ │ │ │ │ ├── developer:docs:details:algorand_consensus.md
│ │ │ │ │ ├── developer:docs:details:algorand-networks:betanet.md
│ │ │ │ │ ├── developer:docs:details:algorand-networks:index.md
│ │ │ │ │ ├── developer:docs:details:algorand-networks:mainnet.md
│ │ │ │ │ ├── developer:docs:details:algorand-networks:testnet.md
│ │ │ │ │ ├── developer:docs:details:asa.md
│ │ │ │ │ ├── developer:docs:details:atc.md
│ │ │ │ │ ├── developer:docs:details:atomic_transfers.md
│ │ │ │ │ ├── developer:docs:details:conduit.md
│ │ │ │ │ ├── developer:docs:details:crust.md
│ │ │ │ │ ├── developer:docs:details:dapps:avm:index.md
│ │ │ │ │ ├── developer:docs:details:dapps:avm:teal:guidelines.md
│ │ │ │ │ ├── developer:docs:details:dapps:avm:teal:index.md
│ │ │ │ │ ├── developer:docs:details:dapps:avm:teal:jsonspec.md
│ │ │ │ │ ├── developer:docs:details:dapps:avm:teal:opcodes:index.md
│ │ │ │ │ ├── developer:docs:details:dapps:avm:teal:opcodes:v1.md
│ │ │ │ │ ├── developer:docs:details:dapps:avm:teal:opcodes:v10.md
│ │ │ │ │ ├── developer:docs:details:dapps:avm:teal:opcodes:v2.md
│ │ │ │ │ ├── developer:docs:details:dapps:avm:teal:opcodes:v3.md
│ │ │ │ │ ├── developer:docs:details:dapps:avm:teal:opcodes:v4.md
│ │ │ │ │ ├── developer:docs:details:dapps:avm:teal:opcodes:v5.md
│ │ │ │ │ ├── developer:docs:details:dapps:avm:teal:opcodes:v6.md
│ │ │ │ │ ├── developer:docs:details:dapps:avm:teal:opcodes:v7.md
│ │ │ │ │ ├── developer:docs:details:dapps:avm:teal:opcodes:v8.md
│ │ │ │ │ ├── developer:docs:details:dapps:avm:teal:opcodes:v9.md
│ │ │ │ │ ├── developer:docs:details:dapps:avm:teal:specification.md
│ │ │ │ │ ├── developer:docs:details:dapps:smart-contracts:ABI:index.md
│ │ │ │ │ ├── developer:docs:details:dapps:smart-contracts:apps:create.md
│ │ │ │ │ ├── developer:docs:details:dapps:smart-contracts:apps:index.md
│ │ │ │ │ ├── developer:docs:details:dapps:smart-contracts:apps:innertx.md
│ │ │ │ │ ├── developer:docs:details:dapps:smart-contracts:apps:state.md
│ │ │ │ │ ├── developer:docs:details:dapps:smart-contracts:apps:txs.md
│ │ │ │ │ ├── developer:docs:details:dapps:smart-contracts:debugging.md
│ │ │ │ │ ├── developer:docs:details:dapps:smart-contracts:frontend:apps.md
│ │ │ │ │ ├── developer:docs:details:dapps:smart-contracts:frontend:smartsigs.md
│ │ │ │ │ ├── developer:docs:details:dapps:smart-contracts:guidelines.md
│ │ │ │ │ ├── developer:docs:details:dapps:smart-contracts:index.md
│ │ │ │ │ ├── developer:docs:details:dapps:smart-contracts:smartsigs:index.md
│ │ │ │ │ ├── developer:docs:details:dapps:smart-contracts:smartsigs:modes.md
│ │ │ │ │ ├── developer:docs:details:dapps:smart-contracts:smartsigs:walkthrough.md
│ │ │ │ │ ├── developer:docs:details:dapps:writing-contracts:beaker.md
│ │ │ │ │ ├── developer:docs:details:dapps:writing-contracts:pyteal.md
│ │ │ │ │ ├── developer:docs:details:dapps:writing-contracts:python.md
│ │ │ │ │ ├── developer:docs:details:encoding.md
│ │ │ │ │ ├── developer:docs:details:ethereum_to_algorand.md
│ │ │ │ │ ├── developer:docs:details:index.md
│ │ │ │ │ ├── developer:docs:details:indexer.md
│ │ │ │ │ ├── developer:docs:details:parameter_tables.md
│ │ │ │ │ ├── developer:docs:details:stateproofs:index.md
│ │ │ │ │ ├── developer:docs:details:stateproofs:light_client.md
│ │ │ │ │ ├── developer:docs:details:technical_faq.md
│ │ │ │ │ ├── developer:docs:details:transactions:index.md
│ │ │ │ │ ├── developer:docs:details:transactions:offline_transactions.md
│ │ │ │ │ ├── developer:docs:details:transactions:payment_prompts.md
│ │ │ │ │ ├── developer:docs:details:transactions:signatures.md
│ │ │ │ │ ├── developer:docs:details:transactions:transactions.md
│ │ │ │ │ ├── developer:docs:details:useful_resources.md
│ │ │ │ │ ├── developer:docs:get-started:algokit.md
│ │ │ │ │ ├── developer:docs:get-started:basics:what_is_blockchain.md
│ │ │ │ │ ├── developer:docs:get-started:basics:whats_a_dapp.md
│ │ │ │ │ ├── developer:docs:get-started:basics:where_to_start.md
│ │ │ │ │ ├── developer:docs:get-started:basics:why_algorand.md
│ │ │ │ │ ├── developer:docs:get-started:tokenization:ft.md
│ │ │ │ │ ├── developer:docs:get-started:tokenization:nft.md
│ │ │ │ │ ├── developer:docs:index.md
│ │ │ │ │ ├── developer:docs:rest-apis:algod.md
│ │ │ │ │ ├── developer:docs:rest-apis:indexer.md
│ │ │ │ │ ├── developer:docs:rest-apis:kmd.md
│ │ │ │ │ ├── developer:docs:rest-apis:restendpoints.md
│ │ │ │ │ ├── developer:docs:run-a-node:operations:catchup.md
│ │ │ │ │ ├── developer:docs:run-a-node:operations:switch_networks.md
│ │ │ │ │ ├── developer:docs:run-a-node:participate:generate_keys.md
│ │ │ │ │ ├── developer:docs:run-a-node:participate:index.md
│ │ │ │ │ ├── developer:docs:run-a-node:participate:offline.md
│ │ │ │ │ ├── developer:docs:run-a-node:participate:online.md
│ │ │ │ │ ├── developer:docs:run-a-node:participate:renew.md
│ │ │ │ │ ├── developer:docs:run-a-node:reference:artifacts.md
│ │ │ │ │ ├── developer:docs:run-a-node:reference:config.md
│ │ │ │ │ ├── developer:docs:run-a-node:reference:relay.md
│ │ │ │ │ ├── developer:docs:run-a-node:reference:telemetry-config.md
│ │ │ │ │ ├── developer:docs:run-a-node:setup:indexer.md
│ │ │ │ │ ├── developer:docs:run-a-node:setup:install.md
│ │ │ │ │ ├── developer:docs:run-a-node:setup:node-troubleshooting.md
│ │ │ │ │ ├── developer:docs:run-a-node:setup:types.md
│ │ │ │ │ ├── developer:docs:sdks:go:index.md
│ │ │ │ │ ├── developer:docs:sdks:index.md
│ │ │ │ │ ├── developer:docs:sdks:java:index.md
│ │ │ │ │ ├── developer:docs:sdks:javascript:index.md
│ │ │ │ │ ├── developer:docs:sdks:python:index.md
│ │ │ │ │ ├── developer:python:code:example:accounts.md
│ │ │ │ │ ├── developer:python:code:example:arc4_types.md
│ │ │ │ │ ├── developer:python:code:example:assets.md
│ │ │ │ │ ├── developer:python:code:example:box_storage.md
│ │ │ │ │ ├── developer:python:code:example:control_flow.md
│ │ │ │ │ ├── developer:python:code:example:crypto:merkle_tree.md
│ │ │ │ │ ├── developer:python:code:example:defi:amm.md
│ │ │ │ │ ├── developer:python:code:example:defi:auction.md
│ │ │ │ │ ├── developer:python:code:example:defi:htlc_logicsig.md
│ │ │ │ │ ├── developer:python:code:example:defi:marketplace.md
│ │ │ │ │ ├── developer:python:code:example:events:arc28_events.md
│ │ │ │ │ ├── developer:python:code:example:global_storage.md
│ │ │ │ │ ├── developer:python:code:example:governance:simple_voting.md
│ │ │ │ │ ├── developer:python:code:example:hello_world.md
│ │ │ │ │ ├── developer:python:code:example:inner_transactions.md
│ │ │ │ │ ├── developer:python:code:example:local_storage.md
│ │ │ │ │ ├── developer:python:code:example:nft:proof_of_attendance.md
│ │ │ │ │ ├── developer:python:code:example:privacy:zk_whitelist.md
│ │ │ │ │ ├── developer:python:code:example:scratch_storage.md
│ │ │ │ │ ├── developer:python:code:example:self_payment.md
│ │ │ │ │ ├── developer:python:code:example:struct_in_box.md
│ │ │ │ │ ├── developer:python:code:example:subsidize_app_call.md
│ │ │ │ │ ├── developer:python:code:example:transactions.md
│ │ │ │ │ ├── developer:python:code:example:utility:calculator.md
│ │ │ │ │ ├── devportal-code-examples:projects:python-contract-examples:README.md
│ │ │ │ │ ├── devportal-code-examples:README.md
│ │ │ │ │ ├── docs:.walletconnect:index.md
│ │ │ │ │ ├── docs:.walletconnect:walletconnect-schema.md
│ │ │ │ │ ├── docs:README.md
│ │ │ │ │ ├── docs:scripts:example_tracker:example_list.md
│ │ │ │ │ ├── docs:scripts:README.md
│ │ │ │ │ ├── index.md
│ │ │ │ │ ├── liquid_auth_index.md
│ │ │ │ │ ├── liquid-auth:ARCHITECTURE.md
│ │ │ │ │ ├── liquid-auth:decisions:1-Service-Authentication.md
│ │ │ │ │ ├── liquid-auth:decisions:2-Bidirectional-Communication.md
│ │ │ │ │ ├── liquid-auth:decisions:3-Peer-to-Peer-Signaling.md
│ │ │ │ │ ├── liquid-auth:decisions:4-Fido-Extension.md
│ │ │ │ │ ├── liquid-auth:decisions:README.md
│ │ │ │ │ ├── liquid-auth:docs:architecture.md
│ │ │ │ │ ├── liquid-auth:docs:clients:android:provider-service:authenticate.md
│ │ │ │ │ ├── liquid-auth:docs:clients:android:provider-service:register.md
│ │ │ │ │ ├── liquid-auth:docs:clients:browser:authentication.md
│ │ │ │ │ ├── liquid-auth:docs:clients:browser:example.md
│ │ │ │ │ ├── liquid-auth:docs:introduction.md
│ │ │ │ │ ├── liquid-auth:docs:README.md
│ │ │ │ │ ├── liquid-auth:docs:server:environment-variables.md
│ │ │ │ │ ├── liquid-auth:docs:server:integrations.md
│ │ │ │ │ ├── liquid-auth:docs:server:introduction.md
│ │ │ │ │ ├── liquid-auth:docs:server:running-locally.md
│ │ │ │ │ ├── liquid-auth:README.md
│ │ │ │ │ ├── liquid-auth:SEQUENCE.md
│ │ │ │ │ ├── liquid-auth:services:liquid-auth-api-js:src:assertion:assertion.controller.post.request.md
│ │ │ │ │ ├── liquid-auth:services:liquid-auth-api-js:src:assertion:assertion.controller.post.response.md
│ │ │ │ │ ├── liquid-auth:services:liquid-auth-api-js:src:attestation:attestation.controller.post.request.md
│ │ │ │ │ ├── liquid-auth:services:liquid-auth-api-js:src:auth:auth.controller.get.user.md
│ │ │ │ │ ├── liquid-auth:sites:express-dapp:README.md
│ │ │ │ │ ├── liquid-auth:VISION.md
│ │ │ │ │ ├── puya_index.md
│ │ │ │ │ ├── puya:docs:algopy_testing:index.md
│ │ │ │ │ ├── puya:docs:api-algopy.arc4.md
│ │ │ │ │ ├── puya:docs:api-algopy.gtxn.md
│ │ │ │ │ ├── puya:docs:api-algopy.itxn.md
│ │ │ │ │ ├── puya:docs:api-algopy.md
│ │ │ │ │ ├── puya:docs:api-algopy.op.md
│ │ │ │ │ ├── puya:docs:api.md
│ │ │ │ │ ├── puya:docs:compiler.md
│ │ │ │ │ ├── puya:docs:index.md
│ │ │ │ │ ├── puya:docs:language-guide.md
│ │ │ │ │ ├── puya:docs:lg-arc28.md
│ │ │ │ │ ├── puya:docs:lg-arc4.md
│ │ │ │ │ ├── puya:docs:lg-builtins.md
│ │ │ │ │ ├── puya:docs:lg-calling-apps.md
│ │ │ │ │ ├── puya:docs:lg-compile.md
│ │ │ │ │ ├── puya:docs:lg-control.md
│ │ │ │ │ ├── puya:docs:lg-errors.md
│ │ │ │ │ ├── puya:docs:lg-logs.md
│ │ │ │ │ ├── puya:docs:lg-modules.md
│ │ │ │ │ ├── puya:docs:lg-opcode-budget.md
│ │ │ │ │ ├── puya:docs:lg-ops.md
│ │ │ │ │ ├── puya:docs:lg-storage.md
│ │ │ │ │ ├── puya:docs:lg-structure.md
│ │ │ │ │ ├── puya:docs:lg-transactions.md
│ │ │ │ │ ├── puya:docs:lg-types.md
│ │ │ │ │ ├── puya:docs:lg-unsupported-python-features.md
│ │ │ │ │ ├── puya:docs:principles.md
│ │ │ │ │ ├── puya:examples:auction:README.md
│ │ │ │ │ ├── puya:python:testing:docs:algopy.md
│ │ │ │ │ ├── puya:python:testing:docs:api.md
│ │ │ │ │ ├── puya:python:testing:docs:coverage.md
│ │ │ │ │ ├── puya:python:testing:docs:examples.md
│ │ │ │ │ ├── puya:python:testing:docs:faq.md
│ │ │ │ │ ├── puya:python:testing:docs:index.md
│ │ │ │ │ ├── puya:python:testing:docs:testing-guide:arc4-types.md
│ │ │ │ │ ├── puya:python:testing:docs:testing-guide:avm-types.md
│ │ │ │ │ ├── puya:python:testing:docs:testing-guide:concepts.md
│ │ │ │ │ ├── puya:python:testing:docs:testing-guide:contract-testing.md
│ │ │ │ │ ├── puya:python:testing:docs:testing-guide:index.md
│ │ │ │ │ ├── puya:python:testing:docs:testing-guide:opcodes.md
│ │ │ │ │ ├── puya:python:testing:docs:testing-guide:signature-testing.md
│ │ │ │ │ ├── puya:python:testing:docs:testing-guide:state-management.md
│ │ │ │ │ ├── puya:python:testing:docs:testing-guide:subroutines.md
│ │ │ │ │ ├── puya:python:testing:docs:testing-guide:transactions.md
│ │ │ │ │ ├── puya:python:testing:examples:README.md
│ │ │ │ │ ├── puya:python:testing:README.md
│ │ │ │ │ ├── puya:README.md
│ │ │ │ │ ├── puya:src:puya:ARCHITECTURE.md
│ │ │ │ │ ├── puya:src:puyapy:_typeshed:README.md
│ │ │ │ │ ├── puya:src:puyapy:_vendor:mypy:typeshed:stdlib:_typeshed:README.md
│ │ │ │ │ ├── puya:src:puyapy:awst_build:README.md
│ │ │ │ │ ├── puya:stubs:README.md
│ │ │ │ │ ├── puya:tests:test_expected_output:README.md
│ │ │ │ │ ├── puya:typescript:docs:architecture-decisions:2024-05-21_primitive-bytes-and-strings.md
│ │ │ │ │ ├── puya:typescript:docs:architecture-decisions:2024-05-21_primitive-integer-types.md
│ │ │ │ │ ├── puya:typescript:docs:README.md
│ │ │ │ │ ├── puya:typescript:packages:algo-ts:readme.md
│ │ │ │ │ ├── puya:typescript:README.md
│ │ │ │ │ ├── SDKs:javascript:classes:ABIAddressType.md
│ │ │ │ │ ├── SDKs:javascript:classes:ABIArrayDynamicType.md
│ │ │ │ │ ├── SDKs:javascript:classes:ABIArrayStaticType.md
│ │ │ │ │ ├── SDKs:javascript:classes:ABIBoolType.md
│ │ │ │ │ ├── SDKs:javascript:classes:ABIByteType.md
│ │ │ │ │ ├── SDKs:javascript:classes:ABIContract.md
│ │ │ │ │ ├── SDKs:javascript:classes:ABIInterface.md
│ │ │ │ │ ├── SDKs:javascript:classes:ABIMethod.md
│ │ │ │ │ ├── SDKs:javascript:classes:ABIStringType.md
│ │ │ │ │ ├── SDKs:javascript:classes:ABITupleType.md
│ │ │ │ │ ├── SDKs:javascript:classes:ABIType.md
│ │ │ │ │ ├── SDKs:javascript:classes:ABIUfixedType.md
│ │ │ │ │ ├── SDKs:javascript:classes:ABIUintType.md
│ │ │ │ │ ├── SDKs:javascript:classes:Algodv2.md
│ │ │ │ │ ├── SDKs:javascript:classes:AtomicTransactionComposer.md
│ │ │ │ │ ├── SDKs:javascript:classes:DryrunResult.md
│ │ │ │ │ ├── SDKs:javascript:classes:Indexer.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.Account.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.AccountParticipation.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.AccountResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.AccountsResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.AccountStateDelta.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.Application.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.ApplicationLocalState.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.ApplicationLocalStatesResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.ApplicationLogData.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.ApplicationLogsResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.ApplicationParams.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.ApplicationResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.ApplicationsResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.ApplicationStateSchema.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.Asset.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.AssetBalancesResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.AssetHolding.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.AssetHoldingsResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.AssetParams.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.AssetResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.AssetsResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.Block.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.BlockRewards.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.BlockUpgradeState.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.BlockUpgradeVote.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.Box.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.BoxDescriptor.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.BoxesResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.ErrorResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.EvalDelta.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.EvalDeltaKeyValue.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.HashFactory.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.HealthCheck.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.IndexerStateProofMessage.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.MerkleArrayProof.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.MiniAssetHolding.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.ParticipationUpdates.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.StateProofFields.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.StateProofParticipant.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.StateProofReveal.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.StateProofSignature.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.StateProofSigSlot.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.StateProofTracking.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.StateProofVerifier.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.StateSchema.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.TealKeyValue.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.TealValue.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.Transaction.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.TransactionApplication.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.TransactionAssetConfig.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.TransactionAssetFreeze.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.TransactionAssetTransfer.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.TransactionKeyreg.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.TransactionPayment.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.TransactionResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.TransactionSignature.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.TransactionSignatureLogicsig.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.TransactionSignatureMultisig.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.TransactionSignatureMultisigSubsignature.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.TransactionsResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.TransactionStateProof.md
│ │ │ │ │ ├── SDKs:javascript:classes:Kmd.md
│ │ │ │ │ ├── SDKs:javascript:classes:LogicSig.md
│ │ │ │ │ ├── SDKs:javascript:classes:LogicSigAccount.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.Account.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.AccountApplicationResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.AccountAssetHolding.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.AccountAssetResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.AccountAssetsInformationResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.AccountParticipation.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.AccountStateDelta.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.AppCallLogs.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.Application.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.ApplicationInitialStates.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.ApplicationKVStorage.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.ApplicationLocalReference.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.ApplicationLocalState.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.ApplicationParams.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.ApplicationStateOperation.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.ApplicationStateSchema.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.Asset.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.AssetHolding.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.AssetHoldingReference.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.AssetParams.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.AvmKeyValue.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.AvmValue.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.BlockHashResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.BlockLogsResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.BlockResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.BlockTxidsResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.Box.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.BoxDescriptor.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.BoxesResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.BoxReference.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.BuildVersion.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.CompileResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.DisassembleResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.DryrunRequest.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.DryrunResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.DryrunSource.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.DryrunState.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.DryrunTxnResult.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.ErrorResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.EvalDelta.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.EvalDeltaKeyValue.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.GetBlockTimeStampOffsetResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.GetSyncRoundResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.KvDelta.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.LedgerStateDeltaForTransactionGroup.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.LightBlockHeaderProof.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.NodeStatusResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.PendingTransactionResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.PendingTransactionsResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.PostTransactionsResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.ScratchChange.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.SimulateInitialStates.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.SimulateRequest.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.SimulateRequestTransactionGroup.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.SimulateResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.SimulateTraceConfig.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.SimulateTransactionGroupResult.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.SimulateTransactionResult.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.SimulateUnnamedResourcesAccessed.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.SimulationEvalOverrides.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.SimulationOpcodeTraceUnit.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.SimulationTransactionExecTrace.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.StateProof.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.StateProofMessage.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.SupplyResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.TealKeyValue.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.TealValue.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.TransactionGroupLedgerStateDeltasForRoundResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.TransactionParametersResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.TransactionProofResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.Version.md
│ │ │ │ │ ├── SDKs:javascript:classes:SourceMap.md
│ │ │ │ │ ├── SDKs:javascript:classes:Transaction.md
│ │ │ │ │ ├── SDKs:javascript:enums:ABIReferenceType.md
│ │ │ │ │ ├── SDKs:javascript:enums:ABITransactionType.md
│ │ │ │ │ ├── SDKs:javascript:enums:AtomicTransactionComposerStatus.md
│ │ │ │ │ ├── SDKs:javascript:enums:IntDecoding.md
│ │ │ │ │ ├── SDKs:javascript:enums:OnApplicationComplete.md
│ │ │ │ │ ├── SDKs:javascript:enums:TransactionType.md
│ │ │ │ │ ├── SDKs:javascript:examples:README.md
│ │ │ │ │ ├── SDKs:javascript:FAQ.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:ABIContractNetworkInfo.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:ABIContractNetworks.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:ABIContractParams.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:ABIInterfaceParams.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:ABIMethodArgParams.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:ABIMethodParams.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:ABIMethodReturnParams.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:ABIResult.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:Account.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:Address.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:AlgodTokenHeader.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:BaseHTTPClient.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:BaseHTTPClientError.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:BaseHTTPClientResponse.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:BoxReference.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:CustomTokenHeader.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:EncodedAssetParams.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:EncodedBoxReference.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:EncodedGlobalStateSchema.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:EncodedLocalStateSchema.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:EncodedLogicSig.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:EncodedLogicSigAccount.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:EncodedMultisig.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:EncodedSignedTransaction.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:EncodedSubsig.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:EncodedTransaction.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:IndexerTokenHeader.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:KMDTokenHeader.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:MultisigMetadata.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:SignedTransaction.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:SuggestedParams.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:TransactionParams.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:TransactionWithSigner.md
│ │ │ │ │ ├── SDKs:javascript:modules:indexerModels.md
│ │ │ │ │ ├── SDKs:javascript:modules:modelsv2.md
│ │ │ │ │ ├── SDKs:javascript:modules.md
│ │ │ │ │ ├── SDKs:javascript:README.md
│ │ │ │ │ ├── SDKs:python:algosdk:v2client:harness:README.md
│ │ │ │ │ ├── SDKs:python:examples:README.md
│ │ │ │ │ ├── SDKs:python:README.md
│ │ │ │ │ ├── tealscript:examples_amm_README.md
│ │ │ │ │ ├── tealscript:examples_auction_README.md
│ │ │ │ │ ├── tealscript:examples_big_box_README.md
│ │ │ │ │ ├── tealscript:examples_itxns_README.md
│ │ │ │ │ ├── tealscript:examples_lsig_with_app_README.md
│ │ │ │ │ ├── tealscript:examples_reti_README.md
│ │ │ │ │ ├── tealscript:FEATURES.md
│ │ │ │ │ ├── tealscript:guides_atomic_txn.md
│ │ │ │ │ ├── tealscript:guides_features.md
│ │ │ │ │ ├── tealscript:guides_getting_started.md
│ │ │ │ │ ├── tealscript:guides_inner_transactions.md
│ │ │ │ │ ├── tealscript:guides_lifecycle.md
│ │ │ │ │ ├── tealscript:guides_math.md
│ │ │ │ │ ├── tealscript:guides_methods.md
│ │ │ │ │ ├── tealscript:guides_multiple_contracts.md
│ │ │ │ │ ├── tealscript:guides_pyteal.md
│ │ │ │ │ ├── tealscript:guides_storage.md
│ │ │ │ │ ├── tealscript:guides_Supported Types_arrays.md
│ │ │ │ │ ├── tealscript:guides_Supported Types_numbers.md
│ │ │ │ │ ├── TEALScript:README.md
│ │ │ │ │ ├── tealscript:tests_test_package_README.md
│ │ │ │ │ ├── tealscript:tutorials_Hello World_0001-intro.md
│ │ │ │ │ ├── tealscript:tutorials_Hello World_0002-init.md
│ │ │ │ │ ├── tealscript:tutorials_Hello World_0003-contract.md
│ │ │ │ │ ├── tealscript:tutorials_Hello World_0004-artifacts.md
│ │ │ │ │ ├── tealscript:tutorials_Hello World_0005-hello.md
│ │ │ │ │ └── tealscript:tutorials_Hello World_0006-test.md
│ │ │ │ └── taxonomy-categories
│ │ │ │ ├── algokit-utils.json
│ │ │ │ ├── algokit.json
│ │ │ │ ├── arcs.json
│ │ │ │ ├── clis.json
│ │ │ │ ├── details.json
│ │ │ │ ├── developers.json
│ │ │ │ ├── liquid-auth.json
│ │ │ │ ├── nodes.json
│ │ │ │ ├── puya.json
│ │ │ │ ├── python.json
│ │ │ │ ├── sdks.json
│ │ │ │ └── tealscript.json
│ │ │ └── wallet
│ │ │ └── index.ts
│ │ ├── tools
│ │ │ ├── accountManager.ts
│ │ │ ├── algodManager.ts
│ │ │ ├── apiManager
│ │ │ │ ├── algod
│ │ │ │ │ ├── account.ts
│ │ │ │ │ ├── application.ts
│ │ │ │ │ ├── asset.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── transaction.ts
│ │ │ │ ├── example
│ │ │ │ │ ├── get-balance.ts
│ │ │ │ │ └── index.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── indexer
│ │ │ │ │ ├── account.ts
│ │ │ │ │ ├── application.ts
│ │ │ │ │ ├── asset.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── transaction.ts
│ │ │ │ ├── nfd
│ │ │ │ │ └── index.ts
│ │ │ │ ├── tinyman
│ │ │ │ │ ├── analytics.ts
│ │ │ │ │ ├── bootstrap.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── liquidity.ts
│ │ │ │ │ ├── opt_in.ts
│ │ │ │ │ ├── pool.ts
│ │ │ │ │ ├── remove_liquidity.ts
│ │ │ │ │ └── swap.ts
│ │ │ │ ├── ultrade
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── market.ts
│ │ │ │ │ ├── system.ts
│ │ │ │ │ └── wallet.ts
│ │ │ │ └── vestige
│ │ │ │ ├── assets.ts
│ │ │ │ ├── balances.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── networks.ts
│ │ │ │ ├── notes.ts
│ │ │ │ ├── pools.ts
│ │ │ │ ├── protocols.ts
│ │ │ │ ├── swaps.ts
│ │ │ │ └── vaults.ts
│ │ │ ├── arc26Manager.ts
│ │ │ ├── index.ts
│ │ │ ├── knowledgeManager.ts
│ │ │ ├── transactionManager
│ │ │ │ ├── accountTransactions.ts
│ │ │ │ ├── appTransactions
│ │ │ │ │ ├── callTxn.ts
│ │ │ │ │ ├── clearTxn.ts
│ │ │ │ │ ├── closeOutTxn.ts
│ │ │ │ │ ├── createTxn.ts
│ │ │ │ │ ├── deleteTxn.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── optInTxn.ts
│ │ │ │ │ ├── test
│ │ │ │ │ │ ├── counter_approval.teal
│ │ │ │ │ │ ├── counter_clear.teal
│ │ │ │ │ │ ├── storage_test_approval_v2.teal
│ │ │ │ │ │ ├── storage_test_approval.teal
│ │ │ │ │ │ └── storage_test_clear.teal
│ │ │ │ │ ├── types.ts
│ │ │ │ │ └── updateTxn.ts
│ │ │ │ ├── assetTransactions.ts
│ │ │ │ ├── generalTransaction.ts
│ │ │ │ └── index.ts
│ │ │ └── utilityManager.ts
│ │ ├── types.ts
│ │ └── utils
│ │ └── responseProcessor.ts
│ ├── tests
│ │ ├── resources
│ │ │ ├── algod
│ │ │ │ ├── account.test.ts
│ │ │ │ ├── application.test.ts
│ │ │ │ ├── asset.test.ts
│ │ │ │ └── transaction.test.ts
│ │ │ └── indexer
│ │ │ ├── account.test.ts
│ │ │ ├── application.test.ts
│ │ │ ├── asset.test.ts
│ │ │ └── transaction.test.ts
│ │ └── tools
│ │ ├── accountManager.test.ts
│ │ ├── algodManager.test.ts
│ │ ├── apiManager
│ │ │ └── example
│ │ │ └── get-balance.test.ts
│ │ ├── transactionManager
│ │ │ ├── accountTransactionManager.test.ts
│ │ │ ├── appTransactionManager.test.ts
│ │ │ ├── assetTransactionManager.test.ts
│ │ │ ├── generalTransactionManager.test.ts
│ │ │ └── transactionManager.test.ts
│ │ └── utilityManager.test.ts
│ └── tsconfig.json
├── README.md
├── rename_files.sh
└── tsconfig.json
```
# Files
--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/algokit:utils:typescript:code:modules:types_app.md:
--------------------------------------------------------------------------------
```markdown
1 | [@algorandfoundation/algokit-utils](../README.md) / types/app
2 |
3 | # Module: types/app
4 |
5 | ## Table of contents
6 |
7 | ### Enumerations
8 |
9 | - [OnSchemaBreak](../enums/types_app.OnSchemaBreak.md)
10 | - [OnUpdate](../enums/types_app.OnUpdate.md)
11 |
12 | ### Interfaces
13 |
14 | - [AppCallParams](../interfaces/types_app.AppCallParams.md)
15 | - [AppCallTransactionResultOfType](../interfaces/types_app.AppCallTransactionResultOfType.md)
16 | - [AppCompilationResult](../interfaces/types_app.AppCompilationResult.md)
17 | - [AppDeployMetadata](../interfaces/types_app.AppDeployMetadata.md)
18 | - [AppDeploymentParams](../interfaces/types_app.AppDeploymentParams.md)
19 | - [AppLookup](../interfaces/types_app.AppLookup.md)
20 | - [AppMetadata](../interfaces/types_app.AppMetadata.md)
21 | - [AppReference](../interfaces/types_app.AppReference.md)
22 | - [AppState](../interfaces/types_app.AppState.md)
23 | - [AppStorageSchema](../interfaces/types_app.AppStorageSchema.md)
24 | - [BoxName](../interfaces/types_app.BoxName.md)
25 | - [BoxReference](../interfaces/types_app.BoxReference.md)
26 | - [BoxValueRequestParams](../interfaces/types_app.BoxValueRequestParams.md)
27 | - [BoxValuesRequestParams](../interfaces/types_app.BoxValuesRequestParams.md)
28 | - [CompiledTeal](../interfaces/types_app.CompiledTeal.md)
29 | - [CoreAppCallArgs](../interfaces/types_app.CoreAppCallArgs.md)
30 | - [CreateAppParams](../interfaces/types_app.CreateAppParams.md)
31 | - [RawAppCallArgs](../interfaces/types_app.RawAppCallArgs.md)
32 | - [TealTemplateParams](../interfaces/types_app.TealTemplateParams.md)
33 | - [UpdateAppParams](../interfaces/types_app.UpdateAppParams.md)
34 |
35 | ### Type Aliases
36 |
37 | - [ABIAppCallArg](types_app.md#abiappcallarg)
38 | - [ABIAppCallArgs](types_app.md#abiappcallargs)
39 | - [ABIReturn](types_app.md#abireturn)
40 | - [AppCallArgs](types_app.md#appcallargs)
41 | - [AppCallTransactionResult](types_app.md#appcalltransactionresult)
42 | - [AppCallType](types_app.md#appcalltype)
43 | - [AppReturn](types_app.md#appreturn)
44 | - [BoxIdentifier](types_app.md#boxidentifier)
45 | - [SendAppCreateTransactionResult](types_app.md#sendappcreatetransactionresult)
46 | - [SendAppTransactionResult](types_app.md#sendapptransactionresult)
47 | - [SendAppUpdateTransactionResult](types_app.md#sendappupdatetransactionresult)
48 |
49 | ### Variables
50 |
51 | - [ABI\_RETURN\_PREFIX](types_app.md#abi_return_prefix)
52 | - [APP\_DEPLOY\_NOTE\_DAPP](types_app.md#app_deploy_note_dapp)
53 | - [APP\_PAGE\_MAX\_SIZE](types_app.md#app_page_max_size)
54 | - [DELETABLE\_TEMPLATE\_NAME](types_app.md#deletable_template_name)
55 | - [UPDATABLE\_TEMPLATE\_NAME](types_app.md#updatable_template_name)
56 |
57 | ## Type Aliases
58 |
59 | ### ABIAppCallArg
60 |
61 | Ƭ **ABIAppCallArg**: `ABIArgument` \| [`TransactionToSign`](../interfaces/types_transaction.TransactionToSign.md) \| `Transaction` \| `Promise`\<[`SendTransactionResult`](../interfaces/types_transaction.SendTransactionResult.md)\> \| [`SendTransactionResult`](../interfaces/types_transaction.SendTransactionResult.md) \| `undefined`
62 |
63 | An argument for an ABI method, either a primitive value, or a transaction with or without signer, or the unawaited async return value of an algokit method that returns a `SendTransactionResult`
64 |
65 | #### Defined in
66 |
67 | [src/types/app.ts:102](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L102)
68 |
69 | ___
70 |
71 | ### ABIAppCallArgs
72 |
73 | Ƭ **ABIAppCallArgs**: [`CoreAppCallArgs`](../interfaces/types_app.CoreAppCallArgs.md) & \{ `method`: `ABIMethodParams` \| `ABIMethod` ; `methodArgs`: [`ABIAppCallArg`](types_app.md#abiappcallarg)[] }
74 |
75 | App call args for an ABI call
76 |
77 | #### Defined in
78 |
79 | [src/types/app.ts:113](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L113)
80 |
81 | ___
82 |
83 | ### ABIReturn
84 |
85 | Ƭ **ABIReturn**: \{ `decodeError`: `undefined` ; `method`: `ABIMethod` ; `rawReturnValue`: `Uint8Array` ; `returnValue`: `ABIValue` } \| \{ `decodeError`: `Error` ; `method?`: `undefined` ; `rawReturnValue?`: `undefined` ; `returnValue?`: `undefined` }
86 |
87 | The return value of an ABI method call
88 |
89 | #### Defined in
90 |
91 | [src/types/app.ts:235](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L235)
92 |
93 | ___
94 |
95 | ### AppCallArgs
96 |
97 | Ƭ **AppCallArgs**: [`RawAppCallArgs`](../interfaces/types_app.RawAppCallArgs.md) \| [`ABIAppCallArgs`](types_app.md#abiappcallargs)
98 |
99 | Arguments to pass to an app call either:
100 | * The raw app call values to pass through into the transaction (after processing); or
101 | * An ABI method definition (method and args)
102 |
103 | #### Defined in
104 |
105 | [src/types/app.ts:124](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L124)
106 |
107 | ___
108 |
109 | ### AppCallTransactionResult
110 |
111 | Ƭ **AppCallTransactionResult**: [`AppCallTransactionResultOfType`](../interfaces/types_app.AppCallTransactionResultOfType.md)\<[`ABIReturn`](types_app.md#abireturn)\>
112 |
113 | Result from calling an app
114 |
115 | #### Defined in
116 |
117 | [src/types/app.ts:232](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L232)
118 |
119 | ___
120 |
121 | ### AppCallType
122 |
123 | Ƭ **AppCallType**: ``"no_op"`` \| ``"opt_in"`` \| ``"close_out"`` \| ``"clear_state"`` \| ``"update_application"`` \| ``"delete_application"``
124 |
125 | **`Deprecated`**
126 |
127 | Use `algosdk.OnApplicationComplete` directly instead.
128 |
129 | The type of call / [on-completion action](https://developer.algorand.org/docs/get-details/dapps/smart-contracts/apps/#the-lifecycle-of-a-smart-contract) for a smart contract call.
130 |
131 | Equivalent of `algosdk.OnApplicationComplete`, but as a more convenient string enum.
132 |
133 | * `no_op`: Normal smart contract call, no special on-complete action
134 | * `opt_in`: Opt-in to smart contract local storage
135 | * `close_out`: Close-out local storage storage
136 | * `clear_state`: Clear local storage state
137 | * `update_application`: Update the smart contract
138 | * `delete_application`: Delete the smart contract
139 |
140 | #### Defined in
141 |
142 | [src/types/app.ts:180](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L180)
143 |
144 | ___
145 |
146 | ### AppReturn
147 |
148 | Ƭ **AppReturn**\<`TReturn`\>: `Object`
149 |
150 | #### Type parameters
151 |
152 | | Name |
153 | | :------ |
154 | | `TReturn` |
155 |
156 | #### Type declaration
157 |
158 | | Name | Type | Description |
159 | | :------ | :------ | :------ |
160 | | `return?` | `TReturn` | The ABI method call return value |
161 |
162 | #### Defined in
163 |
164 | [src/types/app.ts:340](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L340)
165 |
166 | ___
167 |
168 | ### BoxIdentifier
169 |
170 | Ƭ **BoxIdentifier**: `string` \| `Uint8Array` \| [`SendTransactionFrom`](types_transaction.md#sendtransactionfrom)
171 |
172 | **`Deprecated`**
173 |
174 | Use `types/app-manager/BoxIdentifier` instead.
175 |
176 | Something that identifies a box name - either a:
177 | * `Uint8Array`
178 | * `string` (that will be encoded to a Uint8Array)
179 | * `SendTransactionFrom` (encoded into the public key address of the corresponding account)
180 |
181 | #### Defined in
182 |
183 | [src/types/app.ts:70](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L70)
184 |
185 | ___
186 |
187 | ### SendAppCreateTransactionResult
188 |
189 | Ƭ **SendAppCreateTransactionResult**: [`Expand`](types_expand.md#expand)\<[`SendAppUpdateTransactionResult`](types_app.md#sendappupdatetransactionresult) & \{ `appAddress`: `Address` ; `appId`: `bigint` }\>
190 |
191 | Result from sending a single app transaction.
192 |
193 | #### Defined in
194 |
195 | [src/types/app.ts:357](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L357)
196 |
197 | ___
198 |
199 | ### SendAppTransactionResult
200 |
201 | Ƭ **SendAppTransactionResult**: [`Expand`](types_expand.md#expand)\<[`SendSingleTransactionResult`](types_transaction.md#sendsingletransactionresult) & \{ `return?`: [`ABIReturn`](types_app.md#abireturn) }\>
202 |
203 | Result from sending a single app transaction.
204 |
205 | #### Defined in
206 |
207 | [src/types/app.ts:346](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L346)
208 |
209 | ___
210 |
211 | ### SendAppUpdateTransactionResult
212 |
213 | Ƭ **SendAppUpdateTransactionResult**: [`Expand`](types_expand.md#expand)\<[`SendAppTransactionResult`](types_app.md#sendapptransactionresult) & `Partial`\<[`AppCompilationResult`](../interfaces/types_app.AppCompilationResult.md)\>\>
214 |
215 | Result from sending a single app transaction.
216 |
217 | #### Defined in
218 |
219 | [src/types/app.ts:354](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L354)
220 |
221 | ## Variables
222 |
223 | ### ABI\_RETURN\_PREFIX
224 |
225 | • `Const` **ABI\_RETURN\_PREFIX**: `Uint8Array`
226 |
227 | First 4 bytes of SHA-512/256 hash of "return" for retrieving ABI return values
228 |
229 | #### Defined in
230 |
231 | [src/types/app.ts:36](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L36)
232 |
233 | ___
234 |
235 | ### APP\_DEPLOY\_NOTE\_DAPP
236 |
237 | • `Const` **APP\_DEPLOY\_NOTE\_DAPP**: ``"ALGOKIT_DEPLOYER"``
238 |
239 | The app create/update [ARC-2](https://github.com/algorandfoundation/ARCs/blob/main/ARCs/arc-0002.md) transaction note prefix
240 |
241 | #### Defined in
242 |
243 | [src/types/app.ts:30](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L30)
244 |
245 | ___
246 |
247 | ### APP\_PAGE\_MAX\_SIZE
248 |
249 | • `Const` **APP\_PAGE\_MAX\_SIZE**: ``2048``
250 |
251 | The maximum number of bytes in a single app code page
252 |
253 | #### Defined in
254 |
255 | [src/types/app.ts:33](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L33)
256 |
257 | ___
258 |
259 | ### DELETABLE\_TEMPLATE\_NAME
260 |
261 | • `Const` **DELETABLE\_TEMPLATE\_NAME**: ``"TMPL_DELETABLE"``
262 |
263 | The name of the TEAL template variable for deploy-time permanence control
264 |
265 | #### Defined in
266 |
267 | [src/types/app.ts:27](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L27)
268 |
269 | ___
270 |
271 | ### UPDATABLE\_TEMPLATE\_NAME
272 |
273 | • `Const` **UPDATABLE\_TEMPLATE\_NAME**: ``"TMPL_UPDATABLE"``
274 |
275 | The name of the TEAL template variable for deploy-time immutability control
276 |
277 | #### Defined in
278 |
279 | [src/types/app.ts:24](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L24)
280 |
```
--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/puya:python:testing:docs:testing-guide:transactions.md:
--------------------------------------------------------------------------------
```markdown
1 | # Transactions
2 |
3 | The testing framework follows the Transaction definitions described in [`algorand-python` docs](https://algorand-python.readthedocs.io/en/latest/algorand_sdk/transactions.html). This section focuses on _value generators_ and interactions with inner transactions, it also explains how the framework identifies _active_ transaction group during contract method/subroutine/logicsig invocation.
4 |
5 | ```{testsetup}
6 | import algopy
7 | import algopy_testing
8 | from algopy_testing import algopy_testing_context
9 |
10 | # Create the context manager for snippets below
11 | ctx_manager = algopy_testing_context()
12 |
13 | # Enter the context
14 | context = ctx_manager.__enter__()
15 | ```
16 |
17 | ## Group Transactions
18 |
19 | Refers to test implementation of transaction stubs available under `algopy.gtxn.*` namespace. Available under [`algopy.TxnValueGenerator`](../api.md) instance accessible via `context.any.txn` property:
20 |
21 | ```{mermaid}
22 | graph TD
23 | A[TxnValueGenerator] --> B[payment]
24 | A --> C[asset_transfer]
25 | A --> D[application_call]
26 | A --> E[asset_config]
27 | A --> F[key_registration]
28 | A --> G[asset_freeze]
29 | A --> H[transaction]
30 | ```
31 |
32 | ```{testcode}
33 | ... # instantiate test context
34 |
35 | # Generate a random payment transaction
36 | pay_txn = context.any.txn.payment(
37 | sender=context.any.account(), # Optional: Defaults to context's default sender if not provided
38 | receiver=context.any.account(), # Required
39 | amount=algopy.UInt64(1000000) # Required
40 | )
41 |
42 | # Generate a random asset transfer transaction
43 | asset_transfer_txn = context.any.txn.asset_transfer(
44 | sender=context.any.account(), # Optional: Defaults to context's default sender if not provided
45 | receiver=context.any.account(), # Required
46 | asset_id=algopy.UInt64(1), # Required
47 | amount=algopy.UInt64(1000) # Required
48 | )
49 |
50 | # Generate a random application call transaction
51 | app_call_txn = context.any.txn.application_call(
52 | app_id=context.any.application(), # Required
53 | app_args=[algopy.Bytes(b"arg1"), algopy.Bytes(b"arg2")], # Optional: Defaults to empty list if not provided
54 | accounts=[context.any.account()], # Optional: Defaults to empty list if not provided
55 | assets=[context.any.asset()], # Optional: Defaults to empty list if not provided
56 | apps=[context.any.application()], # Optional: Defaults to empty list if not provided
57 | approval_program_pages=[algopy.Bytes(b"approval_code")], # Optional: Defaults to empty list if not provided
58 | clear_state_program_pages=[algopy.Bytes(b"clear_code")], # Optional: Defaults to empty list if not provided
59 | scratch_space={0: algopy.Bytes(b"scratch")} # Optional: Defaults to empty dict if not provided
60 | )
61 |
62 | # Generate a random asset config transaction
63 | asset_config_txn = context.any.txn.asset_config(
64 | sender=context.any.account(), # Optional: Defaults to context's default sender if not provided
65 | asset_id=algopy.UInt64(1), # Optional: If not provided, creates a new asset
66 | total=1000000, # Required for new assets
67 | decimals=0, # Required for new assets
68 | default_frozen=False, # Optional: Defaults to False if not provided
69 | unit_name="UNIT", # Optional: Defaults to empty string if not provided
70 | asset_name="Asset", # Optional: Defaults to empty string if not provided
71 | url="http://asset-url", # Optional: Defaults to empty string if not provided
72 | metadata_hash=b"metadata_hash", # Optional: Defaults to empty bytes if not provided
73 | manager=context.any.account(), # Optional: Defaults to sender if not provided
74 | reserve=context.any.account(), # Optional: Defaults to zero address if not provided
75 | freeze=context.any.account(), # Optional: Defaults to zero address if not provided
76 | clawback=context.any.account() # Optional: Defaults to zero address if not provided
77 | )
78 |
79 | # Generate a random key registration transaction
80 | key_reg_txn = context.any.txn.key_registration(
81 | sender=context.any.account(), # Optional: Defaults to context's default sender if not provided
82 | vote_pk=algopy.Bytes(b"vote_pk"), # Optional: Defaults to empty bytes if not provided
83 | selection_pk=algopy.Bytes(b"selection_pk"), # Optional: Defaults to empty bytes if not provided
84 | vote_first=algopy.UInt64(1), # Optional: Defaults to 0 if not provided
85 | vote_last=algopy.UInt64(1000), # Optional: Defaults to 0 if not provided
86 | vote_key_dilution=algopy.UInt64(10000) # Optional: Defaults to 0 if not provided
87 | )
88 |
89 | # Generate a random asset freeze transaction
90 | asset_freeze_txn = context.any.txn.asset_freeze(
91 | sender=context.any.account(), # Optional: Defaults to context's default sender if not provided
92 | asset_id=algopy.UInt64(1), # Required
93 | freeze_target=context.any.account(), # Required
94 | freeze_state=True # Required
95 | )
96 |
97 | # Generate a random transaction of a specified type
98 | generic_txn = context.any.txn.transaction(
99 | type=algopy.TransactionType.Payment, # Required
100 | sender=context.any.account(), # Optional: Defaults to context's default sender if not provided
101 | receiver=context.any.account(), # Required for Payment
102 | amount=algopy.UInt64(1000000) # Required for Payment
103 | )
104 | ```
105 |
106 | ## Preparing for execution
107 |
108 | When a smart contract instance (application) is interacted with on the Algorand network, it must be performed in relation to a specific transaction or transaction group where one or many transactions are application calls to target smart contract instances.
109 |
110 | To emulate this behaviour, the `create_group` context manager is available on [`algopy.TransactionContext`](../api.md) instance that allows setting temporary transaction fields within a specific scope, passing in emulated transaction objects and identifying the active transaction index within the transaction group
111 |
112 | ```{testcode}
113 | import algopy
114 | from algopy_testing import AlgopyTestContext, algopy_testing_context
115 |
116 | class SimpleContract(algopy.ARC4Contract):
117 | @algopy.arc4.abimethod
118 | def check_sender(self) -> algopy.arc4.Address:
119 | return algopy.arc4.Address(algopy.Txn.sender)
120 | ...
121 |
122 | # Create a contract instance
123 | contract = SimpleContract()
124 | # Use active_txn_overrides to change the sender
125 | test_sender = context.any.account()
126 | with context.txn.create_group(active_txn_overrides={"sender": test_sender}):
127 | # Call the contract method
128 | result = contract.check_sender()
129 | assert result == test_sender
130 |
131 | # Assert that the sender is the test_sender after exiting the
132 | # transaction group context
133 | assert context.txn.last_active.sender == test_sender
134 | # Assert the size of last transaction group
135 | assert len(context.txn.last_group.txns) == 1
136 | ```
137 |
138 | ## Inner Transaction
139 |
140 | Inner transactions are AVM transactions that are signed and executed by AVM applications (instances of deployed smart contracts or signatures).
141 |
142 | When testing smart contracts, to stay consistent with AVM, the framework \_does not allow you to submit inner transactions outside of contract/subroutine invocation, but you can interact with and manage inner transactions using the test context manager as follows:
143 |
144 | ```{testcode}
145 | class MyContract(algopy.ARC4Contract):
146 | @algopy.arc4.abimethod
147 | def pay_via_itxn(self, asset: algopy.Asset) -> None:
148 | algopy.itxn.Payment(
149 | receiver=algopy.Txn.sender,
150 | amount=algopy.UInt64(1)
151 | ).submit()
152 |
153 | ... # setup context (below assumes available under 'context' variable)
154 |
155 | # Create a contract instance
156 | contract = MyContract()
157 |
158 | # Generate a random asset
159 | asset = context.any.asset()
160 |
161 | # Execute the contract method
162 | contract.pay_via_itxn(asset=asset)
163 |
164 | # Access the last submitted inner transaction
165 | payment_txn = context.txn.last_group.last_itxn.payment
166 |
167 | # Assert properties of the inner transaction
168 | assert payment_txn.receiver == context.txn.last_active.sender
169 | assert payment_txn.amount == algopy.UInt64(1)
170 |
171 | # Access all inner transactions in the last group
172 | for itxn in context.txn.last_group.itxn_groups[-1]:
173 | # Perform assertions on each inner transaction
174 | ...
175 |
176 | # Access a specific inner transaction group
177 | first_itxn_group = context.txn.last_group.get_itxn_group(0)
178 | first_payment_txn = first_itxn_group.payment(0)
179 | ```
180 |
181 | In this example, we define a contract method `pay_via_itxn` that creates and submits an inner payment transaction. The test context automatically captures and stores the inner transactions submitted by the contract method.
182 |
183 | Note that we don't need to wrap the execution in a `create_group` context manager because the method is decorated with `@algopy.arc4.abimethod`, which automatically creates a transaction group for the method. The `create_group` context manager is only needed when you want to create more complex transaction groups or patch transaction fields for various transaction-related opcodes in AVM.
184 |
185 | To access the submitted inner transactions:
186 |
187 | 1. Use `context.txn.last_group.last_itxn` to access the last submitted inner transaction of a specific type.
188 | 2. Iterate over all inner transactions in the last group using `context.txn.last_group.itxn_groups[-1]`.
189 | 3. Access a specific inner transaction group using `context.txn.last_group.get_itxn_group(index)`.
190 |
191 | These methods provide type validation and will raise an error if the requested transaction type doesn't match the actual type of the inner transaction.
192 |
193 | ## References
194 |
195 | - [API](../api.md) for more details on the test context manager and inner transactions related methods that perform implicit inner transaction type validation.
196 | - [Examples](../examples.md) for more examples of smart contracts and associated tests that interact with inner transactions.
197 |
198 | ```{testcleanup}
199 | ctx_manager.__exit__(None, None, None)
200 | ```
201 |
```
--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/puya:docs:lg-storage.md:
--------------------------------------------------------------------------------
```markdown
1 | # Storing data on-chain
2 |
3 | Algorand smart contracts have [three different types of on-chain storage](https://developer.algorand.org/docs/get-details/dapps/smart-contracts/apps/state/)
4 | they can utilise: [Global storage](#global-storage), [Local storage](#local-storage), [Box Storage](#box-storage), and [Scratch storage](#scratch-storage).
5 |
6 | The life-cycle of a smart contract matches the semantics of Python classes when you consider
7 | deploying a smart contract as "instantiating" the class. Any calls to that smart contract are made
8 | to that instance of the smart contract, and any state assigned to `self.` variables will persist
9 | across different invocations (provided the transaction it was a part of succeeds, of course). You can
10 | deploy the same contract class multiple times, each will become a distinct and isolated instance.
11 |
12 | During a single smart contract execution there is also the ability to use "temporary" storage
13 | either global to the contract execution via [Scratch storage](#scratch-storage), or local to
14 | the current method via [local variables and subroutine params](./lg-structure.md#subroutines).
15 |
16 | ## Global storage
17 |
18 | Global storage is state that is stored against the contract instance and can be retrieved
19 | by key. There are [AVM limits to the amount of global storage that can be allocated to a contract](https://developer.algorand.org/docs/get-details/dapps/smart-contracts/apps/state/#global-storage).
20 |
21 | This is represented in Algorand Python by either:
22 |
23 | 1. Assigning any [Algorand Python typed](./lg-types.md) value to an instance variable (e.g. `self.value = UInt64(3)`)
24 | 2. Using an instance of `GlobalState`, which gives [some extra features](./api-algopy.md#algopy.GlobalState) to understand
25 | and control the value and the metadata of it (which propagates to the ARC-32 app spec file)
26 |
27 | For example:
28 |
29 | ```python
30 | self.global_int_full = GlobalState(UInt64(55), key="gif", description="Global int full")
31 | self.global_int_simplified = UInt64(33)
32 | self.global_int_no_default = GlobalState(UInt64)
33 |
34 | self.global_bytes_full = GlobalState(Bytes(b"Hello"))
35 | self.global_bytes_simplified = Bytes(b"Hello")
36 | self.global_bytes_no_default = GlobalState(Bytes)
37 |
38 | global_int_full_set = bool(self.global_int_full)
39 | bytes_with_default_specified = self.global_bytes_no_default.get(b"Default if no value set")
40 | int, is_set = self.global_int_simplified.maybe()
41 | error_if_not_set = self.global_int_no_default.value
42 | ```
43 |
44 | These values can be assigned anywhere you have access to `self` i.e. any instance methods/subroutines. The information about
45 | global storage is automatically included in the ARC-32 app spec file and thus will automatically appear within
46 | any [generated typed clients](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/generate.md#1-typed-clients).
47 |
48 | ## Local storage
49 |
50 | Local storage is state that is stored against the contract instance for a specific account and can be retrieved
51 | by key and account address. There are [AVM limits to the amount of local storage that can be allocated to a contract](https://developer.algorand.org/docs/get-details/dapps/smart-contracts/apps/state/#local-storage).
52 |
53 | This is represented in Algorand Python by using an instance of [`LocalState`](./api-algopy.md#algopy.LocalState).
54 |
55 | For example:
56 |
57 | ```python
58 | def __init__(self) -> None:
59 | self.local = LocalState(Bytes)
60 | self.local_with_metadata = LocalState(UInt64, key = "lwm", description = "Local with metadata")
61 |
62 | @subroutine
63 | def get_guaranteed_data(self, for_account: Account) -> Bytes:
64 | return self.local[for_account]
65 |
66 | @subroutine
67 | def get_data_with_default(self, for_account: Account, default: Bytes) -> Bytes:
68 | return self.local.get(for_account, default)
69 |
70 | @subroutine
71 | def get_data_or_assert(self, for_account: Account) -> Bytes:
72 | result, exists = self.local.maybe(for_account)
73 | assert exists, "no data for account"
74 | return result
75 |
76 | @subroutine
77 | def set_data(self, for_account: Account, value: Bytes) -> None:
78 | self.local[for_account] = value
79 |
80 | @subroutine
81 | def delete_data(self, for_account: Account) -> None:
82 | del self.local[for_account]
83 | ```
84 |
85 | These values can be assigned anywhere you have access to `self` i.e. any instance methods/subroutines. The information about
86 | local storage is automatically included in the ARC-32 app spec file and thus will automatically appear within
87 | any [generated typed clients](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/generate.md#1-typed-clients).
88 |
89 | ## Box storage
90 |
91 | We provide 3 different types for accessing box storage: [Box](./api-algopy.md#algopy.Box), [BoxMap](./api-algopy.md#algopy.BoxMap), and [BoxRef](./api-algopy.md#algopy.BoxBlob). We also expose raw operations via the [AVM ops](./lg-ops.md) module.
92 |
93 | Before using box storage, be sure to familiarise yourself with the [requirements and restrictions](https://developer.algorand.org/articles/smart-contract-storage-boxes/) of the underlying API.
94 |
95 | The `Box` type provides an abstraction over storing a single value in a single box. A box can be declared against `self`
96 | in an `__init__` method (in which case the key must be a compile time constant); or as a local variable within any
97 | subroutine. `Box` proxy instances can be passed around like any other value.
98 |
99 | Once declared, you can interact with the box via its instance methods.
100 |
101 |
102 | ```python
103 | import typing as t
104 | from algopy import Box, arc4, Contract, op
105 |
106 |
107 | class MyContract(Contract):
108 | def __init__(self) -> None:
109 | self.box_a = Box(arc4.StaticArray[arc4.UInt32, t.Literal[20]], key=b"a")
110 |
111 | def approval_program(self) -> bool:
112 | box_b = Box(arc4.String, key=b"b")
113 | box_b.value = arc4.String("Hello")
114 | # Check if the box exists
115 | if self.box_a:
116 | # Reassign the value
117 | self.box_a.value[2] = arc4.UInt32(40)
118 | else:
119 | # Assign a new value
120 | self.box_a.value = arc4.StaticArray[arc4.UInt32, t.Literal[20]].from_bytes(op.bzero(20 * 4))
121 | # Read a value
122 | return self.box_a.value[4] == arc4.UInt32(2)
123 | ```
124 |
125 | `BoxMap` is similar to the `Box` type, but allows for grouping a set of boxes with a common key and content type.
126 | A custom `key_prefix` can optionally be provided, with the default being to use the variable name as the prefix.
127 | The key can be a `Bytes` value, or anything that can be converted to `Bytes`. The final box name is the combination of `key_prefix + key`.
128 |
129 | ```python
130 | from algopy import BoxMap, Contract, Account, Txn, String
131 |
132 | class MyContract(Contract):
133 | def __init__(self) -> None:
134 | self.my_map = BoxMap(Account, String, key_prefix=b"a_")
135 |
136 | def approval_program(self) -> bool:
137 | # Check if the box exists
138 | if Txn.sender in self.my_map:
139 | # Reassign the value
140 | self.my_map[Txn.sender] = String(" World")
141 | else:
142 | # Assign a new value
143 | self.my_map[Txn.sender] = String("Hello")
144 | # Read a value
145 | return self.my_map[Txn.sender] == String("Hello World")
146 | ```
147 |
148 | `BoxRef` is a specialised type for interacting with boxes which contain binary data. In addition to being able to set and read the box value, there are operations for extracting and replacing just a portion of the box data which
149 | is useful for minimizing the amount of reads and writes required, but also allows you to interact with byte arrays which are longer than the AVM can support (currently 4096).
150 |
151 | ```python
152 | from algopy import BoxRef, Contract, Global, Txn
153 |
154 |
155 | class MyContract(Contract):
156 | def approval_program(self) -> bool:
157 | my_blob = BoxRef(key=b"blob")
158 |
159 | sender_bytes = Txn.sender.bytes
160 | app_address = Global.current_application_address.bytes
161 | assert my_blob.create(8000)
162 | my_blob.replace(0, sender_bytes)
163 | my_blob.splice(0, 0, app_address)
164 | first_64 = my_blob.extract(0, 32 * 2)
165 | assert first_64 == app_address + sender_bytes
166 | assert my_blob.delete()
167 | value, exists = my_blob.maybe()
168 | assert not exists
169 | assert my_blob.get(default=sender_bytes) == sender_bytes
170 | my_blob.create(sender_bytes + app_address)
171 | assert my_blob, "Blob exists"
172 | assert my_blob.length == 64
173 | return True
174 | ```
175 |
176 |
177 |
178 | If none of these abstractions suit your needs, you can use the box storage [AVM ops](./lg-ops.md) to interact with box storage. These ops match closely to the opcodes available on the AVM.
179 |
180 | For example:
181 |
182 | ```python
183 | op.Box.create(b"key", size)
184 | op.Box.put(Txn.sender.bytes, answer_ids.bytes)
185 | (votes, exists) = op.Box.get(Txn.sender.bytes)
186 | op.Box.replace(TALLY_BOX_KEY, index, op.itob(current_vote + 1))
187 | ```
188 |
189 | See the [voting contract example](https://github.com/algorandfoundation/puya/tree/main/examples/voting/voting.py) for a real-world example that uses box storage.
190 |
191 | ## Scratch storage
192 |
193 | To use stratch storage you need to [register the scratch storage that you want to use](./lg-structure.md#contract-class-configuration) and then you can use the scratch storage [AVM ops](./lg-ops.md).
194 |
195 | For example:
196 |
197 | ```python
198 | from algopy import Bytes, Contract, UInt64, op, urange
199 |
200 | TWO = 2
201 | TWENTY = 20
202 |
203 |
204 | class MyContract(Contract, scratch_slots=(1, TWO, urange(3, TWENTY))):
205 | def approval_program(self) -> bool:
206 | op.Scratch.store(1, UInt64(5))
207 |
208 | op.Scratch.store(2, Bytes(b"Hello World"))
209 |
210 | for i in urange(3, 20):
211 | op.Scratch.store(i, i)
212 |
213 | assert op.Scratch.load_uint64(1) == UInt64(5)
214 |
215 | assert op.Scratch.load_bytes(2) == b"Hello World"
216 |
217 | assert op.Scratch.load_uint64(5) == UInt64(5)
218 | return True
219 |
220 | def clear_state_program(self) -> bool:
221 | return True
222 | ```
223 |
```
--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/algokit:utils:typescript:code:interfaces:types_app_arc56.Arc56Contract.md:
--------------------------------------------------------------------------------
```markdown
1 | [@algorandfoundation/algokit-utils](../README.md) / [types/app-arc56](../modules/types_app_arc56.md) / Arc56Contract
2 |
3 | # Interface: Arc56Contract
4 |
5 | [types/app-arc56](../modules/types_app_arc56.md).Arc56Contract
6 |
7 | Describes the entire contract. This interface is an extension of the interface described in ARC-4
8 |
9 | ## Table of contents
10 |
11 | ### Properties
12 |
13 | - [arcs](types_app_arc56.Arc56Contract.md#arcs)
14 | - [bareActions](types_app_arc56.Arc56Contract.md#bareactions)
15 | - [byteCode](types_app_arc56.Arc56Contract.md#bytecode)
16 | - [compilerInfo](types_app_arc56.Arc56Contract.md#compilerinfo)
17 | - [desc](types_app_arc56.Arc56Contract.md#desc)
18 | - [events](types_app_arc56.Arc56Contract.md#events)
19 | - [methods](types_app_arc56.Arc56Contract.md#methods)
20 | - [name](types_app_arc56.Arc56Contract.md#name)
21 | - [networks](types_app_arc56.Arc56Contract.md#networks)
22 | - [scratchVariables](types_app_arc56.Arc56Contract.md#scratchvariables)
23 | - [source](types_app_arc56.Arc56Contract.md#source)
24 | - [sourceInfo](types_app_arc56.Arc56Contract.md#sourceinfo)
25 | - [state](types_app_arc56.Arc56Contract.md#state)
26 | - [structs](types_app_arc56.Arc56Contract.md#structs)
27 | - [templateVariables](types_app_arc56.Arc56Contract.md#templatevariables)
28 |
29 | ## Properties
30 |
31 | ### arcs
32 |
33 | • **arcs**: `number`[]
34 |
35 | The ARCs used and/or supported by this contract. All contracts implicitly support ARC4 and ARC56
36 |
37 | #### Defined in
38 |
39 | [src/types/app-arc56.ts:233](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app-arc56.ts#L233)
40 |
41 | ___
42 |
43 | ### bareActions
44 |
45 | • **bareActions**: `Object`
46 |
47 | Supported bare actions for the contract. An action is a combination of call/create and an OnComplete
48 |
49 | #### Type declaration
50 |
51 | | Name | Type | Description |
52 | | :------ | :------ | :------ |
53 | | `call` | (``"NoOp"`` \| ``"OptIn"`` \| ``"DeleteApplication"`` \| ``"CloseOut"`` \| ``"ClearState"`` \| ``"UpdateApplication"``)[] | OnCompletes this method allows when appID !== 0 |
54 | | `create` | (``"NoOp"`` \| ``"OptIn"`` \| ``"DeleteApplication"``)[] | OnCompletes this method allows when appID === 0 |
55 |
56 | #### Defined in
57 |
58 | [src/types/app-arc56.ts:281](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app-arc56.ts#L281)
59 |
60 | ___
61 |
62 | ### byteCode
63 |
64 | • `Optional` **byteCode**: `Object`
65 |
66 | The compiled bytecode for the application. MUST be omitted if included as part of ARC23
67 |
68 | #### Type declaration
69 |
70 | | Name | Type | Description |
71 | | :------ | :------ | :------ |
72 | | `approval` | `string` | The approval program |
73 | | `clear` | `string` | The clear program |
74 |
75 | #### Defined in
76 |
77 | [src/types/app-arc56.ts:302](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app-arc56.ts#L302)
78 |
79 | ___
80 |
81 | ### compilerInfo
82 |
83 | • `Optional` **compilerInfo**: `Object`
84 |
85 | Information used to get the given byteCode and/or PC values in sourceInfo. MUST be given if byteCode or PC values are present
86 |
87 | #### Type declaration
88 |
89 | | Name | Type | Description |
90 | | :------ | :------ | :------ |
91 | | `compiler` | ``"algod"`` \| ``"puya"`` | The name of the compiler |
92 | | `compilerVersion` | \{ `commitHash?`: `string` ; `major`: `number` ; `minor`: `number` ; `patch`: `number` } | Compiler version information |
93 | | `compilerVersion.commitHash?` | `string` | - |
94 | | `compilerVersion.major` | `number` | - |
95 | | `compilerVersion.minor` | `number` | - |
96 | | `compilerVersion.patch` | `number` | - |
97 |
98 | #### Defined in
99 |
100 | [src/types/app-arc56.ts:309](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app-arc56.ts#L309)
101 |
102 | ___
103 |
104 | ### desc
105 |
106 | • `Optional` **desc**: `string`
107 |
108 | Optional, user-friendly description for the interface
109 |
110 | #### Defined in
111 |
112 | [src/types/app-arc56.ts:237](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app-arc56.ts#L237)
113 |
114 | ___
115 |
116 | ### events
117 |
118 | • `Optional` **events**: [`Event`](types_app_arc56.Event.md)[]
119 |
120 | ARC-28 events that MAY be emitted by this contract
121 |
122 | #### Defined in
123 |
124 | [src/types/app-arc56.ts:321](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app-arc56.ts#L321)
125 |
126 | ___
127 |
128 | ### methods
129 |
130 | • **methods**: [`Method`](types_app_arc56.Method.md)[]
131 |
132 | All of the methods that the contract implements
133 |
134 | #### Defined in
135 |
136 | [src/types/app-arc56.ts:254](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app-arc56.ts#L254)
137 |
138 | ___
139 |
140 | ### name
141 |
142 | • **name**: `string`
143 |
144 | A user-friendly name for the contract
145 |
146 | #### Defined in
147 |
148 | [src/types/app-arc56.ts:235](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app-arc56.ts#L235)
149 |
150 | ___
151 |
152 | ### networks
153 |
154 | • `Optional` **networks**: `Object`
155 |
156 | Optional object listing the contract instances across different networks.
157 | The key is the base64 genesis hash of the network, and the value contains
158 | information about the deployed contract in the network indicated by the
159 | key. A key containing the human-readable name of the network MAY be
160 | included, but the corresponding genesis hash key MUST also be defined
161 |
162 | #### Index signature
163 |
164 | ▪ [network: `string`]: \{ `appID`: `number` }
165 |
166 | #### Defined in
167 |
168 | [src/types/app-arc56.ts:245](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app-arc56.ts#L245)
169 |
170 | ___
171 |
172 | ### scratchVariables
173 |
174 | • `Optional` **scratchVariables**: `Object`
175 |
176 | The scratch variables used during runtime
177 |
178 | #### Index signature
179 |
180 | ▪ [name: `string`]: \{ `slot`: `number` ; `type`: [`ABIType`](../modules/types_app_arc56.md#abitype) \| [`AVMType`](../modules/types_app_arc56.md#avmtype) \| [`StructName`](../modules/types_app_arc56.md#structname) }
181 |
182 | #### Defined in
183 |
184 | [src/types/app-arc56.ts:332](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app-arc56.ts#L332)
185 |
186 | ___
187 |
188 | ### source
189 |
190 | • `Optional` **source**: `Object`
191 |
192 | The pre-compiled TEAL that may contain template variables. MUST be omitted if included as part of ARC23
193 |
194 | #### Type declaration
195 |
196 | | Name | Type | Description |
197 | | :------ | :------ | :------ |
198 | | `approval` | `string` | The approval program |
199 | | `clear` | `string` | The clear program |
200 |
201 | #### Defined in
202 |
203 | [src/types/app-arc56.ts:295](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app-arc56.ts#L295)
204 |
205 | ___
206 |
207 | ### sourceInfo
208 |
209 | • `Optional` **sourceInfo**: `Object`
210 |
211 | Information about the TEAL programs
212 |
213 | #### Type declaration
214 |
215 | | Name | Type | Description |
216 | | :------ | :------ | :------ |
217 | | `approval` | [`ProgramSourceInfo`](types_app_arc56.ProgramSourceInfo.md) | Approval program information |
218 | | `clear` | [`ProgramSourceInfo`](types_app_arc56.ProgramSourceInfo.md) | Clear program information |
219 |
220 | #### Defined in
221 |
222 | [src/types/app-arc56.ts:288](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app-arc56.ts#L288)
223 |
224 | ___
225 |
226 | ### state
227 |
228 | • **state**: `Object`
229 |
230 | #### Type declaration
231 |
232 | | Name | Type | Description |
233 | | :------ | :------ | :------ |
234 | | `keys` | \{ `box`: \{ `[name: string]`: [`StorageKey`](types_app_arc56.StorageKey.md); } ; `global`: \{ `[name: string]`: [`StorageKey`](types_app_arc56.StorageKey.md); } ; `local`: \{ `[name: string]`: [`StorageKey`](types_app_arc56.StorageKey.md); } } | Mapping of human-readable names to StorageKey objects |
235 | | `keys.box` | \{ `[name: string]`: [`StorageKey`](types_app_arc56.StorageKey.md); } | - |
236 | | `keys.global` | \{ `[name: string]`: [`StorageKey`](types_app_arc56.StorageKey.md); } | - |
237 | | `keys.local` | \{ `[name: string]`: [`StorageKey`](types_app_arc56.StorageKey.md); } | - |
238 | | `maps` | \{ `box`: \{ `[name: string]`: [`StorageMap`](types_app_arc56.StorageMap.md); } ; `global`: \{ `[name: string]`: [`StorageMap`](types_app_arc56.StorageMap.md); } ; `local`: \{ `[name: string]`: [`StorageMap`](types_app_arc56.StorageMap.md); } } | Mapping of human-readable names to StorageMap objects |
239 | | `maps.box` | \{ `[name: string]`: [`StorageMap`](types_app_arc56.StorageMap.md); } | - |
240 | | `maps.global` | \{ `[name: string]`: [`StorageMap`](types_app_arc56.StorageMap.md); } | - |
241 | | `maps.local` | \{ `[name: string]`: [`StorageMap`](types_app_arc56.StorageMap.md); } | - |
242 | | `schema` | \{ `global`: \{ `bytes`: `number` ; `ints`: `number` } ; `local`: \{ `bytes`: `number` ; `ints`: `number` } } | Defines the values that should be used for GlobalNumUint, GlobalNumByteSlice, LocalNumUint, and LocalNumByteSlice when creating the application |
243 | | `schema.global` | \{ `bytes`: `number` ; `ints`: `number` } | - |
244 | | `schema.global.bytes` | `number` | - |
245 | | `schema.global.ints` | `number` | - |
246 | | `schema.local` | \{ `bytes`: `number` ; `ints`: `number` } | - |
247 | | `schema.local.bytes` | `number` | - |
248 | | `schema.local.ints` | `number` | - |
249 |
250 | #### Defined in
251 |
252 | [src/types/app-arc56.ts:255](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app-arc56.ts#L255)
253 |
254 | ___
255 |
256 | ### structs
257 |
258 | • **structs**: `Object`
259 |
260 | Named structs used by the application. Each struct field appears in the same order as ABI encoding.
261 |
262 | #### Index signature
263 |
264 | ▪ [structName: [`StructName`](../modules/types_app_arc56.md#structname)]: [`StructField`](types_app_arc56.StructField.md)[]
265 |
266 | #### Defined in
267 |
268 | [src/types/app-arc56.ts:252](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app-arc56.ts#L252)
269 |
270 | ___
271 |
272 | ### templateVariables
273 |
274 | • `Optional` **templateVariables**: `Object`
275 |
276 | A mapping of template variable names as they appear in the TEAL (not including TMPL_ prefix) to their respective types and values (if applicable)
277 |
278 | #### Index signature
279 |
280 | ▪ [name: `string`]: \{ `type`: [`ABIType`](../modules/types_app_arc56.md#abitype) \| [`AVMType`](../modules/types_app_arc56.md#avmtype) \| [`StructName`](../modules/types_app_arc56.md#structname) ; `value?`: `string` }
281 |
282 | #### Defined in
283 |
284 | [src/types/app-arc56.ts:323](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app-arc56.ts#L323)
285 |
```
--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/algokit:utils:python:markdown:capabilities:app-client.md:
--------------------------------------------------------------------------------
```markdown
1 | # App client
2 |
3 | Application client that works with ARC-0032 application spec defined smart contracts (e.g. via Beaker).
4 |
5 | App client is a high productivity application client that works with ARC-0032 application spec defined smart contracts, which you can use to create, update, delete, deploy and call a smart contract and access state data for it.
6 |
7 | To see some usage examples check out the [automated tests](https://github.com/algorandfoundation/algokit-utils-py/blob/main/tests/test_app_client_call.py).
8 |
9 | ## Design
10 |
11 | The design for the app client is based on a wrapper for parsing an [ARC-0032](https://github.com/algorandfoundation/ARCs/pull/150) application spec and wrapping the [App deployment](app-deploy.md) functionality and corresponding [design](app-deploy.md#id1).
12 |
13 | ## Creating an application client
14 |
15 | There are two key ways of instantiating an ApplicationClient:
16 |
17 | 1. By app ID - When needing to call an existing app by app ID or unconditionally create a new app.
18 | The signature `ApplicationClient(algod_client, app_spec, app_id=..., ...)` requires:
19 | * `algod_client`: An `AlgodClient`
20 | * `app_spec`: An `ApplicationSpecification`
21 | * `app_id`: The app_id of an existing application, or 0 if creating a new app
22 | 2. By creator and app name - When needing to deploy or find an app associated with a specific creator account and app name.
23 | The signature `ApplicationClient(algod_client, app_spec, creator=..., indexer=..., app_lookup)` requires:
24 | * `algod_client`: An `AlgodClient`
25 | * `app_spec`: An `ApplicationSpecification`
26 | * `creator`: The address or `Account` of the creator of the app for which to search for the deployed app under
27 | * `indexer`:
28 | * `app_lookup`: Optional if an indexer is provided,
29 | * `app_name`: An overridden name to identify the contract with, otherwise `contract.name` is used from the app spec
30 |
31 | Both approaches also allow specifying the following parameters that will be used as defaults for all application calls:
32 |
33 | * `signer`: `TransactionSigner` to sign transactions with.
34 | * `sender`: Address to use for transaction signing, will be derived from the signer if not provided.
35 | * `suggested_params`: Default `SuggestedParams` to use, will use current network suggested params by default
36 |
37 | Both approaches also allow specifying a mapping of template values via the `template_values` parameter, this will be used before compiling the application to replace any
38 | `TMPL_` variables that may be in the TEAL. The `TMPL_UPDATABLE` and `TMPL_DELETABLE` variables used in some AlgoKit templates are handled by the `deploy` method, but should be included if
39 | using `create` or `update` directly.
40 |
41 | ## Calling methods on the app
42 |
43 | There are various methods available on `ApplicationClient` that can be used to call an app:
44 |
45 | * `call`: Used to call methods with an on complete action of `no_op`
46 | * `create`: Used to create an instance of the app, by using an `app_id` of 0, includes the approval and clear programs in the call
47 | * `update`: Used to update an existing app, includes the approval and clear programs in the call, and is called with an on complete action of `update_application`
48 | * `delete`: Used to remove an existing app, is called with an on complete action of `delete_application`
49 | * `opt_in`: Used to opt in to an existing app, is called with an on complete action of `opt_in`
50 | * `close_out`: Used to close out of an existing app, is called with an on complete action of `opt_in`
51 | * `clear_state`: Used to unconditionally close out from an app, calls the clear program of an app
52 |
53 | ### Specifying which method
54 |
55 | All methods for calling an app that support ABI methods (everything except `clear_state`) take a parameter `call_abi_method` which can be used to specify which method to call.
56 | The method selected can be specified explicitly, or allow the client to infer the method where possible, supported values are:
57 |
58 | * `None`: The default value, when `None` is passed the client will attempt to find any ABI method or bare method that is compatible with the provided arguments
59 | * `False`: Indicates that an ABI method should not be used, and instead a bare method call is made
60 | * `True`: Indicates that an ABI method should be used, and the client will attempt to find an ABI method that is compatible with the provided arguments
61 | * `str`: If a string is provided, it will be interpreted as either an ABI signature specifying a method, or as an ABI method name
62 | * `algosdk.abi.Method`: The specified ABI method will be called
63 | * `ABIReturnSubroutine`: Any type that has a `method_spec` function that returns an `algosd.abi.Method`
64 |
65 | ### ABI arguments
66 |
67 | ABI arguments are passed as python keyword arguments e.g. to pass the ABI parameter `name` for the ABI method `hello` the following syntax is used `client.call("hello", name="world")`
68 |
69 | ### Transaction Parameters
70 |
71 | All methods for calling an app take an optional `transaction_parameters` argument, with the following supported parameters:
72 |
73 | * `signer`: The `TransactionSigner` to use on the call. This overrides any signer specified on the client
74 | * `sender`: The address of the sender to use on the call, must be able to be signed for by the `signer`. This overrides any sender specified on the client
75 | * `suggested_params`: `SuggestedParams` to use on the call. This overrides any suggested_params specified on the client
76 | * `note`: Note to include in the transaction
77 | * `lease`: Lease parameter for the transaction
78 | * `boxes`: A sequence of boxes to use in the transaction, this is a list of (app_index, box_name) tuples `[(0, "box_name"), (0, ...)]`
79 | * `accounts`: Account references to include in the transaction
80 | * `foreign_apps`: Foreign apps to include in the transaction
81 | * `foreign_assets`: Foreign assets to include in the transaction
82 | * `on_complete`: The on complete action to use for the transaction, only available when using `call` or `create`
83 | * `extra_pages`: Additional pages to allocate when calling `create`, by default a sufficient amount will be calculated based on the current approval and clear. This can be overridden, if more is required
84 | for a future update
85 |
86 | Parameters can be passed as one of the dataclasses `CommonCallParameters`, `OnCompleteCallParameters`, `CreateCallParameters` (exact type depends on method used)
87 |
88 | ```python
89 | client.call("hello", transaction_parameters=algokit_utils.OnCompleteCallParameters(signer=...))
90 | ```
91 |
92 | Alternatively, parameters can be passed as a dictionary e.g.
93 |
94 | ```python
95 | client.call("hello", transaction_parameters={"signer":...})
96 | ```
97 |
98 | ## Composing calls
99 |
100 | If multiple calls need to be made in a single transaction, the `compose_` method variants can be used. All these methods take an `AtomicTransactionComposer` as their first argument.
101 | Once all the calls have been added to the ATC, it can then be executed. For example:
102 |
103 | ```python
104 | from algokit_utils import ApplicationClient
105 | from algosdk.atomic_transaction_composer import AtomicTransactionComposer
106 |
107 | client = ApplicationClient(...)
108 | atc = AtomicTransactionComposer()
109 | client.compose_call(atc, "hello", name="world")
110 | ... # additional compose calls
111 |
112 | response = client.execute_atc(atc)
113 | ```
114 |
115 | ## Reading state
116 |
117 | There are various methods defined that let you read state from the smart contract app:
118 |
119 | * `get_global_state` - Gets the current global state of the app
120 | * `get_local_state` - Gets the current local state for the given account address
121 |
122 | ## Handling logic errors and diagnosing errors
123 |
124 | Often when calling a smart contract during development you will get logic errors that cause an exception to throw. This may be because of a failing assertion, a lack of fees,
125 | exhaustion of opcode budget, or any number of other reasons.
126 |
127 | When this occurs, you will generally get an error that looks something like: `TransactionPool.Remember: transaction {TRANSACTION_ID}: logic eval error: {ERROR_MESSAGE}. Details: pc={PROGRAM_COUNTER_VALUE}, opcodes={LIST_OF_OP_CODES}`.
128 |
129 | The information in that error message can be parsed and when combined with the [source map from compilation](app-deploy.md#id2) you can expose debugging
130 | information that makes it much easier to understand what’s happening.
131 |
132 | When an error is thrown then the resulting error that is re-thrown will be a `LogicError`, which has the following fields:
133 |
134 | * `logic_error`: Original exception
135 | * `program`: Program source (if available)
136 | * `source_map`: Source map used (if available)
137 | * `transaction_id`: Transaction ID of failing transaction
138 | * `message`: The error message
139 | * `line_no`: The line number in the TEAL program that
140 | * `traces`: A list of Trace objects providing additional insights on simulation when debug mode is active.
141 |
142 | The function `trace()` will provide a formatted output of the surrounding TEAL where the error occurred.
143 |
144 | #### NOTE
145 | The extended information will only show if the Application Client has a source map. This will occur if:
146 |
147 | 1.) The ApplicationClient instance has already called, `create, `update`or`deploy`OR 2.)`template_values`are provided when creating the ApplicationClient, so a SourceMap can be obtained automatically OR 3.)`approval_source_map`on`ApplicationClient`has been set from a previously compiled approval program OR 4.) A source map has been exported/imported using`export_source_map`/`import_source_map\`”””
148 |
149 | ### Debug Mode and traces Field
150 |
151 | When debug mode is active, the LogicError will contain a field named traces. This field will include raw simulate execution traces, providing a detailed account of the transaction simulation. These traces are crucial for diagnosing complex issues and are automatically included in all application client calls when debug mode is active.
152 |
153 | #### NOTE
154 | Remember to enable debug mode (`config.debug = True`) to include raw simulate execution traces in the `LogicError`.
155 |
```
--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/algokit:utils:python:source:capabilities:app-client.md:
--------------------------------------------------------------------------------
```markdown
1 | # App client
2 |
3 | Application client that works with ARC-0032 application spec defined smart contracts (e.g. via Beaker).
4 |
5 | App client is a high productivity application client that works with ARC-0032 application spec defined smart contracts, which you can use to create, update, delete, deploy and call a smart contract and access state data for it.
6 |
7 | To see some usage examples check out the [automated tests](https://github.com/algorandfoundation/algokit-utils-py/blob/main/tests/test_app_client_call.py).
8 |
9 | ## Design
10 |
11 | The design for the app client is based on a wrapper for parsing an [ARC-0032](https://github.com/algorandfoundation/ARCs/pull/150) application spec and wrapping the [App deployment](./app-deploy.md) functionality and corresponding [design](./app-deploy.md#design).
12 |
13 | ## Creating an application client
14 |
15 | There are two key ways of instantiating an ApplicationClient:
16 |
17 | 1. By app ID - When needing to call an existing app by app ID or unconditionally create a new app.
18 | The signature `ApplicationClient(algod_client, app_spec, app_id=..., ...)` requires:
19 | * `algod_client`: An `AlgodClient`
20 | * `app_spec`: An `ApplicationSpecification`
21 | * `app_id`: The app_id of an existing application, or 0 if creating a new app
22 |
23 | 2. By creator and app name - When needing to deploy or find an app associated with a specific creator account and app name.
24 | The signature `ApplicationClient(algod_client, app_spec, creator=..., indexer=..., app_lookup)` requires:
25 | * `algod_client`: An `AlgodClient`
26 | * `app_spec`: An `ApplicationSpecification`
27 | * `creator`: The address or `Account` of the creator of the app for which to search for the deployed app under
28 | * `indexer`:
29 | * `app_lookup`: Optional if an indexer is provided,
30 | * `app_name`: An overridden name to identify the contract with, otherwise `contract.name` is used from the app spec
31 |
32 | Both approaches also allow specifying the following parameters that will be used as defaults for all application calls:
33 | * `signer`: `TransactionSigner` to sign transactions with.
34 | * `sender`: Address to use for transaction signing, will be derived from the signer if not provided.
35 | * `suggested_params`: Default `SuggestedParams` to use, will use current network suggested params by default
36 |
37 | Both approaches also allow specifying a mapping of template values via the `template_values` parameter, this will be used before compiling the application to replace any
38 | `TMPL_` variables that may be in the TEAL. The `TMPL_UPDATABLE` and `TMPL_DELETABLE` variables used in some AlgoKit templates are handled by the `deploy` method, but should be included if
39 | using `create` or `update` directly.
40 |
41 | ## Calling methods on the app
42 |
43 | There are various methods available on `ApplicationClient` that can be used to call an app:
44 |
45 | * `call`: Used to call methods with an on complete action of `no_op`
46 | * `create`: Used to create an instance of the app, by using an `app_id` of 0, includes the approval and clear programs in the call
47 | * `update`: Used to update an existing app, includes the approval and clear programs in the call, and is called with an on complete action of `update_application`
48 | * `delete`: Used to remove an existing app, is called with an on complete action of `delete_application`
49 | * `opt_in`: Used to opt in to an existing app, is called with an on complete action of `opt_in`
50 | * `close_out`: Used to close out of an existing app, is called with an on complete action of `opt_in`
51 | * `clear_state`: Used to unconditionally close out from an app, calls the clear program of an app
52 |
53 | ### Specifying which method
54 |
55 | All methods for calling an app that support ABI methods (everything except `clear_state`) take a parameter `call_abi_method` which can be used to specify which method to call.
56 | The method selected can be specified explicitly, or allow the client to infer the method where possible, supported values are:
57 |
58 | * `None`: The default value, when `None` is passed the client will attempt to find any ABI method or bare method that is compatible with the provided arguments
59 | * `False`: Indicates that an ABI method should not be used, and instead a bare method call is made
60 | * `True`: Indicates that an ABI method should be used, and the client will attempt to find an ABI method that is compatible with the provided arguments
61 | * `str`: If a string is provided, it will be interpreted as either an ABI signature specifying a method, or as an ABI method name
62 | * `algosdk.abi.Method`: The specified ABI method will be called
63 | * `ABIReturnSubroutine`: Any type that has a `method_spec` function that returns an `algosd.abi.Method`
64 |
65 | ### ABI arguments
66 |
67 | ABI arguments are passed as python keyword arguments e.g. to pass the ABI parameter `name` for the ABI method `hello` the following syntax is used `client.call("hello", name="world")`
68 |
69 | ### Transaction Parameters
70 |
71 | All methods for calling an app take an optional `transaction_parameters` argument, with the following supported parameters:
72 |
73 | * `signer`: The `TransactionSigner` to use on the call. This overrides any signer specified on the client
74 | * `sender`: The address of the sender to use on the call, must be able to be signed for by the `signer`. This overrides any sender specified on the client
75 | * `suggested_params`: `SuggestedParams` to use on the call. This overrides any suggested_params specified on the client
76 | * `note`: Note to include in the transaction
77 | * `lease`: Lease parameter for the transaction
78 | * `boxes`: A sequence of boxes to use in the transaction, this is a list of (app_index, box_name) tuples `[(0, "box_name"), (0, ...)]`
79 | * `accounts`: Account references to include in the transaction
80 | * `foreign_apps`: Foreign apps to include in the transaction
81 | * `foreign_assets`: Foreign assets to include in the transaction
82 | * `on_complete`: The on complete action to use for the transaction, only available when using `call` or `create`
83 | * `extra_pages`: Additional pages to allocate when calling `create`, by default a sufficient amount will be calculated based on the current approval and clear. This can be overridden, if more is required
84 | for a future update
85 |
86 | Parameters can be passed as one of the dataclasses `CommonCallParameters`, `OnCompleteCallParameters`, `CreateCallParameters` (exact type depends on method used)
87 | ```python
88 | client.call("hello", transaction_parameters=algokit_utils.OnCompleteCallParameters(signer=...))
89 | ```
90 |
91 | Alternatively, parameters can be passed as a dictionary e.g.
92 | ```python
93 | client.call("hello", transaction_parameters={"signer":...})
94 | ```
95 |
96 | ## Composing calls
97 |
98 | If multiple calls need to be made in a single transaction, the `compose_` method variants can be used. All these methods take an `AtomicTransactionComposer` as their first argument.
99 | Once all the calls have been added to the ATC, it can then be executed. For example:
100 |
101 | ```python
102 | from algokit_utils import ApplicationClient
103 | from algosdk.atomic_transaction_composer import AtomicTransactionComposer
104 |
105 | client = ApplicationClient(...)
106 | atc = AtomicTransactionComposer()
107 | client.compose_call(atc, "hello", name="world")
108 | ... # additional compose calls
109 |
110 | response = client.execute_atc(atc)
111 | ```
112 |
113 |
114 | ## Reading state
115 |
116 | There are various methods defined that let you read state from the smart contract app:
117 |
118 | * `get_global_state` - Gets the current global state of the app
119 | * `get_local_state` - Gets the current local state for the given account address
120 |
121 | ## Handling logic errors and diagnosing errors
122 |
123 | Often when calling a smart contract during development you will get logic errors that cause an exception to throw. This may be because of a failing assertion, a lack of fees,
124 | exhaustion of opcode budget, or any number of other reasons.
125 |
126 | When this occurs, you will generally get an error that looks something like: `TransactionPool.Remember: transaction {TRANSACTION_ID}: logic eval error: {ERROR_MESSAGE}. Details: pc={PROGRAM_COUNTER_VALUE}, opcodes={LIST_OF_OP_CODES}`.
127 |
128 | The information in that error message can be parsed and when combined with the [source map from compilation](./app-deploy.md#compilation-and-template-substitution) you can expose debugging
129 | information that makes it much easier to understand what's happening.
130 |
131 | When an error is thrown then the resulting error that is re-thrown will be a `LogicError`, which has the following fields:
132 |
133 | * `logic_error`: Original exception
134 | * `program`: Program source (if available)
135 | * `source_map`: Source map used (if available)
136 | * `transaction_id`: Transaction ID of failing transaction
137 | * `message`: The error message
138 | * `line_no`: The line number in the TEAL program that
139 | * `traces`: A list of Trace objects providing additional insights on simulation when debug mode is active.
140 |
141 | The function `trace()` will provide a formatted output of the surrounding TEAL where the error occurred.
142 |
143 | ```{note}
144 | The extended information will only show if the Application Client has a source map. This will occur if:
145 |
146 | 1.) The ApplicationClient instance has already called, `create, `update` or `deploy` OR
147 | 2.) `template_values` are provided when creating the ApplicationClient, so a SourceMap can be obtained automatically OR
148 | 3.) `approval_source_map` on `ApplicationClient` has been set from a previously compiled approval program OR
149 | 4.) A source map has been exported/imported using `export_source_map`/`import_source_map`"""
150 | ```
151 |
152 | ### Debug Mode and traces Field
153 | When debug mode is active, the LogicError will contain a field named traces. This field will include raw simulate execution traces, providing a detailed account of the transaction simulation. These traces are crucial for diagnosing complex issues and are automatically included in all application client calls when debug mode is active.
154 |
155 | ```{note}
156 | Remember to enable debug mode (`config.debug = True`) to include raw simulate execution traces in the `LogicError`.
157 | ```
```
--------------------------------------------------------------------------------
/packages/server/src/tools/apiManager/vestige/assets.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { Tool, ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
2 | import { ResponseProcessor } from '../../../utils/responseProcessor.js';
3 | import { env } from '../../../env.js';
4 |
5 | export const assetTools: Tool[] = [
6 | // Asset List and Search
7 | {
8 | name: 'api_vestige_view_assets',
9 | description: 'Get data about assets',
10 | inputSchema: {
11 | type: 'object',
12 | properties: {
13 | network_id: {
14 | type: 'integer',
15 | description: 'Network ID'
16 | },
17 | asset_ids: {
18 | type: 'string',
19 | description: 'Comma-separated list of asset IDs'
20 | }
21 | },
22 | required: ['network_id', 'asset_ids']
23 | }
24 | },
25 | {
26 | name: 'api_vestige_view_assets_list',
27 | description: 'Get asset list',
28 | inputSchema: {
29 | type: 'object',
30 | properties: {
31 | network_id: {
32 | type: 'integer',
33 | description: 'Network ID'
34 | },
35 | asset_ids: {
36 | type: 'string',
37 | description: 'Optional comma-separated list of asset IDs'
38 | },
39 | denominating_asset_id: {
40 | type: 'integer',
41 | description: 'Optional denominating asset ID',
42 | default: 0
43 | },
44 | include_labels: {
45 | type: 'string',
46 | description: 'Optional comma-separated list of labels to include'
47 | },
48 | exclude_labels: {
49 | type: 'string',
50 | description: 'Optional comma-separated list of labels to exclude'
51 | },
52 | limit: {
53 | type: 'integer',
54 | description: 'Maximum number of results',
55 | default: 50,
56 | maximum: 250,
57 | minimum: 1
58 | },
59 | offset: {
60 | type: 'integer',
61 | description: 'Number of results to skip',
62 | default: 0,
63 | minimum: 0
64 | },
65 | order_by: {
66 | type: 'string',
67 | description: 'Field to order by'
68 | },
69 | order_dir: {
70 | type: 'string',
71 | description: 'Order direction (asc/desc)',
72 | default: 'desc',
73 | pattern: '^(asc|desc)$'
74 | },
75 | tvl__lt: {
76 | type: 'number',
77 | description: 'Filter by TVL less than'
78 | },
79 | tvl__gt: {
80 | type: 'number',
81 | description: 'Filter by TVL greater than'
82 | },
83 | market_cap__lt: {
84 | type: 'number',
85 | description: 'Filter by market cap less than'
86 | },
87 | market_cap__gt: {
88 | type: 'number',
89 | description: 'Filter by market cap greater than'
90 | },
91 | fully_diluted_market_cap__lt: {
92 | type: 'number',
93 | description: 'Filter by fully diluted market cap less than'
94 | },
95 | fully_diluted_market_cap__gt: {
96 | type: 'number',
97 | description: 'Filter by fully diluted market cap greater than'
98 | },
99 | volume1d__lt: {
100 | type: 'number',
101 | description: 'Filter by 24h volume less than'
102 | },
103 | volume1d__gt: {
104 | type: 'number',
105 | description: 'Filter by 24h volume greater than'
106 | },
107 | created_at__lt: {
108 | type: 'integer',
109 | description: 'Filter by creation time less than'
110 | },
111 | created_at__gt: {
112 | type: 'integer',
113 | description: 'Filter by creation time greater than'
114 | }
115 | },
116 | required: ['network_id']
117 | }
118 | },
119 | {
120 | name: 'api_vestige_view_assets_search',
121 | description: 'Search assets by query',
122 | inputSchema: {
123 | type: 'object',
124 | properties: {
125 | network_id: {
126 | type: 'integer',
127 | description: 'Network ID'
128 | },
129 | query: {
130 | type: 'string',
131 | description: 'Search query'
132 | },
133 | protocol_id: {
134 | type: 'integer',
135 | description: 'Optional protocol ID filter'
136 | },
137 | denominating_asset_id: {
138 | type: 'integer',
139 | description: 'Optional denominating asset ID',
140 | default: 0
141 | },
142 | limit: {
143 | type: 'integer',
144 | description: 'Maximum number of results',
145 | default: 50,
146 | maximum: 250,
147 | minimum: 1
148 | },
149 | offset: {
150 | type: 'integer',
151 | description: 'Number of results to skip',
152 | default: 0,
153 | minimum: 0
154 | },
155 | order_by: {
156 | type: 'string',
157 | description: 'Field to order by'
158 | },
159 | order_dir: {
160 | type: 'string',
161 | description: 'Order direction (asc/desc)',
162 | default: 'desc',
163 | pattern: '^(asc|desc)$'
164 | }
165 | },
166 | required: ['network_id', 'query']
167 | }
168 | },
169 |
170 | // Asset Details and Price
171 | {
172 | name: 'api_vestige_view_asset_price',
173 | description: 'Get asset prices',
174 | inputSchema: {
175 | type: 'object',
176 | properties: {
177 | network_id: {
178 | type: 'integer',
179 | description: 'Network ID'
180 | },
181 | asset_ids: {
182 | type: 'string',
183 | description: 'Comma-separated list of asset IDs'
184 | },
185 | denominating_asset_id: {
186 | type: 'integer',
187 | description: 'Optional denominating asset ID',
188 | default: 0
189 | }
190 | },
191 | required: ['network_id', 'asset_ids']
192 | }
193 | },
194 |
195 | // Asset History and Candles
196 | {
197 | name: 'api_vestige_view_asset_candles',
198 | description: 'Get asset candles',
199 | inputSchema: {
200 | type: 'object',
201 | properties: {
202 | network_id: {
203 | type: 'integer',
204 | description: 'Network ID'
205 | },
206 | asset_id: {
207 | type: 'integer',
208 | description: 'Asset ID'
209 | },
210 | interval: {
211 | type: 'integer',
212 | description: 'Candle interval in seconds'
213 | },
214 | start: {
215 | type: 'integer',
216 | description: 'Start timestamp'
217 | },
218 | end: {
219 | type: 'integer',
220 | description: 'Optional end timestamp'
221 | },
222 | denominating_asset_id: {
223 | type: 'integer',
224 | description: 'Optional denominating asset ID',
225 | default: 0
226 | },
227 | volume_in_denominating_asset: {
228 | type: 'boolean',
229 | description: 'Whether to return volume in denominating asset',
230 | default: false
231 | }
232 | },
233 | required: ['network_id', 'asset_id', 'interval', 'start']
234 | }
235 | },
236 | {
237 | name: 'api_vestige_view_asset_history',
238 | description: 'Get asset volume, swaps, total lockup, vwap and confidence history',
239 | inputSchema: {
240 | type: 'object',
241 | properties: {
242 | network_id: {
243 | type: 'integer',
244 | description: 'Network ID'
245 | },
246 | asset_id: {
247 | type: 'integer',
248 | description: 'Asset ID'
249 | },
250 | interval: {
251 | type: 'integer',
252 | description: 'History interval in seconds'
253 | },
254 | start: {
255 | type: 'integer',
256 | description: 'Start timestamp'
257 | },
258 | end: {
259 | type: 'integer',
260 | description: 'Optional end timestamp'
261 | },
262 | denominating_asset_id: {
263 | type: 'integer',
264 | description: 'Optional denominating asset ID',
265 | default: 0
266 | },
267 | volume_in_denominating_asset: {
268 | type: 'boolean',
269 | description: 'Whether to return volume in denominating asset',
270 | default: false
271 | }
272 | },
273 | required: ['network_id', 'asset_id', 'interval', 'start']
274 | }
275 | },
276 |
277 | // Asset Composition
278 | {
279 | name: 'api_vestige_view_asset_composition',
280 | description: 'Get asset lockups based on protocol and pair',
281 | inputSchema: {
282 | type: 'object',
283 | properties: {
284 | network_id: {
285 | type: 'integer',
286 | description: 'Network ID'
287 | },
288 | asset_id: {
289 | type: 'integer',
290 | description: 'Asset ID'
291 | }
292 | },
293 | required: ['network_id', 'asset_id']
294 | }
295 | }
296 | ];
297 |
298 |
299 |
300 | export const handleAssetTools = ResponseProcessor.wrapResourceHandler(async function handleAssetTools(args: any): Promise<any> {
301 | const name = args.name;
302 | const baseUrl = env.vestige_api_url;
303 | let endpoint = '';
304 |
305 | switch (name) {
306 | case 'api_vestige_view_assets':
307 | endpoint = '/assets';
308 | break;
309 | case 'api_vestige_view_assets_list':
310 | endpoint = '/assets/list';
311 | break;
312 | case 'api_vestige_view_assets_search':
313 | endpoint = '/assets/search';
314 | break;
315 | case 'api_vestige_view_asset_price':
316 | endpoint = '/assets/price';
317 | break;
318 | case 'api_vestige_view_asset_candles':
319 | endpoint = `/assets/${args.asset_id}/candles`;
320 | break;
321 | case 'api_vestige_view_asset_history':
322 | endpoint = `/assets/${args.asset_id}/history`;
323 | break;
324 | case 'api_vestige_view_asset_composition':
325 | endpoint = `/assets/${args.asset_id}/composition`;
326 | break;
327 | default:
328 | throw new McpError(
329 | ErrorCode.MethodNotFound,
330 | `Unknown tool: ${name}`
331 | );
332 | }
333 |
334 | try {
335 | // Add query parameters if they exist
336 | const queryParams = new URLSearchParams();
337 | for (const [key, value] of Object.entries(args)) {
338 | if (value !== undefined && key !== 'asset_id') {
339 | queryParams.append(key, String(value));
340 | }
341 | }
342 | const url = `${baseUrl}${endpoint}${queryParams.toString() ? `?${queryParams.toString()}` : ''}`;
343 |
344 | const response = await fetch(url);
345 | if (!response.ok) {
346 | throw new McpError(
347 | ErrorCode.InternalError,
348 | `Vestige API error: ${response.status} ${response.statusText}`
349 | );
350 | }
351 | const data = await response.json();
352 | return data;
353 | } catch (error) {
354 | if (error instanceof McpError) {
355 | throw error;
356 | }
357 | throw new McpError(
358 | ErrorCode.InternalError,
359 | `Failed to fetch asset data: ${error instanceof Error ? error.message : String(error)}`
360 | );
361 | }
362 | });
363 |
```
--------------------------------------------------------------------------------
/packages/server/src/tools/apiManager/indexer/asset.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
2 | import { indexerClient } from '../../../algorand-client.js';
3 | import { ResponseProcessor } from '../../../utils/responseProcessor.js';
4 | import type {
5 | AssetResponse,
6 | AssetsResponse,
7 | AssetBalancesResponse,
8 | TransactionsResponse
9 | } from 'algosdk/dist/types/client/v2/indexer/models/types';
10 |
11 | export const assetTools = [
12 | {
13 | name: 'api_indexer_lookup_asset_by_id',
14 | description: 'Get asset information and configuration',
15 | inputSchema: {
16 | type: 'object',
17 | properties: {
18 | assetId: {
19 | type: 'integer',
20 | description: 'Asset ID'
21 | }
22 | },
23 | required: ['assetId']
24 | }
25 | },
26 | {
27 | name: 'api_indexer_lookup_asset_balances',
28 | description: 'Get accounts holding this asset and their balances',
29 | inputSchema: {
30 | type: 'object',
31 | properties: {
32 | assetId: {
33 | type: 'integer',
34 | description: 'Asset ID'
35 | },
36 | limit: {
37 | type: 'integer',
38 | description: 'Maximum number of balances to return'
39 | },
40 | currencyGreaterThan: {
41 | type: 'integer',
42 | description: 'Filter by minimum balance'
43 | },
44 | currencyLessThan: {
45 | type: 'integer',
46 | description: 'Filter by maximum balance'
47 | },
48 | nextToken: {
49 | type: 'string',
50 | description: 'Token for retrieving the next page of results'
51 | },
52 | address: {
53 | type: 'string',
54 | description: 'Filter by account address'
55 | }
56 | },
57 | required: ['assetId']
58 | }
59 | },
60 | {
61 | name: 'api_indexer_lookup_asset_transactions',
62 | description: 'Get transactions involving this asset',
63 | inputSchema: {
64 | type: 'object',
65 | properties: {
66 | assetId: {
67 | type: 'integer',
68 | description: 'Asset ID'
69 | },
70 | limit: {
71 | type: 'integer',
72 | description: 'Maximum number of transactions to return'
73 | },
74 | beforeTime: {
75 | type: 'string',
76 | description: 'Only return transactions before this time'
77 | },
78 | afterTime: {
79 | type: 'string',
80 | description: 'Only return transactions after this time'
81 | },
82 | minRound: {
83 | type: 'integer',
84 | description: 'Only return transactions after this round'
85 | },
86 | maxRound: {
87 | type: 'integer',
88 | description: 'Only return transactions before this round'
89 | },
90 | address: {
91 | type: 'string',
92 | description: 'Filter by account address'
93 | },
94 | addressRole: {
95 | type: 'string',
96 | description: 'Filter by address role (sender or receiver)'
97 | },
98 | excludeCloseTo: {
99 | type: 'boolean',
100 | description: 'Whether to exclude close-to transactions'
101 | },
102 | nextToken: {
103 | type: 'string',
104 | description: 'Token for retrieving the next page of results'
105 | },
106 | txid: {
107 | type: 'string',
108 | description: 'Filter by transaction ID'
109 | }
110 | },
111 | required: ['assetId']
112 | }
113 | },
114 | {
115 | name: 'api_indexer_search_for_assets',
116 | description: 'Search for assets with various criteria',
117 | inputSchema: {
118 | type: 'object',
119 | properties: {
120 | limit: {
121 | type: 'integer',
122 | description: 'Maximum number of assets to return'
123 | },
124 | creator: {
125 | type: 'string',
126 | description: 'Filter by creator address'
127 | },
128 | name: {
129 | type: 'string',
130 | description: 'Filter by asset name'
131 | },
132 | unit: {
133 | type: 'string',
134 | description: 'Filter by asset unit name'
135 | },
136 | assetId: {
137 | type: 'integer',
138 | description: 'Filter by asset ID'
139 | },
140 | nextToken: {
141 | type: 'string',
142 | description: 'Token for retrieving the next page of results'
143 | }
144 | }
145 | }
146 | }
147 | ];
148 |
149 | export async function lookupAssetByID(assetId: number): Promise<AssetResponse> {
150 | try {
151 | console.log(`Looking up asset info for ID ${assetId}`);
152 | const response = await indexerClient.lookupAssetByID(assetId).do() as AssetResponse;
153 | console.log('Asset response:', JSON.stringify(response, null, 2));
154 | return response;
155 | } catch (error) {
156 | console.error('Asset lookup error:', error);
157 | if (error instanceof McpError) {
158 | throw error;
159 | }
160 | throw new McpError(
161 | ErrorCode.InternalError,
162 | `Failed to get asset info: ${error instanceof Error ? error.message : String(error)}`
163 | );
164 | }
165 | }
166 |
167 | export async function lookupAssetBalances(assetId: number, params?: {
168 | limit?: number;
169 | currencyGreaterThan?: number;
170 | currencyLessThan?: number;
171 | nextToken?: string;
172 | address?: string;
173 | }): Promise<AssetBalancesResponse> {
174 | try {
175 | console.log(`Looking up balances for asset ${assetId}`);
176 | let search = indexerClient.lookupAssetBalances(assetId);
177 |
178 | if (params?.limit) {
179 | search = search.limit(params.limit);
180 | }
181 | if (params?.currencyGreaterThan) {
182 | search = search.currencyGreaterThan(params.currencyGreaterThan);
183 | }
184 | if (params?.currencyLessThan) {
185 | search = search.currencyLessThan(params.currencyLessThan);
186 | }
187 | if (params?.nextToken) {
188 | search = search.nextToken(params.nextToken);
189 | }
190 |
191 | const response = await search.do() as AssetBalancesResponse;
192 | console.log('Asset balances response:', JSON.stringify(response, null, 2));
193 | return response;
194 | } catch (error) {
195 | console.error('Asset balances lookup error:', error);
196 | if (error instanceof McpError) {
197 | throw error;
198 | }
199 | throw new McpError(
200 | ErrorCode.InternalError,
201 | `Failed to get asset balances: ${error instanceof Error ? error.message : String(error)}`
202 | );
203 | }
204 | }
205 |
206 | export async function lookupAssetTransactions(assetId: number, params?: {
207 | limit?: number;
208 | beforeTime?: string;
209 | afterTime?: string;
210 | minRound?: number;
211 | maxRound?: number;
212 | address?: string;
213 | addressRole?: string;
214 | excludeCloseTo?: boolean;
215 | nextToken?: string;
216 | txid?: string;
217 | }): Promise<TransactionsResponse> {
218 | try {
219 | console.log(`Looking up transactions for asset ${assetId}`);
220 | let search = indexerClient.lookupAssetTransactions(assetId);
221 |
222 | if (params?.limit) {
223 | search = search.limit(params.limit);
224 | }
225 | if (params?.beforeTime) {
226 | search = search.beforeTime(params.beforeTime);
227 | }
228 | if (params?.afterTime) {
229 | search = search.afterTime(params.afterTime);
230 | }
231 | if (params?.minRound) {
232 | search = search.minRound(params.minRound);
233 | }
234 | if (params?.maxRound) {
235 | search = search.maxRound(params.maxRound);
236 | }
237 | if (params?.address) {
238 | search = search.address(params.address);
239 | }
240 | if (params?.addressRole) {
241 | search = search.addressRole(params.addressRole);
242 | }
243 | if (params?.excludeCloseTo) {
244 | search = search.excludeCloseTo(params.excludeCloseTo);
245 | }
246 | if (params?.nextToken) {
247 | search = search.nextToken(params.nextToken);
248 | }
249 |
250 | const response = await search.do() as TransactionsResponse;
251 | console.log('Asset transactions response:', JSON.stringify(response, null, 2));
252 | return response;
253 | } catch (error) {
254 | console.error('Asset transactions lookup error:', error);
255 | if (error instanceof McpError) {
256 | throw error;
257 | }
258 | throw new McpError(
259 | ErrorCode.InternalError,
260 | `Failed to get asset transactions: ${error instanceof Error ? error.message : String(error)}`
261 | );
262 | }
263 | }
264 |
265 | export async function searchForAssets(params?: {
266 | limit?: number;
267 | creator?: string;
268 | name?: string;
269 | unit?: string;
270 | assetId?: number;
271 | nextToken?: string;
272 | }): Promise<AssetsResponse> {
273 | try {
274 | console.log('Searching assets with params:', params);
275 | let search = indexerClient.searchForAssets();
276 |
277 | if (params?.limit) {
278 | search = search.limit(params.limit);
279 | }
280 | if (params?.creator) {
281 | search = search.creator(params.creator);
282 | }
283 | if (params?.name) {
284 | search = search.name(params.name);
285 | }
286 | if (params?.unit) {
287 | search = search.unit(params.unit);
288 | }
289 | if (params?.assetId) {
290 | search = search.index(params.assetId);
291 | }
292 | if (params?.nextToken) {
293 | search = search.nextToken(params.nextToken);
294 | }
295 |
296 | const response = await search.do() as AssetsResponse;
297 | console.log('Search assets response:', JSON.stringify(response, null, 2));
298 | return response;
299 | } catch (error) {
300 | console.error('Search assets error:', error);
301 | if (error instanceof McpError) {
302 | throw error;
303 | }
304 | throw new McpError(
305 | ErrorCode.InternalError,
306 | `Failed to search assets: ${error instanceof Error ? error.message : String(error)}`
307 | );
308 | }
309 | }
310 |
311 | export const handleAssetTools = ResponseProcessor.wrapResourceHandler(async function handleAssetTools(args: any): Promise<any> {
312 | const name = args.name;
313 |
314 | switch (name) {
315 | case 'api_indexer_lookup_asset_by_id': {
316 | const { assetId } = args;
317 | const info = await lookupAssetByID(assetId);
318 | return info.asset;
319 | }
320 | case 'api_indexer_lookup_asset_balances': {
321 | const { assetId, ...params } = args;
322 | const balances = await lookupAssetBalances(assetId, params);
323 | return balances.balances;
324 | }
325 | case 'api_indexer_lookup_asset_transactions': {
326 | const { assetId, ...params } = args;
327 | const transactions = await lookupAssetTransactions(assetId, params);
328 | return transactions.transactions;
329 | }
330 | case 'api_indexer_search_for_assets': {
331 | const assets = await searchForAssets(args);
332 | return assets.assets;
333 | }
334 | default:
335 | throw new McpError(
336 | ErrorCode.MethodNotFound,
337 | `Unknown tool: ${name}`
338 | );
339 | }
340 | });
341 |
```
--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/puya:typescript:docs:architecture-decisions:2024-05-21_primitive-bytes-and-strings.md:
--------------------------------------------------------------------------------
```markdown
1 | # Architecture Decision Record - Primitive bytes and strings
2 |
3 | - **Status**: Draft
4 | - **Owner:** Tristan Menzel
5 | - **Deciders**: Alessandro Cappellato (Algorand Foundation), Joe Polny (Algorand Foundation), Rob Moore (MakerX)
6 | - **Date created**: 2024-05-21
7 | - **Date decided**: N/A
8 | - **Date updated**: 2024-05-31
9 |
10 | ## Context
11 |
12 | See [Architecture Decision Record - Primitive integer types](./2024-05-21_primitive-integer-types.md) for related decision and context.
13 |
14 | The AVM's only non-integer type is a variable length byte array. When *not* being interpreted as a `biguint`, leading zeros are significant and length is constant unless explicitly manipulated. Strings can only be represented in the AVM if they are encoded as bytes. The AVM supports byte literals in the form of base16, base64, and UTF-8 encoded strings. Once a literal has been parsed, the AVM has no concept of the original encoding or of UTF-8 characters. As a result, whilst a byte array can be indexed to receive a single byte (or a slice of bytes); it cannot be indexed to return a single UTF-8 *character* - unless one assumes all characters in the original string were ASCII (i.e. single byte) characters.
15 |
16 | Algorand Python has specific [Bytes and String types](https://algorandfoundation.github.io/puya/lg-types.html#avm-types) that have semantics that exactly match the AVM semantics. Python allows for operator overloading so these types also use native operators (where they align to functionality in the underlying AVM).
17 |
18 |
19 | ## Requirements
20 |
21 | - Support bytes AVM type and a string type that supports ASCII UTF-8 strings
22 | - Use idiomatic TypeScript expressions for string expressions
23 | - Semantic compatibility between AVM execution and TypeScript execution (e.g. in unit tests)
24 |
25 | ## Principles
26 |
27 | - **[AlgoKit Guiding Principles](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/algokit.md#guiding-principles)** - specifically Seamless onramp, Leverage existing ecosystem, Meet devs where they are
28 | - **[Algorand Python Principles](https://algorandfoundation.github.io/puya/principles.html#principles)**
29 | - **[Algorand TypeScript Guiding Principles](../README.md#guiding-principals)**
30 |
31 | ## Options
32 |
33 |
34 | ### Option 1 - Direct use of native EcmaScript types
35 |
36 |
37 | EcmaScript provides two relevant types for bytes and strings.
38 |
39 | - **string**: The native string type. Supports arbitrary length, concatenation, indexation/slicing of characters plus many utility methods (upper/lower/startswith/endswith/charcodeat/trim etc). Supports concat with binary `+` operator.
40 | - **Uint8Array**: A variable length mutable array of 8-bit numbers. Supports indexing/slicing of 'bytes'.
41 |
42 |
43 | ```ts
44 | const b1 = "somebytes"
45 |
46 | const b2 = new Uint8Array([1, 2, 3, 4])
47 |
48 | const b3 = b1 + b1
49 | ```
50 |
51 | Whilst binary data is often a representation of a utf-8 string, it is not always - so direct use of the string type is not a natural fit. It doesn't allow us to represent alternative encodings (b16/b64) and the existing api surface is very 'string' centric. Much of the api would also be expensive to implement on the AVM leading to a bunch of 'dead' methods hanging off the type (or a significant amount of work implementing all the methods). The signatures of these methods also use `number` which is [not a semantically relevant type](./2024-05-21_primitive-integer-types.md).
52 |
53 | Achieving semantic compatability with EcmaScript's `String` type would also be very expensive as it uses utf-16 encoding underneath whilst an ABI string is utf-8 encoded. A significant number of ops (and program size) would be required to convert between the two. If we were to ignore this and use utf-8 at runtime, apis such as `.length` would return different results. For example `"😄".length` in ES returns `2` whilst utf-8 encoding would yield `1` codepoint or `4` bytes, similarly indexing and slicing would yield different results.
54 |
55 | The Uint8Array type is fit for purpose as an encoding mechanism but the API is not as friendly as it could be for writing declarative contracts. The `new` keyword feels unnatural for something that is ostensibly a primitive type. The fact that it is mutable also complicates the implementation the compiler produces for the AVM.
56 |
57 |
58 |
59 | ### Option 2 - Branded strings (TEALScript approach)
60 |
61 |
62 | TEALScript uses a branded `string` to represent `bytes` and native `string` to represent UTF-8 bytes. Base64/Base16 encoding/decoding is performed with specific methods.
63 |
64 | ```typescript
65 | const someString = "foo"
66 | const someHexValue = hex("0xdeadbeef") // branded "bytes"
67 | ```
68 |
69 | Bytes and UTF-8 strings are typed via branded `string` types. UTF-8 strings are the most common use case for strings, thus have the JavaScript `String` prototype functions when working with byteslice, which provides a familiar set of function signatures. This option also enables the usage of `+` for concatenation.
70 |
71 | To differentiate between ABI `string` and AVM `byteslice`, a branded type, `bytes`, can be used to represent non-encoded byteslices that may or may not be UTF-8 strings.
72 |
73 | Additional functions can be used when wanting to have string literals of a specific encoding represent a string or byteslice.
74 |
75 |
76 | The downsides of using `string` are listed in Option 1.
77 |
78 |
79 | ### Option 3 - Define a class to represent Bytes
80 |
81 | A `Bytes` class and `Str` (Name TBD) class are defined with a very specific API tailored to operations which are available on the AVM:
82 |
83 | ```ts
84 | class Bytes {
85 | constructor(v: string) {
86 | this.v = v
87 | }
88 |
89 | concat(other: Bytes): Bytes {
90 | return new Bytes(this.v + other.v)
91 | }
92 |
93 | at(x: uint64): Bytes {
94 | return new Bytes(this.v[x])
95 | }
96 |
97 | /* etc */
98 | }
99 |
100 | class Str {
101 | /* implementation */
102 | }
103 |
104 | ```
105 |
106 | This solution provides great type safety and requires no transpilation to run _correctly_ on Node.js. However, non-primitive types in Node.js have equality checked by reference. Again the `new` keyword feels unnatural. Due to lack of overloading, `+` will not work as expected however concatenations do not require the same understanding of "order of operations" and nesting as numeric operations, so a `concat` method isn't as unwieldy (but still isn't idiomatic).
107 |
108 | ```ts
109 | const a = new Bytes("Hello")
110 | const b = new Bytes("World")
111 | const c = new Str("Example string")
112 | const ab = a.concat(b)
113 |
114 | function testValue(x: Bytes) {
115 | // No compile error, but will work on reference not value
116 | switch(x) {
117 | case a:
118 | return b
119 | case b:
120 | return a
121 | }
122 | return new Bytes("default")
123 | }
124 | ```
125 |
126 | To have equality checks behave as expected we would need a transpilation step to replace bytes values in certain expressions with a primitive type.
127 |
128 | ### Option 4 - Implement bytes as a class but define it as a type + factory
129 |
130 | We can iron out some of the rough edges of using a class by only exposing a factory method for `Bytes`/`Str` and a resulting type `bytes`/`str`. This removes the need for the `new` keyword and lets us use a 'primitive looking' type alias (`bytes` versus `Bytes`, `str` versus `Str` - much like `string` and `String`). We can use [tagged templates](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#tagged_templates) to improve the user experience of multipart concat expressions in lieu of having the `+` operator.
131 |
132 | ```ts
133 |
134 | export type bytes = {
135 | readonly length: uint64
136 |
137 | at(i: Uint64Compat): bytes
138 |
139 | concat(other: BytesCompat): bytes
140 | } & symbol
141 |
142 | export function Bytes(value: TemplateStringsArray, ...replacements: BytesCompat[]): bytes
143 | export function Bytes(value: BytesCompat): bytes
144 | export function Bytes(value: BytesCompat | TemplateStringsArray, ...replacements: BytesCompat[]): bytes {
145 | /* implementation */
146 | }
147 |
148 | const a = Bytes("Hello")
149 | const b = Bytes.fromHex("ABFF")
150 | const c = Bytes.fromBase64("...")
151 | const d = Bytes.fromInts(255, 123, 28, 20)
152 | const e = Bytes`${a} World!`
153 |
154 |
155 | function testValue(x: bytes, y: bytes): bytes {
156 | return Bytes`${x} and ${y}`
157 | }
158 |
159 | const f = Str`Example string`
160 |
161 | ```
162 |
163 | Whilst we still can't accept string literals on their own, the tagged template is almost as concise.
164 |
165 | Having `bytes` and `str` behave like a primitive value type (value equality) whilst not _actually_ being a primitive is not strictly semantically compatible with EcmaScript however the lowercase type names (plus factory with no `new` keyword) communicates the intention of it being a primitive value type and there is an existing precedence of introducing new value types to the language in a similar pattern (`bigint` and `BigInt`). Essentially - if EcmaScript were to have a primitive bytes type, this is most likely what it would look like.
166 |
167 | ## Preferred option
168 |
169 | Option 3 can be excluded because the requirement for a `new` keyword feels unnatural for representing a primitive value type.
170 |
171 | Option 1 and 2 are not preferred as they make maintaining semantic compatability with EcmaScript impractical.
172 |
173 | Option 4 gives us the most natural feeling api whilst still giving us full control over the api surface. It doesn't support the `+` operator, but supports interpolation and `.concat` which gives us most of what `+` provides other than augmented assignment (ie. `+=`).
174 |
175 | We should select an appropriate name for the type representing an AVM string. It should not conflict with the semantically incompatible EcmaScript type `string`.
176 | - `str`/`Str`:
177 | - ✅ Short
178 | - ✅ obvious what it is
179 | - ✅ obvious equivalent in ABI types
180 | - ❌ NOT obvious how it differs from EcmaScript `string`
181 | - `utf8`/`Utf8`:
182 | - ✅ Short
183 | - ✅ reasonably obvious what it is
184 | - 🤔 less obvious equivalent in ABI types
185 | - ✅ obvious how it differs to `string`
186 | - `utf8string`/`Utf8String`
187 | - ❌ Verbose
188 | - ✅ obvious equivalent in ABI types
189 | - ✅ very obvious what it is
190 | - ✅ obvious how it differs to `string`
191 |
192 |
193 |
194 | ## Selected option
195 |
196 | Option 4 has been selected as the best option
```