This is page 26 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:interfaces:types_app.UpdateAppParams.md:
--------------------------------------------------------------------------------
```markdown
1 | [@algorandfoundation/algokit-utils](../README.md) / [types/app](../modules/types_app.md) / UpdateAppParams
2 |
3 | # Interface: UpdateAppParams
4 |
5 | [types/app](../modules/types_app.md).UpdateAppParams
6 |
7 | **`Deprecated`**
8 |
9 | Use `TransactionComposer` to construct update app transactions instead.
10 |
11 | Parameters that are passed in when updating an app.
12 |
13 | ## Hierarchy
14 |
15 | - `CreateOrUpdateAppParams`
16 |
17 | ↳ **`UpdateAppParams`**
18 |
19 | ## Table of contents
20 |
21 | ### Properties
22 |
23 | - [appId](types_app.UpdateAppParams.md#appid)
24 | - [approvalProgram](types_app.UpdateAppParams.md#approvalprogram)
25 | - [args](types_app.UpdateAppParams.md#args)
26 | - [atc](types_app.UpdateAppParams.md#atc)
27 | - [clearStateProgram](types_app.UpdateAppParams.md#clearstateprogram)
28 | - [fee](types_app.UpdateAppParams.md#fee)
29 | - [from](types_app.UpdateAppParams.md#from)
30 | - [maxFee](types_app.UpdateAppParams.md#maxfee)
31 | - [maxRoundsToWaitForConfirmation](types_app.UpdateAppParams.md#maxroundstowaitforconfirmation)
32 | - [note](types_app.UpdateAppParams.md#note)
33 | - [populateAppCallResources](types_app.UpdateAppParams.md#populateappcallresources)
34 | - [skipSending](types_app.UpdateAppParams.md#skipsending)
35 | - [skipWaiting](types_app.UpdateAppParams.md#skipwaiting)
36 | - [suppressLog](types_app.UpdateAppParams.md#suppresslog)
37 | - [transactionParams](types_app.UpdateAppParams.md#transactionparams)
38 |
39 | ## Properties
40 |
41 | ### appId
42 |
43 | • **appId**: `number` \| `bigint`
44 |
45 | The id of the app to update
46 |
47 | #### Defined in
48 |
49 | [src/types/app.ts:163](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L163)
50 |
51 | ___
52 |
53 | ### approvalProgram
54 |
55 | • **approvalProgram**: `string` \| `Uint8Array`
56 |
57 | The approval program as raw teal (string) or compiled teal, base 64 encoded as a byte array (Uint8Array)
58 |
59 | #### Inherited from
60 |
61 | CreateOrUpdateAppParams.approvalProgram
62 |
63 | #### Defined in
64 |
65 | [src/types/app.ts:135](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L135)
66 |
67 | ___
68 |
69 | ### args
70 |
71 | • `Optional` **args**: [`AppCallArgs`](../modules/types_app.md#appcallargs)
72 |
73 | The arguments passed in to the app call
74 |
75 | #### Inherited from
76 |
77 | CreateOrUpdateAppParams.args
78 |
79 | #### Defined in
80 |
81 | [src/types/app.ts:143](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L143)
82 |
83 | ___
84 |
85 | ### atc
86 |
87 | • `Optional` **atc**: `AtomicTransactionComposer`
88 |
89 | An optional `AtomicTransactionComposer` to add the transaction to, if specified then `skipSending: undefined` has the same effect as `skipSending: true`
90 |
91 | #### Inherited from
92 |
93 | CreateOrUpdateAppParams.atc
94 |
95 | #### Defined in
96 |
97 | [src/types/transaction.ts:36](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transaction.ts#L36)
98 |
99 | ___
100 |
101 | ### clearStateProgram
102 |
103 | • **clearStateProgram**: `string` \| `Uint8Array`
104 |
105 | The clear state program as raw teal (string) or compiled teal, base 64 encoded as a byte array (Uint8Array)
106 |
107 | #### Inherited from
108 |
109 | CreateOrUpdateAppParams.clearStateProgram
110 |
111 | #### Defined in
112 |
113 | [src/types/app.ts:137](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L137)
114 |
115 | ___
116 |
117 | ### fee
118 |
119 | • `Optional` **fee**: [`AlgoAmount`](../classes/types_amount.AlgoAmount.md)
120 |
121 | The flat fee you want to pay, useful for covering extra fees in a transaction group or app call
122 |
123 | #### Inherited from
124 |
125 | CreateOrUpdateAppParams.fee
126 |
127 | #### Defined in
128 |
129 | [src/types/transaction.ts:40](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transaction.ts#L40)
130 |
131 | ___
132 |
133 | ### from
134 |
135 | • **from**: [`SendTransactionFrom`](../modules/types_transaction.md#sendtransactionfrom)
136 |
137 | The account (with private key loaded) that will send the transaction
138 |
139 | #### Inherited from
140 |
141 | CreateOrUpdateAppParams.from
142 |
143 | #### Defined in
144 |
145 | [src/types/app.ts:133](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L133)
146 |
147 | ___
148 |
149 | ### maxFee
150 |
151 | • `Optional` **maxFee**: [`AlgoAmount`](../classes/types_amount.AlgoAmount.md)
152 |
153 | The maximum fee that you are happy to pay (default: unbounded) - if this is set it's possible the transaction could get rejected during network congestion
154 |
155 | #### Inherited from
156 |
157 | CreateOrUpdateAppParams.maxFee
158 |
159 | #### Defined in
160 |
161 | [src/types/transaction.ts:42](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transaction.ts#L42)
162 |
163 | ___
164 |
165 | ### maxRoundsToWaitForConfirmation
166 |
167 | • `Optional` **maxRoundsToWaitForConfirmation**: `number`
168 |
169 | The maximum number of rounds to wait for confirmation, only applies if `skipWaiting` is `undefined` or `false`, default: wait up to 5 rounds
170 |
171 | #### Inherited from
172 |
173 | CreateOrUpdateAppParams.maxRoundsToWaitForConfirmation
174 |
175 | #### Defined in
176 |
177 | [src/types/transaction.ts:44](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transaction.ts#L44)
178 |
179 | ___
180 |
181 | ### note
182 |
183 | • `Optional` **note**: [`TransactionNote`](../modules/types_transaction.md#transactionnote)
184 |
185 | The (optional) transaction note
186 |
187 | #### Inherited from
188 |
189 | CreateOrUpdateAppParams.note
190 |
191 | #### Defined in
192 |
193 | [src/types/app.ts:141](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L141)
194 |
195 | ___
196 |
197 | ### populateAppCallResources
198 |
199 | • `Optional` **populateAppCallResources**: `boolean`
200 |
201 | Whether to use simulate to automatically populate app call resources in the txn objects. Defaults to true when there are app calls in the group.
202 |
203 | #### Inherited from
204 |
205 | CreateOrUpdateAppParams.populateAppCallResources
206 |
207 | #### Defined in
208 |
209 | [src/types/transaction.ts:46](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transaction.ts#L46)
210 |
211 | ___
212 |
213 | ### skipSending
214 |
215 | • `Optional` **skipSending**: `boolean`
216 |
217 | Whether to skip signing and sending the transaction to the chain (default: transaction signed and sent to chain, unless `atc` specified)
218 | and instead just return the raw transaction, e.g. so you can add it to a group of transactions
219 |
220 | #### Inherited from
221 |
222 | CreateOrUpdateAppParams.skipSending
223 |
224 | #### Defined in
225 |
226 | [src/types/transaction.ts:32](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transaction.ts#L32)
227 |
228 | ___
229 |
230 | ### skipWaiting
231 |
232 | • `Optional` **skipWaiting**: `boolean`
233 |
234 | Whether to skip waiting for the submitted transaction (only relevant if `skipSending` is `false` or unset)
235 |
236 | #### Inherited from
237 |
238 | CreateOrUpdateAppParams.skipWaiting
239 |
240 | #### Defined in
241 |
242 | [src/types/transaction.ts:34](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transaction.ts#L34)
243 |
244 | ___
245 |
246 | ### suppressLog
247 |
248 | • `Optional` **suppressLog**: `boolean`
249 |
250 | Whether to suppress log messages from transaction send, default: do not suppress
251 |
252 | #### Inherited from
253 |
254 | CreateOrUpdateAppParams.suppressLog
255 |
256 | #### Defined in
257 |
258 | [src/types/transaction.ts:38](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transaction.ts#L38)
259 |
260 | ___
261 |
262 | ### transactionParams
263 |
264 | • `Optional` **transactionParams**: `SuggestedParams`
265 |
266 | Optional transaction parameters
267 |
268 | #### Inherited from
269 |
270 | CreateOrUpdateAppParams.transactionParams
271 |
272 | #### Defined in
273 |
274 | [src/types/app.ts:139](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L139)
275 |
```
--------------------------------------------------------------------------------
/packages/server/tests/resources/algod/account.test.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
2 | import {
3 | accountResources,
4 | accountResourceSchemas,
5 | accountInformation,
6 | accountApplicationInformation,
7 | accountAssetInformation,
8 | handleAccountResource
9 | } from '../../../src/resources/algod/account.js';
10 | import { algodClient } from '../../../src/algorand-client.js';
11 |
12 | // Mock algosdk client
13 | jest.mock('../../../src/algorand-client.js', () => ({
14 | algodClient: {
15 | accountInformation: jest.fn(),
16 | accountApplicationInformation: jest.fn(),
17 | accountAssetInformation: jest.fn()
18 | },
19 | API_URIS: {
20 | ACCOUNT_DETAILS: 'algorand://account/{address}',
21 | APPLICATION_STATE: 'algorand://account/{address}/application/{app-id}',
22 | ASSET_HOLDINGS: 'algorand://account/{address}/asset/{asset-id}'
23 | }
24 | }));
25 |
26 | describe('Algod Account Resources', () => {
27 | beforeEach(() => {
28 | jest.clearAllMocks();
29 | });
30 |
31 | describe('Resource Definitions', () => {
32 | it('should define account resources', () => {
33 | expect(accountResources).toHaveLength(3);
34 | expect(accountResources.map(r => r.name)).toEqual([
35 | 'Account Details',
36 | 'Account Application Info',
37 | 'Account Asset Info'
38 | ]);
39 | });
40 |
41 | it('should define resource schemas', () => {
42 | expect(Object.keys(accountResourceSchemas)).toHaveLength(3);
43 | expect(accountResourceSchemas).toHaveProperty('algorand://account/{address}');
44 | expect(accountResourceSchemas).toHaveProperty('algorand://account/{address}/application/{app-id}');
45 | expect(accountResourceSchemas).toHaveProperty('algorand://account/{address}/asset/{asset-id}');
46 | });
47 | });
48 |
49 | describe('Account Information', () => {
50 | const mockAddress = 'MOCK_ADDRESS';
51 | const mockResponse = {
52 | account: { address: mockAddress, amount: 1000 },
53 | currentRound: 1234
54 | };
55 |
56 | beforeEach(() => {
57 | (algodClient.accountInformation as jest.Mock).mockReturnValue({
58 | do: jest.fn().mockResolvedValue(mockResponse)
59 | });
60 | });
61 |
62 | it('should fetch account information', async () => {
63 | const result = await accountInformation(mockAddress);
64 | expect(result).toEqual(mockResponse);
65 | expect(algodClient.accountInformation).toHaveBeenCalledWith(mockAddress);
66 | });
67 |
68 | it('should handle errors', async () => {
69 | const error = new Error('Network error');
70 | (algodClient.accountInformation as jest.Mock).mockReturnValue({
71 | do: jest.fn().mockRejectedValue(error)
72 | });
73 |
74 | await expect(accountInformation(mockAddress))
75 | .rejects
76 | .toThrow('Failed to get account info: Network error');
77 | });
78 | });
79 |
80 | describe('Account Application Information', () => {
81 | const mockAddress = 'MOCK_ADDRESS';
82 | const mockAppId = 123;
83 | const mockResponse = {
84 | account: { address: mockAddress, appLocalState: {} },
85 | currentRound: 1234
86 | };
87 |
88 | beforeEach(() => {
89 | (algodClient.accountApplicationInformation as jest.Mock).mockReturnValue({
90 | do: jest.fn().mockResolvedValue(mockResponse)
91 | });
92 | });
93 |
94 | it('should fetch application information', async () => {
95 | const result = await accountApplicationInformation(mockAddress, mockAppId);
96 | expect(result).toEqual(mockResponse);
97 | expect(algodClient.accountApplicationInformation).toHaveBeenCalledWith(mockAddress, mockAppId);
98 | });
99 |
100 | it('should handle errors', async () => {
101 | const error = new Error('Network error');
102 | (algodClient.accountApplicationInformation as jest.Mock).mockReturnValue({
103 | do: jest.fn().mockRejectedValue(error)
104 | });
105 |
106 | await expect(accountApplicationInformation(mockAddress, mockAppId))
107 | .rejects
108 | .toThrow('Failed to get account application info: Network error');
109 | });
110 | });
111 |
112 | describe('Account Asset Information', () => {
113 | const mockAddress = 'MOCK_ADDRESS';
114 | const mockAssetId = 456;
115 | const mockResponse = {
116 | account: { address: mockAddress, assets: [] },
117 | currentRound: 1234
118 | };
119 |
120 | beforeEach(() => {
121 | (algodClient.accountAssetInformation as jest.Mock).mockReturnValue({
122 | do: jest.fn().mockResolvedValue(mockResponse)
123 | });
124 | });
125 |
126 | it('should fetch asset information', async () => {
127 | const result = await accountAssetInformation(mockAddress, mockAssetId);
128 | expect(result).toEqual(mockResponse);
129 | expect(algodClient.accountAssetInformation).toHaveBeenCalledWith(mockAddress, mockAssetId);
130 | });
131 |
132 | it('should handle errors', async () => {
133 | const error = new Error('Network error');
134 | (algodClient.accountAssetInformation as jest.Mock).mockReturnValue({
135 | do: jest.fn().mockRejectedValue(error)
136 | });
137 |
138 | await expect(accountAssetInformation(mockAddress, mockAssetId))
139 | .rejects
140 | .toThrow('Failed to get account asset info: Network error');
141 | });
142 | });
143 |
144 | describe('Resource Handler', () => {
145 | const mockAddress = 'MOCK_ADDRESS';
146 | const mockResponse = {
147 | account: { address: mockAddress },
148 | currentRound: 1234
149 | };
150 |
151 | beforeEach(() => {
152 | (algodClient.accountInformation as jest.Mock).mockReturnValue({
153 | do: jest.fn().mockResolvedValue(mockResponse)
154 | });
155 | (algodClient.accountApplicationInformation as jest.Mock).mockReturnValue({
156 | do: jest.fn().mockResolvedValue(mockResponse)
157 | });
158 | (algodClient.accountAssetInformation as jest.Mock).mockReturnValue({
159 | do: jest.fn().mockResolvedValue(mockResponse)
160 | });
161 | });
162 |
163 | it('should handle account details URI', async () => {
164 | const uri = `algorand://account/${mockAddress}`;
165 | const result = await handleAccountResource(uri);
166 | expect(result).toHaveLength(1);
167 | expect(JSON.parse(result[0].text)).toEqual(mockResponse);
168 | });
169 |
170 | it('should handle application info URI', async () => {
171 | const uri = `algorand://account/${mockAddress}/application/123`;
172 | const result = await handleAccountResource(uri);
173 | expect(result).toHaveLength(1);
174 | expect(JSON.parse(result[0].text)).toEqual(mockResponse);
175 | });
176 |
177 | it('should handle asset info URI', async () => {
178 | const uri = `algorand://account/${mockAddress}/asset/456`;
179 | const result = await handleAccountResource(uri);
180 | expect(result).toHaveLength(1);
181 | expect(JSON.parse(result[0].text)).toEqual(mockResponse);
182 | });
183 |
184 | it('should return empty array for unknown URI', async () => {
185 | const uri = 'algorand://unknown';
186 | const result = await handleAccountResource(uri);
187 | expect(result).toHaveLength(0);
188 | });
189 |
190 | it('should handle errors with McpError', async () => {
191 | const error = new Error('Network error');
192 | (algodClient.accountInformation as jest.Mock).mockReturnValue({
193 | do: jest.fn().mockRejectedValue(error)
194 | });
195 |
196 | const uri = `algorand://account/${mockAddress}`;
197 | await expect(handleAccountResource(uri))
198 | .rejects
199 | .toThrow(new McpError(ErrorCode.InternalError, 'Network error'));
200 | });
201 | });
202 | });
203 |
```
--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/algokit:utils:typescript:code:interfaces:types_transfer.AlgoRekeyParams.md:
--------------------------------------------------------------------------------
```markdown
1 | [@algorandfoundation/algokit-utils](../README.md) / [types/transfer](../modules/types_transfer.md) / AlgoRekeyParams
2 |
3 | # Interface: AlgoRekeyParams
4 |
5 | [types/transfer](../modules/types_transfer.md).AlgoRekeyParams
6 |
7 | **`Deprecated`**
8 |
9 | Parameters for `rekeyAccount` call.
10 |
11 | ## Hierarchy
12 |
13 | - [`SendTransactionParams`](types_transaction.SendTransactionParams.md)
14 |
15 | ↳ **`AlgoRekeyParams`**
16 |
17 | ## Table of contents
18 |
19 | ### Properties
20 |
21 | - [atc](types_transfer.AlgoRekeyParams.md#atc)
22 | - [fee](types_transfer.AlgoRekeyParams.md#fee)
23 | - [from](types_transfer.AlgoRekeyParams.md#from)
24 | - [lease](types_transfer.AlgoRekeyParams.md#lease)
25 | - [maxFee](types_transfer.AlgoRekeyParams.md#maxfee)
26 | - [maxRoundsToWaitForConfirmation](types_transfer.AlgoRekeyParams.md#maxroundstowaitforconfirmation)
27 | - [note](types_transfer.AlgoRekeyParams.md#note)
28 | - [populateAppCallResources](types_transfer.AlgoRekeyParams.md#populateappcallresources)
29 | - [rekeyTo](types_transfer.AlgoRekeyParams.md#rekeyto)
30 | - [skipSending](types_transfer.AlgoRekeyParams.md#skipsending)
31 | - [skipWaiting](types_transfer.AlgoRekeyParams.md#skipwaiting)
32 | - [suppressLog](types_transfer.AlgoRekeyParams.md#suppresslog)
33 | - [transactionParams](types_transfer.AlgoRekeyParams.md#transactionparams)
34 |
35 | ## Properties
36 |
37 | ### atc
38 |
39 | • `Optional` **atc**: `AtomicTransactionComposer`
40 |
41 | An optional `AtomicTransactionComposer` to add the transaction to, if specified then `skipSending: undefined` has the same effect as `skipSending: true`
42 |
43 | #### Inherited from
44 |
45 | [SendTransactionParams](types_transaction.SendTransactionParams.md).[atc](types_transaction.SendTransactionParams.md#atc)
46 |
47 | #### Defined in
48 |
49 | [src/types/transaction.ts:36](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transaction.ts#L36)
50 |
51 | ___
52 |
53 | ### fee
54 |
55 | • `Optional` **fee**: [`AlgoAmount`](../classes/types_amount.AlgoAmount.md)
56 |
57 | The flat fee you want to pay, useful for covering extra fees in a transaction group or app call
58 |
59 | #### Inherited from
60 |
61 | [SendTransactionParams](types_transaction.SendTransactionParams.md).[fee](types_transaction.SendTransactionParams.md#fee)
62 |
63 | #### Defined in
64 |
65 | [src/types/transaction.ts:40](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transaction.ts#L40)
66 |
67 | ___
68 |
69 | ### from
70 |
71 | • **from**: [`SendTransactionFrom`](../modules/types_transaction.md#sendtransactionfrom)
72 |
73 | The account that will be rekeyed
74 |
75 | #### Defined in
76 |
77 | [src/types/transfer.ts:26](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transfer.ts#L26)
78 |
79 | ___
80 |
81 | ### lease
82 |
83 | • `Optional` **lease**: `string` \| `Uint8Array`
84 |
85 | An (optional) [transaction lease](https://developer.algorand.org/articles/leased-transactions-securing-advanced-smart-contract-design/) to apply
86 |
87 | #### Defined in
88 |
89 | [src/types/transfer.ts:34](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transfer.ts#L34)
90 |
91 | ___
92 |
93 | ### maxFee
94 |
95 | • `Optional` **maxFee**: [`AlgoAmount`](../classes/types_amount.AlgoAmount.md)
96 |
97 | The maximum fee that you are happy to pay (default: unbounded) - if this is set it's possible the transaction could get rejected during network congestion
98 |
99 | #### Inherited from
100 |
101 | [SendTransactionParams](types_transaction.SendTransactionParams.md).[maxFee](types_transaction.SendTransactionParams.md#maxfee)
102 |
103 | #### Defined in
104 |
105 | [src/types/transaction.ts:42](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transaction.ts#L42)
106 |
107 | ___
108 |
109 | ### maxRoundsToWaitForConfirmation
110 |
111 | • `Optional` **maxRoundsToWaitForConfirmation**: `number`
112 |
113 | The maximum number of rounds to wait for confirmation, only applies if `skipWaiting` is `undefined` or `false`, default: wait up to 5 rounds
114 |
115 | #### Inherited from
116 |
117 | [SendTransactionParams](types_transaction.SendTransactionParams.md).[maxRoundsToWaitForConfirmation](types_transaction.SendTransactionParams.md#maxroundstowaitforconfirmation)
118 |
119 | #### Defined in
120 |
121 | [src/types/transaction.ts:44](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transaction.ts#L44)
122 |
123 | ___
124 |
125 | ### note
126 |
127 | • `Optional` **note**: [`TransactionNote`](../modules/types_transaction.md#transactionnote)
128 |
129 | The (optional) transaction note
130 |
131 | #### Defined in
132 |
133 | [src/types/transfer.ts:32](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transfer.ts#L32)
134 |
135 | ___
136 |
137 | ### populateAppCallResources
138 |
139 | • `Optional` **populateAppCallResources**: `boolean`
140 |
141 | Whether to use simulate to automatically populate app call resources in the txn objects. Defaults to true when there are app calls in the group.
142 |
143 | #### Inherited from
144 |
145 | [SendTransactionParams](types_transaction.SendTransactionParams.md).[populateAppCallResources](types_transaction.SendTransactionParams.md#populateappcallresources)
146 |
147 | #### Defined in
148 |
149 | [src/types/transaction.ts:46](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transaction.ts#L46)
150 |
151 | ___
152 |
153 | ### rekeyTo
154 |
155 | • **rekeyTo**: `string` \| [`SendTransactionFrom`](../modules/types_transaction.md#sendtransactionfrom)
156 |
157 | The account / account address that will have the private key that is authorised to transact on behalf of the from account from now on
158 |
159 | #### Defined in
160 |
161 | [src/types/transfer.ts:28](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transfer.ts#L28)
162 |
163 | ___
164 |
165 | ### skipSending
166 |
167 | • `Optional` **skipSending**: `boolean`
168 |
169 | Whether to skip signing and sending the transaction to the chain (default: transaction signed and sent to chain, unless `atc` specified)
170 | and instead just return the raw transaction, e.g. so you can add it to a group of transactions
171 |
172 | #### Inherited from
173 |
174 | [SendTransactionParams](types_transaction.SendTransactionParams.md).[skipSending](types_transaction.SendTransactionParams.md#skipsending)
175 |
176 | #### Defined in
177 |
178 | [src/types/transaction.ts:32](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transaction.ts#L32)
179 |
180 | ___
181 |
182 | ### skipWaiting
183 |
184 | • `Optional` **skipWaiting**: `boolean`
185 |
186 | Whether to skip waiting for the submitted transaction (only relevant if `skipSending` is `false` or unset)
187 |
188 | #### Inherited from
189 |
190 | [SendTransactionParams](types_transaction.SendTransactionParams.md).[skipWaiting](types_transaction.SendTransactionParams.md#skipwaiting)
191 |
192 | #### Defined in
193 |
194 | [src/types/transaction.ts:34](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transaction.ts#L34)
195 |
196 | ___
197 |
198 | ### suppressLog
199 |
200 | • `Optional` **suppressLog**: `boolean`
201 |
202 | Whether to suppress log messages from transaction send, default: do not suppress
203 |
204 | #### Inherited from
205 |
206 | [SendTransactionParams](types_transaction.SendTransactionParams.md).[suppressLog](types_transaction.SendTransactionParams.md#suppresslog)
207 |
208 | #### Defined in
209 |
210 | [src/types/transaction.ts:38](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transaction.ts#L38)
211 |
212 | ___
213 |
214 | ### transactionParams
215 |
216 | • `Optional` **transactionParams**: `SuggestedParams`
217 |
218 | Optional transaction parameters
219 |
220 | #### Defined in
221 |
222 | [src/types/transfer.ts:30](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transfer.ts#L30)
223 |
```
--------------------------------------------------------------------------------
/packages/server/tests/tools/transactionManager/generalTransactionManager.test.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
2 | import { GeneralTransactionManager, generalTransactionTools } from '../../../src/tools/transactionManager/generalTransaction.js';
3 | import algosdk from 'algosdk';
4 | import type { Transaction } from 'algosdk';
5 |
6 | // Mock algosdk
7 | jest.mock('algosdk');
8 |
9 | // Create mock functions
10 | const mockTransaction = jest.fn().mockImplementation((txn: any) => ({
11 | ...txn,
12 | get_obj_for_encoding: () => txn,
13 | }));
14 |
15 | const mockAssignGroupID = jest.fn().mockImplementation((txns: any[]) =>
16 | txns.map(txn => ({
17 | ...txn,
18 | group: 'group1',
19 | }))
20 | );
21 |
22 | // Override mock implementations
23 | (algosdk as any).Transaction = mockTransaction;
24 | (algosdk as any).assignGroupID = mockAssignGroupID;
25 |
26 | describe('GeneralTransactionManager', () => {
27 | beforeEach(() => {
28 | jest.clearAllMocks();
29 | });
30 |
31 | describe('Tool Schemas', () => {
32 | it('should have valid tool schemas', () => {
33 | expect(generalTransactionTools).toHaveLength(1);
34 | expect(generalTransactionTools.map((t: { name: string }) => t.name)).toEqual([
35 | 'assign_group_id',
36 | ]);
37 | });
38 | });
39 |
40 | describe('Group ID Assignment', () => {
41 | const mockTxn1 = { type: 'pay', from: 'sender1' };
42 | const mockTxn2 = { type: 'pay', from: 'sender2' };
43 | const mockGroupedTxns = [
44 | { ...mockTxn1, group: 'group1' },
45 | { ...mockTxn2, group: 'group1' },
46 | ];
47 |
48 | beforeEach(() => {
49 | // Reset mock implementations
50 | mockTransaction.mockImplementation((txn: any) => ({
51 | ...txn,
52 | get_obj_for_encoding: () => txn,
53 | }));
54 | mockAssignGroupID.mockImplementation((txns: any[]) =>
55 | txns.map(txn => ({
56 | ...txn,
57 | group: 'group1',
58 | }))
59 | );
60 | });
61 |
62 | it('should assign group ID to transactions', async () => {
63 | const args = {
64 | transactions: [mockTxn1, mockTxn2],
65 | };
66 |
67 | const result = await GeneralTransactionManager.handleTool('assign_group_id', args);
68 |
69 | expect(result).toEqual({
70 | content: [{
71 | type: 'text',
72 | text: JSON.stringify(mockGroupedTxns, null, 2),
73 | }],
74 | });
75 |
76 | expect(mockTransaction).toHaveBeenCalledTimes(2);
77 | expect(mockTransaction).toHaveBeenCalledWith(mockTxn1);
78 | expect(mockTransaction).toHaveBeenCalledWith(mockTxn2);
79 | expect(mockAssignGroupID).toHaveBeenCalledWith(
80 | expect.arrayContaining([
81 | expect.objectContaining(mockTxn1),
82 | expect.objectContaining(mockTxn2),
83 | ])
84 | );
85 | });
86 |
87 | it('should handle single transaction', async () => {
88 | const args = {
89 | transactions: [mockTxn1],
90 | };
91 |
92 | const result = await GeneralTransactionManager.handleTool('assign_group_id', args);
93 |
94 | expect(mockTransaction).toHaveBeenCalledTimes(1);
95 | expect(mockTransaction).toHaveBeenCalledWith(mockTxn1);
96 | expect(mockAssignGroupID).toHaveBeenCalledWith(
97 | expect.arrayContaining([
98 | expect.objectContaining(mockTxn1),
99 | ])
100 | );
101 | });
102 | });
103 |
104 | describe('Error Handling', () => {
105 | it('should throw error for unknown tool', async () => {
106 | await expect(GeneralTransactionManager.handleTool('unknown_tool', {}))
107 | .rejects
108 | .toThrow(new McpError(ErrorCode.MethodNotFound, 'Unknown general transaction tool: unknown_tool'));
109 | });
110 |
111 | it('should throw error for missing transactions array', async () => {
112 | await expect(GeneralTransactionManager.handleTool('assign_group_id', {}))
113 | .rejects
114 | .toThrow(new McpError(ErrorCode.InvalidParams, 'Transactions array is required'));
115 | });
116 |
117 | it('should throw error for invalid transactions array', async () => {
118 | await expect(GeneralTransactionManager.handleTool('assign_group_id', {
119 | transactions: 'not-an-array'
120 | }))
121 | .rejects
122 | .toThrow(new McpError(ErrorCode.InvalidParams, 'Transactions array is required'));
123 | });
124 |
125 | it('should throw error for invalid transaction object', async () => {
126 | await expect(GeneralTransactionManager.handleTool('assign_group_id', {
127 | transactions: [null]
128 | }))
129 | .rejects
130 | .toThrow(new McpError(ErrorCode.InvalidParams, 'Each transaction must be a valid transaction object'));
131 | });
132 |
133 | it('should handle transaction creation errors', async () => {
134 | const error = new Error('Invalid transaction format');
135 | mockTransaction.mockImplementation(() => {
136 | throw error;
137 | });
138 |
139 | await expect(GeneralTransactionManager.handleTool('assign_group_id', {
140 | transactions: [{ type: 'invalid' }]
141 | }))
142 | .rejects
143 | .toThrow(new McpError(ErrorCode.InvalidParams, 'Failed to assign group ID: Invalid transaction format'));
144 | });
145 |
146 | it('should handle group ID assignment errors', async () => {
147 | // Reset Transaction mock to succeed
148 | mockTransaction.mockImplementation((txn: any) => ({
149 | ...txn,
150 | get_obj_for_encoding: () => txn,
151 | }));
152 |
153 | // Make assignGroupID throw
154 | const error = new Error('Group ID assignment failed');
155 | mockAssignGroupID.mockImplementation(() => {
156 | throw error;
157 | });
158 |
159 | await expect(GeneralTransactionManager.handleTool('assign_group_id', {
160 | transactions: [
161 | { type: 'pay', from: 'sender1' },
162 | { type: 'pay', from: 'sender2' }
163 | ]
164 | }))
165 | .rejects
166 | .toThrow(new McpError(ErrorCode.InvalidParams, 'Failed to assign group ID: Group ID assignment failed'));
167 | });
168 | });
169 |
170 | describe('Transaction Object Conversion', () => {
171 | beforeEach(() => {
172 | // Reset mock implementations
173 | mockTransaction.mockImplementation((txn: any) => ({
174 | ...txn,
175 | get_obj_for_encoding: () => txn,
176 | }));
177 | mockAssignGroupID.mockImplementation((txns: any[]) =>
178 | txns.map(txn => ({
179 | ...txn,
180 | group: 'group1',
181 | }))
182 | );
183 | });
184 |
185 | it('should convert transaction objects to Transaction instances', async () => {
186 | const mockTxn = {
187 | type: 'pay',
188 | from: 'sender',
189 | to: 'receiver',
190 | amount: 1000,
191 | };
192 |
193 | await GeneralTransactionManager.handleTool('assign_group_id', {
194 | transactions: [mockTxn, { ...mockTxn, from: 'sender2' }]
195 | });
196 |
197 | expect(mockTransaction).toHaveBeenCalledWith(mockTxn);
198 | });
199 |
200 | it('should preserve transaction properties after conversion', async () => {
201 | const mockTxn = {
202 | type: 'pay',
203 | from: 'sender',
204 | to: 'receiver',
205 | amount: 1000,
206 | note: new Uint8Array([1, 2, 3]),
207 | lease: new Uint8Array([4, 5, 6]),
208 | };
209 |
210 | const result = await GeneralTransactionManager.handleTool('assign_group_id', {
211 | transactions: [mockTxn, { ...mockTxn, from: 'sender2' }]
212 | });
213 |
214 | const resultTxn = JSON.parse(result.content[0].text)[0];
215 | expect(resultTxn).toEqual(expect.objectContaining({
216 | type: 'pay',
217 | from: 'sender',
218 | to: 'receiver',
219 | amount: 1000,
220 | }));
221 | });
222 | });
223 | });
224 |
```
--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/ARCs:specs:arc-0054.md:
--------------------------------------------------------------------------------
```markdown
1 | ---
2 | arc: 54
3 | title: ASA Burning App
4 | description: Standardized Application for Burning ASAs
5 | author: Joe Polny (@joe-p), Brian Whippo (@silentrhetoric)
6 | discussions-to: https://github.com/algorandfoundation/ARCs/issues/245
7 | status: Final
8 | type: Standards Track
9 | category: ARC
10 | sub-category: Application
11 | created: 2023-09-15
12 | ---
13 |
14 | ## Abstract
15 | This ARC provides TEAL which would deploy a application that can be used for burning Algorand Standard Assets. The goal is to have the apps deployed on the public networks using this TEAL to provide a standardized burn address and app ID.
16 |
17 | ## Motivation
18 | Currently there is no official way to burn ASAs. While one can currently deploy their own app or rekey an account holding the asset to some other address, having a standardized address for burned assets enables explorers and dapps to easily calculate and display burnt supply for any ASA burned here.
19 |
20 | ### Definitions Related to Token Supply & Burning
21 |
22 | It is important to note that assets with clawback enabled are effectively impossible to "burn" and could at any point be clawed back from any account or contract. The definitions below attempt to clarify some terminology around tokens and what can be considered burned.
23 |
24 | | Token Type | Clawback | No Clawback |
25 | | ---------- | -------- | ----------- |
26 | | Total Supply | Total | Total |
27 | | Circulating Supply | Total - Qty in Reserve Address - Qty in burn address | Total - Qty in Reserve Address - Qty in burn address |
28 | | Available Supply | Total | Total - Qty in burn address |
29 | | Burned Supply | N/A (Impossible to burn) | Qty in burn address |
30 |
31 | ## Specification
32 |
33 | ### `ARC-4` JSON Description
34 | ```json
35 | {
36 | "name": "ARC54",
37 | "desc": "Standardized application for burning ASAs",
38 | "methods": [
39 | {
40 | "name": "arc54_optIntoASA",
41 | "args": [
42 | {
43 | "name": "asa",
44 | "type": "asset",
45 | "desc": "The asset to which the contract will opt in"
46 | }
47 | ],
48 | "desc": "A method to opt the contract into an ASA",
49 | "returns": {
50 | "type": "void",
51 | "desc": ""
52 | }
53 | },
54 | {
55 | "name": "createApplication",
56 | "desc": "",
57 | "returns": {
58 | "type": "void",
59 | "desc": ""
60 | },
61 | "args": []
62 | }
63 | ]
64 | }
65 | ```
66 |
67 | ## Rationale
68 | This simple application is only able to opt in to ASAs but not send them. As such, once an ASA has been sent to the app address it is effectively burnt.
69 |
70 | If the burned ASA does not have clawback enabled, it will remain permanently in this account and can be considered out of circulation.
71 |
72 | The app will accept ASAs which have clawback enabled, but any such assets can never be considered permanently burned. Users may use the burning app as a convenient receptable to remove ASAs from their account rather than returning them to the creator account.
73 |
74 | The app will, of course, only be able to opt into a new ASA if it has sufficient Algo balance to cover the increase minimum balance requirement (MBR). Callers should fund the contract account as needed to cover the opt-in requests. It is possible for the contract to be funded by donated Algo so that subsequent callers need not pay the MBR requirement to request new ASA opt-ins.
75 |
76 | ## Reference Implementation
77 |
78 | ### TEAL Approval Program
79 |
80 | ```
81 | #pragma version 9
82 |
83 | // This TEAL was generated by TEALScript v0.62.2
84 | // https://github.com/algorandfoundation/TEALScript
85 |
86 | // This contract is compliant with and/or implements the following ARCs: [ ARC4 ]
87 |
88 | // The following ten lines of TEAL handle initial program flow
89 | // This pattern is used to make it easy for anyone to parse the start of the program and determine if a specific action is allowed
90 | // Here, action refers to the OnComplete in combination with whether the app is being created or called
91 | // Every possible action for this contract is represented in the switch statement
92 | // If the action is not implemented in the contract, its respective branch will be "NOT_IMPLEMENTED" which just contains "err"
93 | txn ApplicationID
94 | int 0
95 | >
96 | int 6
97 | *
98 | txn OnCompletion
99 | +
100 | switch create_NoOp NOT_IMPLEMENTED NOT_IMPLEMENTED NOT_IMPLEMENTED NOT_IMPLEMENTED NOT_IMPLEMENTED call_NoOp
101 |
102 | NOT_IMPLEMENTED:
103 | err
104 |
105 | // arc54_optIntoASA(asset)void
106 | //
107 | // /*
108 | // Sends an inner transaction to opt the contract account into an ASA.
109 | // The fee for the inner transaction must be covered by the caller.
110 | //
111 | // @param asa The ASA to opt in to
112 | abi_route_arc54_optIntoASA:
113 | // asa: asset
114 | txna ApplicationArgs 1
115 | btoi
116 | txnas Assets
117 |
118 | // execute arc54_optIntoASA(asset)void
119 | callsub arc54_optIntoASA
120 | int 1
121 | return
122 |
123 | arc54_optIntoASA:
124 | proto 1 0
125 |
126 | // contracts/arc54.algo.ts:13
127 | // sendAssetTransfer({
128 | // assetReceiver: globals.currentApplicationAddress,
129 | // xferAsset: asa,
130 | // assetAmount: 0,
131 | // fee: 0,
132 | // })
133 | itxn_begin
134 | int axfer
135 | itxn_field TypeEnum
136 |
137 | // contracts/arc54.algo.ts:14
138 | // assetReceiver: globals.currentApplicationAddress
139 | global CurrentApplicationAddress
140 | itxn_field AssetReceiver
141 |
142 | // contracts/arc54.algo.ts:15
143 | // xferAsset: asa
144 | frame_dig -1 // asa: asset
145 | itxn_field XferAsset
146 |
147 | // contracts/arc54.algo.ts:16
148 | // assetAmount: 0
149 | int 0
150 | itxn_field AssetAmount
151 |
152 | // contracts/arc54.algo.ts:17
153 | // fee: 0
154 | int 0
155 | itxn_field Fee
156 |
157 | // Submit inner transaction
158 | itxn_submit
159 | retsub
160 |
161 | abi_route_createApplication:
162 | int 1
163 | return
164 |
165 | create_NoOp:
166 | method "createApplication()void"
167 | txna ApplicationArgs 0
168 | match abi_route_createApplication
169 | err
170 |
171 | call_NoOp:
172 | method "arc54_optIntoASA(asset)void"
173 | txna ApplicationArgs 0
174 | match abi_route_arc54_optIntoASA
175 | err
176 | ```
177 |
178 | ### TealScript Source Code
179 | ```
180 | import { Contract } from '@algorandfoundation/tealscript';
181 |
182 | // eslint-disable-next-line no-unused-vars
183 | class ARC54 extends Contract {
184 | /*
185 | * Sends an inner transaction to opt the contract account into an ASA.
186 | * The fee for the inner transaction must be covered by the caller.
187 | *
188 | * @param asa The ASA to opt in to
189 | */
190 | arc54_optIntoASA(asa: Asset): void {
191 | sendAssetTransfer({
192 | assetReceiver: globals.currentApplicationAddress,
193 | xferAsset: asa,
194 | assetAmount: 0,
195 | fee: 0,
196 | });
197 | }
198 | }
199 | ```
200 |
201 | ### Deployments
202 |
203 | An application per the above reference implementation has been deployed to each of Algorand's networks at these app IDs:
204 |
205 | | Network | App ID | Address |
206 | | --- | --- | --- |
207 | | MainNet | 1257620981 | BNFIREKGRXEHCFOEQLTX3PU5SUCMRKDU7WHNBGZA4SXPW42OAHZBP7BPHY |
208 | | TestNet | 497806551 | 3TKF2GMZJ5VZ4BQVQGC72BJ63WFN4QBPU2EUD4NQYHFLC3NE5D7GXHXYOQ |
209 | | BetaNet | 2019020358 | XRXCALSRDVUY2OQXWDYCRMHPCF346WKIV5JPAHXQ4MZADSROJGDIHZP7AI |
210 |
211 | ## Security Considerations
212 | It should be noted that once an asset is sent to the contract there will be no way to recover the asset unless it has clawback enabled.
213 |
214 | Due to the simplicity of a TEAL, an audit is not needed. The contract has no code paths which can send tokens, thus there is no concern of an exploit that undoes burning of ASAs without clawback.
215 |
216 | ## Copyright
217 | Copyright and related rights waived via <a href="https://creativecommons.org/publicdomain/zero/1.0/">CCO</a>.
218 |
```
--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/developer:python:code:example:arc4_types.md:
--------------------------------------------------------------------------------
```markdown
1 | # ARC4 Types in Algorand Smart Contracts
2 |
3 | This guide covers the various ARC4 data types available in Algorand smart contracts using Python, including integers, arrays, bytes, addresses, structs, and tuples.
4 |
5 | ## Integer Types
6 |
7 | ### Basic Integer Types
8 |
9 | ```python
10 | from algopy import ARC4Contract, UInt64, arc4
11 |
12 | class Arc4Types(ARC4Contract):
13 | @abimethod()
14 | def add_arc4_uint64(self, a: arc4.UInt64, b: arc4.UInt64) -> arc4.UInt64:
15 | # Use .native for arithmetic operations
16 | c = a.native + b.native
17 | return arc4.UInt64(c)
18 | ```
19 |
20 | ### Different Integer Sizes
21 |
22 | ```python
23 | @abimethod()
24 | def add_arc4_uint_n(
25 | self, a: arc4.UInt8, b: arc4.UInt16, c: arc4.UInt32, d: arc4.UInt64
26 | ) -> arc4.UInt64:
27 | # Different integer sizes have different byte lengths
28 | assert a.bytes.length == 1 # UInt8 = 1 byte
29 | assert b.bytes.length == 2 # UInt16 = 2 bytes
30 | assert c.bytes.length == 4 # UInt32 = 4 bytes
31 | assert d.bytes.length == 8 # UInt64 = 8 bytes
32 |
33 | total = a.native + b.native + c.native + d.native
34 | return arc4.UInt64(total)
35 | ```
36 |
37 | ### Big Integers
38 |
39 | ```python
40 | @abimethod()
41 | def add_arc4_biguint_n(
42 | self, a: arc4.UInt128, b: arc4.UInt256, c: arc4.UInt512
43 | ) -> arc4.UInt512:
44 | # Support for larger integers up to 512 bits
45 | assert a.bytes.length == 16 # 128 bits
46 | assert b.bytes.length == 32 # 256 bits
47 | assert c.bytes.length == 64 # 512 bits
48 |
49 | total = a.native + b.native + c.native
50 | return arc4.UInt512(total)
51 | ```
52 |
53 | ## Bytes and Address Types
54 |
55 | ### Bytes
56 |
57 | ```python
58 | @abimethod()
59 | def arc4_byte(self, a: arc4.Byte) -> arc4.Byte:
60 | # arc4.Byte is an 8-bit integer
61 | return arc4.Byte(a.native + 1)
62 | ```
63 |
64 | ### Addresses
65 |
66 | ```python
67 | @abimethod()
68 | def arc4_address_properties(self, address: arc4.Address) -> UInt64:
69 | # Access address properties
70 | underlying_bytes = address.bytes
71 | account = address.native # Get account type
72 |
73 | bal = account.balance
74 | total_asset = account.total_assets
75 |
76 | return bal
77 |
78 | @abimethod()
79 | def arc4_address_return(self, address: arc4.Address) -> arc4.Address:
80 | # Convert Account type to Address
81 | account = address.native
82 | converted_address = arc4.Address(account)
83 | return converted_address
84 | ```
85 |
86 | ## Arrays
87 |
88 | ### Static Arrays
89 |
90 | ```python
91 | import typing as t
92 |
93 | # Define a static array type alias
94 | AliasedStaticArray: t.TypeAlias = arc4.StaticArray[arc4.UInt8, t.Literal[1]]
95 |
96 | class Arc4StaticArray(ARC4Contract):
97 | @abimethod()
98 | def arc4_static_array(self) -> None:
99 | # Create static array directly
100 | static_uint32_array = arc4.StaticArray(
101 | arc4.UInt32(1), arc4.UInt32(10),
102 | arc4.UInt32(255), arc4.UInt32(128)
103 | )
104 |
105 | # Iterate over array
106 | total = UInt64(0)
107 | for uint32_item in static_uint32_array:
108 | total += uint32_item.native
109 |
110 | # Use type alias
111 | aliased_static = AliasedStaticArray(arc4.UInt8(101))
112 | aliased_static[0] = arc4.UInt8(202)
113 | ```
114 |
115 | ### Dynamic Arrays
116 |
117 | ```python
118 | # Define dynamic array type alias
119 | goodbye: t.TypeAlias = arc4.DynamicArray[arc4.String]
120 |
121 | class Arc4DynamicArray(ARC4Contract):
122 | @abimethod()
123 | def hello(self, name: arc4.String) -> String:
124 | # Create dynamic array
125 | dynamic_string_array = arc4.DynamicArray[arc4.String](arc4.String("Hello "))
126 |
127 | # Extend array
128 | extension = arc4.DynamicArray[arc4.String](name, arc4.String("!"))
129 | dynamic_string_array.extend(extension)
130 |
131 | # Copy and modify
132 | copied_array = dynamic_string_array.copy()
133 | copied_array.pop()
134 | copied_array.append(arc4.String("world!"))
135 |
136 | # Iterate over array
137 | greeting = String()
138 | for x in dynamic_string_array:
139 | greeting += x.native
140 |
141 | return greeting
142 | ```
143 |
144 | ### Dynamic Bytes
145 |
146 | ```python
147 | @abimethod()
148 | def arc4_dynamic_bytes(self) -> arc4.DynamicBytes:
149 | # Create dynamic bytes
150 | dynamic_bytes = arc4.DynamicBytes(b"\xff\xff\xff")
151 |
152 | # Access native bytes
153 | native_dynamic_bytes = dynamic_bytes.native
154 |
155 | # Modify bytes
156 | dynamic_bytes[0] = arc4.Byte(0)
157 | dynamic_bytes.extend(arc4.DynamicBytes(b"\xaa\xbb\xcc"))
158 | dynamic_bytes.pop()
159 | dynamic_bytes.append(arc4.Byte(255))
160 |
161 | return dynamic_bytes
162 | ```
163 |
164 | ## Structs and Tuples
165 |
166 | ### Structs
167 |
168 | ```python
169 | class Todo(arc4.Struct):
170 | task: arc4.String
171 | completed: arc4.Bool
172 |
173 | Todos: t.TypeAlias = arc4.DynamicArray[Todo]
174 |
175 | class Arc4Struct(ARC4Contract):
176 | def __init__(self) -> None:
177 | self.todos = Todos()
178 |
179 | @abimethod()
180 | def add_todo(self, task: arc4.String) -> Todos:
181 | # Create and add struct instance
182 | todo = Todo(task=task, completed=arc4.Bool(False))
183 |
184 | if not self.todos:
185 | self.todos = Todos(todo.copy())
186 | else:
187 | self.todos.append(todo.copy())
188 |
189 | return self.todos
190 |
191 | @abimethod()
192 | def complete_todo(self, task: arc4.String) -> None:
193 | # Modify struct field
194 | for index in urange(self.todos.length):
195 | if self.todos[index].task == task:
196 | self.todos[index].completed = arc4.Bool(True)
197 | break
198 | ```
199 |
200 | ### Tuples
201 |
202 | ```python
203 | # Define tuple type
204 | contact_info_tuple = arc4.Tuple[arc4.String, arc4.String, arc4.UInt64]
205 |
206 | class Arc4Tuple(ARC4Contract):
207 | def __init__(self) -> None:
208 | self.contact_info = GlobalState(
209 | contact_info_tuple((
210 | arc4.String(""),
211 | arc4.String(""),
212 | arc4.UInt64(0)
213 | ))
214 | )
215 |
216 | @abimethod()
217 | def add_contact_info(self, contact: contact_info_tuple) -> UInt64:
218 | # Unpack tuple values
219 | name, email, phone = contact.native
220 | self.contact_info.value = contact
221 | return phone.native
222 |
223 | @abimethod()
224 | def return_contact(self) -> arc4.Tuple[arc4.String, arc4.String, arc4.UInt64]:
225 | # Return tuple
226 | return self.contact_info.value
227 | ```
228 |
229 | ## Best Practices
230 |
231 | 1. **Integer Operations**:
232 | - Use `.native` for arithmetic operations
233 | - Choose appropriate integer size
234 | - Handle overflow conditions
235 | - Convert back to ARC4 types for returns
236 |
237 | 2. **Array Management**:
238 | - Use static arrays for fixed-size collections
239 | - Use dynamic arrays for variable-size collections
240 | - Make copies when needed
241 | - Handle array bounds properly
242 |
243 | 3. **Struct Usage**:
244 | - Define clear struct layouts
245 | - Use appropriate field types
246 | - Copy structs when storing
247 | - Validate struct data
248 |
249 | 4. **Type Safety**:
250 | - Use type aliases for clarity
251 | - Verify type conversions
252 | - Handle type constraints
253 | - Document type requirements
254 |
255 | 5. **Memory Management**:
256 | - Consider size limitations
257 | - Use appropriate data structures
258 | - Clean up unused data
259 | - Optimize storage usage
260 |
261 | 6. **Performance**:
262 | - Choose efficient types
263 | - Minimize type conversions
264 | - Use appropriate data structures
265 | - Consider operation costs
266 |
267 | This guide demonstrates the various ARC4 data types available in Algorand smart contracts using Python. Understanding these types is crucial for developing efficient and type-safe smart contracts.
268 |
```
--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/algokit:utils:typescript:code:interfaces:types_app.AppCallParams.md:
--------------------------------------------------------------------------------
```markdown
1 | [@algorandfoundation/algokit-utils](../README.md) / [types/app](../modules/types_app.md) / AppCallParams
2 |
3 | # Interface: AppCallParams
4 |
5 | [types/app](../modules/types_app.md).AppCallParams
6 |
7 | Parameters representing a call to an app.
8 |
9 | ## Hierarchy
10 |
11 | - [`SendTransactionParams`](types_transaction.SendTransactionParams.md)
12 |
13 | ↳ **`AppCallParams`**
14 |
15 | ## Table of contents
16 |
17 | ### Properties
18 |
19 | - [appId](types_app.AppCallParams.md#appid)
20 | - [args](types_app.AppCallParams.md#args)
21 | - [atc](types_app.AppCallParams.md#atc)
22 | - [callType](types_app.AppCallParams.md#calltype)
23 | - [fee](types_app.AppCallParams.md#fee)
24 | - [from](types_app.AppCallParams.md#from)
25 | - [maxFee](types_app.AppCallParams.md#maxfee)
26 | - [maxRoundsToWaitForConfirmation](types_app.AppCallParams.md#maxroundstowaitforconfirmation)
27 | - [note](types_app.AppCallParams.md#note)
28 | - [populateAppCallResources](types_app.AppCallParams.md#populateappcallresources)
29 | - [skipSending](types_app.AppCallParams.md#skipsending)
30 | - [skipWaiting](types_app.AppCallParams.md#skipwaiting)
31 | - [suppressLog](types_app.AppCallParams.md#suppresslog)
32 | - [transactionParams](types_app.AppCallParams.md#transactionparams)
33 |
34 | ## Properties
35 |
36 | ### appId
37 |
38 | • **appId**: `number` \| `bigint`
39 |
40 | The id of the app to call
41 |
42 | #### Defined in
43 |
44 | [src/types/app.ts:185](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L185)
45 |
46 | ___
47 |
48 | ### args
49 |
50 | • `Optional` **args**: [`AppCallArgs`](../modules/types_app.md#appcallargs)
51 |
52 | The arguments passed in to the app call
53 |
54 | #### Defined in
55 |
56 | [src/types/app.ts:195](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L195)
57 |
58 | ___
59 |
60 | ### atc
61 |
62 | • `Optional` **atc**: `AtomicTransactionComposer`
63 |
64 | An optional `AtomicTransactionComposer` to add the transaction to, if specified then `skipSending: undefined` has the same effect as `skipSending: true`
65 |
66 | #### Inherited from
67 |
68 | [SendTransactionParams](types_transaction.SendTransactionParams.md).[atc](types_transaction.SendTransactionParams.md#atc)
69 |
70 | #### Defined in
71 |
72 | [src/types/transaction.ts:36](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transaction.ts#L36)
73 |
74 | ___
75 |
76 | ### callType
77 |
78 | • **callType**: ``"no_op"`` \| ``"opt_in"`` \| ``"close_out"`` \| ``"clear_state"`` \| ``"delete_application"`` \| `NoOpOC` \| `OptInOC` \| `CloseOutOC` \| `ClearStateOC` \| `DeleteApplicationOC`
79 |
80 | The type of call, everything except create (see `createApp`) and update (see `updateApp`)
81 |
82 | #### Defined in
83 |
84 | [src/types/app.ts:187](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L187)
85 |
86 | ___
87 |
88 | ### fee
89 |
90 | • `Optional` **fee**: [`AlgoAmount`](../classes/types_amount.AlgoAmount.md)
91 |
92 | The flat fee you want to pay, useful for covering extra fees in a transaction group or app call
93 |
94 | #### Inherited from
95 |
96 | [SendTransactionParams](types_transaction.SendTransactionParams.md).[fee](types_transaction.SendTransactionParams.md#fee)
97 |
98 | #### Defined in
99 |
100 | [src/types/transaction.ts:40](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transaction.ts#L40)
101 |
102 | ___
103 |
104 | ### from
105 |
106 | • **from**: [`SendTransactionFrom`](../modules/types_transaction.md#sendtransactionfrom)
107 |
108 | The account to make the call from
109 |
110 | #### Defined in
111 |
112 | [src/types/app.ts:189](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L189)
113 |
114 | ___
115 |
116 | ### maxFee
117 |
118 | • `Optional` **maxFee**: [`AlgoAmount`](../classes/types_amount.AlgoAmount.md)
119 |
120 | The maximum fee that you are happy to pay (default: unbounded) - if this is set it's possible the transaction could get rejected during network congestion
121 |
122 | #### Inherited from
123 |
124 | [SendTransactionParams](types_transaction.SendTransactionParams.md).[maxFee](types_transaction.SendTransactionParams.md#maxfee)
125 |
126 | #### Defined in
127 |
128 | [src/types/transaction.ts:42](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transaction.ts#L42)
129 |
130 | ___
131 |
132 | ### maxRoundsToWaitForConfirmation
133 |
134 | • `Optional` **maxRoundsToWaitForConfirmation**: `number`
135 |
136 | The maximum number of rounds to wait for confirmation, only applies if `skipWaiting` is `undefined` or `false`, default: wait up to 5 rounds
137 |
138 | #### Inherited from
139 |
140 | [SendTransactionParams](types_transaction.SendTransactionParams.md).[maxRoundsToWaitForConfirmation](types_transaction.SendTransactionParams.md#maxroundstowaitforconfirmation)
141 |
142 | #### Defined in
143 |
144 | [src/types/transaction.ts:44](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transaction.ts#L44)
145 |
146 | ___
147 |
148 | ### note
149 |
150 | • `Optional` **note**: [`TransactionNote`](../modules/types_transaction.md#transactionnote)
151 |
152 | The (optional) transaction note
153 |
154 | #### Defined in
155 |
156 | [src/types/app.ts:193](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L193)
157 |
158 | ___
159 |
160 | ### populateAppCallResources
161 |
162 | • `Optional` **populateAppCallResources**: `boolean`
163 |
164 | Whether to use simulate to automatically populate app call resources in the txn objects. Defaults to true when there are app calls in the group.
165 |
166 | #### Inherited from
167 |
168 | [SendTransactionParams](types_transaction.SendTransactionParams.md).[populateAppCallResources](types_transaction.SendTransactionParams.md#populateappcallresources)
169 |
170 | #### Defined in
171 |
172 | [src/types/transaction.ts:46](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transaction.ts#L46)
173 |
174 | ___
175 |
176 | ### skipSending
177 |
178 | • `Optional` **skipSending**: `boolean`
179 |
180 | Whether to skip signing and sending the transaction to the chain (default: transaction signed and sent to chain, unless `atc` specified)
181 | and instead just return the raw transaction, e.g. so you can add it to a group of transactions
182 |
183 | #### Inherited from
184 |
185 | [SendTransactionParams](types_transaction.SendTransactionParams.md).[skipSending](types_transaction.SendTransactionParams.md#skipsending)
186 |
187 | #### Defined in
188 |
189 | [src/types/transaction.ts:32](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transaction.ts#L32)
190 |
191 | ___
192 |
193 | ### skipWaiting
194 |
195 | • `Optional` **skipWaiting**: `boolean`
196 |
197 | Whether to skip waiting for the submitted transaction (only relevant if `skipSending` is `false` or unset)
198 |
199 | #### Inherited from
200 |
201 | [SendTransactionParams](types_transaction.SendTransactionParams.md).[skipWaiting](types_transaction.SendTransactionParams.md#skipwaiting)
202 |
203 | #### Defined in
204 |
205 | [src/types/transaction.ts:34](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transaction.ts#L34)
206 |
207 | ___
208 |
209 | ### suppressLog
210 |
211 | • `Optional` **suppressLog**: `boolean`
212 |
213 | Whether to suppress log messages from transaction send, default: do not suppress
214 |
215 | #### Inherited from
216 |
217 | [SendTransactionParams](types_transaction.SendTransactionParams.md).[suppressLog](types_transaction.SendTransactionParams.md#suppresslog)
218 |
219 | #### Defined in
220 |
221 | [src/types/transaction.ts:38](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transaction.ts#L38)
222 |
223 | ___
224 |
225 | ### transactionParams
226 |
227 | • `Optional` **transactionParams**: `SuggestedParams`
228 |
229 | Optional transaction parameters
230 |
231 | #### Defined in
232 |
233 | [src/types/app.ts:191](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L191)
234 |
```
--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/algokit:utils:typescript:code:classes:types_kmd_account_manager.KmdAccountManager.md:
--------------------------------------------------------------------------------
```markdown
1 | [@algorandfoundation/algokit-utils](../README.md) / [types/kmd-account-manager](../modules/types_kmd_account_manager.md) / KmdAccountManager
2 |
3 | # Class: KmdAccountManager
4 |
5 | [types/kmd-account-manager](../modules/types_kmd_account_manager.md).KmdAccountManager
6 |
7 | Provides abstractions over a [KMD](https://github.com/algorand/go-algorand/blob/master/daemon/kmd/README.md) instance
8 | that makes it easier to get and manage accounts using KMD.
9 |
10 | ## Table of contents
11 |
12 | ### Constructors
13 |
14 | - [constructor](types_kmd_account_manager.KmdAccountManager.md#constructor)
15 |
16 | ### Properties
17 |
18 | - [\_clientManager](types_kmd_account_manager.KmdAccountManager.md#_clientmanager)
19 | - [\_kmd](types_kmd_account_manager.KmdAccountManager.md#_kmd)
20 |
21 | ### Methods
22 |
23 | - [getLocalNetDispenserAccount](types_kmd_account_manager.KmdAccountManager.md#getlocalnetdispenseraccount)
24 | - [getOrCreateWalletAccount](types_kmd_account_manager.KmdAccountManager.md#getorcreatewalletaccount)
25 | - [getWalletAccount](types_kmd_account_manager.KmdAccountManager.md#getwalletaccount)
26 | - [kmd](types_kmd_account_manager.KmdAccountManager.md#kmd)
27 |
28 | ## Constructors
29 |
30 | ### constructor
31 |
32 | • **new KmdAccountManager**(`clientManager`): [`KmdAccountManager`](types_kmd_account_manager.KmdAccountManager.md)
33 |
34 | Create a new KMD manager.
35 |
36 | #### Parameters
37 |
38 | | Name | Type | Description |
39 | | :------ | :------ | :------ |
40 | | `clientManager` | [`ClientManager`](types_client_manager.ClientManager.md) | A ClientManager client to use for algod and kmd clients |
41 |
42 | #### Returns
43 |
44 | [`KmdAccountManager`](types_kmd_account_manager.KmdAccountManager.md)
45 |
46 | #### Defined in
47 |
48 | [src/types/kmd-account-manager.ts:18](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/kmd-account-manager.ts#L18)
49 |
50 | ## Properties
51 |
52 | ### \_clientManager
53 |
54 | • `Private` **\_clientManager**: `Omit`\<[`ClientManager`](types_client_manager.ClientManager.md), ``"kmd"``\>
55 |
56 | #### Defined in
57 |
58 | [src/types/kmd-account-manager.ts:11](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/kmd-account-manager.ts#L11)
59 |
60 | ___
61 |
62 | ### \_kmd
63 |
64 | • `Private` `Optional` **\_kmd**: ``null`` \| `KmdClient`
65 |
66 | #### Defined in
67 |
68 | [src/types/kmd-account-manager.ts:12](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/kmd-account-manager.ts#L12)
69 |
70 | ## Methods
71 |
72 | ### getLocalNetDispenserAccount
73 |
74 | ▸ **getLocalNetDispenserAccount**(): `Promise`\<[`TransactionSignerAccount`](../interfaces/types_account.TransactionSignerAccount.md) & \{ `account`: [`SigningAccount`](types_account.SigningAccount.md) }\>
75 |
76 | Returns an Algorand account with private key loaded for the default LocalNet dispenser account (that can be used to fund other accounts).
77 |
78 | #### Returns
79 |
80 | `Promise`\<[`TransactionSignerAccount`](../interfaces/types_account.TransactionSignerAccount.md) & \{ `account`: [`SigningAccount`](types_account.SigningAccount.md) }\>
81 |
82 | The default LocalNet dispenser account
83 |
84 | **`Example`**
85 |
86 | ```typescript
87 | const dispenser = await kmdAccountManager.getLocalNetDispenserAccount()
88 | ```
89 |
90 | #### Defined in
91 |
92 | [src/types/kmd-account-manager.ts:186](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/kmd-account-manager.ts#L186)
93 |
94 | ___
95 |
96 | ### getOrCreateWalletAccount
97 |
98 | ▸ **getOrCreateWalletAccount**(`name`, `fundWith?`): `Promise`\<[`TransactionSignerAccount`](../interfaces/types_account.TransactionSignerAccount.md) & \{ `account`: [`SigningAccount`](types_account.SigningAccount.md) }\>
99 |
100 | Gets an account with private key loaded from a KMD wallet of the given name, or alternatively creates one with funds in it via a KMD wallet of the given name.
101 |
102 | This is useful to get idempotent accounts from LocalNet without having to specify the private key (which will change when resetting the LocalNet).
103 |
104 | This significantly speeds up local dev time and improves experience since you can write code that *just works* first go without manual config in a fresh LocalNet.
105 |
106 | If this is used via `mnemonicAccountFromEnvironment`, then you can even use the same code that runs on production without changes for local development!
107 |
108 | #### Parameters
109 |
110 | | Name | Type | Description |
111 | | :------ | :------ | :------ |
112 | | `name` | `string` | The name of the wallet to retrieve / create |
113 | | `fundWith?` | [`AlgoAmount`](types_amount.AlgoAmount.md) | The number of Algo to fund the account with when it gets created, if not specified then 1000 ALGO will be funded from the dispenser account |
114 |
115 | #### Returns
116 |
117 | `Promise`\<[`TransactionSignerAccount`](../interfaces/types_account.TransactionSignerAccount.md) & \{ `account`: [`SigningAccount`](types_account.SigningAccount.md) }\>
118 |
119 | An Algorand account with private key loaded - either one that already existed in the given KMD wallet, or a new one that is funded for you
120 |
121 | **`Example`**
122 |
123 | ```typescript
124 | // Idempotently get (if exists) or crate (if it doesn't exist yet) an account by name using KMD
125 | // if creating it then fund it with 2 ALGO from the default dispenser account
126 | const newAccount = await kmdAccountManager.getOrCreateWalletAccount('account1', (2).algo())
127 | // This will return the same account as above since the name matches
128 | const existingAccount = await kmdAccountManager.getOrCreateWalletAccount('account1')
129 | ```
130 |
131 | #### Defined in
132 |
133 | [src/types/kmd-account-manager.ts:135](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/kmd-account-manager.ts#L135)
134 |
135 | ___
136 |
137 | ### getWalletAccount
138 |
139 | ▸ **getWalletAccount**(`walletName`, `predicate?`, `sender?`): `Promise`\<`undefined` \| [`TransactionSignerAccount`](../interfaces/types_account.TransactionSignerAccount.md) & \{ `account`: [`SigningAccount`](types_account.SigningAccount.md) }\>
140 |
141 | Returns an Algorand signing account with private key loaded from the given KMD wallet (identified by name).
142 |
143 | #### Parameters
144 |
145 | | Name | Type | Description |
146 | | :------ | :------ | :------ |
147 | | `walletName` | `string` | The name of the wallet to retrieve an account from |
148 | | `predicate?` | (`account`: `Record`\<`string`, `any`\>) => `boolean` | An optional filter to use to find the account (otherwise it will return a random account from the wallet) |
149 | | `sender?` | `string` \| `Address` | The optional sender address to use this signer for (aka a rekeyed account) |
150 |
151 | #### Returns
152 |
153 | `Promise`\<`undefined` \| [`TransactionSignerAccount`](../interfaces/types_account.TransactionSignerAccount.md) & \{ `account`: [`SigningAccount`](types_account.SigningAccount.md) }\>
154 |
155 | The signing account (with private key loaded) or undefined if no matching wallet or account was found
156 |
157 | **`Example`**
158 |
159 | ```typescript
160 | const defaultDispenserAccount = await kmdAccountManager.getWalletAccount(
161 | 'unencrypted-default-wallet',
162 | a => a.status !== 'Offline' && a.amount > 1_000_000_000
163 | )
164 | ```
165 |
166 | #### Defined in
167 |
168 | [src/types/kmd-account-manager.ts:62](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/kmd-account-manager.ts#L62)
169 |
170 | ___
171 |
172 | ### kmd
173 |
174 | ▸ **kmd**(): `Promise`\<`KmdClient`\>
175 |
176 | #### Returns
177 |
178 | `Promise`\<`KmdClient`\>
179 |
180 | #### Defined in
181 |
182 | [src/types/kmd-account-manager.ts:27](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/kmd-account-manager.ts#L27)
183 |
```
--------------------------------------------------------------------------------
/packages/server/tests/tools/accountManager.test.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
2 | import { AccountManager } from '../../src/tools/accountManager.js';
3 | import algosdk from 'algosdk';
4 | import { algodClient } from '../../src/algorand-client.js';
5 |
6 | // Mock algosdk
7 | jest.mock('algosdk', () => ({
8 | generateAccount: jest.fn(),
9 | secretKeyToMnemonic: jest.fn(),
10 | mnemonicToMasterDerivationKey: jest.fn(),
11 | masterDerivationKeyToMnemonic: jest.fn(),
12 | mnemonicToSecretKey: jest.fn(),
13 | seedFromMnemonic: jest.fn(),
14 | mnemonicFromSeed: jest.fn(),
15 | makePaymentTxnWithSuggestedParamsFromObject: jest.fn(),
16 | }));
17 |
18 | // Mock algodClient
19 | jest.mock('../../src/algorand-client.js', () => ({
20 | algodClient: {
21 | getTransactionParams: jest.fn().mockReturnValue({
22 | do: jest.fn().mockResolvedValue({
23 | firstRound: 1000,
24 | lastRound: 2000,
25 | genesisHash: 'hash',
26 | genesisID: 'testnet-v1.0',
27 | }),
28 | }),
29 | },
30 | }));
31 |
32 | describe('AccountManager', () => {
33 | beforeEach(() => {
34 | jest.clearAllMocks();
35 | });
36 |
37 | describe('Tool Schemas', () => {
38 | it('should have valid tool schemas', () => {
39 | expect(AccountManager.accountTools).toHaveLength(8);
40 | expect(AccountManager.accountTools.map((t: { name: string }) => t.name)).toEqual([
41 | 'create_account',
42 | 'rekey_account',
43 | 'mnemonic_to_mdk',
44 | 'mdk_to_mnemonic',
45 | 'secret_key_to_mnemonic',
46 | 'mnemonic_to_secret_key',
47 | 'seed_from_mnemonic',
48 | 'mnemonic_from_seed',
49 | ]);
50 | });
51 | });
52 |
53 | describe('createAccount', () => {
54 | it('should create a new account', () => {
55 | const mockAccount = {
56 | addr: 'test-address',
57 | sk: new Uint8Array([1, 2, 3]),
58 | };
59 | const mockMnemonic = 'test mnemonic';
60 |
61 | (algosdk.generateAccount as jest.Mock).mockReturnValue(mockAccount);
62 | (algosdk.secretKeyToMnemonic as jest.Mock).mockReturnValue(mockMnemonic);
63 |
64 | const result = AccountManager.createAccount();
65 |
66 | expect(result).toEqual({
67 | address: mockAccount.addr,
68 | mnemonic: mockMnemonic,
69 | });
70 | expect(algosdk.generateAccount).toHaveBeenCalled();
71 | expect(algosdk.secretKeyToMnemonic).toHaveBeenCalledWith(mockAccount.sk);
72 | });
73 | });
74 |
75 | describe('createRekeyTransaction', () => {
76 | it('should create a rekey transaction', async () => {
77 | const fromAddress = 'from-address';
78 | const toAddress = 'to-address';
79 | const mockTxn = { type: 'pay' };
80 |
81 | (algosdk.makePaymentTxnWithSuggestedParamsFromObject as jest.Mock).mockReturnValue(mockTxn);
82 |
83 | const result = await AccountManager.createRekeyTransaction(fromAddress, toAddress);
84 |
85 | expect(result).toBe(mockTxn);
86 | expect(algosdk.makePaymentTxnWithSuggestedParamsFromObject).toHaveBeenCalledWith(
87 | expect.objectContaining({
88 | from: fromAddress,
89 | to: fromAddress,
90 | amount: 0,
91 | rekeyTo: toAddress,
92 | })
93 | );
94 | });
95 | });
96 |
97 | describe('handleTool', () => {
98 | it('should handle create_account', async () => {
99 | const mockAccount = {
100 | address: 'test-address',
101 | mnemonic: 'test mnemonic',
102 | };
103 | jest.spyOn(AccountManager, 'createAccount').mockReturnValue(mockAccount);
104 |
105 | const result = await AccountManager.handleTool('create_account', {});
106 |
107 | expect(result).toEqual({
108 | content: [{
109 | type: 'text',
110 | text: JSON.stringify(mockAccount, null, 2),
111 | }],
112 | });
113 | });
114 |
115 | it('should handle rekey_account', async () => {
116 | const mockTxn = { type: 'pay' };
117 | jest.spyOn(AccountManager, 'createRekeyTransaction').mockResolvedValue(mockTxn as any);
118 |
119 | const result = await AccountManager.handleTool('rekey_account', {
120 | sourceAddress: 'from-address',
121 | targetAddress: 'to-address',
122 | });
123 |
124 | expect(result).toEqual({
125 | content: [{
126 | type: 'text',
127 | text: JSON.stringify(mockTxn, null, 2),
128 | }],
129 | });
130 | });
131 |
132 | it('should handle mnemonic_to_mdk', async () => {
133 | const mockMdk = new Uint8Array([1, 2, 3]);
134 | (algosdk.mnemonicToMasterDerivationKey as jest.Mock).mockReturnValue(mockMdk);
135 |
136 | const result = await AccountManager.handleTool('mnemonic_to_mdk', {
137 | mnemonic: 'test mnemonic',
138 | });
139 |
140 | expect(result).toEqual({
141 | content: [{
142 | type: 'text',
143 | text: JSON.stringify({ mdk: Buffer.from(mockMdk).toString('hex') }, null, 2),
144 | }],
145 | });
146 | });
147 |
148 | it('should handle mdk_to_mnemonic', async () => {
149 | const mockMnemonic = 'test mnemonic';
150 | (algosdk.masterDerivationKeyToMnemonic as jest.Mock).mockReturnValue(mockMnemonic);
151 |
152 | const result = await AccountManager.handleTool('mdk_to_mnemonic', {
153 | mdk: '010203',
154 | });
155 |
156 | expect(result).toEqual({
157 | content: [{
158 | type: 'text',
159 | text: JSON.stringify({ mnemonic: mockMnemonic }, null, 2),
160 | }],
161 | });
162 | });
163 |
164 | it('should throw error for unknown tool', async () => {
165 | await expect(AccountManager.handleTool('unknown_tool', {}))
166 | .rejects
167 | .toThrow(new McpError(ErrorCode.MethodNotFound, 'Unknown tool: unknown_tool'));
168 | });
169 |
170 | it('should throw error for invalid parameters', async () => {
171 | await expect(AccountManager.handleTool('rekey_account', {}))
172 | .rejects
173 | .toThrow(new McpError(ErrorCode.InvalidParams, 'Invalid rekey account parameters'));
174 | });
175 | });
176 |
177 | describe('Mnemonic Conversions', () => {
178 | it('should convert mnemonic to secret key', () => {
179 | const mockResult = {
180 | sk: new Uint8Array([1, 2, 3]),
181 | addr: 'test-address',
182 | };
183 | (algosdk.mnemonicToSecretKey as jest.Mock).mockReturnValue(mockResult);
184 |
185 | const result = AccountManager.mnemonicToSecretKey('test mnemonic');
186 |
187 | expect(result).toBe(mockResult);
188 | expect(algosdk.mnemonicToSecretKey).toHaveBeenCalledWith('test mnemonic');
189 | });
190 |
191 | it('should convert secret key to mnemonic', () => {
192 | const mockMnemonic = 'test mnemonic';
193 | (algosdk.secretKeyToMnemonic as jest.Mock).mockReturnValue(mockMnemonic);
194 |
195 | const secretKey = new Uint8Array([1, 2, 3]);
196 | const result = AccountManager.secretKeyToMnemonic(secretKey);
197 |
198 | expect(result).toBe(mockMnemonic);
199 | expect(algosdk.secretKeyToMnemonic).toHaveBeenCalledWith(secretKey);
200 | });
201 |
202 | it('should generate seed from mnemonic', () => {
203 | const mockSeed = new Uint8Array([1, 2, 3]);
204 | (algosdk.seedFromMnemonic as jest.Mock).mockReturnValue(mockSeed);
205 |
206 | const result = AccountManager.seedFromMnemonic('test mnemonic');
207 |
208 | expect(result).toBe(mockSeed);
209 | expect(algosdk.seedFromMnemonic).toHaveBeenCalledWith('test mnemonic');
210 | });
211 |
212 | it('should generate mnemonic from seed', () => {
213 | const mockMnemonic = 'test mnemonic';
214 | (algosdk.mnemonicFromSeed as jest.Mock).mockReturnValue(mockMnemonic);
215 |
216 | const seed = new Uint8Array([1, 2, 3]);
217 | const result = AccountManager.mnemonicFromSeed(seed);
218 |
219 | expect(result).toBe(mockMnemonic);
220 | expect(algosdk.mnemonicFromSeed).toHaveBeenCalledWith(seed);
221 | });
222 | });
223 | });
224 |
```
--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/algokit:utils:typescript:code:classes:types_async_event_emitter.AsyncEventEmitter.md:
--------------------------------------------------------------------------------
```markdown
1 | [@algorandfoundation/algokit-utils](../README.md) / [types/async-event-emitter](../modules/types_async_event_emitter.md) / AsyncEventEmitter
2 |
3 | # Class: AsyncEventEmitter
4 |
5 | [types/async-event-emitter](../modules/types_async_event_emitter.md).AsyncEventEmitter
6 |
7 | ## Table of contents
8 |
9 | ### Constructors
10 |
11 | - [constructor](types_async_event_emitter.AsyncEventEmitter.md#constructor)
12 |
13 | ### Properties
14 |
15 | - [listenerMap](types_async_event_emitter.AsyncEventEmitter.md#listenermap)
16 | - [listenerWrapperMap](types_async_event_emitter.AsyncEventEmitter.md#listenerwrappermap)
17 | - [off](types_async_event_emitter.AsyncEventEmitter.md#off)
18 |
19 | ### Methods
20 |
21 | - [emitAsync](types_async_event_emitter.AsyncEventEmitter.md#emitasync)
22 | - [on](types_async_event_emitter.AsyncEventEmitter.md#on)
23 | - [once](types_async_event_emitter.AsyncEventEmitter.md#once)
24 | - [removeListener](types_async_event_emitter.AsyncEventEmitter.md#removelistener)
25 |
26 | ## Constructors
27 |
28 | ### constructor
29 |
30 | • **new AsyncEventEmitter**(): [`AsyncEventEmitter`](types_async_event_emitter.AsyncEventEmitter.md)
31 |
32 | #### Returns
33 |
34 | [`AsyncEventEmitter`](types_async_event_emitter.AsyncEventEmitter.md)
35 |
36 | ## Properties
37 |
38 | ### listenerMap
39 |
40 | • `Private` **listenerMap**: `Record`\<`string` \| `symbol`, [`AsyncEventListener`](../modules/types_async_event_emitter.md#asynceventlistener)\<`unknown`\>[]\> = `{}`
41 |
42 | #### Defined in
43 |
44 | [src/types/async-event-emitter.ts:7](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/async-event-emitter.ts#L7)
45 |
46 | ___
47 |
48 | ### listenerWrapperMap
49 |
50 | • `Private` **listenerWrapperMap**: `WeakMap`\<[`AsyncEventListener`](../modules/types_async_event_emitter.md#asynceventlistener)\<`unknown`\>, [`AsyncEventListener`](../modules/types_async_event_emitter.md#asynceventlistener)\<`unknown`\>\>
51 |
52 | #### Defined in
53 |
54 | [src/types/async-event-emitter.ts:6](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/async-event-emitter.ts#L6)
55 |
56 | ___
57 |
58 | ### off
59 |
60 | • **off**: (`eventName`: `string` \| `symbol`, `listener`: [`AsyncEventListener`](../modules/types_async_event_emitter.md#asynceventlistener)\<`unknown`\>) => [`AsyncEventEmitter`](types_async_event_emitter.AsyncEventEmitter.md)
61 |
62 | #### Type declaration
63 |
64 | ▸ (`eventName`, `listener`): [`AsyncEventEmitter`](types_async_event_emitter.AsyncEventEmitter.md)
65 |
66 | ##### Parameters
67 |
68 | | Name | Type |
69 | | :------ | :------ |
70 | | `eventName` | `string` \| `symbol` |
71 | | `listener` | [`AsyncEventListener`](../modules/types_async_event_emitter.md#asynceventlistener)\<`unknown`\> |
72 |
73 | ##### Returns
74 |
75 | [`AsyncEventEmitter`](types_async_event_emitter.AsyncEventEmitter.md)
76 |
77 | #### Defined in
78 |
79 | [src/types/async-event-emitter.ts:55](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/async-event-emitter.ts#L55)
80 |
81 | ## Methods
82 |
83 | ### emitAsync
84 |
85 | ▸ **emitAsync**\<`K`\>(`eventName`, `event`): `Promise`\<`void`\>
86 |
87 | #### Type parameters
88 |
89 | | Name | Type |
90 | | :------ | :------ |
91 | | `K` | extends [`EventType`](../enums/types_lifecycle_events.EventType.md) |
92 |
93 | #### Parameters
94 |
95 | | Name | Type |
96 | | :------ | :------ |
97 | | `eventName` | `K` |
98 | | `event` | [`EventDataMap`](../modules/types_lifecycle_events.md#eventdatamap)[`K`] |
99 |
100 | #### Returns
101 |
102 | `Promise`\<`void`\>
103 |
104 | #### Defined in
105 |
106 | [src/types/async-event-emitter.ts:9](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/async-event-emitter.ts#L9)
107 |
108 | ▸ **emitAsync**(`eventName`, `event`): `Promise`\<`void`\>
109 |
110 | #### Parameters
111 |
112 | | Name | Type |
113 | | :------ | :------ |
114 | | `eventName` | `string` \| `symbol` |
115 | | `event` | `unknown` |
116 |
117 | #### Returns
118 |
119 | `Promise`\<`void`\>
120 |
121 | #### Defined in
122 |
123 | [src/types/async-event-emitter.ts:10](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/async-event-emitter.ts#L10)
124 |
125 | ___
126 |
127 | ### on
128 |
129 | ▸ **on**\<`K`\>(`eventName`, `listener`): [`AsyncEventEmitter`](types_async_event_emitter.AsyncEventEmitter.md)
130 |
131 | #### Type parameters
132 |
133 | | Name | Type |
134 | | :------ | :------ |
135 | | `K` | extends [`EventType`](../enums/types_lifecycle_events.EventType.md) |
136 |
137 | #### Parameters
138 |
139 | | Name | Type |
140 | | :------ | :------ |
141 | | `eventName` | `K` |
142 | | `listener` | [`AsyncEventListener`](../modules/types_async_event_emitter.md#asynceventlistener)\<[`EventDataMap`](../modules/types_lifecycle_events.md#eventdatamap)[`K`]\> |
143 |
144 | #### Returns
145 |
146 | [`AsyncEventEmitter`](types_async_event_emitter.AsyncEventEmitter.md)
147 |
148 | #### Defined in
149 |
150 | [src/types/async-event-emitter.ts:17](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/async-event-emitter.ts#L17)
151 |
152 | ▸ **on**\<`T`\>(`eventName`, `listener`): [`AsyncEventEmitter`](types_async_event_emitter.AsyncEventEmitter.md)
153 |
154 | #### Type parameters
155 |
156 | | Name | Type |
157 | | :------ | :------ |
158 | | `T` | `unknown` |
159 |
160 | #### Parameters
161 |
162 | | Name | Type |
163 | | :------ | :------ |
164 | | `eventName` | `string` \| `symbol` |
165 | | `listener` | [`AsyncEventListener`](../modules/types_async_event_emitter.md#asynceventlistener)\<`T`\> |
166 |
167 | #### Returns
168 |
169 | [`AsyncEventEmitter`](types_async_event_emitter.AsyncEventEmitter.md)
170 |
171 | #### Defined in
172 |
173 | [src/types/async-event-emitter.ts:18](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/async-event-emitter.ts#L18)
174 |
175 | ___
176 |
177 | ### once
178 |
179 | ▸ **once**\<`K`\>(`eventName`, `listener`): [`AsyncEventEmitter`](types_async_event_emitter.AsyncEventEmitter.md)
180 |
181 | #### Type parameters
182 |
183 | | Name | Type |
184 | | :------ | :------ |
185 | | `K` | extends [`EventType`](../enums/types_lifecycle_events.EventType.md) |
186 |
187 | #### Parameters
188 |
189 | | Name | Type |
190 | | :------ | :------ |
191 | | `eventName` | `K` |
192 | | `listener` | [`AsyncEventListener`](../modules/types_async_event_emitter.md#asynceventlistener)\<[`EventDataMap`](../modules/types_lifecycle_events.md#eventdatamap)[`K`]\> |
193 |
194 | #### Returns
195 |
196 | [`AsyncEventEmitter`](types_async_event_emitter.AsyncEventEmitter.md)
197 |
198 | #### Defined in
199 |
200 | [src/types/async-event-emitter.ts:25](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/async-event-emitter.ts#L25)
201 |
202 | ▸ **once**\<`T`\>(`eventName`, `listener`): [`AsyncEventEmitter`](types_async_event_emitter.AsyncEventEmitter.md)
203 |
204 | #### Type parameters
205 |
206 | | Name | Type |
207 | | :------ | :------ |
208 | | `T` | `unknown` |
209 |
210 | #### Parameters
211 |
212 | | Name | Type |
213 | | :------ | :------ |
214 | | `eventName` | `string` \| `symbol` |
215 | | `listener` | [`AsyncEventListener`](../modules/types_async_event_emitter.md#asynceventlistener)\<`T`\> |
216 |
217 | #### Returns
218 |
219 | [`AsyncEventEmitter`](types_async_event_emitter.AsyncEventEmitter.md)
220 |
221 | #### Defined in
222 |
223 | [src/types/async-event-emitter.ts:26](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/async-event-emitter.ts#L26)
224 |
225 | ___
226 |
227 | ### removeListener
228 |
229 | ▸ **removeListener**(`eventName`, `listener`): [`AsyncEventEmitter`](types_async_event_emitter.AsyncEventEmitter.md)
230 |
231 | #### Parameters
232 |
233 | | Name | Type |
234 | | :------ | :------ |
235 | | `eventName` | `string` \| `symbol` |
236 | | `listener` | [`AsyncEventListener`](../modules/types_async_event_emitter.md#asynceventlistener)\<`unknown`\> |
237 |
238 | #### Returns
239 |
240 | [`AsyncEventEmitter`](types_async_event_emitter.AsyncEventEmitter.md)
241 |
242 | #### Defined in
243 |
244 | [src/types/async-event-emitter.ts:39](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/async-event-emitter.ts#L39)
245 |
```
--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/algokit:cli:architecture-decisions:2022-11-22_beaker-testing-strategy.md:
--------------------------------------------------------------------------------
```markdown
1 | # Beaker testing strategy
2 |
3 | - **Status**: Draft
4 | - **Owner:** Rob Moore
5 | - **Deciders**: Anne Kenyon (Algorand Inc.), Alessandro Cappellato (Algorand Foundation), Michael Diamant (Algorand Inc.), Benjamin Guidarelli (Algorand Foundation)
6 | - **Date created**: 2022-11-22
7 | - **Date decided:** TBD
8 | - **Date updated**: 2022-11-28
9 |
10 | ## Context
11 |
12 | AlgoKit will be providing a smart contract development experience built on top of [PyTEAL](https://pyteal.readthedocs.io/en/stable/) and [Beaker](https://developer.algorand.org/articles/hello-beaker/). Beaker is currently in a pre-production state and needs to be productionised to provide confidence for use in generating production-ready smart contracts by AlgoKit users. One of the key things to resolve to productionisation of Beaker is to improve the automated test coverage.
13 |
14 | Beaker itself is currently split into the PyTEAL generation related code and the deployment and invocation related code (including interacting with Sandbox). This decision is solely focussed on the PyTEAL generation components of Beaker. The current automated test coverage of this part of the codebase is ~50% and is largely based on compiling and/or executing smart contracts against Algorand Sandbox. While it's generally not best practice to try and case a specific code coverage percentage, a coverage of ~80%+ is likely indicative of good coverage in a dynamic language such as Python.
15 |
16 | The Sandbox tests provide a great deal of confidence, but are also slow to execute, which can potentially impair Beaker development and maintenance experience, especially as the coverage % is grown and/or features are added over time.
17 |
18 | Beaker, like PyTEAL, can be considered to be a transpiler on top of TEAL. When generating smart contracts, the individual TEAL opcodes are significant, since security audits will often consider the impact at that level, and it can have impacts on (limited!) resource usage of the smart contract. As such, "output stability" is potentially an important characteristic to test for.
19 |
20 | ## Requirements
21 |
22 | - We have a high degree of confidence that writing smart contracts in Beaker leads to expected results for production smart contracts
23 | - We have reasonable regression coverage so features are unlikely to break as new features and refactorings are added over time
24 | - We have a level of confidence in the "output stability" of the TEAL code generated from a Beaker smart contract
25 |
26 | ## Principles
27 |
28 | - **Fast development feedback loops** - The feedback loop during normal development should be as fast as possible to improve the development experience of developing Beaker itself
29 | - **Low overhead** - The overhead of writing and maintaining tests is as low as possible; tests should be quick to read and write
30 | - **Implementation decoupled** - Tests aren't testing the implementation details of Beaker, but rather the user-facing experience and output of it; this reduces the likelihood of needing to rewrite tests when performing refactoring of the codebase
31 |
32 | ## Options
33 |
34 | ### Option 1: TEAL Approval tests
35 |
36 | Writing [approval tests](https://approvaltests.com/) of the TEAL output generated from a given Beaker smart contract.
37 |
38 | **Pros**
39 |
40 | - Ensures TEAL output stability and focussing on asserting the output of Beaker rather than testing whether Algorand Protocol is working
41 | - Runs in-memory/in-process so will execute in low 10s of milliseconds making it easy to provide high coverage with low developer feedback loop overhead
42 | - Tests are easy to write - the assertion is a single line of code (no tedious assertions)
43 | - The tests go from Beaker contract -> TEAL approval so don't bake implementation detail and thus allow full Beaker refactoring with regression confidence without needing to modify the tests
44 | - Excellent regression coverage characteristics - fast test run and quick to write allows for high coverage and anchoring assertions to TEAL output is a very clear regression marker
45 |
46 | **Cons**
47 |
48 | - The tests rely on the approver to understand the TEAL opcodes that are emitted and verify they match the intent of the Beaker contract - anecdotally this can be difficult at times even for experienced (Py)TEAL developers
49 | - Doesn't assert the correctness of the TEAL output, just that it matches the previously manually approved output
50 |
51 | ### Option 2: Sandbox compile tests
52 |
53 | Writing Beaker smart contracts and checking that the TEAL output successfully compiles against algod.
54 |
55 | **Pros**
56 |
57 | - Ensures that the TEAL output compiles, giving some surety about the intactness of it and focussing on asserting the output of Beaker rather than testing whether Algorand Protocol is working
58 | - Faster than executing the contract
59 | - Tests are easy to write - the assertion is a single line of code (no tedious assertions)
60 |
61 | **Cons**
62 |
63 | - Order of magnitude slower than asserting TEAL output (out of process communication)
64 | - Doesn't assert the correctness of the TEAL output, just that it compiles
65 |
66 | ### Option 3: Sandbox execution tests
67 |
68 | Execute the smart contracts and assert the output is as expected. This can be done using dry run and/or actual transactions.
69 |
70 | **Pros**
71 |
72 | - Asserts that the TEAL output _executes_ correctly giving the highest confidence
73 | - Doesn't require the test writer to understand the TEAL output
74 | - Tests don't bake implementation detail and do assert on output so give a reasonable degree of refactoring confidence without modifying tests
75 |
76 | **Cons**
77 |
78 | - Tests are more complex to write
79 | - Tests take an order of magnitude longer to run than just compilation (two orders of magnitude to run than checking TEAL output)
80 | - Harder to get high regression coverage since it's slower to write and run the tests making it impractical to get full coverage
81 | - Doesn't ensure output stability
82 | - Is testing that the Algorand Protocol itself works (TEAL `x` when executed does `y`) so the testing scope is broader than just Beaker itself
83 |
84 | ## Preferred option
85 |
86 | Option 1 (combined with Option 2 to ensure the approved TEAL actually compiles, potentially only run on CI by default to ensure fast local dev loop) for the bulk of testing to provide a rapid feedback loop for developers as well as ensuring output stability and great regression coverage.
87 |
88 | ## Selected option
89 |
90 | Combination of option 1, 2 and 3:
91 |
92 | - While Option 1 + 2 provides high confidence with fast feedback loop, it relies on the approver being able to determine the TEAL output does what they think it does, which isn't always the case
93 | - Option 3 will be used judiciously to provide that extra level of confidence that the fundamentals of the Beaker output are correct for each main feature; this will involve key scenarios being tested with execution based tests, the goal isn't to get combinatorial coverage, which would be slow and time-consuming, but to give a higher degree of confidence
94 | - The decision of when to use Option 3 as well as Option 1+2 will be made on a per-feature basis and reviewed via pull request, over time a set of principles may be able to be revised that outline a clear delineation
95 | - Use of PyTest markers to separate execution so by default the dev feedback loop is still fast, but the full suite is always run against pull requests and merges to main
96 |
```