This is page 17 of 74. Use http://codebase.md/goplausible/algorand-mcp?format=md&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-0048.md:
--------------------------------------------------------------------------------

```markdown
---
arc: 48
title: Targeted DeFi Rewards
description: Targeted DeFi Rewards, Terms and Conditions
author: Stéphane BARROSO (@SudoWeezy)
discussions-to: https://github.com/algorandfoundation/ARCs/issues/227
status: Deprecated
type: Informational
created: 2023-07-19
---

## Abstract
The Targeted DeFi Rewards is a temporary incentive program that distributes Algo to be deployed in targeted activities to attract new DeFi users from within and outside the ecosystem.
The goal is to give DeFi projects more flexibility in how these rewards are structured and distributed among their user base, targeting rapid growth, deeper DEX liquidity, and incentives for users who come to Algorand in the middle of a governance period.

## 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" target=_blank>RFC-2119</a>.

### Eligibility Criteria

To be eligible to apply to this program, projects must abide by the <a href="https://www.algorand.foundation/disclaimers">Disclaimers</a> (in particular the “Excluded Jurisdictions” section) and be willing to enter into a binding contract in the form of the template provided by the Algorand Foundation.

> The Algorand Foundation is temporarily allowing US-based entities to apply for this program. Approved projects will have their rewards swapped to USDCa on the day of the payment. This exception will be reviewed periodically.

Projects must have at least 500K Algo equivalent in TVL of white-listed assets, at the time of the quarterly snapshot block, which happens on the 15th day of the last month of each calendar quarter. All related wallet addresses will be provided in advance for peer scrutiny.

The DeFi Advisory Committee will review applications to verify each TVL claim, thus ensuring that claims are valid prior to application approval.

For AMMs we will leverage the Eligible Liquidity Pool list that is currently adopted to allow the governors commitment of LP tokens in the DeFi Rewards program, with extension to the assets defined below.

For Lending/Borrowing protocols, each project will provide a list of their assets and their holding wallet address(es).

For Bridges, each project will provide a list of the bridged assets and their holding wallet address(es).

### Assets Selection

The metrics used to select eligible assets to be used for Eligibility TVL Calculation (as per Eligibility Criteria above) were chosen to ensure that the selected tokens have a strong reputation, are difficult to manipulate, and are valuable to the ecosystem. This reputation is built on a combination of factors, including Total Value Locked (TVL), Market Cap, and listings.

>Assets are expected to meet at least two of the three criteria below to be included in the white-list.

|Criteria||
|:-|-:|
|TVL|The total value locked in different Algorand protocols plays a key role. It's a good indicator of the token's popularity. Minimum TVL requirement: $100K across all the protocols.|
|Market Cap|Market cap is a measure of a crypto token’s total circulating supply multiplied by its current market price. This parameter can be used to consider the positioning of the tokens on the entire crypto market. Minimum Market Cap requirement: USD 1MM.|
|Listing|Tokens listed on multiple stable and respected exchanges are often seen as more established and trustworthy. This can also contribute to increased demand for the token and further the growth of its reputation within the ecosystem.|

The following assets are qualified and meet the above criteria:
- ALGO
- gALGO - ASA ID 793124631
- USDC - ASA ID 31566704
- USDT - ASA ID 312769
- goBTC - ASA ID 386192725
- goETH - ASA ID 386195940
- PLANETS - ASA ID 27165954
- OPUL - ASA ID 287867876
- VESTIGE - ASA ID 700965019
- CHIPS - ASA ID 388592191
- DEFLY - ASA ID 470842789
- goUSD - ASA 672913181
- WBTC - ASA 1058926737
- WETH - ASA 887406851
- GOLD$ - ASA 246516580
- SILVER$ - ASA 246519683
- PEPE - ASA 1096015467
- COOP - ASA 796425061
- GORA - ASA 1138500612

> Applications for the above list can be submitted at any time <a href="https://forms.gle/kpEpZ8sih69M5xa39">using this form</a>. Cut off for the applications review is the 7th day of the last month of each calendar quarter, or one week before the quarterly snapshot date.

### Rewards Distribution

Projects will receive 11250 Algo for each 500K Algo TVL as defined above, rounded down. In the event that the available Algo are not sufficient for all the projects, Algo rewards will be distributed to each protocol based on their weighted contribution of TVL to Algorand DeFi.

Rewards per project are capped at 25% of the total rewards distributed under this program for that period.  In the event of partial distribution of the allocated 7.5MM, the remaining funds will be distributed as regular DeFi governance rewards. For Governance Period 8, the AMM TVL count has doubled, when compared to lending/borrow and bridge projects, in recognition of their strategic role in providing liquidity for the ecosystem. This modification was approved by the DeFi Committee.

Rewards under this program will be distributed to projects within 4 weeks of the scheduled start date of the new governance period and the project(s). The usage of these rewards will be made public, and they will be entirely dedicated to protocol provision, user rewards, and user engagement. The use of rewards and methodology for payment must be made public and approved by the Algorand DeFi advisory committee prior to distribution.

## Rationale
This document was versioned using google doc, it made more sense to move it on github.

## Security Considerations
Disclaimer: This document may be revised until the day before the voting session opens, as we are still collecting community feedback.

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

```

--------------------------------------------------------------------------------
/packages/server/src/tools/apiManager/vestige/swaps.ts:
--------------------------------------------------------------------------------

```typescript
import { Tool, ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
import { ResponseProcessor } from '../../../utils/responseProcessor.js';
import { env } from '../../../env.js';

export const swapTools: Tool[] = [
  {
    name: 'api_vestige_view_swaps',
    description: 'Get swaps',
    inputSchema: {
      type: 'object',
      properties: {
        network_id: {
          type: 'integer',
          description: 'Network ID'
        },
        start: {
          type: 'integer',
          description: 'Start timestamp'
        },
        end: {
          type: 'integer',
          description: 'Optional end timestamp'
        },
        protocol_id: {
          type: 'integer',
          description: 'Optional protocol ID filter'
        },
        asset_id: {
          type: 'integer',
          description: 'Optional asset ID filter'
        },
        address: {
          type: 'string',
          description: 'Optional address filter'
        },
        executor: {
          type: 'string',
          description: 'Optional executor filter'
        },
        next: {
          type: 'string',
          description: 'Optional next token for pagination'
        },
        denominating_asset_id: {
          type: 'integer',
          description: 'Optional denominating asset ID',
          default: 0
        },
        limit: {
          type: 'integer',
          description: 'Maximum number of results',
          default: 50,
          maximum: 250,
          minimum: 1
        },
        order_dir: {
          type: 'string',
          description: 'Order direction (asc/desc)',
          default: 'desc',
          pattern: '^(asc|desc)$'
        }
      },
      required: ['network_id', 'start']
    }
  },
  {
    name: 'api_vestige_get_best_v4_swap_data',
    description: 'Get best V4 swap data',
    inputSchema: {
      type: 'object',
      properties: {
        from_asa: {
          type: 'integer',
          description: 'Source ASA ID'
        },
        to_asa: {
          type: 'integer',
          description: 'Target ASA ID'
        },
        amount: {
          type: 'integer',
          description: 'Amount to swap'
        },
        mode: {
          type: 'string',
          description: 'Swap mode (sef/sfe)',
          pattern: '^(sef|sfe)$'
        },
        denominating_asset_id: {
          type: 'integer',
          description: 'Optional denominating asset ID',
          default: 0
        },
        enabled_providers: {
          type: 'string',
          description: 'Optional comma-separated list of enabled providers'
        },
        disabled_providers: {
          type: 'string',
          description: 'Optional comma-separated list of disabled providers'
        }
      },
      required: ['from_asa', 'to_asa', 'amount', 'mode']
    }
  },
  {
    name: 'api_vestige_get_v4_swap_discount',
    description: 'Get V4 swap discount',
    inputSchema: {
      type: 'object',
      properties: {
        address: {
          type: 'string',
          description: 'Account address'
        }
      },
      required: ['address']
    }
  },
  {
    name: 'api_vestige_get_v4_swap_data_transactions',
    description: 'Get V4 swap data transactions',
    inputSchema: {
      type: 'object',
      properties: {
        sender: {
          type: 'string',
          description: 'Sender address'
        },
        slippage: {
          type: 'number',
          description: 'Slippage tolerance'
        },
        random_signer: {
          type: 'string',
          description: 'Optional random signer address'
        },
        swap_data: {
          type: 'object',
          description: 'V4 swap data from get_best_v4_swap_data'
        }
      },
      required: ['sender', 'slippage', 'swap_data']
    }
  },
  {
    name: 'api_vestige_get_aggregator_stats',
    description: 'Get aggregator stats',
    inputSchema: {
      type: 'object',
      properties: {
        denominating_asset_id: {
          type: 'integer',
          description: 'Optional denominating asset ID',
          default: 0
        }
      }
    }
  }
];

export const handleSwapTools = ResponseProcessor.wrapResourceHandler(async function handleSwapTools(args: any): Promise<any> {
  const name = args.name;
  const baseUrl = env.vestige_api_url;
  let endpoint = '';
  let method = 'GET';

  switch (name) {
    case 'api_vestige_view_swaps':
      endpoint = '/swaps';
      break;
    case 'api_vestige_get_best_v4_swap_data':
      endpoint = '/swap/v4';
      break;
    case 'api_vestige_get_v4_swap_discount':
      endpoint = '/swap/v4/fee';
      break;
    case 'api_vestige_get_v4_swap_data_transactions':
      endpoint = '/swap/v4/transactions';
      method = 'POST';
      break;
    case 'api_vestige_get_aggregator_stats':
      endpoint = '/swap/v4/stats';
      break;
    default:
      throw new McpError(
        ErrorCode.MethodNotFound,
        `Unknown tool: ${name}`
      );
  }

  try {
    // Add query parameters if they exist
    const queryParams = new URLSearchParams();
    for (const [key, value] of Object.entries(args)) {
      if (value !== undefined && key !== 'swap_data') {
        queryParams.append(key, String(value));
      }
    }
    const url = `${baseUrl}${endpoint}${queryParams.toString() ? `?${queryParams.toString()}` : ''}`;

    const options: RequestInit = {
      method
    };

    // Add body for POST requests
    if (method === 'POST' && args.swap_data) {
      options.body = JSON.stringify(args.swap_data);
      options.headers = {
        'Content-Type': 'application/json'
      };
    }

    const response = await fetch(url, options);
    if (!response.ok) {
      throw new McpError(
        ErrorCode.InternalError,
        `Vestige API error: ${response.status} ${response.statusText}`
      );
    }
    const data = await response.json();
    return data;
  } catch (error) {
    if (error instanceof McpError) {
      throw error;
    }
    throw new McpError(
      ErrorCode.InternalError,
      `Failed to fetch swap data: ${error instanceof Error ? error.message : String(error)}`
    );
  }
});

```

--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/developer:docs:run-a-node:participate:index.md:
--------------------------------------------------------------------------------

