#
tokens: 47413/50000 8/942 files (page 29/74)
lines: off (toggle) GitHub
raw markdown copy
This is page 29 of 74. Use http://codebase.md/goplausible/algorand-mcp?lines=false&page={x} to view the full context.

# Directory Structure

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

# Files

--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/ARCs:specs:arc-0019.md:
--------------------------------------------------------------------------------

```markdown
---
arc: 19
title: Templating of NFT ASA URLs for mutability
description: Templating mechanism of the URL so that changeable data in an asset can be substituted by a client, providing a mutable URL.
author: Patrick Bennett / TxnLab Inc. (@pbennett)
discussions-to: https://github.com/algorandfoundation/ARCs/issues/73
status: Final
type: Standards Track
category: ARC
sub-category: Asa
created: 2021-01-23
---

## Abstract
This ARC describes a template substitution for URLs in ASAs, initially for ipfs:// scheme URLs allowing mutable CID replacement in rendered URLs.

The proposed template-XXX scheme has substitutions like:
```
template-ipfs://{ipfscid:<version>:<multicodec>:<field name containing 32-byte digest, ie reserve>:<hash type>}[/...]
```

This will allow modifying the 32-byte 'Reserve address' in an ASA to represent a new IPFS content-id hash. Changing of the reserve address via an asset-config transaction will be all that is needed to point an ASA URL to new IPFS content. The client reading this URL, will compose a fully formed IPFS Content-ID based on the version, multicodec, and hash arguments provided in the ipfscid substitution.

## Motivation

While immutability for many NFTs is appropriate (see [ARC-3](./arc-0003.md) link), there are cases where some type of mutability is desired for NFT metadata and/or digital media. The data being referenced by the pointer should be immutable but the pointer may be updated to provide a kind of mutability. The data being referenced may be of any size.

Algorand ASAs support mutation of several parameters, namely the role address fields (Manager, Clawback, Freeze, and Reserve addresses), unless previously cleared. These are changed via an asset-config transaction from the Manager account. An asset-config transaction may include a note, but it is limited to 1KB and accessing this value requires clients to use an indexer to iterate/retrieve the values.

Of the parameters that are mutable, the Reserve address is somewhat distinct in that it is not used for anything directly as part of the protocol. It is used solely for determining what is in/out of circulation (by subtracting supply from that held by the reserve address). With a (pure) NFT, the Reserve address is irrelevant as it is a 1 of 1 unit. Thus, the Reserve address may be repurposed as a 32-byte 'bitbucket'.

These 32-bytes can, for example, hold a SHA2-256 hash uniquely referencing the desired content for the ASA (ARC-3-like metadata for example)

Using the reserve address in this way means that what an ASA 'points to' for metadata can be changed with a single asset config transaction, changing only the 32-bytes of the reserve address.  The new value is accessible via even non-archival nodes with a single call to the `/v2/assets/xxx` REST endpoint.

## Specification

The key words "**MUST**", "**MUST NOT**", "**REQUIRED**", "**SHALL**", "**SHALL NOT**", "**SHOULD**", "**SHOULD NOT**", "**RECOMMENDED**", "**MAY**", and "**OPTIONAL**" in this document are to be interpreted as described in <a href="https://www.ietf.org/rfc/rfc2119.txt">RFC-2119</a>.

This proposal specifies a method to provide mutability for IPFS hosted content-ids.  The intention is that FUTURE ARCs could define additional template substitutions, but this is not meant to be a kitchen sink of templates, only to establish a possible baseline of syntax.

An indication that this ARC is in use is defined by an ASA URL's "scheme" having the prefix "**template-**".

An Asset conforming this specification **MUST** have:

1. **URL Scheme of "template-ipfs"**

The URL of the asset must be of the form:
```plain
template-ipfs://(...)
```

> The ipfs:// scheme is already somewhat of a meta scheme in that clients interpret the ipfs scheme as referencing an IPFS CID (version 0/base58 or 1/base32 currently) followed by optional path within certain types of IPFS DAG content (IPLD CAR content for example). The clients take the CID and use to fetch directly from the IPFS network directly via IPFS nodes, or via various IPFS gateways (https://ipfs.io/ipfs/CID[/...], pinata, etc.)).

2. **An "ipfscid" _template_ argument in place of the normal CID.**

Where the format of templates are `{<template type>:<parameters...>])`

The ipfscid template definitions is based on properties within the IPFS CID spec: https://github.com/multiformats/cid

```
ipfscid:<version>:<multicodec content-type name>:<field name (containing 32-byte digest, i.e., "reserve")>:<hash type>
```

> The intent is to recompose a complete CID based on the content-hash contained within the 32-byte reserve address, but using the correct multicodec content type, ipfs content-id version, and hash type to match how the asset creator will seed the IPFS content.  If a single file is added using the 'ipfs' CLI via `ipfs add --cid-version=1 metadata.json` then the resulting content will be encoded using the 'raw' multicodec type.  If a directory is added containing one or more files, then it will be encoded using the dag-pb multicodec.  CAR content will also be dag-pb. Thus based on the method used to post content to IPFS, the ipfscid template should match.

The parameters to the template ipfscid are:
1. IPFS `<version>`, **MUST** a valid IPFS CID version. Client implementation **MUST** support '0' or '1' and **SHOULD** support future version.
2. `<multicodec content-type name>` **MUST** be an IPFS multicodec name. Client implementations **MUST** support 'raw' or 'dag-pb'. Other codecs **SHOULD** be supported but are beyond the scope of this proposal.
3. `<field name>` **MUST** be 'reserve'.
	> This is to represent the reserve address is used for the 32-byte hash. It is specified here so future iterations of the specification may allow other fields or syntaxes to reference other mutable field types.
4. `<hash type>` **MUST** be the multihash hash function type (as defined in https://multiformats.io/multihash/). Client implementations **MUST** support 'sha2-256' and **SHOULD** support future hash types when introduced by IPFS.

> IPFS may add future versions of the cid spec, and add additional multicodec types or hash types.

Implementations **SHOULD** use IPFS libraries where possible that accept multicodec and hash types as named values and allow a CID to be composed generically.

### Examples

> This whole section is non-normative.

* ASA URL: `template-ipfs://{ipfscid:0:dag-pb:reserve:sha2-256}/arc3.json`
* ASA URL: `template-ipfs://{ipfscid:1:raw:reserve:sha2-256}`
* ASA URL: `template-ipfs://{ipfscid:1:dag-pb:reserve:sha2-256}/metadata.json`

#### Deployed Testnet Example