```markdown
title: Overview

This section covers the procedure for registering an account to participate in the Algorand Consensus Protocol. It begins with a description of important concepts and best practices before getting started. 

!!! tldr
	- Accounts participate in the Algorand consensus protocol by generating a valid participation key and then registering that key online with a special online registration transaction.
	- Accounts mark themselves online by submitting an [online key registration transaction](../../get-details/transactions#register-account-online) for a valid participation key.
	- Accounts mark themselves offline by submitting an [offline key registration transaction](../../get-details/transactions#register-account-offline). 
	- It is important to mark your account offline if it is not participating. Not doing so is bad network behavior and will decrease the honest/dishonest user ratio that underpins the liveness of the agreement protocol.
	- It is important to ensure that only the latest update of the participation key ever exists at any time.
	- In the event of node migration, hardware swap, or other similar events, it is preferable to have your participation key offline for a few rounds than to have it present on multiple nodes at the same time.

# Important Concepts

## Online Participation
In the context of this section, participation means participation in the Algorand consensus protocol. An account that participates in the Algorand consensus protocol is eligible and available to be selected to propose and vote on new blocks in the Algorand blockchain. Note that the likelihood that this account will be selected to propose and vote on blocks is proportional to its amount of stake. Read more about voting and block proposals in the [Algorand Consensus Protocol overview](../../get-details/algorand_consensus#the-algorand-consensus-protocol).

!!! info
    Participation in consensus currently does not affect the proportion of participation rewards an account receives. Participation rewards are [based on the amount](https://algorand.foundation/rewards-faq) of stake an account has, irrespective of whether the account is marked online or offline. Furthermore, currently there are no participation rewards on MainNet.

## Online/Offline Status
In order for an account to participate in consensus, it must first mark itself online. Marking an account online requires the account to have a valid participation key, which has been registered with the network by way of an [online key registration transaction](../../get-details/transactions#register-account-online), authorized by the participating account. Marking an account offline requires an [offline key registration transaction](../../get-details/transactions#register-account-offline) also authorized by the private key of the participating account.

# Guidelines for a Healthy Network

## Ensure that Online Accounts are Participating
If an account registers itself online, it is important that its participation key is online. _A participation key is online if there is a single fully-synchronized node on the Algorand network that has that key in its ledger directory._ You should always mark an account offline if it is not actually available to participate, since the network uses the online/offline status of an account to calculate block vote thresholds. If you are marked online but you are not participating, you would be considered a dishonest user and will negatively impact the voting threshold. Furthermore, if your node experiences issues you are not able to solve promptly, it is recommended that you register the account offline as soon as possible.

!!! tip
	If you keep your private keys in cold storage, it is recommended that you generate and sign enough offline transactions to be able to take the account offline in case of emergencies. Learn more about generating transactions for future rounds in the [Transactions guide](../../get-details/transactions#). Learn how to create and authorize transactions offline in the [Authorizing Transactions Offline](../../get-details/transactions/offline_transactions) guide.

## Renew participation keys before they expire
Participation keys are valid for a specific round range. Make sure to renew participation keys or mark the account offline before the current participation key expires. Your account will _not_ automatically be marked offline.

_Visit the [Renew Participation Keys section](./renew.md) for detailed instructions._

## Ensure that Participation Nodes are working properly

Monitor your participation node to ensure high performance and consistent access to your registered participation key. 
The following should be monitored:

* last committed block (`goal node status` or API) matches a third-party API service
* CPU / RAM / disk use are within thresholds
* clock is accurate (blocks are timestamped using the clock time from the block proposer's node, so keep your node clock accurate and on time)
* the participation node is sending votes and proposing blocks at the expected frequency.

## Securely Store Participation Keys

Registered participation keys that are in operation are regularly updated through the protocol so that they cannot be used to vote on earlier rounds. Essentially, the set of keys corresponding to earlier rounds are deleted after the round passes to ensure that the compromise of a participation key by a bad actor does not give the bad actor the potential to rewrite history. Because of this, it is important that there only exists a single instance of the participation key (files ending in `*.partkey`) at any time in the system. 

!!! warning
	Because of this, holding backups of participation keys is highly discouraged, unless appropriate procedures are setup to purge those backups on a regular basis.

# Technical Procedure

The rest of this section will describe how to [generate a participation key](./generate_keys.md) for an account, [mark or register the account online](./online.md) (with the generated participation key), [mark or register an account offline](./offline.md), and [renew a participation key](./renew.md) for an account.

```

--------------------------------------------------------------------------------
/packages/client/src/index.ts:
--------------------------------------------------------------------------------

```typescript
import { PeraWalletConnect } from '@perawallet/connect';
import { DeflyWalletConnect } from '@blockshake/defly-connect';
import { DaffiWalletConnect } from '@daffiwallet/connect';
import algosdk, { Transaction } from 'algosdk';
import { LocalWallet } from './LocalWallet.js';

export type WalletType = 'pera' | 'defly' | 'daffi' | 'local';

export interface WalletConnectOptions {
  network: 'mainnet' | 'testnet';
}

interface WalletProvider {
  connect(): Promise<string[]>;
  reconnectSession(): Promise<string[]>;
  disconnect(): Promise<void>;
  signTransactions(transactions: { txn: Transaction; message?: string }[][]): Promise<Uint8Array[][]>;
}

export class AlgorandMcpClient {
  private peraWallet: PeraWalletConnect;
  private deflyWallet: DeflyWalletConnect;
  private daffiWallet: DaffiWalletConnect;
  private activeWallet: WalletProvider | null = null;
  private localWallet: LocalWallet;
  private connectedAccounts: string[] = [];
  private activeWalletType: WalletType | null = null;

  constructor(options: WalletConnectOptions) {
    this.localWallet = new LocalWallet();
    this.peraWallet = new PeraWalletConnect({
      chainId: options.network === 'mainnet' ? 416001 : 416002
    });
    this.deflyWallet = new DeflyWalletConnect({
      chainId: options.network === 'mainnet' ? 416001 : 416002
    });
    this.daffiWallet = new DaffiWalletConnect({
      chainId: options.network === 'mainnet' ? 416001 : 416002
    });
  }

  async connect(walletType: WalletType): Promise<string[]> {
    try {
      let accounts: string[] = [];
      
      switch (walletType) {
        case 'local':
          accounts = await this.localWallet.connect();
          this.activeWallet = this.localWallet;
          break;
        case 'pera':
          accounts = await this.peraWallet.connect();
          this.activeWallet = this.peraWallet as unknown as WalletProvider;
          break;
        case 'defly':
          accounts = await this.deflyWallet.connect();
          this.activeWallet = this.deflyWallet as unknown as WalletProvider;
          break;
        case 'daffi':
          accounts = await this.daffiWallet.connect();
          this.activeWallet = this.daffiWallet as unknown as WalletProvider;
          break;
        default:
          throw new Error('Unsupported wallet type');
      }

      this.connectedAccounts = accounts;
      this.activeWalletType = walletType;
      return accounts;
    } catch (error: unknown) {
      throw new Error(`Failed to connect wallet: ${error instanceof Error ? error.message : String(error)}`);
    }
  }

  makeTransactionSigner = async (txnGroup: Uint8Array[], indexesToSign: number[]) => {
    if (!this.activeWallet || !this.activeWalletType) {
      throw new Error('No active wallet');
    }

    if (this.activeWalletType === 'local') {
      const signer = await this.localWallet.makeTransactionSigner();
      const decodedTxns = txnGroup.map(txn => algosdk.decodeUnsignedTransaction(txn));
      return () => signer(decodedTxns, indexesToSign);
    }

    return async () => {
      if (!this.activeWallet) {
        throw new Error('Wallet not connected');
      }

      try {
        // Decode transactions from Uint8Array
        const decodedTxns = txnGroup.map(txn => algosdk.decodeUnsignedTransaction(txn));
        
        // Format transactions for signing
        const txnsToSign = decodedTxns.map(txn => ({
          txn: txn,
          message: 'Please sign the transaction'
        }));

        const result = await this.activeWallet.signTransactions([txnsToSign]);
        return result[0];
      } catch (error: any) {
        // Handle specific error cases
        if (error?.data?.type === "SIGN_MODAL_CLOSED") {
          console.error('Transaction signing cancelled');
          return new Array(indexesToSign.length).fill(null);
        }
        
        const msg = error?.message || "Failed to sign transaction";
        console.error(`Wallet signer error: ${msg}`);
        return new Array(indexesToSign.length).fill(null);
      }
    };
  }

  getAccounts(): string[] {
    return this.connectedAccounts;
  }

  async signTransactions(transactions: { txn: Transaction; message?: string }[][]): Promise<Uint8Array[][]> {
    if (!this.activeWallet) {
      throw new Error('No active wallet connection. Call connect() first.');
    }

    try {
      return await this.activeWallet.signTransactions(transactions);
    } catch (error: unknown) {
      throw new Error(`Failed to sign transactions: ${error instanceof Error ? error.message : String(error)}`);
    }
  }

  // Backward compatibility
  async signTransaction(txn: Transaction): Promise<Uint8Array> {
    const result = await this.signTransactions([[{ txn, message: 'Transaction to sign' }]]);
    return result[0][0];
  }

  async disconnect(): Promise<void> {
    if (this.activeWallet) {
      await this.activeWallet.disconnect();
      this.activeWallet = null;
      this.connectedAccounts = [];
    }
  }

  async reconnectSession(walletType: WalletType): Promise<string[]> {
    try {
      let accounts: string[] = [];
      
      switch (walletType) {
        case 'local':
          accounts = await this.localWallet.reconnectSession();
          this.activeWallet = this.localWallet;
          break;
        case 'pera':
          accounts = await this.peraWallet.reconnectSession();
          this.activeWallet = this.peraWallet as unknown as WalletProvider;
          break;
        case 'defly':
          accounts = await this.deflyWallet.reconnectSession();
          this.activeWallet = this.deflyWallet as unknown as WalletProvider;
          break;
        case 'daffi':
          accounts = await this.daffiWallet.reconnectSession();
          this.activeWallet = this.daffiWallet as unknown as WalletProvider;
          break;
        default:
          throw new Error('Unsupported wallet type');
      }

      this.connectedAccounts = accounts;
      this.activeWalletType = walletType;
      return accounts;
    } catch (error: unknown) {
      throw new Error(`Failed to reconnect session: ${error instanceof Error ? error.message : String(error)}`);
    }
  }
}

```

--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/algokit:cli:features:goal.md:
--------------------------------------------------------------------------------

```markdown
# AlgoKit goal

AlgoKit goal command provides the user with a mechanism to run [goal cli](https://developer.algorand.org/docs/clis/goal/goal/) commands against the current [AlgoKit LocalNet](./localnet.md).

You can explore all possible goal commands by running `algokit goal` e.g.:

```
$ ~ algokit goal
 GOAL is the CLI for interacting Algorand software instance. The binary 'goal' is installed alongside the algod binary and is considered an integral part of the complete installation. The binaries should be used in tandem - you should not try to use a version of goal with a different version of algod.

 Usage:
 goal [flags]
 goal [command]

 Available Commands:
 account     Control and manage Algorand accounts
 app         Manage applications
 asset       Manage assets
 clerk       Provides the tools to control transactions
 completion  Shell completion helper
 help        Help about any command
 kmd         Interact with kmd, the key management daemon
 ledger      Access ledger-related details
 license     Display license information
 logging     Control and manage Algorand logging
 network     Create and manage private, multi-node, locally-hosted networks
 node        Manage a specified algorand node
 protocols
 report
 version     The current version of the Algorand daemon (algod)
 wallet      Manage wallets: encrypted collections of Algorand account keys

 Flags:
 -d, --datadir stringArray   Data directory for the node
 -h, --help                  help for goal
 -k, --kmddir string         Data directory for kmd
 -v, --version               Display and write current build version and exit

 Use "goal [command] --help" for more information about a command.
```

For instance, running `algokit goal report` would result in output like:

```
$ ~ algokit goal report
 12885688322
 3.12.2.dev [rel/stable] (commit #181490e3)
 go-algorand is licensed with AGPLv3.0
 source code available at https://github.com/algorand/go-algorand

 Linux ff7828f2da17 5.15.49-linuxkit #1 SMP PREEMPT Tue Sep 13 07:51:32 UTC 2022 aarch64 GNU/Linux

 Genesis ID from genesis.json: sandnet-v1

 Last committed block: 0
 Time since last block: 0.0s
 Sync Time: 0.0s
 Last consensus protocol: future
 Next consensus protocol: future
 Round for next consensus protocol: 1
 Next consensus protocol supported: true
 Last Catchpoint:
 Genesis ID: sandnet-v1
 Genesis hash: vEg1NCh6SSXwS6O5HAfjYCCNAs4ug328s3RYMr9syBg=
```

If the AlgoKit Sandbox `algod` docker container is not present or not running, the command will fail with a clear error, e.g.:

```
$ ~ algokit goal
 Error: No such container: algokit_algod
 Error: Error executing goal; ensure the Sandbox is started by executing `algokit sandbox status`
```

```
$ ~ algokit goal
 Error response from daemon: Container 5a73961536e2c98e371465739053d174066c40d00647c8742f2bb39eb793ed7e is not running
 Error: Error executing goal; ensure the Sandbox is started by executing `algokit sandbox status`
```

## Working with Files in the Container

When interacting with the container, especially if you're using tools like goal, you might need to reference files or directories. Here's how to efficiently deal with files and directories:

### Automatic File Mounting

When you specify a file or directory path in your `goal` command, the system will automatically mount that path from your local filesystem into the container. This way, you don't need to copy files manually each time.

For instance, if you want to compile a `teal` file:

```
algokit goal clerk compile /Path/to/inputfile/approval.teal -o /Path/to/outputfile/approval.compiled
```

Here, `/Path/to/inputfile/approval.teal` and `/Path/to/outputfile/approval.compiled` are paths on your local file system, and they will be automatically accessible to the `goal` command inside the container.

### Manual Copying of Files

In case you want to manually copy files into the container, you can do so using `docker cp`:

```
docker cp foo.txt algokit_algod:/root
```

This command copies the `foo.txt` from your local system into the root directory of the `algokit_algod` container.

Note: Manual copying is optional and generally only necessary if you have specific reasons for doing so since the system will auto-mount paths specified in commands.

## Running multiple commands

If you want to run multiple commands or interact with the filesystem you can execute `algokit goal --console`. This will open a [Bash](https://www.gnu.org/software/bash/) shell session on the `algod` Docker container and from there you can execute goal directly, e.g.:

```bash
$ algokit goal --console
Opening Bash console on the algod node; execute `exit` to return to original console
root@82d41336608a:~# goal account list
[online]        C62QEFC7MJBPHAUDMGVXGZ7WRWFAF3XYPBU3KZKOFHYVUYDGU5GNWS4NWU      C62QEFC7MJBPHAUDMGVXGZ7WRWFAF3XYPBU3KZKOFHYVUYDGU5GNWS4NWU      4000000000000000 microAlgos
[online]        DVPJVKODAVEKWQHB4G7N6QA3EP7HKAHTLTZNWMV4IVERJQPNGKADGURU7Y      DVPJVKODAVEKWQHB4G7N6QA3EP7HKAHTLTZNWMV4IVERJQPNGKADGURU7Y      4000000000000000 microAlgos
[online]        4BH5IKMDDHEJEOZ7T5LLT4I7EVIH5XCOTX3TPVQB3HY5TUBVT4MYXJOZVA      4BH5IKMDDHEJEOZ7T5LLT4I7EVIH5XCOTX3TPVQB3HY5TUBVT4MYXJOZVA      2000000000000000 microAlgos
```

## Interactive Mode

Some `goal` commands require interactive input from the user. By default, AlgoKit will attempt to run commands in non-interactive mode first, and automatically switch to interactive mode if needed. You can force a command to run in interactive mode by using the `--interactive` flag:

```bash
$ algokit goal --interactive wallet new algodev
Please choose a password for wallet 'algodev':
Please confirm the password:
Creating wallet...
Created wallet 'algodev'
Your new wallet has a backup phrase that can be used for recovery.
Keeping this backup phrase safe is extremely important.
Would you like to see it now? (Y/n): n
```

This is particularly useful when you know a command will require user input, such as creating new accounts, importing keys, or signing transactions.

For more details about the `AlgoKit goal` command, please refer to the [AlgoKit CLI reference documentation](../cli/index.md#goal).

```

--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/SDKs:javascript:classes:modelsv2.SimulationTransactionExecTrace.md:
--------------------------------------------------------------------------------

```markdown
[algosdk](../README.md) / [Exports](../modules.md) / [modelsv2](../modules/modelsv2.md) / SimulationTransactionExecTrace

# Class: SimulationTransactionExecTrace

[modelsv2](../modules/modelsv2.md).SimulationTransactionExecTrace

The execution trace of calling an app or a logic sig, containing the inner app
call trace in a recursive way.

## Hierarchy

- `default`

  ↳ **`SimulationTransactionExecTrace`**

## Table of contents

### Constructors

- [constructor](modelsv2.SimulationTransactionExecTrace.md#constructor)

### Properties

- [approvalProgramHash](modelsv2.SimulationTransactionExecTrace.md#approvalprogramhash)
- [approvalProgramTrace](modelsv2.SimulationTransactionExecTrace.md#approvalprogramtrace)
- [attribute\_map](modelsv2.SimulationTransactionExecTrace.md#attribute_map)
- [clearStateProgramHash](modelsv2.SimulationTransactionExecTrace.md#clearstateprogramhash)
- [clearStateProgramTrace](modelsv2.SimulationTransactionExecTrace.md#clearstateprogramtrace)
- [clearStateRollback](modelsv2.SimulationTransactionExecTrace.md#clearstaterollback)
- [clearStateRollbackError](modelsv2.SimulationTransactionExecTrace.md#clearstaterollbackerror)
- [innerTrace](modelsv2.SimulationTransactionExecTrace.md#innertrace)
- [logicSigHash](modelsv2.SimulationTransactionExecTrace.md#logicsighash)
- [logicSigTrace](modelsv2.SimulationTransactionExecTrace.md#logicsigtrace)

### Methods

- [get\_obj\_for\_encoding](modelsv2.SimulationTransactionExecTrace.md#get_obj_for_encoding)
- [from\_obj\_for\_encoding](modelsv2.SimulationTransactionExecTrace.md#from_obj_for_encoding)

## Constructors

### constructor

• **new SimulationTransactionExecTrace**(`«destructured»`)

Creates a new `SimulationTransactionExecTrace` object.

#### Parameters

| Name | Type |
| :------ | :------ |
| `«destructured»` | `Object` |
| › `approvalProgramHash?` | `string` \| `Uint8Array` |
| › `approvalProgramTrace?` | [`SimulationOpcodeTraceUnit`](modelsv2.SimulationOpcodeTraceUnit.md)[] |
| › `clearStateProgramHash?` | `string` \| `Uint8Array` |
| › `clearStateProgramTrace?` | [`SimulationOpcodeTraceUnit`](modelsv2.SimulationOpcodeTraceUnit.md)[] |
| › `clearStateRollback?` | `boolean` |
| › `clearStateRollbackError?` | `string` |
| › `innerTrace?` | [`SimulationTransactionExecTrace`](modelsv2.SimulationTransactionExecTrace.md)[] |
| › `logicSigHash?` | `string` \| `Uint8Array` |
| › `logicSigTrace?` | [`SimulationOpcodeTraceUnit`](modelsv2.SimulationOpcodeTraceUnit.md)[] |

#### Overrides

BaseModel.constructor

#### Defined in

client/v2/algod/models/types.ts:5288

## Properties

### approvalProgramHash

• `Optional` **approvalProgramHash**: `Uint8Array`

SHA512_256 hash digest of the approval program executed in transaction.

#### Defined in

client/v2/algod/models/types.ts:5226

___

### approvalProgramTrace

• `Optional` **approvalProgramTrace**: [`SimulationOpcodeTraceUnit`](modelsv2.SimulationOpcodeTraceUnit.md)[]

Program trace that contains a trace of opcode effects in an approval program.

#### Defined in

client/v2/algod/models/types.ts:5231

___

### attribute\_map

• **attribute\_map**: `Record`\<`string`, `string`\>

#### Inherited from

BaseModel.attribute\_map

#### Defined in

client/v2/basemodel.ts:56

___

### clearStateProgramHash

• `Optional` **clearStateProgramHash**: `Uint8Array`

SHA512_256 hash digest of the clear state program executed in transaction.

#### Defined in

client/v2/algod/models/types.ts:5236

___

### clearStateProgramTrace

• `Optional` **clearStateProgramTrace**: [`SimulationOpcodeTraceUnit`](modelsv2.SimulationOpcodeTraceUnit.md)[]

Program trace that contains a trace of opcode effects in a clear state program.

#### Defined in

client/v2/algod/models/types.ts:5241

___

### clearStateRollback

• `Optional` **clearStateRollback**: `boolean`

If true, indicates that the clear state program failed and any persistent state
changes it produced should be reverted once the program exits.

#### Defined in

client/v2/algod/models/types.ts:5247

___

### clearStateRollbackError

• `Optional` **clearStateRollbackError**: `string`

The error message explaining why the clear state program failed. This field will
only be populated if clear-state-rollback is true and the failure was due to an
execution error.

#### Defined in

client/v2/algod/models/types.ts:5254

___

### innerTrace

• `Optional` **innerTrace**: [`SimulationTransactionExecTrace`](modelsv2.SimulationTransactionExecTrace.md)[]

An array of SimulationTransactionExecTrace representing the execution trace of
any inner transactions executed.

#### Defined in

client/v2/algod/models/types.ts:5260

___

### logicSigHash

• `Optional` **logicSigHash**: `Uint8Array`

SHA512_256 hash digest of the logic sig executed in transaction.

#### Defined in

client/v2/algod/models/types.ts:5265

___

### logicSigTrace

• `Optional` **logicSigTrace**: [`SimulationOpcodeTraceUnit`](modelsv2.SimulationOpcodeTraceUnit.md)[]

Program trace that contains a trace of opcode effects in a logic sig.

#### Defined in

client/v2/algod/models/types.ts:5270

## Methods

### get\_obj\_for\_encoding

▸ **get_obj_for_encoding**(`binary?`): `Record`\<`string`, `any`\>

Get an object ready for encoding to either JSON or msgpack.

#### Parameters

| Name | Type | Default value | Description |
| :------ | :------ | :------ | :------ |
| `binary` | `boolean` | `false` | Use true to indicate that the encoding can handle raw binary objects (Uint8Arrays). Use false to indicate that raw binary objects should be converted to base64 strings. True should be used for objects that will be encoded with msgpack, and false should be used for objects that will be encoded with JSON. |

#### Returns

`Record`\<`string`, `any`\>

#### Inherited from

BaseModel.get\_obj\_for\_encoding

#### Defined in

client/v2/basemodel.ts:65

___

### from\_obj\_for\_encoding

▸ `Static` **from_obj_for_encoding**(`data`): [`SimulationTransactionExecTrace`](modelsv2.SimulationTransactionExecTrace.md)

#### Parameters

| Name | Type |
| :------ | :------ |
| `data` | `Record`\<`string`, `any`\> |

#### Returns

[`SimulationTransactionExecTrace`](modelsv2.SimulationTransactionExecTrace.md)

#### Defined in

client/v2/algod/models/types.ts:5343

```

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

```markdown
---
arc: 2
title: Algorand Transaction Note Field Conventions
description: Conventions for encoding data in the note field at application-level
author: Fabrice Benhamouda (@fabrice102), Stéphane Barroso (@SudoWeezy), Cosimo Bassi (@cusma)
discussions-to: https://github.com/algorandfoundation/ARCs/issues/2
status: Final
type: Standards Track
category: ARC
sub-category: Explorer
created: 2021-07-06
---

# Algorand Transaction Note Field Conventions

## Abstract

The goal of these conventions is to make it simpler for block explorers and indexers to parse the data in the note fields and filter transactions of certain dApps.

## Specification

Note fields should be formatted as follows:

for dApps
```
<dapp-name>:<data-format><data>
```

for ARCs
```
arc<arc-number>:<data-format><data>
```

where:
* `<dapp-name>` is the name of the dApp:
    * Regexp to satisfy: `[a-zA-Z0-9][a-zA-Z0-9_/@.-]{4-31}`
      In other words, a name should:
         * only contain alphanumerical characters or `_`, `/`, `-`, `@`, `.`
         * start with an alphanumerical character
         * be at least 5 characters long
         * be at most 32 characters long
    * Names starting with `a/` and `af/` are reserved for the Algorand protocol and the Algorand Foundation uses.

* `<arc-number>` is the number of the ARC:
    * Regexp to satisfy: `\b(0|[1-9]\d*)\b`
      In other words, an arc-number should:
        * Only contain a digit number, without any padding

* `<data-format>` is one of the following:
    * `m`: <a href="https://msgpack.org">MsgPack</a>
    * `j`: <a href="https://json.org">JSON</a>
    * `b`: arbitrary bytes
    * `u`: utf-8 string
* `<data>` is the actual data in the format specified by `<data-format>`

**WARNING**: Any user can create transactions with arbitrary data and may impersonate other dApps. In particular, the fact that a note field start with `<dapp-name>` does not guarantee that it indeed comes from this dApp. The value `<dapp-name>` cannot be relied upon to ensure provenance and validity of the `<data>`.

**WARNING**: Any user can create transactions with arbitrary data, including ARC numbers, which may not correspond to the intended standard. An ARC number included in a note field does not ensure compliance with the corresponding standard. The value of the ARC number cannot be relied upon to ensure the provenance and validity of the <data>.

### Versioning

This document suggests the following convention for the names of dApp with multiple versions: `mydapp/v1`, `mydapp/v2`, ... However, dApps are free to use any other convention and may include the version inside the `<data>` part instead of the `<dapp-name>` part.

## Rationale

The goal of these conventions is to facilitate displaying notes by block explorers and filtering of transactions by notes. However, the note field **cannot be trusted**, as any user can create transactions with arbitrary note fields. An external mechanism needs to be used to ensure the validity and provenance of the data. For example:

* Some dApps may only send transactions from a small set of accounts controlled by the dApps. In that case, the sender of the transaction should be checked.
* Some dApps may fund escrow accounts created from some template TEAL script. In that case, the note field may contain the template parameters and the escrow account address should be checked to correspond to the resulting TEAL script.
* Some dApps may include a signature in the `<data>` part of the note field. The `<data>` may be an MsgPack encoding of a structure of the form:
    ```json
    {
        "d": ... // actual data
        "sig": ... // signature of the actual data (encoded using MsgPack)
    }
    ```
    In that case, the signature should be checked.

The conventions were designed to support multiple use cases of the notes. Some dApps may just record data on the blockchain without using any smart contracts. Such dApps typically would use JSON or MsgPack encoding.

On the other hands, dApps that need reading note fields from smart contracts most likely would require easier-to-parse formats of data, which would most likely consist in application-specific byte strings.

Since `<dapp-name>:` is a prefix of the note, transactions for a given dApp can easily be filtered by the <a href="https://github.com/algorand/indexer">indexer</a> ().

The restrictions on dApp names were chosen to allow most usual names while avoiding any encoding or displaying issues. The maximum length (32) matches the maximum length of ASA on Algorand, while the minimum length (5) has been chosen to limit collisions.

## Reference Implementation

> This section is non-normative.

Consider [ARC-20](./arc-0020.md), that provides information about Smart ASA's Application.

Here a potential note indicating that the Application ID is 123:

* JSON without version:
    ```
    arc20:j{"application-id":123}
    ```

Consider a dApp named `algoCityTemp` that stores temperatures from cities on the blockchain.

Here are some potential notes indicating that Singapore's temperature is 35 degree Celsius:
* JSON without version:
    ```
    algoCityTemp:j{"city":"Singapore","temp":35}
    ```
* JSON with version in the name:
    ```
    algoCityTemp/v1:j{"city":"Singapore","temp":35}
    ```
* JSON with version in the name with index lookup:
    ```
    algoCityTemp/v1/35:j{"city":"Singapore","temp":35}
    ```
* JSON with version in the data:
    ```
    algoCityTemp:j{"city":"Singapore","temp":35,"ver":1}
    ```
* UTF-8 string without version:
    ```
    algoCityTemp:uSingapore|35
    ```
* Bytes where the temperature is encoded as a signed 1-byte integer in the first position:
    ```
    algoCityTemp:b#Singapore
    ```
    (`#` is the ASCII character for 35.)
* MsgPack corresponding to the JSON example with version in the name. The string is encoded in base64 as it contains characters that cannot be printed in this document. But the note should contain the actual bytes and not the base64 encoding of them:
    ```
    YWxnb0NpdHlUZW1wL3YxOoKkY2l0ealTaW5nYXBvcmWkdGVtcBg=
    ```

## Security Considerations
> Not Applicable

## Copyright

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

```

--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/developer:docs:run-a-node:setup:types.md:
--------------------------------------------------------------------------------

```markdown
title: Algorand node types

The Algorand network is comprised of two distinct types of nodes, **relay nodes**, and **non-relay nodes**. Relay nodes are primarily used for communication routing to a set of connected non-relay nodes. Relay nodes communicate with other relay nodes and route blocks to all connected non-relay nodes. Non-relay nodes only connect to relay nodes and can also participate in consensus. Non-relay nodes may connect to several relay nodes but never connect to another non-relay node.

In addition to the two node types, nodes can be configured to be [**archival**](#archival-mode). Archival nodes store the entire ledger, as opposed to the last 1000 blocks for non-archival blocks. Relay nodes are necessarily archival. Non-relay archival nodes are often used to feed an [**indexer**](../indexer/) that allows more advanced queries on the history of the blockchain.

Finally, a node may either participate in consensus or not. Participation nodes do not need to be archival. In addition, to reduce attack surfaces and outage risks, it is strongly recommended that participation nodes are only used for the purpose in participating in consensus. In particular, participation nodes should not be relays.

All node types use the same install procedure. To setup a node for a specific type, requires a few configuration parameter changes or operations as described below. The default install will set the node up as a non-relay non-archival non-participation mode.

The table below is a summary of possible configurations:

| Relay? | Archival? | Participation? | |
|-|-|-|-|
| relay | archival | participation | ❌ insecure / strongly discouraged |
| relay | archival | non-participation | ✅ normal configuration for a **relay** |
| relay | non-archival | * | ❌ impossible |
| non-relay | archival | participation | ❓ discouraged, as participation nodes do not need to be archival and should only be used for participation, and not used for any other purpose |
| non-relay | archival | non-participation | ✅ normal configuration for an **archival node**, often connected to an [**indexer**](../indexer/) |
| non-relay | non-archival | participation | ✅ normal configuration for a **participation node** |
| non-relay | non-archival | non-particiption | ✅ normal configuration for a node used to submit transactions to the blockchain and access current state (current balances, smart contract state, ...) but no historical state |


# Which mode do I need?

Here are some common use cases:

* I want to participate in consensus and help secure the Algorand network.
    * ➥ non-relay non-archival participation node.
    * Note: I need to have some Algos for that purpose and I need to monitor my node 24/7 to ensure it is working properly.
* I want to send transactions and read current state of smart contracts/applications:
    * ➥ non-relay non-archival non-participation node.
    * Example: a dApp website that does not use any historical information (past transaction/operation), a website displaying balances of a list of important accounts.
* I want full access to historical data (blocks, transactions) with advanced querying:
    * ➥ non-relay archival non-participation node, together with an [**indexer**](../indexer/).
* I want to get state proofs for any block:
    * ➥ non-relay archival non-participation node.

# Participation Node 
How to install a node is described [here](../install/).  Classifying a node as a participation node is not a configuration parameter but a dynamic operation where the node is hosting participation keys for one or more online accounts. This process is described in [Participate in Consensus](../participate/index.md). Technically both non-relay and relay nodes can participate in consensus, but Algorand recommends *only* non-relay nodes participate in consensus. 

!!! info
    Non-relay nodes do not have to participate in consensus. They still have access to the ledger and can be used with applications that need to connect to the network to submit transactions and read block data. 


# Archival Mode

By default non-relay nodes only store a limited number of blocks (approximately up to the last 1000 blocks) locally. Older blocks are dropped from the local copy of the ledger. This reduces the disk space requirement of the node. These nodes can still participate in consensus and applications can connect to these nodes for transaction submission and reading block data. The primary drawback for this type of operation is that older block data will not be available.

The archival property must be set to true to run in archival mode, which will then set the node to store the entire ledger.

!!! warning
     Setting a node to run in archival mode on MainNet/TestNet/BetaNet will significantly increase the disk space requirements for the node. For example, in September 2023, a MainNet non-archival node uses around 20GB of storage, while an archival node requires approximately 2TB of storage.


!!! info
    Relay nodes are always set to Archival mode. Non-relay nodes have the option to run in either configuration.

# Relay Node

A relay node uses the same software install as a non-relay node and only requires setting a few additional configuration parameters.

A node is a valid relay node if two things are true:

1. The node is configured to accept incoming connections on a publicly-accessible port (4160 by convention on MainNet, and 4161 on TestNet, except if behind a proxy in which case port 80 is used.).
2. The node's public IP address (or a valid DNS name) and assigned port are registered in Algorand's SRV records for a specific network (MainNet/TestNet).
   
Relay nodes are where other nodes connect. Therefore, a relay node must be able to support a large number of connections and handle the processing load associated with all the data flowing to and from these connections. Thus, relay nodes require significantly more power than non-relay nodes. Relay nodes are always configured in archival mode.

Relay nodes also require very high egress bandwidth. In October 2022, MainNet relay nodes egress bandwidth is between 10TB to 30TB per month.

See [Configuring Node as a Relay](../../reference/relay) for more information on setting up a relay.






```

--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/developer:docs:run-a-node:participate:generate_keys.md:
--------------------------------------------------------------------------------

```markdown
title: Generate a participation key

Algorand provides a set of keys for voting and proposing blocks separate from account spending keys. These are called **participation keys** (sometimes referred to as **partkeys**).  At a high-level, participation keys are a specialized set of keys located on a single node. Once this participation key set is associated with an account, the account has the ability to participate in consensus. 

_[Read more about how Participation Keys function in the Algorand Consensus Protocol](../../../get-details/algorand_consensus#participation-keys)._

!!! info "Important"
	- The account’s private spending key does not need to be on the node to generate a participation key. Technically, anyone can generate a participation key for a particular account, but only the private spending key of the account can authorize the transaction that would register the account to go online with a particular participation key. This distinction allows you to keep private keys in cold storage.
	- For security, the individual keys for each round are deleted from the key file as each round is completed. It is critical for the safety of the Algorand blockchain to avoid storing backups of participation key files that have been registered for an account.  
	- The limit to the range you can specify for a partkey validity period is 2^24 - 1 (16,777,215). For security, it is recommended that the range does not exceed 3,000,000 rounds.

# Generate the participation key with `goal`

To generate a participation key, use the [`goal account addpartkey`](../../../clis/goal/account/addpartkey) command on the node where the participation key will reside. This command takes the address of the participating account, a range of rounds, and an optional key dilution parameter.  It then generates a [VRF key pair](../../../get-details/algorand_consensus#verifiable-random-function) and, using optimizations, generates a set of single-round voting keys for each round of the range specified. The VRF private key is what is passed into the VRF to determine if you are selected to propose or vote on a block in any given round. 

=== "goal"
    ```zsh 
    $ goal account addpartkey -a <address-of-participating-account> --roundFirstValid=<partkey-first-round> --roundLastValid=<partkey-last-round>
    Participation key generation successful
    ```

This creates a participation key on the node. You can use the `-o` flag to specify a different location in the case where you will eventually transfer your key to a different node to construct the keyreg transaction.

!!! tip
	To optimize storage, the Key Dilution parameter defaults to the square root of the participation period length but this can be overridden with the flag `--keyDilution`. The Key Dilution determines how many ephemeral keys will be stored on an algorand node, as they are generated in batches. For example, if your participation period is set to 3,000,000 rounds, a batch of 1,732 ephemeral keys will be generated upfront, with additional batches getting generated after each set is used.

# Add participation key

If you chose to save the participation key and now want to add it to the server, you can use the following command to add the partkey file to the node.

```bash
$ goal account installpartkey --partkey ALICE...VWXYZ.0.30000.partkey --delete-input
```

# Check that the key exists

The [`goal account listpartkeys`](../../../clis/goal/account/listpartkeys) command will check for any participation keys that live on the node and display pertinent information about them. 

=== "goal"
    ```zsh
    $ goal account listpartkeys
    Registered  Account      ParticipationID   Last Used  First round  Last round
    yes         TUQ4...NLQQ  GOWHR456...              27            0     3000000
    ```


The output above is an example of `goal account listpartkeys` run from a particular node. It displays all partkeys and whether or not each key has been **registered**, the **filename** of the participation key, the **first** and **last** rounds of validity for the partkey, the **parent address** (i.e. the address of the participating account) and the **first key**. The first key refers to the key batch and the index in that batch (`<key-batch>.<index>`) of the latest key that has not been deleted. This is useful in verifying that your node is participating (i.e. the batch should continue to increment as keys are deleted). It can also help ensure that you don't store extra copies of registered participation keys that have past round keys intact. 


!!! warning
	It is okay to have multiple participation keys on a single node. However, if you generate multiple participation keys for the same account with overlapping rounds make sure you are aware of which one is the active one. It is recommended that you only keep one key per account - the active one - _except_ during partkey renewal when you switch from the old key to the new key. Renewing participation keys is discussed in detail in the [Renew Participation Keys](./renew.md) section.

# View participation key info

Use [`goal account partkeyinfo`](../../../clis/goal/account/partkeyinfo) to dump all the information about each participation key that lives on the node. This information is used to generate the online key registration transaction [described in the next section](./online.md).

=== "goal"
    ```zsh
    $ goal account partkeyinfo
    Dumping participation key info from /opt/data...

    Participation ID:          GOWHR456IK3LPU5KIJ66CRDLZM55MYV2OGNW7QTZYF5RNZEVS33A
    Parent address:            TUQ4HOIR3G5Z3BZUN2W2XTWVJ3AUUME4OKLINJFAGKBO4Y76L4UT5WNLQQ
    Last vote round:           11
    Last block proposal round: 12
    Effective first round:     1
    Effective last round:      3000000
    First round:               0
    Last round:                3000000
    Key dilution:              10000
    Selection key:             l6MsaTt7AiCAdG+69LG/wjaprsI1vImZuGN6gQ1jS88=
    Voting key:                Rleu99r3UqlwuuhaxCTrTQUuq1C9qk5uJd2WQQEG+6U=
    ```


Above is the example output from a particular node. Use these values to create the [key registration transaction](../../../get-details/transactions#register-account-online) that will place the account online.

```

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

```markdown
---
arc: 35
title: Algorand Offline Wallet Backup Protocol
description: Wallet-agnostic backup protocol for multiple accounts
author: Yigit Guler (@yigitguler)
discussions-to: https://github.com/algorandfoundation/ARCs/issues/156
status: Final
type: Standards Track
category: Interface
sub-category: Wallet
created: 2023-01-03
---
# Algorand Secure Offline Wallet Backup Protocol


## Abstract
This document outlines the high-level requirements for a wallet-agnostic backup protocol that can be used across all wallets on the Algorand ecosystem.

## 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>.

### Requirements
At a high-level, offline wallet backup protocol has the following requirements:

 * Wallet applications should allow backing up and storing multiple accounts at the same time.
Account information should be encrypted with a user-defined secret key, utilizing NaCl SecretBox method (audited and endorsed by Algorand).

 * Encrypted final string should be easily copyable to be stored digitally.
When importing, wallet applications should be able to detect already imported accounts and gracefully ignore them.

### Format

Before encryption, account information should be converted to the following JSON format:

```
{
  "device_id": "UNIQUE IDENTIFIER FOR DEVICE (OPTIONAL)",
  "provider_name": "PROVIDER NAME (OPTIONAL, i.e. Pera Wallet)",
  "accounts": [
    {
      "address": "ACCOUNT PUBLIC ADDRESS (REQUIRED)",
      "name": "USER DEFINED ACCOUNT NAME (OPTIONAL)",
      "account_type": "TYPE OF ACCOUNT: single, multisig, watch, contact, ledger (REQUIRED)",
    "private_key": "PRIVATE KEY AS BASE64 ENCODING OF 64 BYTE ALGORAND PRIVATE KEY as encoded by algosdk (NOT PASSPHRASE, REQUIRED for user-owned accounts, can be omitted in case of watch, contact, multisig, ledger accounts)",
      "metadata": "ANY ADDITIONAL CONTENT (OPTIONAL)",
      "multisig": "Multisig information (only required if the account_type is multisig)",
      "ledger": {
        "device_id": "device id",
        "index": <index of the account on device, integer>,
        "connection_type": "bluetooth|usb"
      },
    },
    ...
  ]
}
```

*Clients must accept additional fields in the JSON document.*

Here is an example with a single account:

```
{
  "device_id": "2498232091970170817",
  "provider_name": "Pera Wallet",
  "accounts": [
    {
      "address": "ELWRE6HZ7KIUT46EQ6PBISGD3ND6QSCBVWICYR2QR2Y7LOBRZRCAIKLWDE",
      "name": "My NFT Account",
      "account_type": "single",
      "private_key": "w0HG2VH7tAYz9PD4SYX0flC4CKh1OONCB6U5bP7cXGci7RJ4+fqRSfPEh54USMPbR+hIQa2QLEdQjrH1uDHMRA=="
    }
  ],
}
```

Here is an example with a single multi-sig account:

```
{
  "device_id": "2498232091970170817",
  "provider_name": "Pera Wallet",
  "accounts": [
    {
      "address": "ELWRE6HZ7KIUT46EQ6PBISGD3ND6QSCBVWICYR2QR2Y7LOBRZRCAIKLWDE",
      "name": "Our Multisig Account",
      "account_type": "multisig",
      "multisig": {
        version: 1,
        threshold: 2,
        addrs: [
            account1.addr,
            account2.addr,
            account3.addr,
            ],
     },
    }
  ],
}
```

### Encryption

Once the input JSON is ready, as specified above, it needs to be encrypted. Even if it is assumed that the user is going to store this information in a secure location, copy-pasting it without encryption is not secure since multiple applications can access the clipboard.

The information needs to be encrypted using a very long passphrase. 12 words mnemonic will be used as the key. 12-word mnemonic is secure and it will not create confusion with the 25-word mnemonics that are used to encrypt accounts.

The wallet applications should not allow users to copy the 12-word mnemonic nor allow taking screenshots. The users should note it visually.

The encryption should be made as follows:

1. The wallet generates a random 16-byte string S (using a cryptographically secure random number generator)
2. The wallet derives a 32-byte key: `key = HMAC-SHA256(key="Algorand export 1.0", input=S)`
    On libsodium, use https://libsodium.gitbook.io/doc/advanced/hmac-sha2#hmac-sha-256,
    `crypto_auth_hmacsha256_init` / `crypto_auth_hmacsha256_update` / `crypto_auth_hmacsha256_final`
3. The wallet encrypts the input JSON using `crypto_secretbox_easy` from libsodium (https://libsodium.gitbook.io/doc/secret-key_cryptography/secretbox)
4. The wallet outputs the following output JSON:

```
{
  "version": "1.0",
  "suite": "HMAC-SHA256:sodium_secretbox_easy",
  "ciphertext": <base64 of the ciphertext>
}
```

This JSON document (will be referred as ciphertext envelope JSON) needs to be encoded with base64 again in order to make it easier to copy-paste & store.

5. S is encoded as a 12-word mnemonic (according to BIP-39) and displayed to the user.

The user will be responsible for keeping the 12-word mnemonic and the base64 output of the ciphertext envelope JSON in safe locations. Note that step 5 is the default approach, however, the wallets can support other methods other than mnemonics as well, as long as they are secure.


### Importing
When importing, wallet applications should ask the user for the base64 output of the envelope JSON and the 12-word mnemonic. After getting these values, it should attempt to decrypt the encrypted string using the 12-word mnemonic. On successful decryption, accounts that can be imported can be processed.

## Rationale
There are many benefits to having an openly documented format:

 * Better interoperability across wallets, allowing users to use multiple wallets easily by importing all of their accounts using a single format.

 * Easy and secure backup of all wallet data at a user-defined location, including secure storage in digital environments.

 * Ability to transfer data from device to device securely, such as when moving data from one mobile device to another.


## Security Considerations
Tbd

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

```

--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/developers-clis.txt:
--------------------------------------------------------------------------------

```
developer:docs:clis:kmd.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:processors.md
developer:docs:clis:conduit:list:list.md
developer:docs:clis:conduit:list:importers.md
developer:docs:clis:tealdbg:debug.md
developer:docs:clis:tealdbg:tealdbg.md
developer:docs:clis:tealdbg:remote.md
developer:docs:clis:diagcfg:diagcfg.md
developer:docs:clis:diagcfg:telemetry:endpoint.md
developer:docs:clis:diagcfg:telemetry:disable.md
developer:docs:clis:diagcfg:telemetry:status.md
developer:docs:clis:diagcfg:telemetry:name.md
developer:docs:clis:diagcfg:telemetry:enable.md
developer:docs:clis:diagcfg:telemetry:telemetry.md
developer:docs:clis:diagcfg:metric:metric.md
developer:docs:clis:diagcfg:metric:disable.md
developer:docs:clis:diagcfg:metric:status.md
developer:docs:clis:diagcfg:metric:enable.md
developer:docs:clis:algokey:multisig:append-auth-addr.md
developer:docs:clis:algokey:multisig:multisig.md
developer:docs:clis:algokey:sign.md
developer:docs:clis:algokey:generate.md
developer:docs:clis:algokey:algokey.md
developer:docs:clis:algokey:import.md
developer:docs:clis:algokey:part:reparent.md
developer:docs:clis:algokey:part:part.md
developer:docs:clis:algokey:part:info.md
developer:docs:clis:algokey:part:generate.md
developer:docs:clis:algokey:part:keyreg.md
developer:docs:clis:algokey:export.md
developer:docs:clis:indexer:indexer.md
developer:docs:clis:indexer:api-config.md
developer:docs:clis:indexer:util:validator.md
developer:docs:clis:indexer:util:util.md
developer:docs:clis:indexer:daemon.md
developer:docs:clis:goal:license.md
developer:docs:clis:goal:ledger:supply.md
developer:docs:clis:goal:ledger:block.md
developer:docs:clis:goal:ledger:ledger.md
developer:docs:clis:goal:app:method.md
developer:docs:clis:goal:app:app.md
developer:docs:clis:goal:app:closeout.md
developer:docs:clis:goal:app:box:info.md
developer:docs:clis:goal:app:box:list.md
developer:docs:clis:goal:app:box:box.md
developer:docs:clis:goal:app:read.md
developer:docs:clis:goal:app:info.md
developer:docs:clis:goal:app:call.md
developer:docs:clis:goal:app:clear.md
developer:docs:clis:goal:app:create.md
developer:docs:clis:goal:app:delete.md
developer:docs:clis:goal:app:update.md
developer:docs:clis:goal:app:optin.md
developer:docs:clis:goal:app:interact:interact.md
developer:docs:clis:goal:app:interact:query.md
developer:docs:clis:goal:app:interact:execute.md
developer:docs:clis:goal:asset:freeze.md
developer:docs:clis:goal:asset:info.md
developer:docs:clis:goal:asset:config.md
developer:docs:clis:goal:asset:asset.md
developer:docs:clis:goal:asset:destroy.md
developer:docs:clis:goal:asset:create.md
developer:docs:clis:goal:asset:optin.md
developer:docs:clis:goal:asset:send.md
developer:docs:clis:goal:report.md
developer:docs:clis:goal:network:network.md
developer:docs:clis:goal:network:pregen.md
developer:docs:clis:goal:network:restart.md
developer:docs:clis:goal:network:status.md
developer:docs:clis:goal:network:create.md
developer:docs:clis:goal:network:delete.md
developer:docs:clis:goal:network:start.md
developer:docs:clis:goal:network:stop.md
developer:docs:clis:goal:goal.md
developer:docs:clis:goal:completion:completion.md
developer:docs:clis:goal:completion:zsh.md
developer:docs:clis:goal:completion:bash.md
developer:docs:clis:goal:kmd:kmd.md
developer:docs:clis:goal:kmd:start.md
developer:docs:clis:goal:kmd:stop.md
developer:docs:clis:goal:version.md
developer:docs:clis:goal:wallet:new.md
developer:docs:clis:goal:wallet:wallet.md
developer:docs:clis:goal:wallet:list.md
developer:docs:clis:goal:node:generatetoken.md
developer:docs:clis:goal:node:pendingtxns.md
developer:docs:clis:goal:node:restart.md
developer:docs:clis:goal:node:clone.md
developer:docs:clis:goal:node:status.md
developer:docs:clis:goal:node:generate-p2pid.md
developer:docs:clis:goal:node:node.md
developer:docs:clis:goal:node:lastround.md
developer:docs:clis:goal:node:create.md
developer:docs:clis:goal:node:catchup.md
developer:docs:clis:goal:node:start.md
developer:docs:clis:goal:node:wait.md
developer:docs:clis:goal:node:stop.md
developer:docs:clis:goal:account:assetdetails.md
developer:docs:clis:goal:account:rewards.md
developer:docs:clis:goal:account:new.md
developer:docs:clis:goal:account:dump.md
developer:docs:clis:goal:account:addpartkey.md
developer:docs:clis:goal:account:importrootkey.md
developer:docs:clis:goal:account:listpartkeys.md
developer:docs:clis:goal:account:balance.md
developer:docs:clis:goal:account:account.md
developer:docs:clis:goal:account:multisig:new.md
developer:docs:clis:goal:account:multisig:info.md
developer:docs:clis:goal:account:multisig:delete.md
developer:docs:clis:goal:account:multisig:multisig.md
developer:docs:clis:goal:account:renewpartkey.md
developer:docs:clis:goal:account:info.md
developer:docs:clis:goal:account:installpartkey.md
developer:docs:clis:goal:account:list.md
developer:docs:clis:goal:account:renewallpartkeys.md
developer:docs:clis:goal:account:marknonparticipating.md
developer:docs:clis:goal:account:rename.md
developer:docs:clis:goal:account:partkeyinfo.md
developer:docs:clis:goal:account:import.md
developer:docs:clis:goal:account:delete.md
developer:docs:clis:goal:account:changeonlinestatus.md
developer:docs:clis:goal:account:export.md
developer:docs:clis:goal:account:deletepartkey.md
developer:docs:clis:goal:clerk:compile.md
developer:docs:clis:goal:clerk:group.md
developer:docs:clis:goal:clerk:inspect.md
developer:docs:clis:goal:clerk:split.md
developer:docs:clis:goal:clerk:rawsend.md
developer:docs:clis:goal:clerk:dryrun.md
developer:docs:clis:goal:clerk:multisig:sign.md
developer:docs:clis:goal:clerk:multisig:merge.md
developer:docs:clis:goal:clerk:multisig:signprogram.md
developer:docs:clis:goal:clerk:multisig:multisig.md
developer:docs:clis:goal:clerk:tealsign.md
developer:docs:clis:goal:clerk:dryrun-remote.md
developer:docs:clis:goal:clerk:sign.md
developer:docs:clis:goal:clerk:clerk.md
developer:docs:clis:goal:clerk:send.md
developer:docs:clis:goal:clerk:simulate.md
developer:docs:clis:goal:logging:disable.md
developer:docs:clis:goal:logging:enable.md
developer:docs:clis:goal:logging:logging.md
developer:docs:clis:goal:logging:send.md
developer:docs:clis:goal:protocols.md
```

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

```markdown
title: IPFS Pinning With Crust

## IPFS
Algorand offers [various ways to store data in contracts](../dapps/smart-contracts/apps/state/), but there are still many use cases where storing the data off-chain makes more sense. This is paticularly true when the data is large and not used directly on-chain (for example, NFT metadata and images). A common solution for off-chain data storage is the InterPlanetary File System (IPFS) protocol. In short, IPFS is a peer-to-peer file sharing protocol. For more information on IPFS, see https://docs.ipfs.tech/concepts/faq/.

In order to share files via IPFS, one must pin a file on the network. Pinning a file means assigning it a unique Content Identifier (CID) and making it availible to download. It is common for developers to use a pinning service like Pinata, web3.storage, or nft.storage. While these services do indeed pin the file on IPFS, they are still using centralized servers to do so. This means those using these services are dependend on them to keep running them and are locked into their pricing model.


## Crust

To avoid using centralized services for IPFS pinning, Algorand developers can use the Crust network. Crust is a decentralized pinning service where users can pay the network to pin a file and that file will be pinned on many servers around the world. The pricing model is set by the node runners, rather than a single entity. For more information on Crust, see https://crust.network/faq/.

## Crust and Algorand

Crust is easier than ever to use for Algorand developers because you can pay for storage via ABI method calls to the Crust contracts deployed on testnet and mainnet. 

### Deployments
Testnet storage contract application ID: [507867511](https://testnet.explorer.perawallet.app/application/507867511/)

Mainnet storage contract application ID: [1275319623](https://explorer.perawallet.app/application/1275319623/)


### Usage

The easiest way to use the Crust storage contract is to use the ARC32 `application.json` that was generated by the beaker contract. The JSON and full source can be found at https://github.com/crustio/algorand-storage-contract.

The general process is:

1. Build web3 authentication header
2. Upload files to IPFS
3. Get storage price
4. Place storage order

#### Building Header

```ts
/**
 * Generate a web3 auth header from an Algorand account
 */
function getAuthHeader(account: algosdk.Account) {
    const sk32 = account.sk.slice(0, 32)
    const signingKey = nacl.sign.keyPair.fromSeed(sk32)

    const signature = nacl.sign(Buffer.from(account.addr), signingKey.secretKey)
    const sigHex = Buffer.from(signature).toString('hex').slice(0, 128)
    const authStr = `sub-${account.addr}:0x${sigHex}`

    return Buffer.from(authStr).toString('base64')
}
```

#### Upload to IPFS

```ts
/**
 * upload a file to IPFS and get its CID and size
 * 
 * @param account Account to use to generate the auth header
 */
async function uploadToIPFS(account: algosdk.Account) {
    // Note: Not all gateways require this header
    const headers = {
        "Authorization": `Basic ${getAuthHeader(account)}`
    }

    // list of API hosts
    // https://github.com/crustio/crust-apps/blob/master/packages/apps-config/src/ipfs-gateway-endpoints/index.ts
    const apiEndpoint = 'https://gw-seattle.crustcloud.io:443/api/v0/add'

    // If you're in browser, you should be able to just use a file directly
    const formData = new FormData();
    formData.append('README.md', fs.createReadStream('./README.md'));


    const res = await axios.post(apiEndpoint, formData, {
        headers: {
            ...headers,
            // formData.getHeaders() is only required if you're using nodejs
            ...formData.getHeaders()
        }
    });

    const json: { Hash: string, Size: number } = await res.data

    return { cid: json.Hash, size: Number(json.Size) }
}
```

#### Get Storage Price

```ts
/**
 * Gets the required price to store a file of a given size
 * 
 * @param algod Algod client to use to simulate the ABI method call
 * @param appClient App client to use to compose the ABI method call
 * @param size Size of the file
 * @param isPermanent Whether the file should be added to the renewal pool
 * @returns Price, in uALGO, to store the file
 */
async function getPrice(algod: algosdk.Algodv2, appClient: StorageOrderClient, size: number, isPermanent: boolean = false) {
    const result = await (await appClient.compose().getPrice({ size, is_permanent: isPermanent }).atc()).simulate(algod)

    return result.methodResults[0].returnValue?.valueOf() as number
}
```

#### Place Order

```ts
/**
 * Uses simulate to get a random order node from the storage contract
 * 
 * @param algod Algod client to use to simulate the ABI method call
 * @param appClient The app client to use to compose the ABI method call
 * @returns Address of the order node
 */
async function getOrderNode(algod: algosdk.Algodv2, appClient: StorageOrderClient) {
    return (await (await appClient.compose().getRandomOrderNode({}, { boxes: [new Uint8Array(Buffer.from('nodes'))] }).atc()).simulate(algod)).methodResults[0].returnValue?.valueOf() as string
}

/**
 * Places a storage order for a CID
 * 
 * @param algod Algod client used to get transaction params
 * @param appClient App client used to call the storage app
 * @param account Account used to send the transactions
 * @param cid CID of the file
 * @param size Size of the file
 * @param price Price, in uALGO, to store the file
 * @param isPermanent Whether the file should be added to the renewal pool
 */
async function placeOrder(
    algod: algosdk.Algodv2,
    appClient: StorageOrderClient,
    account: algosdk.Account,
    cid: string,
    size: number,
    price: number,
    isPermanent: boolean
) {
    const merchant = await getOrderNode(algod, appClient)
    const seed = algosdk.makePaymentTxnWithSuggestedParamsFromObject({
        from: account.addr,
        to: (await appClient.appClient.getAppReference()).appAddress,
        amount: price,
        suggestedParams: await algod.getTransactionParams().do(),
    });

    appClient.placeOrder({ seed, cid, size, is_permanent: isPermanent, merchant })
}
```

#### Full Examples

To see the full scripts that use the above functions go to https://github.com/algorand-devrel/crust-examples

```

--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/puya:docs:lg-calling-apps.md:
--------------------------------------------------------------------------------

```markdown
# Calling other applications

The preferred way to call other smart contracts is using [`algopy.arc4.abi_call`](#algopyarc4abi_call), [`algopy.arc4.arc4_create`](#algopyarc4arc4_create) or 
[`algopy.arc4.arc4_update`](#algopyarc4arc4_update). These methods support type checking and encoding of arguments, decoding of results, group transactions,
and in the case of `arc4_create` and `arc4_update` automatic inclusion of approval and clear state programs.

## `algopy.arc4.abi_call`

[`algopy.arc4.abi_call`](#algopy.arc4.abi_call) can be used to call other ARC4 contracts, the first argument should refer to
an ARC4 method either by referencing an Algorand Python [`algopy.arc4.ARC4Contract`](#algopy.arc4.ARC4Contract) method,
an [`algopy.arc4.ARC4Client`](#algopy.arc4.ARC4Client) method generated from an ARC-32 app spec, or a string representing
the ARC4 method signature or name.
The following arguments should then be the arguments required for the call, these arguments will be type checked and converted where appropriate.
Any other related transaction parameters such as `app_id`, `fee` etc. can also be provided as keyword arguments.

If the ARC4 method returns an ARC4 result then the result will be a tuple of the ARC4 result and the inner transaction.
If the ARC4 method does not return a result, or if the result type is not fully qualified then just the inner transaction is returned.

```python
from algopy import Application, ARC4Contract, String, arc4, subroutine

class HelloWorld(ARC4Contract):
    
    @arc4.abimethod()
    def greet(self, name: String) -> String:
        return "Hello " + name

@subroutine
def call_existing_application(app: Application) -> None:
    greeting, greet_txn = arc4.abi_call(HelloWorld.greet, "there", app_id=app)
    
    assert greeting == "Hello there"
    assert greet_txn.app_id == 1234
```


### Alternative ways to use `arc4.abi_call`

#### ARC4Client method 

A ARC4Client client represents the ARC4 abimethods of a smart contract and can be used to call abimethods in a type safe way

ARC4Client's can be produced by using `puyapy --output-client=True` when compiling a smart contract 
(this would be useful if you wanted to publish a client for consumption by other smart contracts)
An ARC4Client can also be be generated from an ARC-32 application.json using `puyapy-clientgen` 
e.g. `puyapy-clientgen examples/hello_world_arc4/out/HelloWorldContract.arc32.json`, this would be
the recommended approach for calling another smart contract that is not written in Algorand Python or does not provide the source

```python
from algopy import arc4, subroutine

class HelloWorldClient(arc4.ARC4Client):
    
    def hello(self, name: arc4.String) -> arc4.String: ...

@subroutine
def call_another_contract() -> None:
    # can reference another algopy contract method
    result, txn = arc4.abi_call(HelloWorldClient.hello, arc4.String("World"), app=...)
    assert result == "Hello, World"
```

#### Method signature or name

An ARC4 method selector can be used e.g. `"hello(string)string` along with a type index to specify the return type.
Additionally just a name can be provided and the method signature will be inferred e.g.

```python
from algopy import arc4, subroutine


@subroutine
def call_another_contract() -> None:
    # can reference a method selector
    result, txn = arc4.abi_call[arc4.String]("hello(string)string", arc4.String("Algo"), app=...)
    assert result == "Hello, Algo"
    
    # can reference a method name, the method selector is inferred from arguments and return type
    result, txn = arc4.abi_call[arc4.String]("hello", "There", app=...)
    assert result == "Hello, There"
```


## `algopy.arc4.arc4_create`

[`algopy.arc4.arc4_create`](#algopy.arc4.arc4_create) can be used to create ARC4 applications, and will automatically populate required fields for app creation (such as approval program, clear state program, and global/local state allocation).

Like [`algopy.arc4.abi_call`](lg-transactions.md#arc4-application-calls) it handles ARC4 arguments and provides ARC4 return values.

If the compiled programs and state allocation fields need to be customized (for example due to [template variables](#within-other-contracts)), 
this can be done by passing a [`algopy.CompiledContract`](#algopy.CompiledContract) via the `compiled` keyword argument.

```python
from algopy import ARC4Contract, String, arc4, subroutine

class HelloWorld(ARC4Contract):
    
    @arc4.abimethod()
    def greet(self, name: String) -> String:
        return "Hello " + name

@subroutine
def create_new_application() -> None:
    hello_world_app = arc4.arc4_create(HelloWorld).created_app

    greeting, _txn = arc4.abi_call(HelloWorld.greet, "there", app_id=hello_world_app)
    
    assert greeting == "Hello there"
```

## `algopy.arc4.arc4_update`

[`algopy.arc4.arc4_update`](#algopy.arc4.arc4_update) is used to update an existing ARC4 application and will automatically populate the required approval and clear state program fields.

Like [`algopy.arc4.abi_call`](lg-transactions.md#arc4-application-calls) it handles ARC4 arguments and provides ARC4 return values.

If the compiled programs need to be customized (for example due to (for example due to [template variables](#within-other-contracts)), 
this can be done by passing a [`algopy.CompiledContract`](#algopy.CompiledContract) via the `compiled` keyword argument.

```python
from algopy import Application, ARC4Contract, String, arc4, subroutine

class NewApp(ARC4Contract):
    
    @arc4.abimethod()
    def greet(self, name: String) -> String:
        return "Hello " + name

@subroutine
def update_existing_application(existing_app: Application) -> None:
    hello_world_app = arc4.arc4_update(NewApp, app_id=existing_app)
    
    greeting, _txn = arc4.abi_call(NewApp.greet, "there", app_id=hello_world_app)
    
    assert greeting == "Hello there"
```

## Using `itxn.ApplicationCall`

If the application being called is not an ARC4 contract, or an application specification is not available,
then [`algopy.itxn.ApplicationCall`](#algopy.itxn.ApplicationCall) can be used. This approach is generally more verbose
than the above approaches, so should only be used if required. See [here](./lg-transactions.md#create-an-arc4-application-and-then-call-it) for an example 

```

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

```markdown
---
arc: 7
title: Algorand Wallet Post Transactions API
description: API function to Post Signed Transactions to the network.
author: DanBurton (@DanBurton)
discussions-to: https://github.com/algorandfoundation/ARCs/issues/52
status: Deprecated
type: Standards Track
category: Interface
created: 2021-08-09
---

# Algorand Wallet Post Transactions API

## Abstract

A function, `postTxns`, which accepts an array of `SignedTransaction`s, and posts them to the network.

## Specification

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

> Comments like this are non-normative.

This ARC uses interchangeably the terms "throw an error" and "reject a promise with an error".

### Interface `PostTxnsFunction`

```ts
export type TxnID = string;
export type SignedTxnStr = string;

export type PostTxnsFunction = (
  stxns: SignedTxnStr[],
) => Promise<PostTxnsResult>;

export interface PostTxnsResult {
  txnIDs: TxnID[];
}

export interface PostTxnsError extends Error {
  code: number;
  data?: any;
  successTxnIDs: (TxnID | null)[];
}
```

A `PostTxnsFunction` with input argument `stxns:string[]` and promised return value `ret:PostTxnsResult`:
* expects `stxns` to be in the correct string format as specified by `SignedTxnStr` (defined below).
* **MUST**, if successful, return an object `ret` such that `ret.txID` is in the correct string format as specified by `TxID`.

> The use of `txID` instead of `txnID` is to follow the standard name for the transaction ID.

### String specification: `SignedTxnStr`

Defined as in [ARC-0001](./arc-0001.md#interface-signedtxnstr):

> [`SignedTxnStr` is] the base64 encoding of the canonical msgpack encoding of the `SignedTxn` corresponding object, as defined in the <a href="https://github.com/algorandfoundation/specs">Algorand specs</a>.

### String specification: `TxnID`

A `TxnID` is a 52-character base32 string (without padding) corresponding to a 32-byte string.
For example: `H2KKVITXKWL2VBZBWNHSYNU3DBLYBXQAVPFPXBCJ6ZZDVXQPSRTQ`.

### Error standard

`PostTxnsError` follows the same rules as `SignTxnsError` from [ARC-0001](./arc-0001.md#error-interface-signtxnserror) and uses the same status codes as well as the following status codes:


| Status Code | Name | Description |
| ----------- | ---- | ----------- |
| 4400 | Failure Sending Some Transactions | Some transactions were not sent properly. |

### Semantic requirements

Regarding a call to `postTxns(stxns)` with promised return value `ret`:

* `postTxns` **MAY** assume that `stxns` is an array of valid `SignedTxnStr` strings that represent correctly signed transactions such that:
  * Either all transaction belong to the same group of transactions and are in the correct order. In other words, either `stxns` is an array of a single transaction with a zero group ID (`txn.Group`), or `stxns` is an array of one or more transactions with the *same* non-zero group ID. The function **MUST** reject if the transactions do not match their group ID. (The caller must provide the transactions in the order defined by the group ID.)
  >An early draft of this ARC required that the size of a group of transactions must be greater than 1 but, since the Algorand protocol supports groups of size 1, this requirement had been changed so dApps don't have to have special cases for single transactions and can always send a group to the wallet.
  * Or `stxns` is a concatenation of arrays satisfying the above.
* `postTxns` **MUST** attempt to post all transactions together.  With the `algod` v2 API, this implies splitting the transactions into groups and making an API call per transaction group. `postTxns` **SHOULD NOT** wait after each transaction group but post all of them without pause in-between.
* `postTxns` **MAY** ask the user whether they approve posting those transactions.
  > A dApp can always post transactions itself without the help of `postTxns` when a public network is used.
  > However, when a private network is used, a dApp may need `postTxns`, and in this case, asking the user's approval can make sense.
  > Another such use case is when the user uses a specific trusted node that has some legal restrictions.
* `postTxns` **MUST** wait for confirmation that the transactions are finalized.
  > TODO: Decide whether to add an optional flag to not wait for that.
* If successful, `postTxns` **MUST** resolve the returned promise with the list of transaction IDs `txnIDs` of the posted transactions `stxn`.
* If unsuccessful, `postTxns` **MUST** reject the promise with an error `err` of type `PostTxnsError` such that:
  * `err.code=4400` if there was a failure sending the transactions or a code as specified in [ARC-0001](./arc-0001.md#error-standards) if the user or function disallowed posting the transactions.
  * `err.message` **SHOULD** describe what went wrong in as much detail as possible.
  * `err.successTxnIDs` **MUST** be an array such that `err.successTxnID[i]` is the transaction ID of `stxns[i]` if `stxns[i]` was successfully committed to the blockchain, and `null` otherwise.

### Security considerations

In case the wallet uses an API service that is secret or provided by the user, the wallet **MUST** ensure that the URL of the service and the potential tokens/headers are not leaked to the dApp.

> Leakage may happen by accidentally including too much information in responses or errors returned by the various methods. For example, if the Node.JS superagent library is used without filtering errors and responses, errors and responses may include the request object, which includes the potentially secret API service URL / secret token headers.

## Rationale

This API allows DApps to use a user's preferred connection in order to submit transactions to the network.

The user may wish to use a specific trusted node, or a particular paid service with their own secret token. This API protects the user's secrets by not exposing connection details to the DApp.

## Security Considerations

None.

## Copyright

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

```

--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/algokit:cli:architecture-decisions:2023-01-11_brew_install.md:
--------------------------------------------------------------------------------

```markdown
# HomeBrew install strategy

- **Status**: Approved
- **Owner:** Daniel McGregor
- **Deciders**: Daniel McGregor, Rob Moore, John Woods, Alessandro Cappellato
- **Date created**: 2023-01-11
- **Date decided:** 2023-01-11

## Context

HomeBrew (brew) is a MacOS package manager, and is commonly used on MacOS systems to install applications and tools like AlgoKit. Brew offers two main installation methods.

 * Formula - A source based install, this is typically recommended for open source and command line based applications. Formula can also be "bottled" to provide pre built packages for quick installs on supported MacOS platforms.
 * Cask - A binary based install, this is typically recommended for closed source or GUI based applications.

Additionally there are also two options for how the brew install scripts could be distributed.

* Homebrew repository - This is the official repository for homebrew installs, and provides bottle support for all moderns MacOS platforms (MacOS 11+, Intel and ARM)
* Algorand hosted repository - A homebrew repository managed by Algorand Foundation.

Creating a HomeBrew Formula initially seemed like the best option for AlgoKit as it meets the [criteria](https://docs.brew.sh/Acceptable-Formulae) for a Formula. However there is a much higher maintenance cost with this approach as everything is built from source. We encountered an issue where one of our newly added python dependencies (pyclip) did not build from source [correctly](https://github.com/algorandfoundation/homebrew-tap/actions/runs/3884956190/jobs/6628201057#step:8:2871). 

The alternative install method of a cask was then considered, and while AlgoKit does not meet the [criteria](https://docs.brew.sh/Acceptable-Casks) for a cask, it does remove the need for a source build on each MacOS platform and the additional maintenance overhead of the Formula approach.

## Requirements

- **Low maintenance**: The ongoing maintenance for supporting brew installs of AlgoKit should be low and not require manual effort for each release.
- **Fast and easy install experience**: The install experience for end users of AlgoKit should be easy and not require multiple complicated steps, additionally it should install in seconds, not minutes.

## Options

### Option 1: Formula on Official Homebrew Repo

This would be the preferred option except for the two notable issues. Firstly there is a high risk of ongoing maintenance overhead due to the need to support source building all the dependencies. Ideally this would not be an issue, but we have already hit a problem with a dependency (pyclip) early on in AlgoKit's development. Secondly inclusion into the official repo is subject to Homebrew's criteria, which AlgoKit won't reach until it is more mature.

**Pros**
* Most discoverable option for end users `brew install algokit`.
* Homebrew supports automatically bottling on all modern MacOS platforms (MacOS 11+ both Intel and ARM variants) meaning fast installs for users.

**Cons**
* Inclusion is subject to Homebrew's approval process, which algokit won't meet for now at least.
* Higher maintenance cost given the source build is more fragile and is likely to break and require investigation, plus build and install approach differs significantly from Chocolatey and pipx
* Longer build time on release
* Not possible to fully automate release, it relies on a Brew maintainer approving the pull request, so there's extra operational overhead to keep track of the release pull requests

### Option 2: Formula on Algorand Repo

This option is similar to Option 1, but allows Algorand to self publish the installer without meeting Homebrews formula criteria. However one issue is that Platform support is more limited, GitHub provides action runners for intel variants for MacOS 11 + 12, but [MacOS 13](https://github.com/github/roadmap/issues/620) and [ARM](https://github.com/github/roadmap/issues/528) support are not yet available. Additional platforms could be supported by using a combination of self-hosted runners and/or third party solutions. This means pre-built bottles aren't easy to build for ARM or MacOS 13 and installation on those environments will take 5+ minutes.

**Pros**
* Algorand Foundation has control over this process and it can be fully automated
* It's what we have already implemented and working today
* Easier to move to the official Brew core repository once AlgoKit is stable and demonstrably popular (thus meeting the constraints Brew place)

**Cons**
* Supporting all modern MacOS platforms may require use of a 3rd party service and more effort, in the meantime the installation experience on ARM and MacOS 13 is slow (5+ min install)
* Less discoverable install for end users `brew install algorandfoundation/algokit` (relies on them following documentation)
* Higher maintenance cost given the source build is more fragile and is likely to break and require investigation, plus build and install approach differs significantly from Chocolatey and pipx
* Longer build time on release

### Option 3: Cask on Algorand Repo

This option uses a cask which does not have the maintenance overhead of a formula, and can be hosted in an Algorand Foundation repo to get around the fact AlgoKit does not meet the normal cask criteria.

**Pros**
* Algorand Foundation has control over this process and it can be fully automated
* Lower maintenance cost as we do not need to support source builds of dependencies and it's consistent with how algokit cli is installed via Chocolatey and pipx
* Fast install for all MacOS platforms
* Fast build time on release

**Cons**
* Less discoverable install for end users `brew install algorandfoundation/algokit`
* AlgoKit does not meet the stated criteria for a cask and as such it would unlikely to be approved as a cask in the official Homebrew Repo if that was a desired future state
* More effort to implement a new way of installing via brew

### Option 4: Cask on Official Homebrew Repo

This is not a viable option as AlgoKit does not meet the criteria for an official cask.

## Preferred option

Option 1 because it would be the best end user experience.

## Selected option

Option 3 because Option 1 isn't possible right now and it's also a higher overhead to maintain. The install experience for end users is similar with option 3 (just with a bit more typing).

```

--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/developer:python:code:example:local_storage.md:
--------------------------------------------------------------------------------

```markdown
# Local Storage in Algorand Smart Contracts

Local storage in Algorand smart contracts allows you to store per-account state data. This guide demonstrates how to work with local storage using Python.

## Initializing Local Storage

```python
from algopy import (
    Account,
    Application,
    ARC4Contract,
    Asset,
    Bytes,
    LocalState,
    UInt64,
    arc4,
)

class LocalStorage(ARC4Contract):
    def __init__(self) -> None:
        # Initialize different types of local storage
        self.local_int = LocalState(UInt64)           # Integer storage
        self.local_bytes = LocalState(Bytes)          # Bytes storage
        self.local_bool = LocalState(bool)            # Boolean storage
        self.local_asset = LocalState(Asset)          # Asset reference
        self.local_application = LocalState(Application)  # Application reference
        self.local_account = LocalState(Account)      # Account reference
```

## Reading Local State

### Basic Access

```python
@arc4.abimethod
def get_item_local_data(self, for_account: Account) -> UInt64:
    # Direct access using indexing
    return self.local_int[for_account]

@arc4.abimethod
def get_local_data_with_default_int(self, for_account: Account) -> UInt64:
    # Access with default value
    return self.local_int.get(for_account, default=UInt64(0))

@arc4.abimethod
def maybe_local_data(self, for_account: Account) -> tuple[UInt64, bool]:
    # Get value and existence flag
    result, exists = self.local_int.maybe(for_account)
    if not exists:
        result = UInt64(0)
    return result, exists
```

### Reading Different Types

```python
@arc4.abimethod
def get_item_local_data_example(self, for_account: Account) -> bool:
    # Reading integers
    assert self.local_int[for_account] == UInt64(10)
    
    # Reading bytes
    assert self.local_bytes[for_account] == b"Hello"
    
    # Reading booleans
    assert bool(self.local_bool[for_account])
    
    # Reading special types
    assert self.local_asset[for_account] == Asset(UInt64(10))
    assert self.local_application[for_account] == Application(UInt64(10))
    assert self.local_account[for_account] == Account(Bytes(b"Hello"))
    return True
```

### Reading with Default Values

```python
@arc4.abimethod
def get_local_data_with_default(self, for_account: Account) -> bool:
    # Integer with default
    assert self.local_int.get(for_account, default=UInt64(0)) == UInt64(10)
    
    # Bytes with default
    assert self.local_bytes.get(
        for_account, 
        default=Bytes(b"Default Value")
    ) == Bytes(b"Hello")
    
    # Boolean with default
    assert bool(self.local_bool.get(for_account, default=False))
    
    # Asset with default
    assert self.local_asset.get(
        for_account, 
        default=Asset(UInt64(0))
    ) == Asset(UInt64(10))
    
    return True
```

## Writing Local State

### Basic Writing

```python
@arc4.abimethod
def set_local_int(self, for_account: Account, value: UInt64) -> None:
    # Set integer value for account
    self.local_int[for_account] = value
```

### Writing Different Types

```python
@arc4.abimethod
def set_local_data_example(
    self,
    for_account: Account,
    value_asset: Asset,
    value_account: Account,
    value_appln: Application,
    value_byte: Bytes,
    *,
    value_bool: bool,
) -> bool:
    # Set bytes
    self.local_bytes[for_account] = value_byte
    
    # Set boolean
    self.local_bool[for_account] = value_bool
    
    # Set asset reference
    self.local_asset[for_account] = value_asset
    
    # Set application reference
    self.local_application[for_account] = value_appln
    
    # Set account reference
    self.local_account[for_account] = value_account
    
    # Verify values
    assert self.local_bytes[for_account] == value_byte
    assert self.local_bool[for_account] == value_bool
    assert self.local_asset[for_account] == value_asset
    return True
```

## Checking State Existence

```python
@arc4.abimethod
def contains_local_data(self, for_account: Account) -> bool:
    # Check if account has local state
    assert for_account in self.local_int
    return True

@arc4.abimethod
def contains_local_data_example(self, for_account: Account) -> bool:
    # Check existence for all types
    assert for_account in self.local_int
    assert for_account in self.local_bytes
    assert for_account in self.local_bool
    assert for_account in self.local_asset
    assert for_account in self.local_application
    assert for_account in self.local_account
    return True
```

## Deleting Local State

```python
@arc4.abimethod
def delete_local_data(self, for_account: Account) -> None:
    # Delete single value
    del self.local_account[for_account]

@arc4.abimethod
def delete_local_data_example(self, for_account: Account) -> bool:
    # Delete all types of local state
    del self.local_int[for_account]
    del self.local_bytes[for_account]
    del self.local_bool[for_account]
    del self.local_asset[for_account]
    del self.local_application[for_account]
    del self.local_account[for_account]
    return True
```

## Best Practices

1. **Initialization**:
   - Use appropriate types for your data
   - Initialize all required state variables
   - Document state variable purposes
   - Consider storage limits

2. **Reading State**:
   - Use `get()` with default values for safe access
   - Use `maybe()` when existence check is needed
   - Handle non-existent values gracefully
   - Verify type consistency

3. **Writing State**:
   - Validate data before writing
   - Use appropriate type conversions
   - Consider storage costs
   - Update related state consistently

4. **State Existence**:
   - Check state existence before access
   - Handle missing state gracefully
   - Use appropriate default values
   - Consider opt-in requirements

5. **Type Safety**:
   - Use proper type annotations
   - Verify type compatibility
   - Handle type conversions explicitly
   - Test with various data types

6. **Performance**:
   - Minimize state operations
   - Use appropriate data structures
   - Consider storage costs
   - Optimize state access patterns

This guide demonstrates the various aspects of working with local state in Algorand smart contracts using Python. Understanding these concepts is crucial for developing applications that need to maintain per-account state.

```

--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/algokit:utils:typescript:capabilities:typed-app-clients.md:
--------------------------------------------------------------------------------

```markdown
# Typed application clients

Typed application clients are automatically generated, typed TypeScript deployment and invocation clients for smart contracts that have a defined [ARC-56](https://github.com/algorandfoundation/ARCs/pull/258) or [ARC-32](https://github.com/algorandfoundation/ARCs/blob/main/ARCs/arc-0032.md) application specification so that the development experience is easier with less upskill ramp-up and less deployment errors. These clients give you a type-safe, intellisense-driven experience for invoking the smart contract.

Typed application clients are the recommended way of interacting with smart contracts. If you don't have/want a typed client, but have an ARC-56/ARC-32 app spec then you can use the [non-typed application clients](./app-client.md) and if you want to call a smart contract you don't have an app spec file for you can use the underlying [app management](./app.md) and [app deployment](./app-deploy.md) functionality to manually construct transactions.

## Generating an app spec

You can generate an app spec file:

- Using [Algorand Python](https://algorandfoundation.github.io/puya/#quick-start)
- Using [TEALScript](https://tealscript.netlify.app/tutorials/hello-world/0004-artifacts/)
- By hand by following the specification [ARC-56](https://github.com/algorandfoundation/ARCs/pull/258)/[ARC-32](https://github.com/algorandfoundation/ARCs/blob/main/ARCs/arc-0032.md)
- Using [Beaker](https://algorand-devrel.github.io/beaker/html/usage.html) (PyTEAL) _(DEPRECATED)_

## Generating a typed client

To generate a typed client from an app spec file you can use [AlgoKit CLI](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/generate.md#1-typed-clients):

```
> algokit generate client application.json --output /absolute/path/to/client.ts
```

Note: AlgoKit Utils >= 7.0.0 is compatible with the older 3.0.0 generated typed clients, however if you want to utilise the new features or leverage ARC-56 support, you will need to generate using >= 4.0.0. See [AlgoKit CLI generator version pinning](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/generate.md#version-pinning) for more information on how to lock to a specific version.

## Getting a typed client instance

To get an instance of a typed client you can use an [`AlgorandClient`](./algorand-client.md) instance or a typed app [`Factory`](#creating-a-typed-factory-instance) instance.

The approach to obtaining a client instance depends on how many app clients you require for a given app spec and if the app has already been deployed, which is summarised below:

### App is deployed

<table>
<thead>
<tr>
<th colspan="2">Resolve App by ID</th>
<th colspan="2">Resolve App by Creator and Name</th>
</tr>
<tr>
<th>Single App Client Instance</th>
<th>Multiple App Client Instances</th>
<th>Single App Client Instance</th>
<th>Multiple App Client Instances</th>
</tr>
</thead>
<tbody>
<tr>
<td>

```typescript
const appClient = algorand.client.getTypedAppClientById(MyContractClient, {
  appId: 1234n,
  // ...
})
//or
const appClient = new MyContractClient({
  algorand,
  appId: 1234n,
  // ...
})
```

</td>
<td>

```typescript
const appClient1 = factory.getAppClientById({
  appId: 1234n,
  // ...
})
const appClient2 = factory.getAppClientById({
  appId: 4321n,
  // ...
})
```

</td>
<td>

```typescript
const appClient = await algorand.client.getTypedAppClientByCreatorAndName(MyContractClient, {
  creatorAddress: 'CREATORADDRESS',
  appName: 'contract-name',
  // ...
})
//or
const appClient = await MyContractClient.fromCreatorAndName({
  algorand,
  creatorAddress: 'CREATORADDRESS',
  appName: 'contract-name',
  // ...
})
```

</td>
<td>

```typescript
const appClient1 = await factory.getAppClientByCreatorAndName({
  creatorAddress: 'CREATORADDRESS',
  appName: 'contract-name',
  // ...
})
const appClient2 = await factory.getAppClientByCreatorAndName({
  creatorAddress: 'CREATORADDRESS',
  appName: 'contract-name-2',
  // ...
})
```

</td>
</tr>
</tbody>
</table>

To understand the difference between resolving by ID vs by creator and name see the underlying [app client documentation](./app-client.md#appclient).

### App is not deployed

<table>
<thead>
<tr>
<th>Deploy a New App</th>
<th>Deploy or Resolve App Idempotently by Creator and Name</th>
</tr>
</thead>
<tbody>
<tr>
<td>

```typescript
const { appClient } = await factory.send.create.bare({
  args: [],
  // ...
})
// or
const { appClient } = await factory.send.create.METHODNAME({
  args: [],
  // ...
})
```

</td>
<td>

```typescript
const { appClient } = await factory.deploy({
  appName: 'contract-name',
  // ...
})
```

</td>
</tr>
</tbody>
</table>

### Creating a typed factory instance

If your scenario calls for an app factory, you can create one using the below:

```typescript
const factory = algorand.client.getTypedAppFactory(MyContractFactory)
//or
const factory = new MyContractFactory({
  algorand,
})
```

## Client usage

See the [official usage docs](https://github.com/algorandfoundation/algokit-client-generator-ts/blob/main/docs/usage.md) for full details.

For a simple example that deploys a contract and calls a `"hello"` method, see below:

```typescript
// A similar working example can be seen in the AlgoKit init production smart contract templates, when using TypeScript deployment
// In this case the generated factory is called `HelloWorldAppFactory` and is in `./artifacts/HelloWorldApp/client.ts`
import { HelloWorldAppClient } from './artifacts/HelloWorldApp/client'
import { AlgorandClient } from '@algorandfoundation/algokit-utils'

// These require environment variables to be present, or it will retrieve from default LocalNet
const algorand = AlgorandClient.fromEnvironment()
const deployer = algorand.account.fromEnvironment('DEPLOYER', (1).algo())

// Create the typed app factory
const factory = algorand.client.getTypedAppFactory(HelloWorldAppFactory, {
  creatorAddress: deployer,
  defaultSender: deployer,
})

// Create the app and get a typed app client for the created app (note: this creates a new instance of the app every time,
//  you can use .deploy() to deploy idempotently if the app wasn't previously
//  deployed or needs to be updated if that's allowed)
const { appClient } = await factory.create()

// Make a call to an ABI method and print the result
const response = await appClient.hello({ name: 'world' })
console.log(response)
```

```