An example was pushed to TestNet, converting from an existing ARC-3 MainNet ASA (asset ID 560421434, https://algoexplorer.io/asset/560421434)

With IPFS URL:
```
ipfs://QmQZyq4b89RfaUw8GESPd2re4hJqB8bnm4kVHNtyQrHnnK
```

The TestNet ASA was minted with the URL:
```
template-ipfs://{ipfscid:0:dag-pb:reserve:sha2-256}
```
as the original CID is a V0 / dag-pb CID.

A helpful link to 'visualize' CIDs and for this specific id, is https://cid.ipfs.io/#QmQZyq4b89RfaUw8GESPd2re4hJqB8bnm4kVHNtyQrHnnK

Using the example encoding implementation, results in virtual 'reserve address' of
```
EEQYWGGBHRDAMTEVDPVOSDVX3HJQIG6K6IVNR3RXHYOHV64ZWAEISS4CTI
```
which is the address (with checksum) corresponding to the 32-byte with hexadecimal value:
```
21218B18C13C46064C951BEAE90EB7D9D3041BCAF22AD8EE373E1C7AFB99B008
```
(Transformation from a 32-byte public key to an address can be found there on the developer website https://developer.algorand.org/docs/get-details/accounts/#transformation-public-key-to-algorand-address.)

The resulting ASA can be seen on https://testnet.algoexplorer.io/asset/66753108

Using the forked <a href="https://github.com/TxnLab/arc3.xyz">repo</a>, with testnet selected, and the /nft/66753108 url - the browser will display the original content as-is, using only the Reserve address as the source of the content hash.

### Interactions with ARC-3

This ARC is compatible with [ARC-3](./arc-0003.md) with the following notable exception:
the ASA Metadata Hash (`am`) is no more necessarily a valid hash of the JSON Metadata File pointed by the URL.

As such, clients cannot be strictly compatible to both ARC-3 and [ARC-19](./arc-0019.md). An ARC-3 and ARC-19 client **SHOULD** ignore validation of the ASA Metadata Hash when the Asset URL is following ARC-19.

ARC-3 clients **SHOULD** clearly indicate to the user when displaying an ARC-19 ASA, as contrary to a strict ARC-3 ASA, the asset may arbitrarily change over time (even after being bought).

ASA that follow both ARC-3 and ARC-19 **MUST NOT** use extra metadata hash (from ARC-3).

## Rationale

See the motivation section above for the general rationale.

### Backwards Compatibility

The 'template-' prefix of the scheme is intended to break clients reading these ASA URLs outright. Clients interpreting these URLs as-is would likely yield unusual errors. Code checking for an explicit 'ipfs' scheme for example will not see this as compatible with any of the default processing and should treat the URL as if it were simply unknown/empty.

## Reference Implementation

### Encoding

#### Go implementation

```go
import (
    "github.com/algorand/go-algorand-sdk/types"
    "github.com/ipfs/go-cid"
    "github.com/multiformats/go-multihash"
)
// ...
func ReserveAddressFromCID(cidToEncode cid.Cid) (string, error) {
    decodedMultiHash, err := multihash.Decode(cidToEncode.Hash())
    if err != nil {
        return "", fmt.Errorf("failed to decode ipfs cid: %w", err))
    }
    return types.EncodeAddress(decodedMultiHash.Digest)
}
// ....
```

### Decoding

#### Go implementation

```go
import (
	"errors"
	"fmt"
	"regexp"
	"strings"

	"github.com/algorand/go-algorand-sdk/types"
	"github.com/ipfs/go-cid"
	"github.com/multiformats/go-multicodec"
	"github.com/multiformats/go-multihash"
)

var (
	ErrUnknownSpec      = errors.New("unsupported template-ipfs spec")
	ErrUnsupportedField = errors.New("unsupported ipfscid field, only reserve is currently supported")
	ErrUnsupportedCodec = errors.New("unknown multicodec type in ipfscid spec")
	ErrUnsupportedHash  = errors.New("unknown hash type in ipfscid spec")
	ErrInvalidV0        = errors.New("cid v0 must always be dag-pb and sha2-256 codec/hash type")
	ErrHashEncoding     = errors.New("error encoding new hash")
	templateIPFSRegexp  = regexp.MustCompile(`template-ipfs://{ipfscid:(?P<version>[01]):(?P<codec>[a-z0-9\-]+):(?P<field>[a-z0-9\-]+):(?P<hash>[a-z0-9\-]+)}`)
)

func ParseASAUrl(asaUrl string, reserveAddress types.Address) (string, error) {
	matches := templateIPFSRegexp.FindStringSubmatch(asaUrl)
	if matches == nil {
		if strings.HasPrefix(asaUrl, "template-ipfs://") {
			return "", ErrUnknownSpec
		}
		return asaUrl, nil
	}
	if matches[templateIPFSRegexp.SubexpIndex("field")] != "reserve" {
		return "", ErrUnsupportedField
	}
	var (
		codec         multicodec.Code
		multihashType uint64
		hash          []byte
		err           error
		cidResult     cid.Cid
	)
	if err = codec.Set(matches[templateIPFSRegexp.SubexpIndex("codec")]); err != nil {
		return "", ErrUnsupportedCodec
	}
	multihashType = multihash.Names[matches[templateIPFSRegexp.SubexpIndex("hash")]]
	if multihashType == 0 {
		return "", ErrUnsupportedHash
	}

	hash, err = multihash.Encode(reserveAddress[:], multihashType)
	if err != nil {
		return "", ErrHashEncoding
	}
	if matches[templateIPFSRegexp.SubexpIndex("version")] == "0" {
		if codec != multicodec.DagPb {
			return "", ErrInvalidV0
		}
		if multihashType != multihash.SHA2_256 {
			return "", ErrInvalidV0
		}
		cidResult = cid.NewCidV0(hash)
	} else {
		cidResult = cid.NewCidV1(uint64(codec), hash)
	}
	return fmt.Sprintf("ipfs://%s", strings.ReplaceAll(asaUrl, matches[0], cidResult.String())), nil
}
```

#### Typescript Implementation

A modified version of a simple ARC-3 viewer can be found <a href="https://github.com/TxnLab/arc3.xyz">here</a> specifically the code segment at <a href="https://github.com/TxnLab/arc3.xyz/blob/main/src/lib/nft.ts#L41">nft.ts#L41</a>

This is a fork of <a href="https://github.com/barnjamin/arc3.xyz">ar3.xyz</a>

## Security Considerations

There should be no specific security issues beyond those of any client accessing any remote content and the risks linked to assets changing (even after the ASA is bought).

The later is handled in the section "Interactions with ARC-3" above.

Regarding the former, URLs within ASAs could point to malicious content, whether that is an http/https link or whether fetched through ipfs protocols or ipfs gateways. As the template changes nothing other than the resulting URL and also defines nothing more than the generation of an IPFS CID hash value, no security concerns derived from this specific proposal are known.

## Copyright
Copyright and related rights waived via <a href="https://creativecommons.org/publicdomain/zero/1.0/">CCO</a>.

```

--------------------------------------------------------------------------------
/packages/server/tests/tools/transactionManager/appTransactionManager.test.ts:
--------------------------------------------------------------------------------

```typescript
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
import { AppTransactionManager, appTransactionTools } from '../../../src/tools/transactionManager/appTransactions.js';
import { algodClient } from '../../../src/algorand-client.js';
import algosdk, { OnApplicationComplete } from 'algosdk';

// Mock algosdk
jest.mock('algosdk', () => ({
  makeApplicationCreateTxnFromObject: jest.fn(),
  makeApplicationUpdateTxnFromObject: jest.fn(),
  makeApplicationDeleteTxnFromObject: jest.fn(),
  makeApplicationOptInTxnFromObject: jest.fn(),
  makeApplicationCloseOutTxnFromObject: jest.fn(),
  makeApplicationClearStateTxnFromObject: jest.fn(),
  makeApplicationNoOpTxnFromObject: jest.fn(),
  OnApplicationComplete: {
    NoOpOC: 0,
    OptInOC: 1,
    CloseOutOC: 2,
    ClearStateOC: 3,
    UpdateApplicationOC: 4,
    DeleteApplicationOC: 5,
  },
}));

// Mock algodClient
jest.mock('../../../src/algorand-client.js', () => ({
  algodClient: {
    getTransactionParams: jest.fn().mockReturnValue({
      do: jest.fn().mockResolvedValue({
        firstRound: 1000,
        lastRound: 2000,
        genesisHash: 'hash',
        genesisID: 'testnet-v1.0',
        fee: 1000,
        flatFee: true,
      }),
    }),
  },
}));

describe('AppTransactionManager', () => {
  const mockSuggestedParams = {
    firstRound: 1000,
    lastRound: 2000,
    genesisHash: 'hash',
    genesisID: 'testnet-v1.0',
    fee: 1000,
    flatFee: true,
  };

  beforeEach(() => {
    jest.clearAllMocks();
    (algodClient.getTransactionParams as jest.Mock)().do.mockResolvedValue(mockSuggestedParams);
  });

  describe('Tool Schemas', () => {
    it('should have valid tool schemas', () => {
      expect(appTransactionTools).toHaveLength(7);
      expect(appTransactionTools.map((t: { name: string }) => t.name)).toEqual([
        'make_app_create_txn',
        'make_app_update_txn',
        'make_app_delete_txn',
        'make_app_optin_txn',
        'make_app_closeout_txn',
        'make_app_clear_txn',
        'make_app_call_txn',
      ]);
    });
  });

  describe('Application Creation', () => {
    const mockAppCreateTxn = { type: 'appl', from: 'sender' };

    beforeEach(() => {
      (algosdk.makeApplicationCreateTxnFromObject as jest.Mock).mockReturnValue(mockAppCreateTxn);
    });

    it('should create a basic application creation transaction', async () => {
      const args = {
        from: 'sender',
        approvalProgram: '#pragma version 6\nint 1',
        clearProgram: '#pragma version 6\nint 1',
        globalByteSlices: 1,
        globalInts: 1,
        localByteSlices: 1,
        localInts: 1,
      };

      const result = await AppTransactionManager.handleTool('make_app_create_txn', args);

      expect(result).toEqual({
        content: [{
          type: 'text',
          text: JSON.stringify(mockAppCreateTxn, null, 2),
        }],
      });

      expect(algosdk.makeApplicationCreateTxnFromObject).toHaveBeenCalledWith(
        expect.objectContaining({
          from: 'sender',
          approvalProgram: new TextEncoder().encode(args.approvalProgram),
          clearProgram: new TextEncoder().encode(args.clearProgram),
          globalByteSlices: 1,
          globalInts: 1,
          localByteSlices: 1,
          localInts: 1,
          onComplete: 0,
          suggestedParams: expect.objectContaining(mockSuggestedParams),
        })
      );
    });

    it('should create an application with optional parameters', async () => {
      const args = {
        from: 'sender',
        approvalProgram: '#pragma version 6\nint 1',
        clearProgram: '#pragma version 6\nint 1',
        globalByteSlices: 1,
        globalInts: 1,
        localByteSlices: 1,
        localInts: 1,
        extraPages: 1,
        note: 'test note',
        lease: 'test lease',
        rekeyTo: 'rekey-addr',
        appArgs: ['arg1', 'arg2'],
        accounts: ['acc1', 'acc2'],
        foreignApps: [1, 2],
        foreignAssets: [3, 4],
      };

      const result = await AppTransactionManager.handleTool('make_app_create_txn', args);

      expect(algosdk.makeApplicationCreateTxnFromObject).toHaveBeenCalledWith(
        expect.objectContaining({
          from: 'sender',
          approvalProgram: new TextEncoder().encode(args.approvalProgram),
          clearProgram: new TextEncoder().encode(args.clearProgram),
          globalByteSlices: 1,
          globalInts: 1,
          localByteSlices: 1,
          localInts: 1,
          extraPages: 1,
          note: new TextEncoder().encode('test note'),
          lease: new TextEncoder().encode('test lease'),
          rekeyTo: 'rekey-addr',
          appArgs: args.appArgs.map(arg => new TextEncoder().encode(arg)),
          accounts: ['acc1', 'acc2'],
          foreignApps: [1, 2],
          foreignAssets: [3, 4],
          onComplete: 0,
          suggestedParams: expect.objectContaining(mockSuggestedParams),
        })
      );
    });
  });

  describe('Application Update', () => {
    const mockAppUpdateTxn = { type: 'appl', from: 'sender' };

    beforeEach(() => {
      (algosdk.makeApplicationUpdateTxnFromObject as jest.Mock).mockReturnValue(mockAppUpdateTxn);
    });

    it('should create an application update transaction', async () => {
      const args = {
        from: 'sender',
        appID: 123,
        approvalProgram: '#pragma version 6\nint 1',
        clearProgram: '#pragma version 6\nint 1',
      };

      const result = await AppTransactionManager.handleTool('make_app_update_txn', args);

      expect(algosdk.makeApplicationUpdateTxnFromObject).toHaveBeenCalledWith(
        expect.objectContaining({
          from: 'sender',
          appID: 123,
          approvalProgram: new TextEncoder().encode(args.approvalProgram),
          clearProgram: new TextEncoder().encode(args.clearProgram),
          onComplete: 4,
          suggestedParams: expect.objectContaining(mockSuggestedParams),
        })
      );
    });
  });

  describe('Application Delete', () => {
    const mockAppDeleteTxn = { type: 'appl', from: 'sender' };

    beforeEach(() => {
      (algosdk.makeApplicationDeleteTxnFromObject as jest.Mock).mockReturnValue(mockAppDeleteTxn);
    });

    it('should create an application delete transaction', async () => {
      const args = {
        from: 'sender',
        appID: 123,
      };

      const result = await AppTransactionManager.handleTool('make_app_delete_txn', args);

      expect(algosdk.makeApplicationDeleteTxnFromObject).toHaveBeenCalledWith(
        expect.objectContaining({
          from: 'sender',
          appID: 123,
          onComplete: 5,
          suggestedParams: expect.objectContaining(mockSuggestedParams),
        })
      );
    });
  });

  describe('Application Opt-In', () => {
    const mockAppOptInTxn = { type: 'appl', from: 'sender' };

    beforeEach(() => {
      (algosdk.makeApplicationOptInTxnFromObject as jest.Mock).mockReturnValue(mockAppOptInTxn);
    });

    it('should create an application opt-in transaction', async () => {
      const args = {
        from: 'sender',
        appID: 123,
      };

      const result = await AppTransactionManager.handleTool('make_app_optin_txn', args);

      expect(algosdk.makeApplicationOptInTxnFromObject).toHaveBeenCalledWith(
        expect.objectContaining({
          from: 'sender',
          appID: 123,
          onComplete: 1,
          suggestedParams: expect.objectContaining(mockSuggestedParams),
        })
      );
    });
  });

  describe('Application Close-Out', () => {
    const mockAppCloseOutTxn = { type: 'appl', from: 'sender' };

    beforeEach(() => {
      (algosdk.makeApplicationCloseOutTxnFromObject as jest.Mock).mockReturnValue(mockAppCloseOutTxn);
    });

    it('should create an application close-out transaction', async () => {
      const args = {
        from: 'sender',
        appID: 123,
      };

      const result = await AppTransactionManager.handleTool('make_app_closeout_txn', args);

      expect(algosdk.makeApplicationCloseOutTxnFromObject).toHaveBeenCalledWith(
        expect.objectContaining({
          from: 'sender',
          appID: 123,
          onComplete: 2,
          suggestedParams: expect.objectContaining(mockSuggestedParams),
        })
      );
    });
  });

  describe('Application Clear State', () => {
    const mockAppClearTxn = { type: 'appl', from: 'sender' };

    beforeEach(() => {
      (algosdk.makeApplicationClearStateTxnFromObject as jest.Mock).mockReturnValue(mockAppClearTxn);
    });

    it('should create an application clear state transaction', async () => {
      const args = {
        from: 'sender',
        appID: 123,
      };

      const result = await AppTransactionManager.handleTool('make_app_clear_txn', args);

      expect(algosdk.makeApplicationClearStateTxnFromObject).toHaveBeenCalledWith(
        expect.objectContaining({
          from: 'sender',
          appID: 123,
          onComplete: 3,
          suggestedParams: expect.objectContaining(mockSuggestedParams),
        })
      );
    });
  });

  describe('Application Call', () => {
    const mockAppCallTxn = { type: 'appl', from: 'sender' };

    beforeEach(() => {
      (algosdk.makeApplicationNoOpTxnFromObject as jest.Mock).mockReturnValue(mockAppCallTxn);
    });

    it('should create an application call transaction', async () => {
      const args = {
        from: 'sender',
        appID: 123,
        appArgs: ['method', 'arg1'],
        accounts: ['acc1'],
        foreignApps: [1],
        foreignAssets: [2],
      };

      const result = await AppTransactionManager.handleTool('make_app_call_txn', args);

      expect(algosdk.makeApplicationNoOpTxnFromObject).toHaveBeenCalledWith(
        expect.objectContaining({
          from: 'sender',
          appID: 123,
          appArgs: args.appArgs.map(arg => new TextEncoder().encode(arg)),
          accounts: ['acc1'],
          foreignApps: [1],
          foreignAssets: [2],
          onComplete: 0,
          suggestedParams: expect.objectContaining(mockSuggestedParams),
        })
      );
    });
  });

  describe('Error Handling', () => {
    it('should throw error for unknown tool', async () => {
      await expect(AppTransactionManager.handleTool('unknown_tool', {}))
        .rejects
        .toThrow(new McpError(ErrorCode.MethodNotFound, 'Unknown application transaction tool: unknown_tool'));
    });

    it('should throw error for missing application creation parameters', async () => {
      await expect(AppTransactionManager.handleTool('make_app_create_txn', {}))
        .rejects
        .toThrow(new McpError(ErrorCode.InvalidParams, 'Invalid application creation parameters'));
    });

    it('should throw error for missing application update parameters', async () => {
      await expect(AppTransactionManager.handleTool('make_app_update_txn', {}))
        .rejects
        .toThrow(new McpError(ErrorCode.InvalidParams, 'Invalid application update parameters'));
    });

    it('should throw error for missing application delete parameters', async () => {
      await expect(AppTransactionManager.handleTool('make_app_delete_txn', {}))
        .rejects
        .toThrow(new McpError(ErrorCode.InvalidParams, 'Invalid application delete parameters'));
    });

    it('should throw error for missing application opt-in parameters', async () => {
      await expect(AppTransactionManager.handleTool('make_app_optin_txn', {}))
        .rejects
        .toThrow(new McpError(ErrorCode.InvalidParams, 'Invalid application opt-in parameters'));
    });

    it('should throw error for missing application close-out parameters', async () => {
      await expect(AppTransactionManager.handleTool('make_app_closeout_txn', {}))
        .rejects
        .toThrow(new McpError(ErrorCode.InvalidParams, 'Invalid application close out parameters'));
    });

    it('should throw error for missing application clear state parameters', async () => {
      await expect(AppTransactionManager.handleTool('make_app_clear_txn', {}))
        .rejects
        .toThrow(new McpError(ErrorCode.InvalidParams, 'Invalid application clear state parameters'));
    });

    it('should throw error for missing application call parameters', async () => {
      await expect(AppTransactionManager.handleTool('make_app_call_txn', {}))
        .rejects
        .toThrow(new McpError(ErrorCode.InvalidParams, 'Invalid application call parameters'));
    });

    it('should handle algod client errors', async () => {
      const error = new Error('Network error');
      (algodClient.getTransactionParams as jest.Mock)().do.mockRejectedValue(error);

      await expect(AppTransactionManager.handleTool('make_app_create_txn', {
        from: 'sender',
        approvalProgram: '#pragma version 6\nint 1',
        clearProgram: '#pragma version 6\nint 1',
        globalByteSlices: 1,
        globalInts: 1,
        localByteSlices: 1,
        localInts: 1,
      }))
        .rejects
        .toThrow(error);
    });
  });
});

```

--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/puya:docs:principles.md:
--------------------------------------------------------------------------------

```markdown
# Principles & Background
## Background

**Smart contracts** on the Algorand blockchain run on the Algorand Virtual Machine ([AVM](https://developer.algorand.org/docs/get-details/dapps/avm/)).
This is a stack based virtual machine, which executes AVM bytecode as part of an [Application Call transaction](https://developer.algorand.org/docs/get-details/transactions/#application-call-transaction).
The official mechanism for generating this bytecode is by submitting TEAL (Transaction Execution Approval Language) to 
an Algorand Node to compile.

**Smart signatures** have the same basis in the AVM and TEAL, but have a different execution model, one not involving 
Application Call transactions. Our focus will primarily be on smart contracts, since they are strictly more powerful
in terms of available AVM functions.

TEAL is a [non-structured](https://en.wikipedia.org/wiki/Non-structured_programming) 
[imperative language](https://en.wikipedia.org/wiki/Procedural_programming#Imperative_programming) 
(albeit one with support for procedure calls that can isolate stack changes since v8 with `proto`). Writing TEAL is very
similar to writing assembly code. It goes without saying that this is a particularly common or well-practiced model for 
programming these days.

As it stands today, developers wanting to write smart contracts specifically for Algorand have the option of writing 
TEAL directly, or using some other mechanism of generating TEAL such as the officially supported [PyTEAL](https://pyteal.readthedocs.io/en/stable/) 
or the community supported [tealish](https://tealish.tinyman.org/en/latest/).

PyTEAL follows a [generative programming](https://en.wikipedia.org/wiki/Automatic_programming#Generative_programming) paradigm,
which is a form of metaprogramming. Naturally, writing programs to generate programs presents an additional hurdle for 
developers looking to pick up smart contract development. Tooling support for this is also suboptimal, for example, many
classes of errors resulting from the interaction between the procedural elements of the Python language and the PyTEAL
expression-building framework go unnoticed until the point of TEAL generation, or worse go completely unnoticed, and even
when PyTEAL can/does provide an error it can be difficult to understand.

Tealish provides a higher level procedural language, bearing a passing resemblance to Python, than compiles down to TEAL.
However, it's still lower level than most developers are used to. 
For example, the expression `1 + 2 + 3`is [not valid in tealish](https://tealish.tinyman.org/en/latest/language.html#math-logic).
Another difference vs a higher level language such as Python is that [functions can only be declared after the program
entry point logic](https://tealish.tinyman.org/en/latest/language.html#functions). 
In essence, tealish abstracts away many difficulties with writing plain TEAL, 
but it is still essentially more of a transpiler than a compiler. 
Furthermore, whilst appearing to have syntax inspired by Python, it both adds and removes many fundamental syntax elements,
presenting an additional learning curve to developers looking to learn blockchain development on Algorand.
Being a bespoke language also means it has a much smaller ecosystem of tooling built around it compared to languages like
Python or JavaScript.

To most developers, the Python programming language needs no introduction. First released in 1991, it's popularity has 
grown steadily over the decades, and as of June 2023 it is consistently ranked as either the most popular langauge, 
or second most popular following JavaScript:

- [GitHub 2022](https://octoverse.github.com/2022/top-programming-languages)
- [StackOverflow 2023](https://stackoverflow.blog/2023/06/13/developer-survey-results-are-in/)
- [Tiobe](https://www.tiobe.com/tiobe-index/)
- [PYPL](https://pypl.github.io/PYPL.html)

The AlgoKit project is an Algorand Foundation initiative to improve the developer experience on Algorand. Within this
broad remit, two of the key [principles](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/algokit.md#guiding-principles) 
are to "meet developers where they are" and "leverage existing ecosystem".
Building a compiler that allows developers to write smart contracts using an idiomatic subset of a high level language 
such as Python would make great strides towards both of these goals.

Wyvern was the original internal code name for just such a compiler (now called Puya), one that will transform Python code into valid TEAL 
smart contracts. In line with the principle of meeting developers where they are, and recognising the popularity of 
JavaScript and TypeScript, a parallel initiative to build a TypeScript to TEAL compiler is [also underway](https://tealscript.netlify.app).

## Principles

The principles listed here should form the basis of our decision-making, both in the design and implementation.

### Least surprise

Our primary objective is to assist developers in creating accurate smart contracts right from the 
start. The often immutable nature of these contracts - although not always the case - and the 
substantial financial value they frequently safeguard, underlines the importance of this goal.

This principle ensures that the code behaves as anticipated by the developer. Specifically, if 
you're a Python developer writing Python smart contract code, you can expect the code to behave 
identically to its execution in a standard Python environment.

Furthermore, we believe in promoting explicitness and correctness in contract code and its 
associated typing. This approach reduces potential errors and enhances the overall integrity of our
smart contracts. Our commitment is to provide a user-friendly platform that aligns with the 
developer's intuition and experience, ultimately simplifying their work and minimizing the
potential for mistakes.

### Inherited from AlgoKit

As a part of the AlgoKit project, the principles outlined [there](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/algokit.md#guiding-principles) 
also apply - to the extent that this project is just one component of AlgoKit. 

#### "Leverage existing ecosystem"

> AlgoKit functionality gets into the hands of Algorand developers quickly by building on top of the 
> existing ecosystem wherever possible and aligned to these principles.

In order to leverage as much existing Python tooling as possible, we should strive to maintain the highest level of 
compatibility with the Python language (and the reference implementation: CPython). 

#### "Meet developers where they are"

> Make Blockchain development mainstream by giving all developers an idiomatic development experience in the operating 
> system, IDE and language they are comfortable with so they can dive in quickly and have less they need to learn before 
> being productive.

Python is a very idiomatic language. We should embrace accepted patterns and practices as much as possible,
such as those listed in [PEP-20](https://peps.python.org/pep-0020/) (aka "The Zen of Python").

#### "Extensible"

> Be extensible for community contribution rather than stifling innovation, bottle-necking all changes through the 
> Algorand Foundation and preventing the opportunity for other ecosystems being represented (e.g. Go, Rust, etc.). 
> This helps make developers feel welcome and is part of the developer experience, plus it makes it easier to add 
> features sustainably

One way to support this principle in the broader AlgoKit context is by building in a mechanism for reusing 
common code between smart contracts, to allow the community to build their own Python packages.

#### "Sustainable"

> AlgoKit should be built in a flexible fashion with long-term maintenance in mind. Updates to latest patches in 
> dependencies, Algorand protocol development updates, and community contributions and feedback will all feed in to the 
> evolution of the software.

Taking this principle further, ensuring the compiler is well-designed (e.g. frontend backend separation, 
with a well-thought-out IR) will help with maintaining and improving the implementation over time. For example,
adding in new TEAL language features will be easier, same for implementing new optimisation strategies.

Looking to the future, best practices for smart contract development are rapidly evolving. We shouldn't tie the 
implementation too tightly to a current standard such as ARC-4 - although in that specific example, we would still
aim for first class support, but it shouldn't be assumed as the only way to write smart contracts.


#### "Modular components"

> Solution components should be modular and loosely coupled to facilitate efficient parallel development by small, 
> effective teams, reduced architectural complexity and allowing developers to pick and choose the specific tools and 
> capabilities they want to use based on their needs and what they are comfortable with.

We will focus on the language and compiler design itself.

An example of a very useful feature, that is strongly related but could be implemented separately instead, 
is the ability to run the users code in a unit-testing context, without compilation+deployment first. 
This would require implementing in Python some level of simulation of Algorand Nodes / AVM behaviour. 

#### "Secure by default"

> Include defaults, patterns and tooling that help developers write secure code and reduce the likelihood of security 
> incidents in the Algorand ecosystem. This solution should help Algorand be the most secure Blockchain ecosystem.

Enforcing security (which is multi-faceted) at a compiler level is difficult, and is some cases impossible. 
The best application of this principle here is to support auditing, which is important and nuanced enough to be 
listed below as a separate principle.

#### "Cohesive developer tool suite" + "Seamless onramp"

> Cohesive developer tool suite: Using AlgoKit should feel professional and cohesive, like it was designed to work 
> together, for the developer; not against them. Developers are guided towards delivering end-to-end, high quality 
> outcomes on MainNet so they and Algorand are more likely to be successful.
 
> Seamless onramp: New developers have a seamless experience to get started and they are guided into a pit of success 
> with best practices, supported by great training collateral; you should be able to go from nothing to debugging code 
> in 5 minutes.

These principles relate more to AlgoKit as a whole, so we can respect them by considering the impacts of our decisions
there more broadly.

### Abstraction without obfuscation

Algorand Python is a high level language, with support for things such as branching logic, operator precedence, etc., 
and not a set of "macros" for generating TEAL. As such, developers will not be able to directly influence specific TEAL 
output, if this is desirable a language such as [Tealish](https://tealish.tinyman.org) is more appropriate.

Whilst this will abstract away certain aspects of the underlying TEAL language, there are certain AVM concerns 
(such as op code budgets) that should not be abstracted away. That said, we should strive to generate code this is
cost-effective and unsurprising. Python mechanisms such as dynamic (runtime) dispatch, and also many of its builtin
functions on types such as `str` that are taken for granted, would require large amounts of ops compared to the
Python code it represents.

### Support auditing

Auditing is a critical part of the security process for deploying smart contracts. We want to support this function,
and can do so in two ways:

1. By ensuring the same Python code as input generates identical output each time the compiler 
is run regardless of the system it's running on. This is what might be termed [Output stability](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/articles/output_stability.md).
Ensuring a consistent output regardless of the system it's run on (assuming the same compiler version), means that
auditing the lower level (ie TEAL) code is possible. 

2. Although auditing the TEAL code should be possible, being able to easily identify and relate it back to the higher level
code can make auditing the contract logic simpler and easier. 

### Revolution, not evolution

This is a new and groundbreaking way of developing for Algorand, and not a continuation of the PyTEAL/Beaker approach. 
By allowing developers to write procedural code, as opposed to constructing an expression tree, 
we can (among other things) significantly reduce the barrier to entry for developing smart contracts for the Algorand platform.

Since the programming paradigm will be fundamentally different, providing a smooth migration experience from PyTEAL 
to this new world is not an intended goal, and shouldn't be a factor in our decisions. For example, it is not a goal of
this project to produce a step-by-step "migrating from PyTEAL" document, as it is not a requirement for users to
switch to this new paradigm in the short to medium term - support for PyTEAL should continue in parallel.

```

--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/developer:docs:get-started:algokit.md:
--------------------------------------------------------------------------------

```markdown
title: AlgoKit Quick Start Guide

AlgoKit is a simple, one-stop tool for developers to quickly and easily build and launch secure, automated, production-ready decentralized applications on the Algorand protocol -- now also featuring native support for Python! This empowers developers to write Algorand apps in regular Python, one of the world's most popular programming languages.

In addition, AlgoKit features:

- A library of smart contract templates to kickstart your  build
- All necessary application infrastructure running locally
- Toolchain integrations for languages you love, like Python and TypeScript
- A simplified frontend design experience

## Prerequisites

- [Python 3.12](https://www.python.org/downloads/) or higher
- [PipX](https://pypa.github.io/pipx/#on-linux-install-via-pip-requires-pip-190-or-later)
- [Git](https://github.com/git-guides/install-git#install-git)
- [Docker](https://docker.com/download/)
- [VSCode](https://code.visualstudio.com/download) (recommended)

## Install AlgoKit

=== "Windows"
    !!! Note
        This method will install the most recent python3 version [via winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/). If you already have python 3.12+ installed, you may you may prefer to use `pipx install algokit` as explained within the pipx on any OS section so you can control the python version used.

    - Ensure prerequisites are installed
        - [Git](https://github.com/git-guides/install-git#install-git-on-windows) (or `winget install git.git`)
        - [Docker](https://docs.docker.com/desktop/install/windows-install/) (or `winget install docker.dockerdesktop`)

            !!! Info
                See [our LocalNet documentation](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/localnet.md#prerequisites) for more tips on installing Docker on Windows

    - Install Python3 using WinGet
        - Install python: `winget install python.python.3.12`
        - Restart the terminal to ensure Python and pip are available on the path

            !!! Info
                Windows has a feature called **App Execution Aliases** that provides redirects for the Python command that guide users to the Windows Store. unfortunately these aliases can prevent normal execution of Python if Python is installed via other means, to disable them search for **Manage app execution aliases** from the start menu, and then turn off entries listed as **App Installer python.exe** or **App Installer python3.exe**.

        - Install pipx:
            ```
            pip install --user pipx
            python -m pipx ensurepath
            ```
        - Restart the terminal to ensure pipx is available on the path
        - Install AlgoKit via pipx: `pipx install algokit`
        - If you used AlgoKit before, update it with pipx: `pipx upgrade algokit`
        - Restart the terminal to ensure AlgoKit is available on the path

=== "macOS"
    !!! Note
        This method will install the latest Python3 release as a dependency via Homebrew. If you already have Python 3.10+ installed, you may prefer to use `pipx install algokit` as explained within the OS agnostic tab so you can control the python version used.

    - Ensure prerequisites are installed

        - [Homebrew](https://docs.brew.sh/Installation)
        - [Git](https://github.com/git-guides/install-git#install-git-on-mac) (should already be available if `brew` is installed)
        - [Docker](https://docs.docker.com/desktop/install/mac-install/), (or `brew install --cask docker`)

            !!! Info
                Docker requires MacOS 11+

    - Install using Homebrew `brew install algorandfoundation/tap/algokit`
    - Restart the terminal to ensure AlgoKit is available on the path


=== "Linux"
    - Ensure prerequisites are installed

        - [Python 3.12+](https://www.python.org/downloads/)

            !!! Info
                There is probably a better way to install Python than to download it directly, e.g. your local Linux package manager

        - [pipx](https://pypa.github.io/pipx/#on-linux-install-via-pip-requires-pip-190-or-later)
        - [Git](https://github.com/git-guides/install-git#install-git-on-linux)
        - [Docker](https://docs.docker.com/desktop/install/linux-install/)
    - Continue with step 2 in the following section to install via `pipx` on any OS

=== "OS agnostic"
    To install AlgoKit, run the following command from a terminal.

    ```shell
    pipx install algokit
    ```

    If you used AlgoKit before, update it with pipx: `pipx upgrade algokit`

    After the installation completes, **restart the terminal**.

Additional AlgoKit videos are available on the [@AlgoDevs YouTube channel](https://youtube.com/@AlgoDevs).

## Verify the Installation

To verify AlgoKit Installed correctly run the following.

```shell
algokit --version
```

Output similar to the following should be displayed:

```shell
algokit, version 2.0.0
```

## Start a LocalNet

AlgoKit supports using a [local version of the Algorand blockchain](../../get-details/algokit/features/localnet/). To start an instance of this LocalNet run the following command from the terminal:

```shell
algokit localnet start
```

This should start an instance of the LocalNet within docker. If you open the Docker Desktop application you should something similar to the following:

![Docker Desktop LocalNet Instance](../imgs/localnet.png)

## Create an AlgoKit project

Now that AlgoKit is installed, you can rapidly create a new project to get started quickly. This can be done by running:

```shell
algokit init
```

This will launch a guided menu system to create a specific project tailored to your needs. You will first be prompted to select a specific template. The templates are basic starter applications for various Algorand development scenarios. To read more about templates checkout AlgoKit detailed documentation. For this guide, we will use the Python smart contract starter template. Select the following options:
1. `Smart Contracts`
2. `Python`
3. name of your project: `DEMO`
4. Template preset: select `Starter`.
5. Contract deployment code: select `Python`
6. algokit project bootstrap: `Y`
7. git repository: `Y`

Once finished, (if you have it installed) VS Code should automatically be opened with the initialized project and you will be prompted to install appropriate VS Code extensions. This starter app will contain one smart contract (built with [Algorand Python](https://algorandfoundation.github.io/puya/) named `contract.py`, in the `hello_world` folder, with one method (`hello`) that takes a `String` and returns a `String`.

![AlgoKit Starter Contract](../imgs/algokitv2_starter.png)

## Run the Demo Application

Once the starter project is created, you will notice in the `smart_contracts/hello_world` folder a file named `deploy_config.py` which is a simple example of using AlgoKit to deploy and make a call to the `contract.py` smart contract on the LocalNet instance started earlier.

![AlgoKit Starter config ](../imgs/algokit_v2_demo.png)

By hitting F5 you will deploy the `HelloWorld` smart contract and then call it passing the parameter `name` with a value of `world`. You can edit this parameter in the `deploy_config.py` file and it will:

1. Start LocalNet
2. Build the smart contract
3. Deploy and call the smart contract (`contract.py`)

If you would like to manually build and deploy the `HelloWorld` smart contract run the following AlgoKit commands:

```shell
algokit project run build
algokit project deploy 
```

This should produce something similar to the following in the VSCode terminal.

```shell
HelloWorld not found in PDEEWXLITMAPDMDYGP4XUV2EUJVPNZVKR7OUSSFZ63U4XNL2Y25FN5PYN4 account, deploying app.
HelloWorld (v1.0) deployed successfully, with app id 1002.
Called hello on HelloWorld (1002) with name=world, received: Hello, world
```

The App ID of of the deployed contract and its Algorand address is displayed, followed by the message returned from the smart contract call (`Hello, world`).

At this point you have deployed a simple contract to an Algorand network and called it successfully!

Additionally, you can find the native TEAL smart contract code and the appropriate smart contract manifest JSON files have been output to the `artifacts` folder.

![AlgoKit Starter Demo](../imgs/algokitv2_json.png)

These files can be used by tools like [Lora](https://lora.algokit.io/localnet), [goal](https://developer.algorand.org/docs/clis/goal/goal/), etc. to deploy your smart contract to the various Algorand networks.

## Using Lora

Lora is a web-based user interface that let's you visualize accounts, transactions, assets and applications on an Algorand network and also provides ability to deploy and call smart contracts. This works for TestNet, MainNet and also LocalNet. While AlgoKit surfaces both a programming interface and a command line interface for interacting with Algorand, it also allows you to quickly open Lora so you can see what's happening visually.

Lora can be launched from AlgoKit by running the following command from the terminal.

```shell
algokit explore
```

By default it will open Lora and point to LocalNet (It will be displayed as `LocalNet` in the upper right hand corner), but you can pass in parameters to point it to TestNet and MainNet too.

This command will launch your default web browser and load the Lora web application.

**Note:** If you are using Safari, then it won't work against LocalNet and you will need to open it in a different browser.

![Lora](../imgs/lora1.png)

### Create / Connect  local account for testing

To issue commands against the LocalNet network you need an account with ALGO in it. Lora gives you three options for connecting to a local wallet: `Connect KMD`, `Connect MNEMONIC`, and `Connect Lute`

- `Connect KMD`: Lora will automatically import KMD wallet.

- `Connect MNEMONIC`: You can manually input a MNEMONIC for an account you own. 

- `Connect Lute`: You can create local accounts from [Lute](https://lute.app/) and connect to them.

In this guide, we will use the KMD wallet.

Select `Connect wallet` located at top right hand side of the webpage and you will be prompted with the three wallet choices. Choose the `Connect KMD` option. This will prompt you to enter the KMD password. If this is your first time building on Algorand, you do not have a KMD password so leave it blank and click `OK`. This will connect the KMD account to Lora so you can use that account for signing transactions from the Lora user interface.

![Lora](../imgs/lora-wallet.png)

### Deploy the Hello World application

1. To deploy your smart contract application, select the `App Lab` menu and click on the `Create` button. 
![Lora](../imgs/lora2.png)

2. Click `Deploy new` and `Select an ARC-32 JSON app spec file` to browse to the artifacts created in the previous section of this guide. Select the `HelloWorld.arc32.json` manifest file. 
![Lora](../imgs/lora3.png)
![Lora](../imgs/lora4.png)
![Lora](../imgs/lora5.png)

3. This will load the specific manifest file for the Hello World sample application. Click `Next`.
![Lora](../imgs/lora6.png)

4. You can change the `Name` and the `Version` of your app. We will keep it as it is. Click `Next`.
![Lora](../imgs/lora7.png)

5. Click the `() Call` button. Then build and add the create transaction by clicking `Add`.
![Lora](../imgs/lora8.png)
![Lora](../imgs/lora9.png)


6. Click `Deploy` and sign the transaction by clicking `OK` in the KMD pop up to deploy the smart contract to the local Algorand network.
![Lora](../imgs/lora10.png)

7. You should now see the deployed `HelloWorld` contract on the `App Lab` page. 
![Lora](../imgs/lora11.png)

8. Now click on the `App ID` inside of the `HelloWorld` card to go to the `Application` page.
![Lora](../imgs/lora12.png)

10. Inside the `ABI Methods` section, you should see the `hello` method. Click on the drop down and the `Call` button. You will be prompted with a popup allowing you to enter the parameter for the `hello` method and call it. 
![Lora](../imgs/lora13.png)


11. Enter a string in the `value` input and click on `Add`. 
![Lora](../imgs/lora14.png)

12. You should now see the transaction you just built on the `Application` page. Click `Send` and sign the transaction with your KMD wallet to execute the transaction.
![Lora](../imgs/lora15.png)

13. You should now see the `Send Result` showing you the details about the transaction you just executed!
![Lora](../imgs/lora16.png)

1.  You can also click on `Transaction ID` to go to the `Transaction` page and see the full detail of the transaction.
![Lora](../imgs/lora17.png)

You have now successfully deployed and executed a smart contract method call using Lora!

## Next steps

- To learn more about AlgoKit and what you can do with it, checkout the [AlgoKit documentation](../index.md).
- To learn more about Python on Algorand, take a look at the [Python documentation](https://algorandfoundation.github.io/puya/).
- More information on Algorand smart contracts is also available in the [smart contract documentation](https://developer.algorand.org/docs/get-details/dapps/smart-contracts/).

```

--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/developer:docs:details:technical_faq.md:
--------------------------------------------------------------------------------

```markdown
title: Technical FAQ


# Protocol Limits

How many transactions can be in an atomic group?
How large can my approval program be?
How many arguments can I pass?
What is the Minimum Balance Requirement increase for an asset opt-in?

The limits applied at the protocol level are documented [here](/docs/get-details/parameter_tables).


# Address Encoding/Decoding

An address comes in 2 forms:
    1) encoded, 58 characters long, looks something like `7K5TT4US7M3FM7L3XBJXSXLJGF2WCXPBV2YZJJO2FH46VCZOS3ICJ7E4QU`
    2) decoded, 32 byte, looks something like `0xfabb39f292fb36567d7bb853795d693175615de1aeb194a5da29f9ea8b2e96d0` as hexadecimal

You can translate from one to the other by using the SDK supplied methods.

For example, in python `encoding.encode_address` will convert the 32 byte version to the encoded 58 character long version and `encoding.decode_address` will perform the opposite translation.

All SDKs have a similarly named method.

!! Note that smart contracts operate _only_ on the 32 byte version, so any interaction where an address is used should be translated prior to passing it to the smart contract. This is handled for you automatically in some cases (e.g. sender on a transaction)

[Address Details](/docs/get-details/accounts/#keys-and-addresses)
[Encoding Details](/docs/get-details/encoding/#address-encoding)

# Application State Encoding/Decoding

When calling the API for global or local state, the result returned is in the form of an array of state values. Each entry in the array represents a key/value pair in global or local state. To decode the key or bytes value, just base64 decode the string into bytes, then encode the bytes in whatever format is required.

*examples*:

- for a simple string, just encode it as `ascii` or `utf-8`
- for an address call `encode_address` or similar depending on SDK
- for an ABI tuple like `(address,uint64,bool)` use `ABIType.from_string("(address,uint64,bool)").decode(value_bytes)`


```ts
    interface StateValue {
      // The base64 encoded key for this state value
      key: string;
      // The value as a sort of union type
      value: {
        // if set, the base64 encoded bytes for the state value
        bytes: string;
        // if set, the number stored in state
        uint: number;
        // 1 for bytes, 2 for uint
        type?: number;
        // Only set in the eval deltas, describes delete/set
        action?: number;
      };
    }
```


# Deciphering Algod Errors

A 400 error typically occurs because there was some issue with the transactions. The exact reason will depend on the circumstances, but the error message will contain more information.

Common reasons include:

- `transaction already in ledger: ...`

    This happens when resending a transaction that has already been approved or accepted into a transaction pool. To make the transaction unique, add a nonce to the note field or change the valid rounds. To check if the transaction is in the pool use `/v2/transactions/pending/{txid}` REST API endpoint.

- `underflow on subtracting SEND_AMOUNT from sender amount AVAILABLE_AMOUNT`, `account ADDRESS balance 0 below min XXX (N assets)`

    All of these happen when some account does not have enough Algos to cover the transaction (taking into account their minimum balance requirement and any other transaction in the same group). Fund the account if necessary or cover the fees from its transactions with another transaction in the group.

- `receiver error: must optin, asset ASSET_ID missing from ACCOUNT_ADDR`

    This happens when the intended receiver of some asset hasn't opted in.

- `should have been authorized by ADDR1 but was actually authorized by ADDR2`

    This happens when the wrong signer is used to sign a transaction.

- `TransactionPool.Remember: txn dead: round XXXXXXXX outside of XXXXXXXX--XXXXXXXX`

    This happens when trying to submit a transaction outside its validity window, transactions may only have up to 1000 rounds between first/last valid round and the current round must be somewhere between first/last valid.

- `fee N below threshold M`

    This happens when the fee attached to a transaction (or transaction group) is not sufficient to cover the fees for the transaction.

- `only clearing out is supported for applications that have been deleted`

    This happens when an attempt is made to call an application that no longer exists

- `this transaction should be issued by the manager. It is issued by ADDR`

    This happens when trying to issue an asset config transaction by an account that is _not_ the manager account for the asset

- `cannot close asset ID in allocating account`

    This happens when the creator of an asset tries to close out of the asset.

- `check failed on ApprovalProgram: program version N greater than protocol supported version M`

    This happens when trying to create an application with a version that is not yet supported by the protocol.
    If this happens on your local sandbox, set the protocol version to `future` to get access to the latest changes.

- `cannot clear state: ADDR is not currently opted in to app N`

    This happens when an account that is not opted in to an application tries to opt out or clear state for that app.

- `invalid : program version mismatch: N != M`

    This happens when you attempt to deploy or update a programs approval and clear state code with two different versions. Check that they both have the same version number.


# Deciphering Logic errors

How can I debug this logic error?

Generally Logic errors can be debugged using [Dryrun, Tealdbg, or Simulate](/docs/get-details/dapps/smart-contracts/debugging).

For some common errors, find an explanation below:

-  `logic eval error: invalid {Asset|App|Account|Box} reference`

    This happens when the reference is not passed in the app call transactions in the appropriate reference field. By passing a reference in the transaction, the node is able to quickly load the reference into memory and have it available for the AVM runtime to consult quickly. See [Box Storage Limitations](#box-storage) for additional information.


- `logic eval error: assert failed pc=XXX`

    An `assert` was invoked on something that evaluated to 0. The `pc` will provide a pointer to where in the program the `assert` failed. To find where in the TEAL source program this corresponds to, compile the source TEAL with [`source_map`](/docs/rest-apis/algod#post-v2tealcompile) enabled and use the result to find the line in the source program.

- `logic eval error: program logs too large.`

    At most, 1k may be logged and the `log` op may be called at most 32 times in a single app call.

- `logic eval error: write budget (N) exceeded`, `logic eval error: box read budget (N) exceeded`

    Every box reference passed allots another 1k to the read/write budget for the app call. By passing more box refs a larger IO budget is available. The budget is shared across app calls within the same group so a 32k box can be read/written to as long as 32 box references are passed (8 per txn, 4 txns). See [Box Storage Limitations](#box-storage) for additional information.

- `logic eval error: store TYPE count N exceeds schema TYPE count M`

    Schema needs to be large enough to allow storage requirements. Since the schema immutable after creation, a new application must be created if more storage is required. See [Global/Local Storage Limitations](#globallocal-storage) for additional information.

- `logic eval error: err opcode executed.`

    Typically, this is the result of the internal routing of the app finding that there are no matching routes for some conditional block. This often happens when something like the ABI method selector passed is not present in the application.

- `logic eval error: overspend`

    The account listed in the error did not have enough Algos to cover the transactions and fees of the transaction.

- `logic eval error: * overflowed.`

    The math operation would have returned a value > max uint64 (2^64 - 1). A solution is to use wide math opcodes to perform the arithmetic or byte math ops like `b*`.

- `logic eval error: - would result negative.`

    The math operation would have returned a negative value (< 0). Consider checking the values before using them within the operation.

- `logic eval error: invalid ApplicationArgs index 0.`

    An attempt was made by the contract to access an Application Arguments array element that was not set. Check that the correct Application Arguments are passed and that the flow of the program does not accidentally reference an invalid index.

# Environment Setup

How do I setup the Algod to connect to sandbox?

Instructions for [Algokit](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/algokit.md)

Or

Instructions for [Sandbox](https://github.com/algorand/sandbox/README.md)


# API Providers

Which API should I use?

Below is a list of API providers that can be used to query Algod or Indexer data.

- [AlgoNode](https://algonode.io/api/) (algod and indexer available, free tier available)
- [Blockdaemon](https://www.blockdaemon.com/protocols/algorand) (algod only)
- [GetBlock.io](https://getblock.io/nodes/algo/) (algod only, free tier available)

Or find others [here](https://developer.algorand.org/ecosystem-projects/?tags=api-services)

# Smart Contract Storage Limitations

When storing data on-chain you must give consideration to the different limitations between state and box storage. Be aware the note field is not an option, as that's transactional data and is not stored directly to the ledger, nor is it accessible to other application calls outside the initial transaction group.

## Global/Local Storage

[Global](/docs/get-details/dapps/smart-contracts/apps/state/#global-storage) and [Local](/docs/get-details/dapps/smart-contracts/apps/state/#local-storage) state storage can store key-value pairs up to a maximum size of 128 bytes, inclusive of the key length. For example if the key is 8 bytes, then a maximum of 120 bytes can be stored in the value. Since each key must be unique, only a single 0 byte length key can be used to store a 128 byte value. Storing larger values requires the data to be split up and stored in multiple key-value pairs within state storage.

## Box Storage

[Box storage](/docs/get-details/dapps/smart-contracts/apps/state/#box-storage) is ideal for storing larger dynamically sized data. Since the minimum balance requirement is proportional to the amount of data you allocate to the box, it's generally more cost efficient, allowing you to allocate exactly the amount you need. Keys must again be unique per application, much like state storage, however the key is not included as part of the box size and instead must be between 1 to 64 bytes. The exact size of the box value can be up to 32KB (32768 bytes), however anything over 1024 bytes is going to require additional box references. This is due to each box reference being given a 1024 bytes of operational budget. For example if you wanted to store 2000 bytes in a box named "data", you'd need to include the "data" box reference two times in your application call transaction.


# Pending Transactions

When you run a non-participation node only transactions submitted to that particular node are seen as pending in the [transaction pool](/docs/rest-apis/algod/#get-v2accountsaddresstransactionspending). If you're interested in receiving all pending transactions within the network you'll need to set `ForceFetchTransactions` to True in the [algod configuration settings](/docs/run-a-node/reference/config/#algod-configuration-settings). Note that this will increase the bandwidth used by the node.

# Verifying Release Binaries

When downloading a release, you're able to look at the accompanying signature files to verify that you've received artifacts provided by Algorand Inc. The steps to do so vary slightly by product and package type.

## algod

The algod binaries have detached signatures for every archive file. The signatures are used as follows:
1. Download public keys from https://releases.algorand.com
2. Install one or more of the public keys with `gpg --import key.pub`.
2. Download an artifact and its .sig file.
3. Verify using a gpg tool: `gpg --verify file.tar.gz.sig file.tar.gz`

## Conduit & Indexer

Instead of detached signatures, these binaries have a single checksum file which is signed. Their public key is also hosted on a keyserver to simplify the process of installing, refreshing and revoking keys as needed. They can also be downloaded and imported from the releases page outlined above.

1. Install the Algorand signing key from keys.openpgp.org or . Using GnuPG this is done with the following command:
    > gpg --keyserver keys.openpgp.org --search-keys [email protected]

2. Refresh keys if necessary. In the event of a security breech, we will revoke the key. To account for this, simply refresh the key:
    > gpg --refresh-keys --keyserver keys.openpgp.org

3. Download `checksums.txt.sig` and `checksums.txt` and verify the signature:
    > gpg --verify checksums.txt.sig checksums.txt

4. Download one or more release archives and verify the checksum:
    > sha256sum -c < checksums.txt


```

--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/ARCs:specs:arc-0072.md:
--------------------------------------------------------------------------------

```markdown
---
arc: 72
title: Algorand Smart Contract NFT Specification
description: Base specification for non-fungible tokens implemented as smart contracts.
author: William G Hatch (@willghatch)
discussions-to: https://github.com/algorandfoundation/ARCs/issues/162
status: Living
type: Standards Track
category: Interface
sub-category: Application
created: 2023-01-10
requires: 3, 4, 16, 22, 28, 73
---

# Algorand Smart Contract NFT Specification

## Abstract
This specifies an interface for non-fungible tokens (NFTs) to be implemented on Algorand as smart contracts.
This interface defines a minimal interface for NFTs to be owned and traded, to be augmented by other standard interfaces and custom methods.


## Motivation
Currently most NFTs in the Algorand ecosystem are implemented as ASAs.
However, to provide rich extra functionality, it can be desirable to implement NFTs as a smart contract instead.
To foster an interoperable NFT ecosystem, it is necessary that the core interfaces for NFTs be standardized.


## Specification
The key words "**MUST**", "**MUST NOT**", "**REQUIRED**", "**SHALL**", "**SHALL NOT**", "**SHOULD**", "**SHOULD NOT**", "**RECOMMENDED**", "**MAY**", and "**OPTIONAL**" in this document are to be interpreted as described in <a href="https://www.ietf.org/rfc/rfc2119.txt">RFC-2119</a>.


### Core NFT specification

A smart contract NFT that is compliant with this standard must implement the interface detection standard defined in [ARC-73](./arc-0073.md).

Additionally, the smart contract MUST implement the following interface:

```json
{
  "name": "ARC-72",
  "desc": "Smart Contract NFT Base Interface",
  "methods": [
    {
      "name": "arc72_ownerOf",
      "desc": "Returns the address of the current owner of the NFT with the given tokenId",
      "readonly": true,
      "args": [
        { "type": "uint256", "name": "tokenId", "desc": "The ID of the NFT" },
      ],
      "returns": { "type": "address", "desc": "The current owner of the NFT." }
    },
    {
      "name": "arc72_transferFrom",
      "desc": "Transfers ownership of an NFT",
      "readonly": false,
      "args": [
        { "type": "address", "name": "from" },
        { "type": "address", "name": "to" },
        { "type": "uint256", "name": "tokenId" }
      ],
      "returns": { "type": "void" }
    },
  ],
  "events": [
    {
      "name": "arc72_Transfer",
      "desc": "Transfer ownership of an NFT",
      "args": [
        {
          "type": "address",
          "name": "from",
          "desc": "The current owner of the NFT"
        },
        {
          "type": "address",
          "name": "to",
          "desc": "The new owner of the NFT"
        },
        {
          "type": "uint256",
          "name": "tokenId",
          "desc": "The ID of the transferred NFT"
        }
      ]
    }
  ]
}
```

Ownership of a token ID by the zero address indicates that ID is invalid.
The `arc72_ownerOf` method MUST return the zero address for invalid token IDs.
The `arc72_transferFrom` method MUST error when `from` is not the owner of `tokenId`.
The `arc72_transferFrom` method MUST error unless called by the owner of `tokenId` or an approved operator as defined by an extension such as the transfer management extension defined in this ARC.
The `arc72_transferFrom` method MUST emit a `arc72_Transfer` event a transfer is successful.
A `arc72_Transfer` event SHOULD be emitted, with `from` being the zero address, when a token is first minted.
A `arc72_Transfer` event SHOULD be emitted, with `to` being the zero address, when a token is destroyed.

All methods in this and other interfaces defined throughout this standard that are marked as `readonly` MUST be read-only as defined by [ARC-22](./arc-0022.md).

The ARC-73 interface selector for this core interface is `0x53f02a40`.


### Metadata Extension

A smart contract NFT that is compliant with this metadata extension MUST implement the interfaces required to comply with the Core NFT Specification, as well as the following interface:

```json
{
  "name": "ARC-72 Metadata Extension",
  "desc": "Smart Contract NFT Metadata Interface",
  "methods": [
    {
      "name": "arc72_tokenURI",
      "desc": "Returns a URI pointing to the NFT metadata",
      "readonly": true,
      "args": [
        { "type": "uint256", "name": "tokenId", "desc": "The ID of the NFT" },
      ],
      "returns": { "type": "byte[256]", "desc": "URI to token metadata." }
    }
  ],
}
```

URIs shorter than the return length MUST be padded with zero bytes at the end of the URI.
The token URI returned SHOULD be an `ipfs://...` URI so the metadata can't expire or be changed by a lapse or takeover of a DNS registration.
The token URI SHOULD NOT be an `http://` URI due to security concerns.
The URI SHOULD resolve to a JSON file following :
- the JSON Metadata File Schema defined in [ARC-3](./arc-0003.md).
- the standard for declaring traits defined in [ARC-16](./arc-0016.md).

Future standards could define new recommended URI or file formats for metadata.

The ARC-73 interface selector for this metadata extension interface is `0xc3c1fc00`.

### Transfer Management Extension

A smart contract NFT that is compliant with this transfer management extension MUST implement the interfaces required to comply with the Core NFT Specification, as well as the following interface:

```json
{
  "name": "ARC-72 Transfer Management Extension",
  "desc": "Smart Contract NFT Transfer Management Interface",
  "methods": [
    {
      "name": "arc72_approve",
      "desc": "Approve a controller for a single NFT",
      "readonly": false,
      "args": [
        { "type": "address", "name": "approved", "desc": "Approved controller address" },
        { "type": "uint256", "name": "tokenId", "desc": "The ID of the NFT" },
      ],
      "returns": { "type": "void" }
    },
    {
      "name": "arc72_setApprovalForAll",
      "desc": "Approve an operator for all NFTs for a user",
      "readonly": false,
      "args": [
        { "type": "address", "name": "operator", "desc": "Approved operator address" },
        { "type": "bool", "name": "approved", "desc": "true to give approval, false to revoke" },
      ],
      "returns": { "type": "void" }
    },
    {
      "name": "arc72_getApproved",
      "desc": "Get the current approved address for a single NFT",
      "readonly": true,
      "args": [
        { "type": "uint256", "name": "tokenId", "desc": "The ID of the NFT" },
      ],
      "returns": { "type": "address", "desc": "address of approved user or zero" }
    },
    {
      "name": "arc72_isApprovedForAll",
      "desc": "Query if an address is an authorized operator for another address",
      "readonly": true,
      "args": [
        { "type": "address", "name": "owner" },
        { "type": "address", "name": "operator" },
      ],
      "returns": { "type": "bool", "desc": "whether operator is authorized for all NFTs of owner" }
    },
  ],
  "events": [
    {
      "name": "arc72_Approval",
      "desc": "An address has been approved to transfer ownership of the NFT",
      "args": [
        {
          "type": "address",
          "name": "owner",
          "desc": "The current owner of the NFT"
        },
        {
          "type": "address",
          "name": "approved",
          "desc": "The approved user for the NFT"
        },
        {
          "type": "uint256",
          "name": "tokenId",
          "desc": "The ID of the NFT"
        }
      ]
    },
    {
      "name": "arc72_ApprovalForAll",
      "desc": "Operator set or unset for all NFTs defined by this contract for an owner",
      "args": [
        {
          "type": "address",
          "name": "owner",
          "desc": "The current owner of the NFT"
        },
        {
          "type": "address",
          "name": "operator",
          "desc": "The approved user for the NFT"
        },
        {
          "type": "bool",
          "name": "approved",
          "desc": "Whether operator is authorized for all NFTs of owner "
        }
      ]
    },
  ]
}
```

The `arc72_Approval` event MUST be emitted when the `arc72_approve` method is called successfully.
The zero address for the `arc72_approve` method and the `arc72_Approval` event indicate no approval, including revocation of previous single NFT controller.
When a `arc72_Transfer` event emits, this also indicates that the approved address for that NFT (if any) is reset to none.
The `arc72_ApprovalForAll` event MUST be emitted when the `arc72_setApprovalForAll` method is called successfully.
The contract MUST allow multiple operators per owner.
The `arc72_transferFrom` method, when its `nftId` argument is owned by its `from` argument, MUST succeed for when called by an address that is approved for the given NFT or approved as operator for the owner.

The ARC-73 interface selector for this transfer management extension interface is `0xb9c6f696`.

### Enumeration Extension

A smart contract NFT that is compliant with this enumeration extension MUST implement the interfaces required to comply with the Core NFT Specification, as well as the following interface:

```json
{
  "name": "ARC-72 Enumeration Extension",
  "desc": "Smart Contract NFT Enumeration Interface",
  "methods": [
    {
      "name": "arc72_balanceOf",
      "desc": "Returns the number of NFTs owned by an address",
      "readonly": true,
      "args": [
        { "type": "address", "name": "owner" },
      ],
      "returns": { "type": "uint256" }
    },
    {
      "name": "arc72_totalSupply",
      "desc": "Returns the number of NFTs currently defined by this contract",
      "readonly": true,
      "args": [],
      "returns": { "type": "uint256" }
    },
    {
      "name": "arc72_tokenByIndex",
      "desc": "Returns the token ID of the token with the given index among all NFTs defined by the contract",
      "readonly": true,
      "args": [
        { "type": "uint256", "name": "index" },
      ],
      "returns": { "type": "uint256" }
    },
  ],
}
```

The sort order for NFT indices is not specified.
The `arc72_tokenByIndex` method MUST error when `index` is greater than `arc72_totalSupply`.

The ARC-73 interface selector for this enumeration extension interface is `0xa57d4679`.


## Rationale

This specification is based on <a href="https://eips.ethereum.org/EIPS/eip-721">ERC-721</a>, with some differences.

### Core Specification

The core specification differs from ERC-721 by:

* removing `safeTransferFrom`, since there is not a test for whether an address on Algorand corresponds to a smart contract
* moving management functionality out of the base specification into an extension
* moving balance query functionality out of the base specification into the enumeration extension

Moving functionality out of the core specification into extensions allows the base specification to be much simpler, and allows extensions for extra capabilities to evolve separately from the core idea of owning and transferring ownership of non-fungible tokens.
It is recommended that NFT contract authors make use of extensions to enrich the capabilities of their NFTs.

### Metadata Extension

The metadata extension differns from the ERC-721 metadata extension by using a fixed-length URI return and removing the `symbol` and `name` operations.  Metadata such as symbol or name can be included in the metadata pointed to by the URI.

### Transfer Management Extension

The transfer management extension is taken from the set of methods and events from the base ERC-721 specification that deal with approving other addresses to transfer ownership of an NFT.
This functionality is important for trusted NFT galleries like OpenSea to list and sell NFTs on behalf of users while allowing the owner to maintain on-chain ownership.
However, this set of functionality is the bulk of the complexity of the ERC-721 standard, and moving it into an extension vastly simplifies the core NFT specification.
Additionally, other interfaces have been proposed to allow for the sale of NFTs in decentralized manners without needing to give transfer control to a trusted third party.

### Enumeration Extension

The enumeration extension is taken from the ERC-721 enumeration extension.
However, it also includes the `arc72_balanceOf` function that is included in the base ERC-721 specification.
This change simplifies the core standard and groups the `arc72_balanceOf` function with related functionality for contracts where supply details are desired.


## Backwards Compatibility

This standard introduces a new kind of NFT that is incompatible with NFTs defined as ASAs.
Applications that want to index, manage, or view NFTs on Algorand will need to handle these new smart NFTs as well as the already popular ASA implementation of NFTs will need to add code to handle both, and existing smart contracts that handle ASA-based NFTs will not work with these new smart contract NFTs.

While this is a severe backwards incompatibility, smart contract NFTs are necessary to provide richer and more diverse functionality for NFTs.


## Security Considerations

The fact that anybody can create a new implementation of a smart contract NFT standard opens the door for many of those implementations to contain security bugs.
Additionally, malicious NFT implementations could contain hidden anti-features unexpected by users.
As with other smart contract domains, it is difficult for users to verify or understand security properties of smart contract NFTs.
This is a tradeoff compared with ASA NFTs, which share a smaller set of security properties that are easier to validate, to gain the possibility of adding novel features.


## Copyright
Copyright and related rights waived via <a href="https://creativecommons.org/publicdomain/zero/1.0/">CCO</a>.

```

--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/algokit:utils:typescript:capabilities:account.md:
--------------------------------------------------------------------------------

```markdown
# Account management

Account management is one of the core capabilities provided by AlgoKit Utils. It allows you to create mnemonic, rekeyed, multisig, transaction signer, idempotent KMD and environment variable injected accounts that can be used to sign transactions as well as representing a sender address at the same time. This significantly simplifies management of transaction signing.

## `AccountManager`

The [`AccountManager`](../code/classes/types_account_manager.AccountManager.md) is a class that is used to get, create, and fund accounts and perform account-related actions such as funding. The `AccountManager` also keeps track of signers for each address so when using the [`TransactionComposer`](./transaction-composer.md) to send transactions, a signer function does not need to manually be specified for each transaction - instead it can be inferred from the sender address automatically!

To get an instance of `AccountManager`, you can use either [`AlgorandClient`](./algorand-client.md) via `algorand.account` or instantiate it directly:

```typescript
import { AccountManager } from '@algorandfoundation/algokit-utils/types/account-manager'

const accountManager = new AccountManager(clientManager)
```

## `TransactionSignerAccount`

The core internal type that holds information about a signer/sender pair for a transaction is [`TransactionSignerAccount`](../code/interfaces/types_account.TransactionSignerAccount.md), which represents an `algosdk.TransactionSigner` (`signer`) along with a sender address (`addr`) as the encoded string address.

Many methods in `AccountManager` expose a `TransactionSignerAccount`. `TransactionSignerAccount` can be used with `AtomicTransactionComposer`, [`TransactionComposer`](./transaction-composer.md) and [useWallet](https://github.com/TxnLab/use-wallet).

## Registering a signer

The `AccountManager` keeps track of which signer is associated with a given sender address. This is used by [`AlgorandClient`](./algorand-client.md) to automatically sign transactions by that sender. Any of the [methods](#accounts) within `AccountManager` that return an account will automatically register the signer with the sender. If however, you are creating a signer external to the `AccountManager`, for instance when using the use-wallet library in a dApp, then you need to register the signer with the `AccountManager` if you want it to be able to automatically sign transactions from that sender.

There are two methods that can be used for this, `setSignerFromAccount`, which takes any number of [account based objects](#underlying-account-classes) that combine signer and sender (`TransactionSignerAccount` | `algosdk.Account` | `algosdk.LogicSigAccount` | `SigningAccount` | `MultisigAccount`), or `setSigner` which takes the sender address and the `TransactionSigner`:

```typescript
algorand.account
  .setSignerFromAccount(algosdk.generateAccount())
  .setSignerFromAccount(new algosdk.LogicSigAccount(program, args))
  .setSignerFromAccount(new SigningAccount(mnemonic, sender))
  .setSignerFromAccount(new MultisigAccount({ version: 1, threshold: 1, addrs: ['ADDRESS1...', 'ADDRESS2...'] }, [account1, account2]))
  .setSignerFromAccount({ addr: 'SENDERADDRESS', signer: transactionSigner })
  .setSigner('SENDERADDRESS', transactionSigner)
```

## Default signer

If you want to have a default signer that is used to sign transactions without a registered signer (rather than throwing an exception) then you can [register a default signer](../code/classes/types_account_manager.AccountManager.md#setdefaultsigner):

```typescript
algorand.account.setDefaultSigner(myDefaultSigner)
```

## Get a signer

[`AlgorandClient`](./algorand-client.md) will automatically retrieve a signer when signing a transaction, but if you need to get a `TransactionSigner` externally to do something more custom then you can [retrieve the signer](../code/classes//types_account_manager.AccountManager.md#getsigner) for a given sender address:

```typescript
const signer = algorand.account.getSigner('SENDER_ADDRESS')
```

If there is no signer registered for that sender address it will either return the default signer ([if registered](#default-signer)) or throw an exception.

## Accounts

In order to get/register accounts for signing operations you can use the following methods on [`AccountManager`](#accountmanager) (expressed here as `algorand.account` to denote the syntax via an [`AlgorandClient`](./algorand-client.md)):

- [`algorand.account.fromEnvironment(name, fundWith)`](../code/classes/types_account_manager.AccountManager.md#fromenvironment) - Registers and returns an account with private key loaded by convention based on the given name identifier - either by idempotently creating the account in KMD or from environment variable via `process.env['{NAME}_MNEMONIC']` and (optionally) `process.env['{NAME}_SENDER']` (if account is rekeyed)
  - This allows you to have powerful code that will automatically create and fund an account by name locally and when deployed against TestNet/MainNet will automatically resolve from environment variables, without having to have different code
  - Note: `fundWith` allows you to control how many Algo are seeded into an account created in KMD
- [`algorand.account.fromMnemonic(mnemonicSecret, sender?)`](../code/classes/types_account_manager.AccountManager.md#frommnemonic) - Registers and returns an account with secret key loaded by taking the mnemonic secret
- [`algorand.account.multisig(multisigParams, signingAccounts)`](../code/classes/types_account_manager.AccountManager.md#multisig) - Registers and returns a multisig account with one or more signing keys loaded
- [`algorand.account.rekeyed(sender, signer)`](../code/classes/types_account_manager.AccountManager.md#rekeyed) - Registers and returns an account representing the given rekeyed sender/signer combination
- [`algorand.account.random()`](../code/classes/types_account_manager.AccountManager.md#random) - Returns a new, cryptographically randomly generated account with private key loaded
- [`algorand.account.fromKmd()`](../code/classes/types_account_manager.AccountManager.md#fromkmd) - Returns an account with private key loaded from the given KMD wallet (identified by name)
- [`algorand.account.logicsig(program, args?)`](../code/classes/types_account_manager.AccountManager.md#logicsig) - Returns an account that represents a logic signature

### Underlying account classes

While `TransactionSignerAccount` is the main class used to represent an account that can sign, there are underlying account classes that can underpin the signer within the transaction signer account.

- `Account` - An in-built `algosdk.Account` object that has an address and private signing key, this can be created
- [`SigningAccount`](../code/classes/types_account.SigningAccount.md) - An abstraction around `algosdk.Account` that supports rekeyed accounts
- `LogicSigAccount` - An in-built algosdk `algosdk.LogicSigAccount` object
- [`MultisigAccount`](../code/classes/types_account.MultisigAccount.md) - An abstraction around `algosdk.MultisigMetadata`, `algosdk.makeMultiSigAccountTransactionSigner`, `algosdk.multisigAddress`, `algosdk.signMultisigTransaction` and `algosdk.appendSignMultisigTransaction` that supports multisig accounts with one or more signers present

### Dispenser

- [`algorand.account.dispenserFromEnvironment()`](../code/classes/types_account_manager.AccountManager.md#dispenserfromenvironment) - Returns an account (with private key loaded) that can act as a dispenser from environment variables, or against default LocalNet if no environment variables present
- [`algorand.account.localNetDispenser()`](../code/classes/types_account_manager.AccountManager.md#localnetdispenser) - Returns an account with private key loaded that can act as a dispenser for the default LocalNet dispenser account

## Rekey account

One of the unique features of Algorand is the ability to change the private key that can authorise transactions for an account. This is called [rekeying](https://developer.algorand.org/docs/get-details/accounts/rekey/).

> [!WARNING]
> Rekeying should be done with caution as a rekey transaction can result in permanent loss of control of an account.

You can issue a transaction to rekey an account by using the [`algorand.account.rekeyAccount(account, rekeyTo, options)`](../code/classes/types_account_manager.AccountManager.md#rekeyaccount) function:

- `account: string | TransactionSignerAccount` - The account address or signing account of the account that will be rekeyed
- `rekeyTo: string | TransactionSignerAccount` - The account address or signing account of the account that will be used to authorise transactions for the rekeyed account going forward. If a signing account is provided that will now be tracked as the signer for `account` in the `AccountManager` instance.
- An `options` object, which has:
  - [Common transaction parameters](./algorand-client.md#transaction-parameters)
  - [Execution parameters](./algorand-client.md#sending-a-single-transaction)

You can also pass in `rekeyTo` as a [common transaction parameter](./algorand-client.md#transaction-parameters) to any transaction.

### Examples

```typescript
// Basic example (with string addresses)

await algorand.account.rekeyAccount({ account: 'ACCOUNTADDRESS', rekeyTo: 'NEWADDRESS' })

// Basic example (with signer accounts)

await algorand.account.rekeyAccount({ account: account1, rekeyTo: newSignerAccount })

// Advanced example

await algorand.account.rekeyAccount({
  account: 'ACCOUNTADDRESS',
  rekeyTo: 'NEWADDRESS',
  lease: 'lease',
  note: 'note',
  firstValidRound: 1000n,
  validityWindow: 10,
  extraFee: (1000).microAlgo(),
  staticFee: (1000).microAlgo(),
  // Max fee doesn't make sense with extraFee AND staticFee
  //  already specified, but here for completeness
  maxFee: (3000).microAlgo(),
  maxRoundsToWaitForConfirmation: 5,
  suppressLog: true,
})

// Using a rekeyed account

// Note: if a signing account is passed into `algorand.account.rekeyAccount` then you don't need to call `rekeyedAccount` to register the new signer
const rekeyedAccount = algorand.account.rekeyed(account, newAccount)
// rekeyedAccount can be used to sign transactions on behalf of account...
```

# KMD account management

When running LocalNet, you have an instance of the [Key Management Daemon](https://github.com/algorand/go-algorand/blob/master/daemon/kmd/README.md), which is useful for:

- Accessing the private key of the default accounts that are pre-seeded with Algo so that other accounts can be funded and it's possible to use LocalNet
- Idempotently creating new accounts against a name that will stay intact while the LocalNet instance is running without you needing to store private keys anywhere (i.e. completely automated)

The KMD SDK is fairly low level so to make use of it there is a fair bit of boilerplate code that's needed. This code has been abstracted away into the `KmdAccountManager` class.

To get an instance of the `KmdAccountManager` class you can access it from [`AlgorandClient`](./algorand-client.md) via `algorand.account.kmd` or instantiate it directly (passing in a [`ClientManager`](./client.md)):

```typescript
import { KmdAccountManager } from '@algorandfoundation/algokit-utils/types/kmd-account-manager'

// Algod client only
const kmdAccountManager = new KmdAccountManager(clientManager)
```

The methods that are available are:

- [`getWalletAccount(walletName, predicate?, sender?)](../code/classes/types_kmd_account_manager.KmdAccountManager.md#getwalletaccount)` - Returns an Algorand signing account with private key loaded from the given KMD wallet (identified by name).
- [`getOrCreateWalletAccount(name, fundWith?)](../code/classes/types_kmd_account_manager.KmdAccountManager.md#getorcreatewalletaccount)` - 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.
- [`getLocalNetDispenserAccount()](../code/classes/types_kmd_account_manager.KmdAccountManager.md#getlocalnetdispenseraccount)` - Returns an Algorand account with private key loaded for the default LocalNet dispenser account (that can be used to fund other accounts)

```typescript
// Get a wallet account that seeded the LocalNet network
const defaultDispenserAccount = await kmdAccountManager.getWalletAccount(
  'unencrypted-default-wallet',
  (a) => a.status !== 'Offline' && a.amount > 1_000_000_000,
)
// Same as above, but dedicated method call for convenience
const localNetDispenserAccount = await kmdAccountManager.getLocalNetDispenserAccount()
// Idempotently get (if exists) or create (if it doesn't exist yet) an account by name using KMD
// if creating it then fund it with 2 ALGO from the default dispenser account
const newAccount = await kmdAccountManager.getOrCreateWalletAccount('account1', (2).algo())
// This will return the same account as above since the name matches
const existingAccount = await kmdAccountManager.getOrCreateWalletAccount('account1')
```

Some of this functionality is directly exposed from [`AccountManager`](#accountmanager), which has the added benefit of registering the account as a signer so they can be automatically used to sign transactions when using via [`AlgorandClient`](./algorand-client.md):

```typescript
// Get and register LocalNet dispenser
const localNetDispenser = await algorand.account.localNetDispenser()
// Get and register a dispenser by environment variable, or if not set then LocalNet dispenser via KMD
const dispenser = await algorand.account.dispenserFromEnvironment()
// Get / create and register account from KMD idempotently by name
const account1 = await algorand.account.fromKmd('account1', (2).algo())
```

```

--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/algokit:cli:architecture-decisions:2023-07-19_advanced_generate_command.md:
--------------------------------------------------------------------------------

```markdown
# Advanced `algokit generate` command

- **Status**: Approved
- **Owner:** Altynbek Orumbayev, Inaie Ignacio
- **Deciders**: Rob Moore, Daniel McGregor, Alessandro Cappellato
- **Date created**: 2023-07-19
- **Date decided:** 2023-07-24
- **Date updated**: 2023-07-24

## Context

The [Frontend Templates ADR](./2023-06-06_frontend-templates.md) introduced and expanded on AlgoKit's principles of Modularity and Maintainability by introducing a new set of official templates for quickly bootstrapping standalone `react` and `fullstack` projects showcasing best practices and patterns for building frontend and fullstack applications with Algorand. As a logical next step, we want to enable developers to extend existing projects instantiated from official templates with new files and features.

## Requirements

### 1. AlgoKit user should be able to use generate command to extend existing algokit compliant projects with new `files` of any kind

This implies scenarios like:

- Adding new contracts into existing algokit compliant projects.
  > Algokit compliant projects are projects that were instantiated from official or community templates and follow the same structure and conventions.
- Overriding existing files with new ones.
- Adding new files into existing projects.

Overall, we want to introduce a notion of `generators` which can be viewed as a modular self-sufficient template units that are hosted within template repositories and describe how to create or update files within projects instantiated from AlgoKit templates.

Ruby on Rails has a similar concept of [generators](https://guides.rubyonrails.org/generators.html) which are used to create or update files within Rails projects. This can be used as a reference for inspiration.

### 2. Template builder should be able to access a clear guideline and refer to official templates for examples on how to create `generators`

This implies extension of existing starter guidelines available for template builders on [AlgoKit Docs](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/tutorials/algokit-template.md) and using one or several official templates as a reference point.

## Principles

- **Modularity**: Artifacts dependant on `advanced algokit generate` command capabilities embedded into templates should follow guiding AlgoKit principles and expand on approaches already utilized in `react`, `fullstack` and `beaker` templates. This implies that giving developers flexibility to define any extra templating logic, allowing to create or update any files within projects instantiated from algokit templates.
- **Maintainability**: The `advanced algokit generate` capabilities on `algokit-cli` and related artifacts on respective official templates should be easy to maintain and extend.
- **Seamless onramp**: Great developer experience for template builders to create their own `generators` and user experience to use them via `advanced algokit generate` command should be a priority.

All of the aforementioned requirements should be met in a way that is consistent with the guiding principles of AlgoKit or attempt to find a balanced trade of between the principles that satisfies the requirements. Refer to [AlgoKit Guiding Principles](../../docs/algokit.md#Guiding-Principles) for detailed reference on the principles.

## Considered Options

Based on preliminary research, all of the options below assume that:
A `generator` is a self contained copier/jinja template that is hosted within a template repository and describes how to create or update files within projects instantiated from algokit templates. Hosting it along with the template is a necessity given that community based templates can follow different conventions, patterns and structure making it hard to attempt to generalize the logic of `generators` and make them work for all templates.

### Option 1: Wrapping generators into self contained copier templates hidden within algokit templates

This option implies that `generators` are self contained copier templates that are hidden within algokit templates and are not exposed to the end user. This option is inspired by [Ruby on Rails generators](https://guides.rubyonrails.org/generators.html) and [Yeoman generators](https://yeoman.io/authoring/).

The main idea is to rely on `_templates_suffix` in copier.yamls to define 2 separate types of suffixes for `templates` and for `generators`:

- Existing templates under all official algokit templates are already prefixed with `.jinja` hence we just need to explicitly prefix it with `.jinja` on root copier
- The new generators jinja templates can be prefixed (for example) with alternative file extension for jinja files such as `.j2`. Which is also a common convention for jinja templates.
- - This only works for files though for regular folders and cases like `{% if %}folder_name{% endif %}.j2` we need to wrap them into {% raw %} to that first pass when template initially initialized unwraps the content allowing second pass via generator to then use them as jinja templates. The only downside here is slightly longer file names for folders, but I think it's a reasonable tradeoff considering simplicity of the solution.

Overview of the proposal can be summarized via the following diagram:

```mermaid
graph TB
  T["Template Folder"]
  T --> C["copier.yaml"]
  T --> C1["..."]
  T --> G[".algokit/generators"]

  G --> G1["Generator 1"]
  G1 --> E1["copier.yaml"]
  G1 --> E2["..."]

  G --> G2["..."]
  G2 --> E3["..."]

  G --> G3["Generator N"]
  G3 --> E["copier.yaml"]
  G3 --> E4["..."]
```

#### Pros

- Generators are hidden within algokit templates and are not exposed to the end user. When user runs `algokit generate` command, cli presents a list of available generators to choose from. This makes it easier for user to understand what generators are available and what they do.
- Generators are self contained copier templates giving template builders flexibility to do any kind of templating logic similar to what they can already do with regular templates.
- Majority of implementation complexity is reduced by relying on copier as a backbone for generators feature.

#### Cons

- Generators are somewhat tightly coupled with individual algokit templates, which implies its not necessarily a matter of copy pasting generators from one template to another. This can be a problem for community template builders who want to reuse generators from official templates. However, this can be mitigated by providing clear guidelines on how to create generators and referring to official templates as a reference point. Additionally, it seems like a reasonable tradeoff given that templates can vastly differ in type, structure, conventions and patterns and it's significantly harder to generalize the logic of generators to make them work for all templates.

#### Implementation details

**1. Adjusting templates structure**

For instance, if we assume existing `beaker` template, the new file/folder structure can look as follows:

```
template_content/.algokit # alternatively could be just `.algokit-generators`
└── generators
    └── {generator_name} # generator name can be anything
        ├── copier.yaml # copier config for generator
        └── smart_contracts # logic for adding new contracts to beaker template
            └── {% raw %}{{ contract_name }}{% endraw %}
                ├── contract.py.j2
                ├── {% raw %}{% if language == 'python' %}deploy_config.py{% endif %}{% endraw %}.j2
                └── {% raw %}{% if language == 'typescript' %}deploy-config.ts{% endif %}{% endraw %}.j2
...rest of the template is left as is
copier.yml
```

The `index.ts` and `config.py` files on beaker template need to be updated to auto import all contracts from sub folders at `smart_contracts` to eliminate the need for developers to manually import them after running the smart contract generator.

> Please note, above is just an example that assumes the generator for adding new contracts, but the proposal is generic enough to support any kind of jinja-based templating logic.

**2. Adjusting `.algokit.toml`**

The proposal for new structure for defining generators in root algokit toml is as follows:

```toml
[generators.create_contract] # [generators.<generator_name>]
description = "Adds new smart contract to existing project" # description of the generator, can appear in cli for extra info
path = ".algokit/generators/create_contract"  # path that cli should grab to forward to copier copy
```

**3. Adjusting `algokit generate` command on cli**

Next step in implementation part of the proposal is adjusting the `generator` command on `algokit-cli` to make sure it knows how to look for generators. The available generators can be provided to user via list picker (a.k.a ruby on rails style) by letting algokit scan contents of `algokit.toml` and look for `.generators` folder.

a) Has no generators
If algokit-cli can't find any generator configured then nothing change from current implementation.

b) Has generators and user runs `algokit generate` command to see the list of available generators
A new `click` command per each generator in `.algokit.toml` is added to the list of generate commands, that will list all available generators for the user to choose from.

```bash
algokit-cli generate

---

Usage: algokit generate [OPTIONS] COMMAND [ARGS]...

  Generate code for an Algorand project.

Options:
  -h, --help  Show this message and exit.

Commands:
  client  Create a typed ApplicationClient from an ARC-32 application.json
  smart-contract  Adds new smart contract to existing project
```

Then, to invoke the interactive flow via copier user runs:

```bash
algokit-cli generate smart-contract `name of the contract`
```

c) Has generators, user knows what to pick and wants to run it non interactively
Using the generator configuration the `generator` will automatically add new `click` commands to the existing list of generate commands allowing the user to run them in the command line.

```bash
algokit-cli generate smart-contract -a contract_name=`name of the contract` -a language=python # passing extra arguments to generator similar to algokit init
```

**4. Testing and documentation**

Lastly we need to make sure that the new feature is properly tested and documented. This includes:

- Testing the new feature works as expected on all official templates that will host generators. This will imply adding a separate test suite that picks some default template state and run generators on top of them confirming that created artifacts are placed in expected locations and have expected content. Tests should be easy to follow and expand on existing tests suite on templates without introducing extra complexity.
- Introduce new tutorial sections on [AlgoKit Docs](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/tutorials/algokit-template.md) on how to create generators and refer to official templates as a reference point.

### Option 2: Wrapping generators into self contained copier templates hosted on separate repositories

This option proposes to host `generators` on separate set of repositories and use them as a dependency for algokit templates.
`algokit.toml` can be extended on template repositories to list generators they depend on.

The only distinction between this option and option 1 is that generators are hosted on separate repositories and are not hidden within algokit templates. Implying that they are not tightly coupled with algokit templates and can be reused/forked by community template builders to build their own generators.

#### Pros

- Generators are not tightly coupled with algokit templates and can be reused/forked by community template builders to build their own generators.
- Generators can be versioned and updated independently from algokit templates.

#### Cons

- Developing and maintaining generators is significantly more complex due to the need to maintain separate repositories and versioning.
- Official maintainers and community template builders need to be put extra effort at keeping generators generic enough to be reused by other templates. Given that templates can vastly differ in type, structure, conventions and patterns, this can be a challenge.
- Given that copier is being considered as a backbone for generators feature, drawbacks outlined for hosting templates on monorepos in the [previous adr](2023-06-06_frontend-templates.md#option-1-monolithic-template) apply here as well.

## Open questions for reviewers

1. What kinds of generators other than `add new contract` do we want to support on initial release (if any)?
2. Are there any other template repositories that we want to integrate with generators other than `beaker` (`fullstack` will contain those as well as it uses `beaker` as a dependency)?

> Please note an MVP PoC is already implemented and available to play around on algokit-cli and beaker template repo under `advanced-generate-command` and `generators` branches respectively.
> To test it out checkout the branche on cli do `pipx install . --force`, navigate to beaker template repo and checkout the branch as well, then navigate to any of the sub folders in `tests_generated`. Lastly do `algokit bootstrap all`, build the contract and execute `algokit generate` from root of that folder to play around with the feature based on the implementation proposal from Option 1.

## Final Decision

The team approved the proposal for Option 1: Wrapping generators into self contained copier templates hidden within algokit templates.

## Next steps

1. Polishing the PoC on algokit-cli and adding tests
2. Polishing the PoC on beaker template and adding tests
3. Adding documentation for new capabilities of the generate command
4. Adding documentation for template builders on how to create generators

```
Page 29/74FirstPrevNextLast