This is page 32 of 74. Use http://codebase.md/goplausible/algorand-mcp?lines=false&page={x} to view the full context.
# Directory Structure
```
├── .gitignore
├── CONTRIBUTING.md
├── LICENSE
├── llms-install.md
├── llms.txt
├── package.json
├── packages
│ ├── client
│ │ ├── .env.example
│ │ ├── package.json
│ │ ├── README.md
│ │ ├── src
│ │ │ ├── env.ts
│ │ │ ├── index.ts
│ │ │ └── LocalWallet.ts
│ │ └── tsconfig.json
│ └── server
│ ├── .env.example
│ ├── API specs
│ │ ├── algod_api.json
│ │ ├── indexer_api.json
│ │ ├── mcp.json
│ │ ├── nfd_api.json
│ │ ├── ultrade_api.json
│ │ ├── vestige_api.json
│ │ └── vestige_free_api.json
│ ├── Dockerfile
│ ├── jest.config.js
│ ├── package.json
│ ├── README.md
│ ├── smithery.yaml
│ ├── src
│ │ ├── algorand-client.ts
│ │ ├── env.ts
│ │ ├── index.ts
│ │ ├── resources
│ │ │ ├── index.ts
│ │ │ ├── knowledge
│ │ │ │ ├── ARCs.txt
│ │ │ │ ├── developers-algokit-architecture-decisions.txt
│ │ │ │ ├── developers-algokit-cli.txt
│ │ │ │ ├── developers-algokit-utils-python.txt
│ │ │ │ ├── developers-algokit-utils-typescript.txt
│ │ │ │ ├── developers-clis.txt
│ │ │ │ ├── developers-details.txt
│ │ │ │ ├── developers-liquid-auth.txt
│ │ │ │ ├── developers-nodes.txt
│ │ │ │ ├── developers-puya.txt
│ │ │ │ ├── developers-python.txt
│ │ │ │ ├── developers-sdks-js.txt
│ │ │ │ ├── developers-sdks-python.txt
│ │ │ │ ├── developers-tealscript.txt
│ │ │ │ ├── developers.txt
│ │ │ │ ├── index.ts
│ │ │ │ ├── taxonomy
│ │ │ │ │ ├── algokit-cli:README.md
│ │ │ │ │ ├── algokit:cli:algokit.md
│ │ │ │ │ ├── algokit:cli:architecture-decisions:2022-11-14_sandbox-approach.md
│ │ │ │ │ ├── algokit:cli:architecture-decisions:2022-11-22_beaker-testing-strategy.md
│ │ │ │ │ ├── algokit:cli:architecture-decisions:2023-01-11_beaker_productionisation_review.md
│ │ │ │ │ ├── algokit:cli:architecture-decisions:2023-01-11_brew_install.md
│ │ │ │ │ ├── algokit:cli:architecture-decisions:2023-01-12_smart-contract-deployment.md
│ │ │ │ │ ├── algokit:cli:architecture-decisions:2023-06-06_frontend-templates.md
│ │ │ │ │ ├── algokit:cli:architecture-decisions:2023-07-19_advanced_generate_command.md
│ │ │ │ │ ├── algokit:cli:architecture-decisions:2024-01-13_native_binaries.md
│ │ │ │ │ ├── algokit:cli:architecture-decisions:2024-01-23_init-wizard-v2.md
│ │ │ │ │ ├── algokit:cli:architecture-decisions:2024-01-31_binary_distribution.md
│ │ │ │ │ ├── algokit:cli:architecture-decisions:2024-03-06_local_dev_ui_packaging.md
│ │ │ │ │ ├── algokit:cli:articles:output_stability.md
│ │ │ │ │ ├── algokit:cli:cli:index.md
│ │ │ │ │ ├── algokit:cli:features:compile.md
│ │ │ │ │ ├── algokit:cli:features:completions.md
│ │ │ │ │ ├── algokit:cli:features:config.md
│ │ │ │ │ ├── algokit:cli:features:dispenser.md
│ │ │ │ │ ├── algokit:cli:features:doctor.md
│ │ │ │ │ ├── algokit:cli:features:explore.md
│ │ │ │ │ ├── algokit:cli:features:generate.md
│ │ │ │ │ ├── algokit:cli:features:goal.md
│ │ │ │ │ ├── algokit:cli:features:init.md
│ │ │ │ │ ├── algokit:cli:features:localnet.md
│ │ │ │ │ ├── algokit:cli:features:project:bootstrap.md
│ │ │ │ │ ├── algokit:cli:features:project:deploy.md
│ │ │ │ │ ├── algokit:cli:features:project:link.md
│ │ │ │ │ ├── algokit:cli:features:project:list.md
│ │ │ │ │ ├── algokit:cli:features:project:run.md
│ │ │ │ │ ├── algokit:cli:features:project.md
│ │ │ │ │ ├── algokit:cli:features:tasks:analyze.md
│ │ │ │ │ ├── algokit:cli:features:tasks:ipfs.md
│ │ │ │ │ ├── algokit:cli:features:tasks:mint.md
│ │ │ │ │ ├── algokit:cli:features:tasks:nfd.md
│ │ │ │ │ ├── algokit:cli:features:tasks:opt.md
│ │ │ │ │ ├── algokit:cli:features:tasks:send.md
│ │ │ │ │ ├── algokit:cli:features:tasks:sign.md
│ │ │ │ │ ├── algokit:cli:features:tasks:transfer.md
│ │ │ │ │ ├── algokit:cli:features:tasks:vanity_address.md
│ │ │ │ │ ├── algokit:cli:features:tasks:wallet.md
│ │ │ │ │ ├── algokit:cli:features:tasks.md
│ │ │ │ │ ├── algokit:cli:tutorials:algokit-template.md
│ │ │ │ │ ├── algokit:cli:tutorials:intro.md
│ │ │ │ │ ├── algokit:cli:tutorials:smart-contracts.md
│ │ │ │ │ ├── algokit:docs:testnet_api.md
│ │ │ │ │ ├── algokit:lora:README.md
│ │ │ │ │ ├── algokit:README.md
│ │ │ │ │ ├── algokit:utils:python:markdown:apidocs:algokit_utils:algokit_utils.md
│ │ │ │ │ ├── algokit:utils:python:markdown:capabilities:account.md
│ │ │ │ │ ├── algokit:utils:python:markdown:capabilities:app-client.md
│ │ │ │ │ ├── algokit:utils:python:markdown:capabilities:app-deploy.md
│ │ │ │ │ ├── algokit:utils:python:markdown:capabilities:client.md
│ │ │ │ │ ├── algokit:utils:python:markdown:capabilities:debugger.md
│ │ │ │ │ ├── algokit:utils:python:markdown:capabilities:dispenser-client.md
│ │ │ │ │ ├── algokit:utils:python:markdown:capabilities:transfer.md
│ │ │ │ │ ├── algokit:utils:python:markdown:index.md
│ │ │ │ │ ├── algokit:utils:python:README.md
│ │ │ │ │ ├── algokit:utils:python:source:capabilities:account.md
│ │ │ │ │ ├── algokit:utils:python:source:capabilities:app-client.md
│ │ │ │ │ ├── algokit:utils:python:source:capabilities:app-deploy.md
│ │ │ │ │ ├── algokit:utils:python:source:capabilities:client.md
│ │ │ │ │ ├── algokit:utils:python:source:capabilities:debugger.md
│ │ │ │ │ ├── algokit:utils:python:source:capabilities:dispenser-client.md
│ │ │ │ │ ├── algokit:utils:python:source:capabilities:transfer.md
│ │ │ │ │ ├── algokit:utils:python:source:index.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:account.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:algorand-client.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:amount.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:app-client.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:app-deploy.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:app.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:asset.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:client.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:debugging.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:dispenser-client.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:event-emitter.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:indexer.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:testing.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:transaction-composer.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:transaction.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:transfer.md
│ │ │ │ │ ├── algokit:utils:typescript:capabilities:typed-app-clients.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:testing.TestLogger.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:testing.TransactionLogger.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_account_manager.AccountManager.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_account.MultisigAccount.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_account.SigningAccount.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_algo_http_client_with_retry.AlgoHttpClientWithRetry.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_algorand_client_transaction_creator.AlgorandClientTransactionCreator.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_algorand_client_transaction_sender.AlgorandClientTransactionSender.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_algorand_client.AlgorandClient.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_amount.AlgoAmount.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_app_arc56.Arc56Method.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_app_client.AppClient.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_app_client.ApplicationClient.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_app_deployer.AppDeployer.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_app_factory.AppFactory.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_app_manager.AppManager.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_asset_manager.AssetManager.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_async_event_emitter.AsyncEventEmitter.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_client_manager.ClientManager.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_composer.TransactionComposer.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_config.UpdatableConfig.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_dispenser_client.TestNetDispenserApiClient.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_kmd_account_manager.KmdAccountManager.md
│ │ │ │ │ ├── algokit:utils:typescript:code:classes:types_logic_error.LogicError.md
│ │ │ │ │ ├── algokit:utils:typescript:code:enums:types_app.OnSchemaBreak.md
│ │ │ │ │ ├── algokit:utils:typescript:code:enums:types_app.OnUpdate.md
│ │ │ │ │ ├── algokit:utils:typescript:code:enums:types_indexer.AccountStatus.md
│ │ │ │ │ ├── algokit:utils:typescript:code:enums:types_indexer.ApplicationOnComplete.md
│ │ │ │ │ ├── algokit:utils:typescript:code:enums:types_indexer.SignatureType.md
│ │ │ │ │ ├── algokit:utils:typescript:code:enums:types_lifecycle_events.EventType.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_account_manager.EnsureFundedResult.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_account.AccountConfig.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_account.TransactionSignerAccount.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_algorand_client_interface.AlgorandClientInterface.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_arc56.Arc56Contract.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_arc56.Event.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_arc56.Method.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_arc56.ProgramSourceInfo.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_arc56.StorageKey.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_arc56.StorageMap.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_arc56.StructField.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_client.AppClientCallABIArgs.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_client.AppClientCallCoreParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_client.AppClientCompilationParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_client.AppClientCompilationResult.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_client.AppClientDeployCallInterfaceParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_client.AppClientDeployCoreParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_client.AppClientDeployParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_client.AppClientParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_client.AppSourceMaps.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_client.FundAppAccountParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_client.ResolveAppById.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_client.ResolveAppByIdBase.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_client.SourceMapExport.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_deployer.AppLookup.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_deployer.AppMetadata.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_factory.AppFactoryParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_manager.AppInformation.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_manager.BoxReference.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_manager.BoxValueRequestParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_manager.BoxValuesRequestParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_spec.AppSources.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_spec.AppSpec.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_spec.CallConfig.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_spec.DeclaredSchemaValueSpec.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_spec.Hint.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_spec.ReservedSchemaValueSpec.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_spec.Schema.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_spec.SchemaSpec.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_spec.StateSchemaSpec.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app_spec.Struct.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.AppCallParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.AppCallTransactionResultOfType.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.AppCompilationResult.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.AppDeploymentParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.AppDeployMetadata.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.AppLookup.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.AppMetadata.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.AppReference.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.AppState.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.AppStorageSchema.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.BoxName.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.BoxReference.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.BoxValueRequestParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.BoxValuesRequestParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.CompiledTeal.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.CoreAppCallArgs.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.CreateAppParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.RawAppCallArgs.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.TealTemplateParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_app.UpdateAppParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_asset_manager.AssetInformation.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_asset_manager.BulkAssetOptInOutResult.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_asset.AssetBulkOptInOutParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_asset.AssetOptInParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_asset.AssetOptOutParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_asset.CreateAssetParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_client_manager.AlgoSdkClients.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_client_manager.TypedAppClient.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_client_manager.TypedAppFactory.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_composer.BuiltTransactions.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_config.Config.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_debugging.AVMTracesEventData.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_debugging.TealSourceDebugEventData.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_debugging.TealSourcesDebugEventData.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_dispenser_client.DispenserFundResponse.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_dispenser_client.DispenserLimitResponse.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_dispenser_client.TestNetDispenserApiClientParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_indexer.LookupAssetHoldingsOptions.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_logic_error.LogicErrorDetails.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_network_client.AlgoClientConfig.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_network_client.AlgoConfig.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_network_client.NetworkDetails.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_testing.AlgoKitLogCaptureFixture.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_testing.AlgorandFixture.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_testing.AlgorandFixtureConfig.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_testing.AlgorandTestAutomationContext.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_testing.GetTestAccountParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_testing.LogSnapshotConfig.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_transaction.AtomicTransactionComposerToSend.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_transaction.ConfirmedTransactionResult.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_transaction.ConfirmedTransactionResults.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_transaction.SendAtomicTransactionComposerResults.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_transaction.SendParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_transaction.SendTransactionParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_transaction.SendTransactionResult.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_transaction.SendTransactionResults.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_transaction.TransactionGroupToSend.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_transaction.TransactionToSign.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_transfer.AlgoRekeyParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_transfer.AlgoTransferParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_transfer.EnsureFundedParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_transfer.EnsureFundedReturnType.md
│ │ │ │ │ ├── algokit:utils:typescript:code:interfaces:types_transfer.TransferAssetParams.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:index.indexer.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:index.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:testing.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_account_manager_spec.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_account_manager.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_account.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_algo_http_client_with_retry.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_algorand_client_asset_spec.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_algorand_client_interface.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_algorand_client_spec.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_algorand_client_transaction_creator.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_algorand_client_transaction_sender.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_algorand_client_transfer_spec.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_algorand_client.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_amount_spec.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_amount.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_app_arc56.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_app_client_spec.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_app_client.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_app_deployer.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_app_factory_and_client_spec.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_app_factory.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_app_manager.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_app_spec.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_app.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_asset_manager.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_asset.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_async_event_emitter_spec.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_async_event_emitter.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_client_manager_spec.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_client_manager.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_composer.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_config.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_debugging.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_dispenser_client_spec.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_dispenser_client.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_expand.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_indexer.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_kmd_account_manager.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_lifecycle_events.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_logging.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_logic_error.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_network_client.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_testing.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_transaction.md
│ │ │ │ │ ├── algokit:utils:typescript:code:modules:types_transfer.md
│ │ │ │ │ ├── algokit:utils:typescript:code:README.md
│ │ │ │ │ ├── algokit:utils:typescript:README.md
│ │ │ │ │ ├── algokit:utils:typescript:v7-migration.md
│ │ │ │ │ ├── algokit:utils:typescript:v8-migration.md
│ │ │ │ │ ├── ARCs:ARC-template.md
│ │ │ │ │ ├── ARCs:assets:arc-0012:README.md
│ │ │ │ │ ├── ARCs:assets:arc-0034:TemplateForm.md
│ │ │ │ │ ├── ARCs:assets:arc-0062:README.md
│ │ │ │ │ ├── ARCs:pages:nfts.md
│ │ │ │ │ ├── ARCs:pages:wallets.md
│ │ │ │ │ ├── ARCs:README.md
│ │ │ │ │ ├── ARCs:specs:arc-0000.md
│ │ │ │ │ ├── ARCs:specs:arc-0001.md
│ │ │ │ │ ├── ARCs:specs:arc-0002.md
│ │ │ │ │ ├── ARCs:specs:arc-0003.md
│ │ │ │ │ ├── ARCs:specs:arc-0004.md
│ │ │ │ │ ├── ARCs:specs:arc-0005.md
│ │ │ │ │ ├── ARCs:specs:arc-0006.md
│ │ │ │ │ ├── ARCs:specs:arc-0007.md
│ │ │ │ │ ├── ARCs:specs:arc-0008.md
│ │ │ │ │ ├── ARCs:specs:arc-0009.md
│ │ │ │ │ ├── ARCs:specs:arc-0010.md
│ │ │ │ │ ├── ARCs:specs:arc-0011.md
│ │ │ │ │ ├── ARCs:specs:arc-0012.md
│ │ │ │ │ ├── ARCs:specs:arc-0015.md
│ │ │ │ │ ├── ARCs:specs:arc-0016.md
│ │ │ │ │ ├── ARCs:specs:arc-0018.md
│ │ │ │ │ ├── ARCs:specs:arc-0019.md
│ │ │ │ │ ├── ARCs:specs:arc-0020.md
│ │ │ │ │ ├── ARCs:specs:arc-0021.md
│ │ │ │ │ ├── ARCs:specs:arc-0022.md
│ │ │ │ │ ├── ARCs:specs:arc-0023.md
│ │ │ │ │ ├── ARCs:specs:arc-0025.md
│ │ │ │ │ ├── ARCs:specs:arc-0026.md
│ │ │ │ │ ├── ARCs:specs:arc-0028.md
│ │ │ │ │ ├── ARCs:specs:arc-0032.md
│ │ │ │ │ ├── ARCs:specs:arc-0033.md
│ │ │ │ │ ├── ARCs:specs:arc-0034.md
│ │ │ │ │ ├── ARCs:specs:arc-0035.md
│ │ │ │ │ ├── ARCs:specs:arc-0036.md
│ │ │ │ │ ├── ARCs:specs:arc-0042.md
│ │ │ │ │ ├── ARCs:specs:arc-0047.md
│ │ │ │ │ ├── ARCs:specs:arc-0048.md
│ │ │ │ │ ├── ARCs:specs:arc-0049.md
│ │ │ │ │ ├── ARCs:specs:arc-0054.md
│ │ │ │ │ ├── ARCs:specs:arc-0055.md
│ │ │ │ │ ├── ARCs:specs:arc-0056.md
│ │ │ │ │ ├── ARCs:specs:arc-0059.md
│ │ │ │ │ ├── ARCs:specs:arc-0062.md
│ │ │ │ │ ├── ARCs:specs:arc-0065.md
│ │ │ │ │ ├── ARCs:specs:arc-0069.md
│ │ │ │ │ ├── ARCs:specs:arc-0072.md
│ │ │ │ │ ├── ARCs:specs:arc-0073.md
│ │ │ │ │ ├── ARCs:specs:arc-0074.md
│ │ │ │ │ ├── ARCs:specs:arc-0076.md
│ │ │ │ │ ├── ARCs:specs:arc-0078.md
│ │ │ │ │ ├── ARCs:specs:arc-0079.md
│ │ │ │ │ ├── ARCs:specs:arc-0200.md
│ │ │ │ │ ├── clis_index.md
│ │ │ │ │ ├── developer:docs:about.md
│ │ │ │ │ ├── developer:docs:clis:algokey:algokey.md
│ │ │ │ │ ├── developer:docs:clis:algokey:generate.md
│ │ │ │ │ ├── developer:docs:clis:algokey:import.md
│ │ │ │ │ ├── developer:docs:clis:algokey:multisig:append-auth-addr.md
│ │ │ │ │ ├── developer:docs:clis:algokey:multisig:multisig.md
│ │ │ │ │ ├── developer:docs:clis:algokey:part:info.md
│ │ │ │ │ ├── developer:docs:clis:algokey:part:part.md
│ │ │ │ │ ├── developer:docs:clis:algokey:part:reparent.md
│ │ │ │ │ ├── developer:docs:clis:algokey:sign.md
│ │ │ │ │ ├── developer:docs:clis:conduit:conduit.md
│ │ │ │ │ ├── developer:docs:clis:conduit:init.md
│ │ │ │ │ ├── developer:docs:clis:conduit:list:exporters.md
│ │ │ │ │ ├── developer:docs:clis:conduit:list:importers.md
│ │ │ │ │ ├── developer:docs:clis:conduit:list:list.md
│ │ │ │ │ ├── developer:docs:clis:conduit:list:processors.md
│ │ │ │ │ ├── developer:docs:clis:diagcfg:diagcfg.md
│ │ │ │ │ ├── developer:docs:clis:diagcfg:metric:disable.md
│ │ │ │ │ ├── developer:docs:clis:diagcfg:metric:enable.md
│ │ │ │ │ ├── developer:docs:clis:diagcfg:metric:metric.md
│ │ │ │ │ ├── developer:docs:clis:diagcfg:metric:status.md
│ │ │ │ │ ├── developer:docs:clis:diagcfg:telemetry:disable.md
│ │ │ │ │ ├── developer:docs:clis:diagcfg:telemetry:enable.md
│ │ │ │ │ ├── developer:docs:clis:diagcfg:telemetry:endpoint.md
│ │ │ │ │ ├── developer:docs:clis:diagcfg:telemetry:name.md
│ │ │ │ │ ├── developer:docs:clis:diagcfg:telemetry:status.md
│ │ │ │ │ ├── developer:docs:clis:diagcfg:telemetry:telemetry.md
│ │ │ │ │ ├── developer:docs:clis:goal:node:restart.md
│ │ │ │ │ ├── developer:docs:clis:goal:node:start.md
│ │ │ │ │ ├── developer:docs:clis:goal:node:status.md
│ │ │ │ │ ├── developer:docs:clis:goal:node:stop.md
│ │ │ │ │ ├── developer:docs:clis:goal:node:wait.md
│ │ │ │ │ ├── developer:docs:clis:goal:protocols.md
│ │ │ │ │ ├── developer:docs:clis:goal:report.md
│ │ │ │ │ ├── developer:docs:clis:goal:version.md
│ │ │ │ │ ├── developer:docs:clis:goal:wallet:list.md
│ │ │ │ │ ├── developer:docs:clis:goal:wallet:new.md
│ │ │ │ │ ├── developer:docs:clis:goal:wallet:wallet.md
│ │ │ │ │ ├── developer:docs:clis:indexer:api-config.md
│ │ │ │ │ ├── developer:docs:clis:indexer:daemon.md
│ │ │ │ │ ├── developer:docs:clis:indexer:indexer.md
│ │ │ │ │ ├── developer:docs:clis:indexer:util:util.md
│ │ │ │ │ ├── developer:docs:clis:indexer:util:validator.md
│ │ │ │ │ ├── developer:docs:clis:kmd.md
│ │ │ │ │ ├── developer:docs:clis:tealdbg:debug.md
│ │ │ │ │ ├── developer:docs:clis:tealdbg:remote.md
│ │ │ │ │ ├── developer:docs:clis:tealdbg:tealdbg.md
│ │ │ │ │ ├── developer:docs:details:accounts:create.md
│ │ │ │ │ ├── developer:docs:details:accounts:index.md
│ │ │ │ │ ├── developer:docs:details:accounts:rekey.md
│ │ │ │ │ ├── developer:docs:details:algorand_consensus.md
│ │ │ │ │ ├── developer:docs:details:algorand-networks:betanet.md
│ │ │ │ │ ├── developer:docs:details:algorand-networks:index.md
│ │ │ │ │ ├── developer:docs:details:algorand-networks:mainnet.md
│ │ │ │ │ ├── developer:docs:details:algorand-networks:testnet.md
│ │ │ │ │ ├── developer:docs:details:asa.md
│ │ │ │ │ ├── developer:docs:details:atc.md
│ │ │ │ │ ├── developer:docs:details:atomic_transfers.md
│ │ │ │ │ ├── developer:docs:details:conduit.md
│ │ │ │ │ ├── developer:docs:details:crust.md
│ │ │ │ │ ├── developer:docs:details:dapps:avm:index.md
│ │ │ │ │ ├── developer:docs:details:dapps:avm:teal:guidelines.md
│ │ │ │ │ ├── developer:docs:details:dapps:avm:teal:index.md
│ │ │ │ │ ├── developer:docs:details:dapps:avm:teal:jsonspec.md
│ │ │ │ │ ├── developer:docs:details:dapps:avm:teal:opcodes:index.md
│ │ │ │ │ ├── developer:docs:details:dapps:avm:teal:opcodes:v1.md
│ │ │ │ │ ├── developer:docs:details:dapps:avm:teal:opcodes:v10.md
│ │ │ │ │ ├── developer:docs:details:dapps:avm:teal:opcodes:v2.md
│ │ │ │ │ ├── developer:docs:details:dapps:avm:teal:opcodes:v3.md
│ │ │ │ │ ├── developer:docs:details:dapps:avm:teal:opcodes:v4.md
│ │ │ │ │ ├── developer:docs:details:dapps:avm:teal:opcodes:v5.md
│ │ │ │ │ ├── developer:docs:details:dapps:avm:teal:opcodes:v6.md
│ │ │ │ │ ├── developer:docs:details:dapps:avm:teal:opcodes:v7.md
│ │ │ │ │ ├── developer:docs:details:dapps:avm:teal:opcodes:v8.md
│ │ │ │ │ ├── developer:docs:details:dapps:avm:teal:opcodes:v9.md
│ │ │ │ │ ├── developer:docs:details:dapps:avm:teal:specification.md
│ │ │ │ │ ├── developer:docs:details:dapps:smart-contracts:ABI:index.md
│ │ │ │ │ ├── developer:docs:details:dapps:smart-contracts:apps:create.md
│ │ │ │ │ ├── developer:docs:details:dapps:smart-contracts:apps:index.md
│ │ │ │ │ ├── developer:docs:details:dapps:smart-contracts:apps:innertx.md
│ │ │ │ │ ├── developer:docs:details:dapps:smart-contracts:apps:state.md
│ │ │ │ │ ├── developer:docs:details:dapps:smart-contracts:apps:txs.md
│ │ │ │ │ ├── developer:docs:details:dapps:smart-contracts:debugging.md
│ │ │ │ │ ├── developer:docs:details:dapps:smart-contracts:frontend:apps.md
│ │ │ │ │ ├── developer:docs:details:dapps:smart-contracts:frontend:smartsigs.md
│ │ │ │ │ ├── developer:docs:details:dapps:smart-contracts:guidelines.md
│ │ │ │ │ ├── developer:docs:details:dapps:smart-contracts:index.md
│ │ │ │ │ ├── developer:docs:details:dapps:smart-contracts:smartsigs:index.md
│ │ │ │ │ ├── developer:docs:details:dapps:smart-contracts:smartsigs:modes.md
│ │ │ │ │ ├── developer:docs:details:dapps:smart-contracts:smartsigs:walkthrough.md
│ │ │ │ │ ├── developer:docs:details:dapps:writing-contracts:beaker.md
│ │ │ │ │ ├── developer:docs:details:dapps:writing-contracts:pyteal.md
│ │ │ │ │ ├── developer:docs:details:dapps:writing-contracts:python.md
│ │ │ │ │ ├── developer:docs:details:encoding.md
│ │ │ │ │ ├── developer:docs:details:ethereum_to_algorand.md
│ │ │ │ │ ├── developer:docs:details:index.md
│ │ │ │ │ ├── developer:docs:details:indexer.md
│ │ │ │ │ ├── developer:docs:details:parameter_tables.md
│ │ │ │ │ ├── developer:docs:details:stateproofs:index.md
│ │ │ │ │ ├── developer:docs:details:stateproofs:light_client.md
│ │ │ │ │ ├── developer:docs:details:technical_faq.md
│ │ │ │ │ ├── developer:docs:details:transactions:index.md
│ │ │ │ │ ├── developer:docs:details:transactions:offline_transactions.md
│ │ │ │ │ ├── developer:docs:details:transactions:payment_prompts.md
│ │ │ │ │ ├── developer:docs:details:transactions:signatures.md
│ │ │ │ │ ├── developer:docs:details:transactions:transactions.md
│ │ │ │ │ ├── developer:docs:details:useful_resources.md
│ │ │ │ │ ├── developer:docs:get-started:algokit.md
│ │ │ │ │ ├── developer:docs:get-started:basics:what_is_blockchain.md
│ │ │ │ │ ├── developer:docs:get-started:basics:whats_a_dapp.md
│ │ │ │ │ ├── developer:docs:get-started:basics:where_to_start.md
│ │ │ │ │ ├── developer:docs:get-started:basics:why_algorand.md
│ │ │ │ │ ├── developer:docs:get-started:tokenization:ft.md
│ │ │ │ │ ├── developer:docs:get-started:tokenization:nft.md
│ │ │ │ │ ├── developer:docs:index.md
│ │ │ │ │ ├── developer:docs:rest-apis:algod.md
│ │ │ │ │ ├── developer:docs:rest-apis:indexer.md
│ │ │ │ │ ├── developer:docs:rest-apis:kmd.md
│ │ │ │ │ ├── developer:docs:rest-apis:restendpoints.md
│ │ │ │ │ ├── developer:docs:run-a-node:operations:catchup.md
│ │ │ │ │ ├── developer:docs:run-a-node:operations:switch_networks.md
│ │ │ │ │ ├── developer:docs:run-a-node:participate:generate_keys.md
│ │ │ │ │ ├── developer:docs:run-a-node:participate:index.md
│ │ │ │ │ ├── developer:docs:run-a-node:participate:offline.md
│ │ │ │ │ ├── developer:docs:run-a-node:participate:online.md
│ │ │ │ │ ├── developer:docs:run-a-node:participate:renew.md
│ │ │ │ │ ├── developer:docs:run-a-node:reference:artifacts.md
│ │ │ │ │ ├── developer:docs:run-a-node:reference:config.md
│ │ │ │ │ ├── developer:docs:run-a-node:reference:relay.md
│ │ │ │ │ ├── developer:docs:run-a-node:reference:telemetry-config.md
│ │ │ │ │ ├── developer:docs:run-a-node:setup:indexer.md
│ │ │ │ │ ├── developer:docs:run-a-node:setup:install.md
│ │ │ │ │ ├── developer:docs:run-a-node:setup:node-troubleshooting.md
│ │ │ │ │ ├── developer:docs:run-a-node:setup:types.md
│ │ │ │ │ ├── developer:docs:sdks:go:index.md
│ │ │ │ │ ├── developer:docs:sdks:index.md
│ │ │ │ │ ├── developer:docs:sdks:java:index.md
│ │ │ │ │ ├── developer:docs:sdks:javascript:index.md
│ │ │ │ │ ├── developer:docs:sdks:python:index.md
│ │ │ │ │ ├── developer:python:code:example:accounts.md
│ │ │ │ │ ├── developer:python:code:example:arc4_types.md
│ │ │ │ │ ├── developer:python:code:example:assets.md
│ │ │ │ │ ├── developer:python:code:example:box_storage.md
│ │ │ │ │ ├── developer:python:code:example:control_flow.md
│ │ │ │ │ ├── developer:python:code:example:crypto:merkle_tree.md
│ │ │ │ │ ├── developer:python:code:example:defi:amm.md
│ │ │ │ │ ├── developer:python:code:example:defi:auction.md
│ │ │ │ │ ├── developer:python:code:example:defi:htlc_logicsig.md
│ │ │ │ │ ├── developer:python:code:example:defi:marketplace.md
│ │ │ │ │ ├── developer:python:code:example:events:arc28_events.md
│ │ │ │ │ ├── developer:python:code:example:global_storage.md
│ │ │ │ │ ├── developer:python:code:example:governance:simple_voting.md
│ │ │ │ │ ├── developer:python:code:example:hello_world.md
│ │ │ │ │ ├── developer:python:code:example:inner_transactions.md
│ │ │ │ │ ├── developer:python:code:example:local_storage.md
│ │ │ │ │ ├── developer:python:code:example:nft:proof_of_attendance.md
│ │ │ │ │ ├── developer:python:code:example:privacy:zk_whitelist.md
│ │ │ │ │ ├── developer:python:code:example:scratch_storage.md
│ │ │ │ │ ├── developer:python:code:example:self_payment.md
│ │ │ │ │ ├── developer:python:code:example:struct_in_box.md
│ │ │ │ │ ├── developer:python:code:example:subsidize_app_call.md
│ │ │ │ │ ├── developer:python:code:example:transactions.md
│ │ │ │ │ ├── developer:python:code:example:utility:calculator.md
│ │ │ │ │ ├── devportal-code-examples:projects:python-contract-examples:README.md
│ │ │ │ │ ├── devportal-code-examples:README.md
│ │ │ │ │ ├── docs:.walletconnect:index.md
│ │ │ │ │ ├── docs:.walletconnect:walletconnect-schema.md
│ │ │ │ │ ├── docs:README.md
│ │ │ │ │ ├── docs:scripts:example_tracker:example_list.md
│ │ │ │ │ ├── docs:scripts:README.md
│ │ │ │ │ ├── index.md
│ │ │ │ │ ├── liquid_auth_index.md
│ │ │ │ │ ├── liquid-auth:ARCHITECTURE.md
│ │ │ │ │ ├── liquid-auth:decisions:1-Service-Authentication.md
│ │ │ │ │ ├── liquid-auth:decisions:2-Bidirectional-Communication.md
│ │ │ │ │ ├── liquid-auth:decisions:3-Peer-to-Peer-Signaling.md
│ │ │ │ │ ├── liquid-auth:decisions:4-Fido-Extension.md
│ │ │ │ │ ├── liquid-auth:decisions:README.md
│ │ │ │ │ ├── liquid-auth:docs:architecture.md
│ │ │ │ │ ├── liquid-auth:docs:clients:android:provider-service:authenticate.md
│ │ │ │ │ ├── liquid-auth:docs:clients:android:provider-service:register.md
│ │ │ │ │ ├── liquid-auth:docs:clients:browser:authentication.md
│ │ │ │ │ ├── liquid-auth:docs:clients:browser:example.md
│ │ │ │ │ ├── liquid-auth:docs:introduction.md
│ │ │ │ │ ├── liquid-auth:docs:README.md
│ │ │ │ │ ├── liquid-auth:docs:server:environment-variables.md
│ │ │ │ │ ├── liquid-auth:docs:server:integrations.md
│ │ │ │ │ ├── liquid-auth:docs:server:introduction.md
│ │ │ │ │ ├── liquid-auth:docs:server:running-locally.md
│ │ │ │ │ ├── liquid-auth:README.md
│ │ │ │ │ ├── liquid-auth:SEQUENCE.md
│ │ │ │ │ ├── liquid-auth:services:liquid-auth-api-js:src:assertion:assertion.controller.post.request.md
│ │ │ │ │ ├── liquid-auth:services:liquid-auth-api-js:src:assertion:assertion.controller.post.response.md
│ │ │ │ │ ├── liquid-auth:services:liquid-auth-api-js:src:attestation:attestation.controller.post.request.md
│ │ │ │ │ ├── liquid-auth:services:liquid-auth-api-js:src:auth:auth.controller.get.user.md
│ │ │ │ │ ├── liquid-auth:sites:express-dapp:README.md
│ │ │ │ │ ├── liquid-auth:VISION.md
│ │ │ │ │ ├── puya_index.md
│ │ │ │ │ ├── puya:docs:algopy_testing:index.md
│ │ │ │ │ ├── puya:docs:api-algopy.arc4.md
│ │ │ │ │ ├── puya:docs:api-algopy.gtxn.md
│ │ │ │ │ ├── puya:docs:api-algopy.itxn.md
│ │ │ │ │ ├── puya:docs:api-algopy.md
│ │ │ │ │ ├── puya:docs:api-algopy.op.md
│ │ │ │ │ ├── puya:docs:api.md
│ │ │ │ │ ├── puya:docs:compiler.md
│ │ │ │ │ ├── puya:docs:index.md
│ │ │ │ │ ├── puya:docs:language-guide.md
│ │ │ │ │ ├── puya:docs:lg-arc28.md
│ │ │ │ │ ├── puya:docs:lg-arc4.md
│ │ │ │ │ ├── puya:docs:lg-builtins.md
│ │ │ │ │ ├── puya:docs:lg-calling-apps.md
│ │ │ │ │ ├── puya:docs:lg-compile.md
│ │ │ │ │ ├── puya:docs:lg-control.md
│ │ │ │ │ ├── puya:docs:lg-errors.md
│ │ │ │ │ ├── puya:docs:lg-logs.md
│ │ │ │ │ ├── puya:docs:lg-modules.md
│ │ │ │ │ ├── puya:docs:lg-opcode-budget.md
│ │ │ │ │ ├── puya:docs:lg-ops.md
│ │ │ │ │ ├── puya:docs:lg-storage.md
│ │ │ │ │ ├── puya:docs:lg-structure.md
│ │ │ │ │ ├── puya:docs:lg-transactions.md
│ │ │ │ │ ├── puya:docs:lg-types.md
│ │ │ │ │ ├── puya:docs:lg-unsupported-python-features.md
│ │ │ │ │ ├── puya:docs:principles.md
│ │ │ │ │ ├── puya:examples:auction:README.md
│ │ │ │ │ ├── puya:python:testing:docs:algopy.md
│ │ │ │ │ ├── puya:python:testing:docs:api.md
│ │ │ │ │ ├── puya:python:testing:docs:coverage.md
│ │ │ │ │ ├── puya:python:testing:docs:examples.md
│ │ │ │ │ ├── puya:python:testing:docs:faq.md
│ │ │ │ │ ├── puya:python:testing:docs:index.md
│ │ │ │ │ ├── puya:python:testing:docs:testing-guide:arc4-types.md
│ │ │ │ │ ├── puya:python:testing:docs:testing-guide:avm-types.md
│ │ │ │ │ ├── puya:python:testing:docs:testing-guide:concepts.md
│ │ │ │ │ ├── puya:python:testing:docs:testing-guide:contract-testing.md
│ │ │ │ │ ├── puya:python:testing:docs:testing-guide:index.md
│ │ │ │ │ ├── puya:python:testing:docs:testing-guide:opcodes.md
│ │ │ │ │ ├── puya:python:testing:docs:testing-guide:signature-testing.md
│ │ │ │ │ ├── puya:python:testing:docs:testing-guide:state-management.md
│ │ │ │ │ ├── puya:python:testing:docs:testing-guide:subroutines.md
│ │ │ │ │ ├── puya:python:testing:docs:testing-guide:transactions.md
│ │ │ │ │ ├── puya:python:testing:examples:README.md
│ │ │ │ │ ├── puya:python:testing:README.md
│ │ │ │ │ ├── puya:README.md
│ │ │ │ │ ├── puya:src:puya:ARCHITECTURE.md
│ │ │ │ │ ├── puya:src:puyapy:_typeshed:README.md
│ │ │ │ │ ├── puya:src:puyapy:_vendor:mypy:typeshed:stdlib:_typeshed:README.md
│ │ │ │ │ ├── puya:src:puyapy:awst_build:README.md
│ │ │ │ │ ├── puya:stubs:README.md
│ │ │ │ │ ├── puya:tests:test_expected_output:README.md
│ │ │ │ │ ├── puya:typescript:docs:architecture-decisions:2024-05-21_primitive-bytes-and-strings.md
│ │ │ │ │ ├── puya:typescript:docs:architecture-decisions:2024-05-21_primitive-integer-types.md
│ │ │ │ │ ├── puya:typescript:docs:README.md
│ │ │ │ │ ├── puya:typescript:packages:algo-ts:readme.md
│ │ │ │ │ ├── puya:typescript:README.md
│ │ │ │ │ ├── SDKs:javascript:classes:ABIAddressType.md
│ │ │ │ │ ├── SDKs:javascript:classes:ABIArrayDynamicType.md
│ │ │ │ │ ├── SDKs:javascript:classes:ABIArrayStaticType.md
│ │ │ │ │ ├── SDKs:javascript:classes:ABIBoolType.md
│ │ │ │ │ ├── SDKs:javascript:classes:ABIByteType.md
│ │ │ │ │ ├── SDKs:javascript:classes:ABIContract.md
│ │ │ │ │ ├── SDKs:javascript:classes:ABIInterface.md
│ │ │ │ │ ├── SDKs:javascript:classes:ABIMethod.md
│ │ │ │ │ ├── SDKs:javascript:classes:ABIStringType.md
│ │ │ │ │ ├── SDKs:javascript:classes:ABITupleType.md
│ │ │ │ │ ├── SDKs:javascript:classes:ABIType.md
│ │ │ │ │ ├── SDKs:javascript:classes:ABIUfixedType.md
│ │ │ │ │ ├── SDKs:javascript:classes:ABIUintType.md
│ │ │ │ │ ├── SDKs:javascript:classes:Algodv2.md
│ │ │ │ │ ├── SDKs:javascript:classes:AtomicTransactionComposer.md
│ │ │ │ │ ├── SDKs:javascript:classes:DryrunResult.md
│ │ │ │ │ ├── SDKs:javascript:classes:Indexer.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.Account.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.AccountParticipation.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.AccountResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.AccountsResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.AccountStateDelta.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.Application.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.ApplicationLocalState.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.ApplicationLocalStatesResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.ApplicationLogData.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.ApplicationLogsResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.ApplicationParams.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.ApplicationResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.ApplicationsResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.ApplicationStateSchema.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.Asset.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.AssetBalancesResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.AssetHolding.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.AssetHoldingsResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.AssetParams.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.AssetResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.AssetsResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.Block.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.BlockRewards.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.BlockUpgradeState.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.BlockUpgradeVote.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.Box.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.BoxDescriptor.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.BoxesResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.ErrorResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.EvalDelta.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.EvalDeltaKeyValue.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.HashFactory.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.HealthCheck.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.IndexerStateProofMessage.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.MerkleArrayProof.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.MiniAssetHolding.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.ParticipationUpdates.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.StateProofFields.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.StateProofParticipant.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.StateProofReveal.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.StateProofSignature.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.StateProofSigSlot.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.StateProofTracking.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.StateProofVerifier.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.StateSchema.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.TealKeyValue.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.TealValue.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.Transaction.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.TransactionApplication.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.TransactionAssetConfig.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.TransactionAssetFreeze.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.TransactionAssetTransfer.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.TransactionKeyreg.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.TransactionPayment.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.TransactionResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.TransactionSignature.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.TransactionSignatureLogicsig.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.TransactionSignatureMultisig.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.TransactionSignatureMultisigSubsignature.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.TransactionsResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:indexerModels.TransactionStateProof.md
│ │ │ │ │ ├── SDKs:javascript:classes:Kmd.md
│ │ │ │ │ ├── SDKs:javascript:classes:LogicSig.md
│ │ │ │ │ ├── SDKs:javascript:classes:LogicSigAccount.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.Account.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.AccountApplicationResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.AccountAssetHolding.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.AccountAssetResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.AccountAssetsInformationResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.AccountParticipation.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.AccountStateDelta.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.AppCallLogs.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.Application.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.ApplicationInitialStates.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.ApplicationKVStorage.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.ApplicationLocalReference.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.ApplicationLocalState.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.ApplicationParams.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.ApplicationStateOperation.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.ApplicationStateSchema.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.Asset.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.AssetHolding.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.AssetHoldingReference.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.AssetParams.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.AvmKeyValue.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.AvmValue.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.BlockHashResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.BlockLogsResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.BlockResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.BlockTxidsResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.Box.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.BoxDescriptor.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.BoxesResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.BoxReference.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.BuildVersion.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.CompileResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.DisassembleResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.DryrunRequest.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.DryrunResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.DryrunSource.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.DryrunState.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.DryrunTxnResult.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.ErrorResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.EvalDelta.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.EvalDeltaKeyValue.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.GetBlockTimeStampOffsetResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.GetSyncRoundResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.KvDelta.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.LedgerStateDeltaForTransactionGroup.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.LightBlockHeaderProof.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.NodeStatusResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.PendingTransactionResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.PendingTransactionsResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.PostTransactionsResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.ScratchChange.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.SimulateInitialStates.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.SimulateRequest.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.SimulateRequestTransactionGroup.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.SimulateResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.SimulateTraceConfig.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.SimulateTransactionGroupResult.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.SimulateTransactionResult.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.SimulateUnnamedResourcesAccessed.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.SimulationEvalOverrides.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.SimulationOpcodeTraceUnit.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.SimulationTransactionExecTrace.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.StateProof.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.StateProofMessage.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.SupplyResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.TealKeyValue.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.TealValue.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.TransactionGroupLedgerStateDeltasForRoundResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.TransactionParametersResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.TransactionProofResponse.md
│ │ │ │ │ ├── SDKs:javascript:classes:modelsv2.Version.md
│ │ │ │ │ ├── SDKs:javascript:classes:SourceMap.md
│ │ │ │ │ ├── SDKs:javascript:classes:Transaction.md
│ │ │ │ │ ├── SDKs:javascript:enums:ABIReferenceType.md
│ │ │ │ │ ├── SDKs:javascript:enums:ABITransactionType.md
│ │ │ │ │ ├── SDKs:javascript:enums:AtomicTransactionComposerStatus.md
│ │ │ │ │ ├── SDKs:javascript:enums:IntDecoding.md
│ │ │ │ │ ├── SDKs:javascript:enums:OnApplicationComplete.md
│ │ │ │ │ ├── SDKs:javascript:enums:TransactionType.md
│ │ │ │ │ ├── SDKs:javascript:examples:README.md
│ │ │ │ │ ├── SDKs:javascript:FAQ.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:ABIContractNetworkInfo.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:ABIContractNetworks.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:ABIContractParams.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:ABIInterfaceParams.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:ABIMethodArgParams.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:ABIMethodParams.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:ABIMethodReturnParams.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:ABIResult.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:Account.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:Address.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:AlgodTokenHeader.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:BaseHTTPClient.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:BaseHTTPClientError.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:BaseHTTPClientResponse.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:BoxReference.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:CustomTokenHeader.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:EncodedAssetParams.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:EncodedBoxReference.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:EncodedGlobalStateSchema.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:EncodedLocalStateSchema.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:EncodedLogicSig.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:EncodedLogicSigAccount.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:EncodedMultisig.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:EncodedSignedTransaction.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:EncodedSubsig.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:EncodedTransaction.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:IndexerTokenHeader.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:KMDTokenHeader.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:MultisigMetadata.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:SignedTransaction.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:SuggestedParams.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:TransactionParams.md
│ │ │ │ │ ├── SDKs:javascript:interfaces:TransactionWithSigner.md
│ │ │ │ │ ├── SDKs:javascript:modules:indexerModels.md
│ │ │ │ │ ├── SDKs:javascript:modules:modelsv2.md
│ │ │ │ │ ├── SDKs:javascript:modules.md
│ │ │ │ │ ├── SDKs:javascript:README.md
│ │ │ │ │ ├── SDKs:python:algosdk:v2client:harness:README.md
│ │ │ │ │ ├── SDKs:python:examples:README.md
│ │ │ │ │ ├── SDKs:python:README.md
│ │ │ │ │ ├── tealscript:examples_amm_README.md
│ │ │ │ │ ├── tealscript:examples_auction_README.md
│ │ │ │ │ ├── tealscript:examples_big_box_README.md
│ │ │ │ │ ├── tealscript:examples_itxns_README.md
│ │ │ │ │ ├── tealscript:examples_lsig_with_app_README.md
│ │ │ │ │ ├── tealscript:examples_reti_README.md
│ │ │ │ │ ├── tealscript:FEATURES.md
│ │ │ │ │ ├── tealscript:guides_atomic_txn.md
│ │ │ │ │ ├── tealscript:guides_features.md
│ │ │ │ │ ├── tealscript:guides_getting_started.md
│ │ │ │ │ ├── tealscript:guides_inner_transactions.md
│ │ │ │ │ ├── tealscript:guides_lifecycle.md
│ │ │ │ │ ├── tealscript:guides_math.md
│ │ │ │ │ ├── tealscript:guides_methods.md
│ │ │ │ │ ├── tealscript:guides_multiple_contracts.md
│ │ │ │ │ ├── tealscript:guides_pyteal.md
│ │ │ │ │ ├── tealscript:guides_storage.md
│ │ │ │ │ ├── tealscript:guides_Supported Types_arrays.md
│ │ │ │ │ ├── tealscript:guides_Supported Types_numbers.md
│ │ │ │ │ ├── TEALScript:README.md
│ │ │ │ │ ├── tealscript:tests_test_package_README.md
│ │ │ │ │ ├── tealscript:tutorials_Hello World_0001-intro.md
│ │ │ │ │ ├── tealscript:tutorials_Hello World_0002-init.md
│ │ │ │ │ ├── tealscript:tutorials_Hello World_0003-contract.md
│ │ │ │ │ ├── tealscript:tutorials_Hello World_0004-artifacts.md
│ │ │ │ │ ├── tealscript:tutorials_Hello World_0005-hello.md
│ │ │ │ │ └── tealscript:tutorials_Hello World_0006-test.md
│ │ │ │ └── taxonomy-categories
│ │ │ │ ├── algokit-utils.json
│ │ │ │ ├── algokit.json
│ │ │ │ ├── arcs.json
│ │ │ │ ├── clis.json
│ │ │ │ ├── details.json
│ │ │ │ ├── developers.json
│ │ │ │ ├── liquid-auth.json
│ │ │ │ ├── nodes.json
│ │ │ │ ├── puya.json
│ │ │ │ ├── python.json
│ │ │ │ ├── sdks.json
│ │ │ │ └── tealscript.json
│ │ │ └── wallet
│ │ │ └── index.ts
│ │ ├── tools
│ │ │ ├── accountManager.ts
│ │ │ ├── algodManager.ts
│ │ │ ├── apiManager
│ │ │ │ ├── algod
│ │ │ │ │ ├── account.ts
│ │ │ │ │ ├── application.ts
│ │ │ │ │ ├── asset.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── transaction.ts
│ │ │ │ ├── example
│ │ │ │ │ ├── get-balance.ts
│ │ │ │ │ └── index.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── indexer
│ │ │ │ │ ├── account.ts
│ │ │ │ │ ├── application.ts
│ │ │ │ │ ├── asset.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── transaction.ts
│ │ │ │ ├── nfd
│ │ │ │ │ └── index.ts
│ │ │ │ ├── tinyman
│ │ │ │ │ ├── analytics.ts
│ │ │ │ │ ├── bootstrap.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── liquidity.ts
│ │ │ │ │ ├── opt_in.ts
│ │ │ │ │ ├── pool.ts
│ │ │ │ │ ├── remove_liquidity.ts
│ │ │ │ │ └── swap.ts
│ │ │ │ ├── ultrade
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── market.ts
│ │ │ │ │ ├── system.ts
│ │ │ │ │ └── wallet.ts
│ │ │ │ └── vestige
│ │ │ │ ├── assets.ts
│ │ │ │ ├── balances.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── networks.ts
│ │ │ │ ├── notes.ts
│ │ │ │ ├── pools.ts
│ │ │ │ ├── protocols.ts
│ │ │ │ ├── swaps.ts
│ │ │ │ └── vaults.ts
│ │ │ ├── arc26Manager.ts
│ │ │ ├── index.ts
│ │ │ ├── knowledgeManager.ts
│ │ │ ├── transactionManager
│ │ │ │ ├── accountTransactions.ts
│ │ │ │ ├── appTransactions
│ │ │ │ │ ├── callTxn.ts
│ │ │ │ │ ├── clearTxn.ts
│ │ │ │ │ ├── closeOutTxn.ts
│ │ │ │ │ ├── createTxn.ts
│ │ │ │ │ ├── deleteTxn.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── optInTxn.ts
│ │ │ │ │ ├── test
│ │ │ │ │ │ ├── counter_approval.teal
│ │ │ │ │ │ ├── counter_clear.teal
│ │ │ │ │ │ ├── storage_test_approval_v2.teal
│ │ │ │ │ │ ├── storage_test_approval.teal
│ │ │ │ │ │ └── storage_test_clear.teal
│ │ │ │ │ ├── types.ts
│ │ │ │ │ └── updateTxn.ts
│ │ │ │ ├── assetTransactions.ts
│ │ │ │ ├── generalTransaction.ts
│ │ │ │ └── index.ts
│ │ │ └── utilityManager.ts
│ │ ├── types.ts
│ │ └── utils
│ │ └── responseProcessor.ts
│ ├── tests
│ │ ├── resources
│ │ │ ├── algod
│ │ │ │ ├── account.test.ts
│ │ │ │ ├── application.test.ts
│ │ │ │ ├── asset.test.ts
│ │ │ │ └── transaction.test.ts
│ │ │ └── indexer
│ │ │ ├── account.test.ts
│ │ │ ├── application.test.ts
│ │ │ ├── asset.test.ts
│ │ │ └── transaction.test.ts
│ │ └── tools
│ │ ├── accountManager.test.ts
│ │ ├── algodManager.test.ts
│ │ ├── apiManager
│ │ │ └── example
│ │ │ └── get-balance.test.ts
│ │ ├── transactionManager
│ │ │ ├── accountTransactionManager.test.ts
│ │ │ ├── appTransactionManager.test.ts
│ │ │ ├── assetTransactionManager.test.ts
│ │ │ ├── generalTransactionManager.test.ts
│ │ │ └── transactionManager.test.ts
│ │ └── utilityManager.test.ts
│ └── tsconfig.json
├── README.md
├── rename_files.sh
└── tsconfig.json
```
# Files
--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/algokit:cli:architecture-decisions:2024-01-31_binary_distribution.md:
--------------------------------------------------------------------------------
```markdown
# AlgoKit CLI binary distribution
- **Status**: Approved
- **Owner:** Altynbek Orumbayev (MakerX)
- **Deciders**: Alessandro (Algorand Foundation), Rob Moore (MakerX), MakerX team
- **Date created**: 2024-01-31
- **Date decided:** 2024-02-01
- **Date updated**: 2024-02-05
## Context
The following ADR is a continuation of [native binaries](./2024-01-13_native_binaries.md) ADR. With initial workflows implemented, the goal is to determine the best way to distribute the native binaries to the end users.
## Requirements
- The solution should support a wide variety of Linux distributions, macOS (both Apple Silicon and Intel architectures), and Windows.
- The solution should allow distribution of native binaries via os specific package managers `brew`, `snap`, `winget`.
## Technical Constraints
- ~~Pyinstaller binaries are dependend on the architecture and the OS. Github Actions mainly support `x86-64` architectures. This means that we need a self hosted runner to build binaries for `arm64` architectures OR use an alternative CI provider which has access to `arm64` and other architectures inside runners.~~ Based on recent announcement made at the date of submission of initial draft of this ADR, GitHub now supports mac os ARM runners on all OSS plans. This means we can target arm64 macos binaries using the default macos runners and potentially reuse them to build arm64 linux binaries using QEMU and/or buildx from Docker. Hence this is no longer a constraint - see [post](https://github.blog/changelog/2024-01-30-github-actions-introducing-the-new-m1-macos-runner-available-to-open-source/).
- Codesigning is a recommended practice for secure distribution and would need to be implemented on top of the initial workflows introduced as part of the implementation of the [native binaries](./2024-01-13_native_binaries.md) ADR.
## Options
### Option 1 - Binaries are only available via dedicated package managers using OSS solutions for multi architecture support
This approach assumes that native binaries are never available for direct consumption but instead extra tailored per each selected package manager. Additionally this approach assumes using OSS solutions for multi architecture support. ~~Primarily using a QEMU/buildx based actions to build the binaries for different linux architectures, using paid m1 github runner for arm macos binaries, using default macos runner for x86 macos binaries and using default windows runner for x86-64 windows binaries~~. Based on recent announcement from [GitHub](https://github.blog/changelog/2024-01-30-github-actions-introducing-the-new-m1-macos-runner-available-to-open-source/) - ARM runners on mac are now available on all OSS plans, given that we agreed that we arent support ARM linux, mac on ARM can be compiled on ARM mac runners and windows can be compiled and targeting x86-64 using default runners. **Hence removing all major constrains and difficulties of this approach**.
Diagram:
```mermaid
flowchart
n1["Release pipeline flow"]
n1 --- n2["Python wheel build & test validation, runs on [3.10, 3.11, 3.12 on windows, mac, ubuntu]"]
n2 --- n3["Build binaries"]
n3 --- n4["Linux"]
n3 --- n5["Mac"]
n3 --- n6["Windows"]
n4 --- n7["ubuntu-latest x86-64"]
n7 --- n9["Upload artifacts"]
n5 --- n10["macos-latest x86-64"]
n5 --- n11["macos-large-latest ARM"]
n6 --- n12["windows-latest (x86-64)"]
n10 --- n9
n11 --- n9
n12 --- n9
n9 --- n13["Distribution"]
n13 --- n14["pypi pure python wheel"]
n13 --- n15["snap"]
n13 --- n16["brew"]
n13 --- n17["winget"]
n17 --- n18["refresh manifest"]
n18 --- n19["submit release PR to winget community repo"]
n16 --- n20["refresh cask definition"]
n20 --- n21["submit pr to algorandfoundation/tap"]
n15 --- n22["x86-64"]
n22 --- n23["build and submit x86-64 snap on ubuntu-latest runner"]
n23 --- n24["publish snap"]
```
#### General pros and cons
**Pros**
- Ability to rely on package manager to handle installation, updates and removal of the binaries
- OSS solutions for multi architecture support are available and can be used to build the binaries for different architectures on Linux using QEMU
**Cons**
- Assuming we are targeting x86-64/ARM64 on mac, x86-64 on Windows and x86-64 on Linux, no major cons are identified with this approach other than certain non deteministic factos around initial setup of Apple dev account, approval of PR on winget repo and setup of the Snapstore profile.
#### Snap
**Pros**
- Snap is available on all major Linux distributions
- Ubuntu provides a Launchpad platform that simplifies compiling snaps on different architectures remotely
- Snap supports distribution of pyinstaller binaries (verified in a PoC on a fork of algokit-cli)
- Has flexible configuration options over release channels (edge, beta, release candidate, production/stable).
**Cons**
- ~~Snap provides a native support for pyhon applications which may be simpler to use than pyinstaller rather than distributing the binaries as it allows us to rely directly on remote Launchpad builds instead of pre-building the binaries per each architecture.~~ **No longer an issue given latest decision not to support ARM64 linux given that pipx is still gonna be a first class citizen alternative.**
- ~~If we are to distribute pyinstaller binaries, the binaries itself need to be cross compiled on target architectures. Currently we get `x86-64` binaries with `ubuntu` runners, however we would need to introduce extra self hosted runners to get `arm64` binaries. In this case we would need to run building of binaries AND building of snaps in build matrices consiting of default `ubuntu` runners and self hosted `arm64` runners. This will increase the build time and complexity of the build process.~~ **No longer an issue given latest decision not to support ARM64 linux given that pipx is still gonna be a first class citizen alternative.**
#### Brew
**Pros**
- A flow for distributing algokit wheel via `brew` is already established
- Brew supports distribution of pyinstaller binaries (verified in a PoC on a fork of algokit-cli)
- Will require minor changes in the existing brew workflow to operate with binary artifacts instead of wheel artifacts
**Cons**
- ~~Algokit cli relies on dependencies that are not [`fat` binaries](https://en.wikipedia.org/wiki/Fat_binary). This means we can't use pyinstaller to target `universal2` architecture and instead need to build the binaries for each architecture separately. Hence using a paid ARM macos runner is a simple solution to get binaries for Apple Silicon.~~ **No longer an issue given announcement from Github that ARM runners are now available on all OSS plans.**
- Codesigning is required for distribution of binaries via `brew`. This means that we need to have a valid Apple Developer account and a valid certificate to sign the binaries. While this is a good practice regardless, listing this as a con given non deterministic nature of obtaining a valid certificate from Apple.
- ~~Separate ARM worker for apple silicon binaries is required. Github provides beta version of such runners for with paid billing plans.~~ **No longer paid given recent announcement from Github.**
#### Winget
**Pros**
- Winget is available on all major Windows distributions
- Winget supports distribution of pyinstaller binaries and in fact it does not support distribution of python wheels, making binaries a good candidate for winget.
- Will require minor changes in the existing brew workflow to convert pyinstaller .exe binaries to winget .msi binaries
**Cons**
- Winget requires contributing the manifest file to an open source repository which may cause potential delays in the distribution of the binaries as each PR needs to be reviewed and approved by the maintainers of the repository.
#### Conclusion
All of the above package managers are viable and can be used to distribute the pyinstaller build binaries. ~~Requirement on supporting additional architectures like `arm64` introduce unique challenges that ideally should be addressed by introducing custom self hosted runners to the build matrix. This will increase the complexity of the build process and will require additional maintenance of the runners.~~ **Given recent decisions around ARM linux support, we can safely assume that this is the most balanced approach that will allow us to distribute the binaries for all supported architectures without introducing additional complexity of maintaining self hosted runners or implementing an in-house self-update mechanism for binaries.**
### Option 2 - Binaries are only available via dedicated package managers using self hosted runners for multi architecture support
This is identical to the option 1 with the exception that we are using self hosted runners to build the binaries for different architectures.
Diagram:
```mermaid
flowchart
n1["Release pipeline flow"]
n1 --- n2["Python wheel build & test validation (runs on [3.10, 3.11, 3.12 on windows, mac, ubuntu]"]
n2 --- n3["Build binaries"]
n3 --- n4["Linux"]
n3 --- n5["Mac"]
n3 --- n6["Windows"]
n4 --- n7["self-hosted aarch64-ubuntu22.04"]
n4 --- n8["self-hosted armv7-ubuntu22.04"]
n7 --- n9["Upload artifacts"]
n5 --- n10["macos-latest x86-64"]
n5 --- n11["macos-large-latest ARM (paid worker)"]
n6 --- n12["windows-latest (x86-64)"]
n8 --- n9
n10 --- n9
n11 --- n9
n12 --- n9
n9 --- n13["Distribution"]
n13 --- n14["pypi pure python wheel"]
n13 --- n15["snap"]
n13 --- n16["brew"]
n13 --- n17["winget"]
n17 --- n18["refresh manifest"]
n18 --- n19["submit release PR to winget community repo "]
n16 --- n20["refresh cask definition (can use conditional that auto picks either ARM or Intel based artifacts)"]
n20 --- n21["submit pr to algorandfoundation/tap"]
n15 --- n22["aarch64"]
n15 --- n23["armv7"]
n22 --- n24["build snap on self hosted runner for aarch64 architecture"]
n23 --- n25["build snap on self hosted runner for armv7 architecture"]
n24 --- n26["publish snap"]
n25 --- n26
```
#### General pros and cons
**Pros**
- Simplified build matrix as we can simply define additional `runs-on` for each architecture we want to support to target our custom self hosted runners
- Same pros as option 1
**Cons**
- The main drawback for self hosted runners is requirements on additional maintenance, very careful configuration and security considerations. This is a non trivial task and will require additional resources to maintain implement. Github itself generally does not recommend using them for public repositories as forked repositories can potentially gain access to the self hosted runners. There is a lot of workarounds to this issue, but it is still a non trivial task to implement and maintain.
### Option 3 - Binaries are available for direct consumption as self contained executables
This approach assumes that native binaries are available for direct consumption as self contained executables. This means that the binaries are not distributed via package managers but instead are available for direct download from the Algorand Foundation website/dedicated installer script that needs to be introduce. The script can figure out the operating system, architecture and pull the correct binary from public github releases page.
Diagram:
```mermaid
flowchart
n1["Release pipeline flow"]
n1 --- n2["Python wheel build & test validation (runs on [3.10, 3.11, 3.12 on windows, mac, ubuntu]"]
n2 --- n3["Build binaries"]
n3 --- n4["Linux"]
n3 --- n5["Mac"]
n3 --- n6["Windows"]
n4 --- n7["ubuntu-latest"]
n7 --- n9["Upload artifacts"]
n5 --- n10["macos-latest x86-64"]
n5 --- n11["macos-large-latest ARM"]
n6 --- n12["windows-latest (x86-64)"]
n10 --- n9
n11 --- n9
n12 --- n9
n9 --- n13["Distribution"]
n13 --- n14["pypi pure python wheel"]
n13 --- n15["binaries"]
n15 --- n16["Windows"]
n15 --- n17["Linux"]
n15 --- n18["Mac"]
n16 --- n19["Transform to msi installer"]
n17 --- n20["codesign"]
n19 --- n20
n18 --- n21["transform to .pkg installer"]
n21 --- n20
n20 --- n22["append to github release"]
```
#### General pros and cons
**Pros**
- Ability to distribute binaries for all supported architectures without extra complexity of maintaining distributions via package managers `brew`, `snap`, `winget`
- Self update mechanism can be implemented within the algokit cli to check for updates and pull newer versions of the binaries. This will allow users to always have the latest version of the binaries without the need to wait for the package manager to update the binaries.
**Cons**
- Users who prefer to use package managers will need to manually install the binaries and keep track of the updates
- Self update mechanism will require additional maintenance and testing to ensure correct handling of the updates
### Option 4 - Binaries are available for direct consumption as self contained executables, dedicated package managers distribute the wheels
This is potentially the most complex approach and it combines option 1 and option 3. This means that we are distributing the binaries for direct consumption as self contained executables and additionally we are distributing the wheels via package managers.
**Pros**
- Ability to distribute binaries for all supported architectures without extra complexity of maintaining distributions via package managers `brew`, `snap`, `winget`
- Ability to rely on python optimizations in dedicated package managers like `snap` and `brew` to distribute the wheel artifacts
**Cons**
- **The major drawback with the approach** is that it does not eliminate dependency on python to run the algokit cli when using package managers which goes against initial goals of this outcome (removing requirement on having python installed on user's machine)
- Self update mechanism will require additional maintenance and testing to ensure correct handling of the updates and is at risk of not being used that often if users will still primarily rely on package managers or `pipx` to install the algokit cli
- Deminishes the value of having self contained binaries as users will still need to have python installed on their machines to run the algokit cli if they prefer to use package managers
## Preferred option
### Notes from discussion on 2024-02-01
- We are not supporting Windows ARM and Ubuntu ARM
- We are not using self-hosted runners approach
- Pending on key decision from Algorand Foundation on whether we want to have brew, snap, winget distribution vs self contained binary executables.
Based on the above, the most balanced option in terms of user experience and maintenance complexity is **Option 1**. This option allows us to distribute the binaries for all supported architectures without introducing additional complexity of maintaining self hosted runners or implementing an in-house self-update mechanism for binaries. Additionally each individual package manager has unique capabilities simplifying aggregation of metrics and controlling the release process.
## Selected option
Option 1
## Next Steps
1. Splitting ADR into self contained work items to parallelize the implementation of the selected option
2. Productizing PoCs implemented as part of this ADR to finalize integrations with `winget`, `snap` and `brew`
3. Aggregating requirements for obtaining accesses to the package managers and developer certificates for codesigning
4. Implementing codesigning mechanisms and finalizing implementation with detailed documentation of new installation options for users
## Open questions
~~Do we want to build the binaries for ARM based windows machines? If so, this implies that we need to introduce self hosted runners for windows as well given that there seems to be no OSS options to build the binaries for ARM based windows machines in Github Actions.~~ Clarified by decision to not support ARM versions of linux and windows given alternative options like pipx still being available as a first class citizen.
```
--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/SDKs:javascript:classes:Indexer.md:
--------------------------------------------------------------------------------
```markdown
[algosdk](../README.md) / [Exports](../modules.md) / Indexer
# Class: Indexer
The Indexer provides a REST API interface of API calls to support searching the Algorand Blockchain.
The Indexer REST APIs retrieve the blockchain data from a PostgreSQL compatible database that must be populated.
This database is populated using the same indexer instance or a separate instance of the indexer which must connect to the algod process of a running Algorand node to read block data.
This node must also be an Archival node to make searching the entire blockchain possible.
#### Relevant Information
[Learn more about Indexer](https://developer.algorand.org/docs/get-details/indexer/)
[Run Indexer in Postman OAS3](https://developer.algorand.org/docs/rest-apis/restendpoints/#algod-indexer-and-kmd-rest-endpoints)
## Hierarchy
- `default`
↳ **`Indexer`**
## Table of contents
### Constructors
- [constructor](Indexer.md#constructor)
### GET Methods
- [lookupAccountAppLocalStates](Indexer.md#lookupaccountapplocalstates)
- [lookupAccountAssets](Indexer.md#lookupaccountassets)
- [lookupAccountByID](Indexer.md#lookupaccountbyid)
- [lookupAccountCreatedApplications](Indexer.md#lookupaccountcreatedapplications)
- [lookupAccountCreatedAssets](Indexer.md#lookupaccountcreatedassets)
- [lookupAccountTransactions](Indexer.md#lookupaccounttransactions)
- [lookupApplicationBoxByIDandName](Indexer.md#lookupapplicationboxbyidandname)
- [lookupApplicationLogs](Indexer.md#lookupapplicationlogs)
- [lookupApplications](Indexer.md#lookupapplications)
- [lookupAssetBalances](Indexer.md#lookupassetbalances)
- [lookupAssetByID](Indexer.md#lookupassetbyid)
- [lookupAssetTransactions](Indexer.md#lookupassettransactions)
- [lookupBlock](Indexer.md#lookupblock)
- [lookupTransactionByID](Indexer.md#lookuptransactionbyid)
- [makeHealthCheck](Indexer.md#makehealthcheck)
- [searchAccounts](Indexer.md#searchaccounts)
- [searchForApplicationBoxes](Indexer.md#searchforapplicationboxes)
- [searchForApplications](Indexer.md#searchforapplications)
- [searchForAssets](Indexer.md#searchforassets)
- [searchForTransactions](Indexer.md#searchfortransactions)
### Other Methods
- [getIntEncoding](Indexer.md#getintencoding)
- [setIntEncoding](Indexer.md#setintencoding)
## Constructors
### constructor
• **new Indexer**(`tokenOrBaseClient`, `baseServer?`, `port?`, `headers?`)
Create an IndexerClient from
* either a token, baseServer, port, and optional headers
* or a base client server for interoperability with external dApp wallets
#### Example
```typescript
const token = "";
const server = "http://localhost";
const port = 8980;
const indexerClient = new algosdk.Indexer(token, server, port);
```
#### Parameters
| Name | Type | Default value | Description |
| :------ | :------ | :------ | :------ |
| `tokenOrBaseClient` | `string` \| [`BaseHTTPClient`](../interfaces/BaseHTTPClient.md) \| [`IndexerTokenHeader`](../interfaces/IndexerTokenHeader.md) \| [`CustomTokenHeader`](../interfaces/CustomTokenHeader.md) | `undefined` | The API token for the Indexer API |
| `baseServer` | `string` | `'http://127.0.0.1'` | REST endpoint |
| `port` | `string` \| `number` | `8080` | Port number if specifically configured by the server |
| `headers` | `Record`\<`string`, `string`\> | `{}` | Optional headers |
**`Remarks`**
The above configuration is for a sandbox private network.
For applications on production, you are encouraged to run your own node with indexer, or use an Algorand REST API provider with a dedicated API key.
#### Overrides
ServiceClient.constructor
#### Defined in
client/v2/indexer/indexer.ts:64
## GET Methods
### lookupAccountAppLocalStates
▸ **lookupAccountAppLocalStates**(`account`): `default`
Returns application local state about the given account.
#### Example
```typescript
const address = "XBYLS2E6YI6XXL5BWCAMOA4GTWHXWENZMX5UHXMRNWWUQ7BXCY5WC5TEPA";
const accountAppLocalStates = await indexerClient.lookupAccountAppLocalStates(address).do();
```
[Response data schema details](https://developer.algorand.org/docs/rest-apis/indexer/#get-v2accountsaccount-idapps-local-state)
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `account` | `string` | The address of the account to look up. |
#### Returns
`default`
#### Defined in
client/v2/indexer/indexer.ts:242
___
### lookupAccountAssets
▸ **lookupAccountAssets**(`account`): `default`
Returns asset about the given account.
#### Example
```typescript
const address = "XBYLS2E6YI6XXL5BWCAMOA4GTWHXWENZMX5UHXMRNWWUQ7BXCY5WC5TEPA";
const accountAssets = await indexerClient.lookupAccountAssets(address).do();
```
[Response data schema details](https://developer.algorand.org/docs/rest-apis/indexer/#get-v2accountsaccount-idassets)
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `account` | `string` | The address of the account to look up. |
#### Returns
`default`
#### Defined in
client/v2/indexer/indexer.ts:208
___
### lookupAccountByID
▸ **lookupAccountByID**(`account`): `default`
Returns information about the given account.
#### Example
```typescript
const address = "XBYLS2E6YI6XXL5BWCAMOA4GTWHXWENZMX5UHXMRNWWUQ7BXCY5WC5TEPA";
const accountInfo = await indexerClient.lookupAccountByID(address).do();
```
[Response data schema details](https://developer.algorand.org/docs/rest-apis/indexer/#get-v2accountsaccount-id)
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `account` | `string` | The address of the account to look up. |
#### Returns
`default`
#### Defined in
client/v2/indexer/indexer.ts:191
___
### lookupAccountCreatedApplications
▸ **lookupAccountCreatedApplications**(`account`): `default`
Returns application information created by the given account.
#### Example
```typescript
const address = "XBYLS2E6YI6XXL5BWCAMOA4GTWHXWENZMX5UHXMRNWWUQ7BXCY5WC5TEPA";
const accountCreatedApps = await indexerClient.lookupAccountCreatedApplications(address).do();
```
[Response data schema details](https://developer.algorand.org/docs/rest-apis/indexer/#get-v2accountsaccount-idcreated-applications)
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `account` | `string` | The address of the account to look up. |
#### Returns
`default`
#### Defined in
client/v2/indexer/indexer.ts:259
___
### lookupAccountCreatedAssets
▸ **lookupAccountCreatedAssets**(`account`): `default`
Returns asset information created by the given account.
#### Example
```typescript
const address = "XBYLS2E6YI6XXL5BWCAMOA4GTWHXWENZMX5UHXMRNWWUQ7BXCY5WC5TEPA";
const accountCreatedAssets = await indexerClient.lookupAccountCreatedAssets(address).do();
```
[Response data schema details](https://developer.algorand.org/docs/rest-apis/indexer/#get-v2accountsaccount-idcreated-assets)
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `account` | `string` | The address of the account to look up. |
#### Returns
`default`
#### Defined in
client/v2/indexer/indexer.ts:225
___
### lookupAccountTransactions
▸ **lookupAccountTransactions**(`account`): `default`
Returns transactions relating to the given account.
#### Example
```typescript
const address = "XBYLS2E6YI6XXL5BWCAMOA4GTWHXWENZMX5UHXMRNWWUQ7BXCY5WC5TEPA";
const accountTxns = await indexerClient.lookupAccountTransactions(address).do();
```
[Response data schema details](https://developer.algorand.org/docs/rest-apis/indexer/#get-v2accountsaccount-idtransactions)
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `account` | `string` | The address of the account. |
#### Returns
`default`
#### Defined in
client/v2/indexer/indexer.ts:140
___
### lookupApplicationBoxByIDandName
▸ **lookupApplicationBoxByIDandName**(`appID`, `boxName`): `default`
Returns information about the application box given its name.
#### Example
```typescript
const boxName = Buffer.from("foo");
const boxResponse = await indexerClient
.LookupApplicationBoxByIDandName(1234, boxName)
.do();
const boxValue = boxResponse.value;
```
[Response data schema details](https://developer.algorand.org/docs/rest-apis/indexer/#get-v2applicationsapplication-idbox)
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `appID` | `number` | The ID of the application with boxes. |
| `boxName` | `Uint8Array` | - |
#### Returns
`default`
#### Defined in
client/v2/indexer/indexer.ts:424
___
### lookupApplicationLogs
▸ **lookupApplicationLogs**(`appID`): `default`
Returns log messages generated by the passed in application.
#### Example
```typescript
const appId = 60553466;
const appLogs = await indexerClient.lookupApplicationLogs(appId).do();
```
[Response data schema details](https://developer.algorand.org/docs/rest-apis/indexer/#get-v2applicationsapplication-idlogs)
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `appID` | `number` | The ID of the application which generated the logs. |
#### Returns
`default`
#### Defined in
client/v2/indexer/indexer.ts:314
___
### lookupApplications
▸ **lookupApplications**(`index`): `default`
Returns information about the passed application.
#### Example
```typescript
const appId = 60553466;
const appInfo = await indexerClient.lookupApplications(appId).do();
```
[Response data schema details](https://developer.algorand.org/docs/rest-apis/indexer/#get-v2applicationsapplication-id)
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `index` | `number` | The ID of the application to look up. |
#### Returns
`default`
#### Defined in
client/v2/indexer/indexer.ts:297
___
### lookupAssetBalances
▸ **lookupAssetBalances**(`index`): `default`
Returns the list of accounts who hold the given asset and their balance.
#### Example
```typescript
const assetId = 163650;
const assetBalances = await indexerClient.lookupAssetBalances(assetId).do();
```
[Response data schema details](https://developer.algorand.org/docs/rest-apis/indexer/#get-v2assetsasset-idbalances)
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `index` | `number` | The asset ID to look up. |
#### Returns
`default`
#### Defined in
client/v2/indexer/indexer.ts:106
___
### lookupAssetByID
▸ **lookupAssetByID**(`index`): `default`
Returns information about the passed asset.
#### Example
```typescript
const assetId = 163650;
const assetInfo = await indexerClient.lookupAssetByID(assetId).do();
```
[Response data schema details](https://developer.algorand.org/docs/rest-apis/indexer/#get-v2assetsasset-id)
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `index` | `number` | The ID of the asset ot look up. |
#### Returns
`default`
#### Defined in
client/v2/indexer/indexer.ts:280
___
### lookupAssetTransactions
▸ **lookupAssetTransactions**(`index`): `default`
Returns transactions relating to the given asset.
#### Example
```typescript
const assetId = 163650;
const assetTxns = await indexerClient.lookupAssetTransactions(assetId).do();
```
[Response data schema details](https://developer.algorand.org/docs/rest-apis/indexer/#get-v2assetsasset-idtransactions)
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `index` | `number` | The asset ID to look up. |
#### Returns
`default`
#### Defined in
client/v2/indexer/indexer.ts:123
___
### lookupBlock
▸ **lookupBlock**(`round`): `default`
Returns the block for the passed round.
#### Example
```typescript
const targetBlock = 18309917;
const blockInfo = await indexerClient.lookupBlock(targetBlock).do();
```
[Response data schema details](https://developer.algorand.org/docs/rest-apis/indexer/#get-v2blocksround-number)
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `round` | `number` | The number of the round to look up. |
#### Returns
`default`
#### Defined in
client/v2/indexer/indexer.ts:157
___
### lookupTransactionByID
▸ **lookupTransactionByID**(`txID`): `default`
Returns information about the given transaction.
#### Example
```typescript
const txnId = "MEUOC4RQJB23CQZRFRKYEI6WBO73VTTPST5A7B3S5OKBUY6LFUDA";
const txnInfo = await indexerClient.lookupTransactionByID(txnId).do();
```
[Response data schema details](https://developer.algorand.org/docs/rest-apis/indexer/#get-v2transactionstxid)
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `txID` | `string` | The ID of the transaction to look up. |
#### Returns
`default`
#### Defined in
client/v2/indexer/indexer.ts:174
___
### makeHealthCheck
▸ **makeHealthCheck**(): `default`
Returns the health object for the service.
Returns 200 if healthy.
#### Example
```typescript
const health = await indexerClient.makeHealthCheck().do();
```
[Response data schema details](https://developer.algorand.org/docs/rest-apis/indexer/#get-health)
#### Returns
`default`
#### Defined in
client/v2/indexer/indexer.ts:89
___
### searchAccounts
▸ **searchAccounts**(): `default`
Returns information about indexed accounts.
#### Example
```typescript
const accounts = await indexerClient.searchAccounts().do();
```
[Response data schema details](https://developer.algorand.org/docs/rest-apis/indexer/#get-v2accounts)
#### Returns
`default`
#### Defined in
client/v2/indexer/indexer.ts:329
___
### searchForApplicationBoxes
▸ **searchForApplicationBoxes**(`appID`): `default`
Returns information about indexed application boxes.
#### Example
```typescript
const maxResults = 20;
const appID = 1234;
const responsePage1 = await indexerClient
.searchForApplicationBoxes(appID)
.limit(maxResults)
.do();
const boxNamesPage1 = responsePage1.boxes.map(box => box.name);
const responsePage2 = await indexerClient
.searchForApplicationBoxes(appID)
.limit(maxResults)
.nextToken(responsePage1.nextToken)
.do();
const boxNamesPage2 = responsePage2.boxes.map(box => box.name);
```
[Response data schema details](https://developer.algorand.org/docs/rest-apis/indexer/#get-v2applicationsapplication-idboxes)
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `appID` | `number` | The ID of the application with boxes. |
#### Returns
`default`
#### Defined in
client/v2/indexer/indexer.ts:404
___
### searchForApplications
▸ **searchForApplications**(): `default`
Returns information about indexed applications.
#### Example
```typescript
const apps = await indexerClient.searchForApplications().do();
```
[Response data schema details](https://developer.algorand.org/docs/rest-apis/indexer/#get-v2applications)
#### Returns
`default`
#### Defined in
client/v2/indexer/indexer.ts:374
___
### searchForAssets
▸ **searchForAssets**(): `default`
Returns information about indexed assets.
#### Example
```typescript
const assets = await indexerClient.searchForAssets().do();
```
[Response data schema details](https://developer.algorand.org/docs/rest-apis/indexer/#get-v2assets)
#### Returns
`default`
#### Defined in
client/v2/indexer/indexer.ts:359
___
### searchForTransactions
▸ **searchForTransactions**(): `default`
Returns information about indexed transactions.
#### Example
```typescript
const txns = await indexerClient.searchForTransactions().do();
```
[Response data schema details](https://developer.algorand.org/docs/rest-apis/indexer/#get-v2transactions)
#### Returns
`default`
#### Defined in
client/v2/indexer/indexer.ts:344
___
## Other Methods
### getIntEncoding
▸ **getIntEncoding**(): [`IntDecoding`](../enums/IntDecoding.md)
Get the default int decoding method for all JSON requests this client creates.
#### Returns
[`IntDecoding`](../enums/IntDecoding.md)
#### Inherited from
ServiceClient.getIntEncoding
#### Defined in
client/v2/serviceClient.ts:86
___
### setIntEncoding
▸ **setIntEncoding**(`method`): `void`
Set the default int decoding method for all JSON requests this client creates.
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `method` | [`IntDecoding`](../enums/IntDecoding.md) | {"default" \| "safe" \| "mixed" \| "bigint"} method The method to use when parsing the response for request. Must be one of "default", "safe", "mixed", or "bigint". See JSONRequest.setIntDecoding for more details about what each method does. |
#### Returns
`void`
#### Inherited from
ServiceClient.setIntEncoding
#### Defined in
client/v2/serviceClient.ts:79
```
--------------------------------------------------------------------------------
/packages/server/src/tools/apiManager/ultrade/wallet.ts:
--------------------------------------------------------------------------------
```typescript
import { Tool, ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
import { ResponseProcessor } from '../../../utils/responseProcessor.js';
import { env } from '../../../env.js';
import algosdk from 'algosdk';
export const walletTools: Tool[] = [
// Signin
{
name: 'api_ultrade_wallet_signin_message',
description: 'Generate message from the sign in data',
inputSchema: {
type: 'object',
properties: {
data: {
type: 'object',
properties: {
address: { type: 'string', description: 'Login wallet address' },
technology: {
type: 'string',
description: 'Technology type',
enum: ['ALGORAND', 'EVM', 'SOLANA']
}
},
required: ['address', 'technology']
},
customMessage: {
type: 'string',
description: 'Custom signing message'
}
},
required: ['data']
}
},
{
name: 'api_ultrade_wallet_signin',
description: 'Sign in to trading account',
inputSchema: {
type: 'object',
properties: {
message: {
type: 'string',
description: 'The signed message in hex format'
},
signature: {
type: 'string',
description: 'The signature of the message'
},
data: {
type: 'object',
properties: {
address: { type: 'string' },
technology: {
type: 'string',
enum: ['ALGORAND', 'EVM', 'SOLANA']
}
},
required: ['address', 'technology']
},
referralToken: {
type: 'string',
description: 'Affiliate referral token'
}
},
required: ['message', 'signature', 'data']
}
},
// Key Management
{
name: 'api_ultrade_wallet_key_message',
description: 'Generate message from the trading key data',
inputSchema: {
type: 'object',
properties: {
tkAddress: {
type: 'string',
description: 'Trading key algorand address'
},
loginAddress: {
type: 'string',
description: 'Login wallet address'
},
loginChainId: {
type: 'number',
description: 'Wormhole chain id',
enum: [1, 8, 5, 4, 6, 23, 24, 30, 2, 10002, 10003, 10004, 10005, 10007]
},
expiredDate: {
type: 'number',
description: 'UTC timestamp in miliseconds; If not set then no expiration'
},
addKey: {
type: 'boolean',
description: 'Add a trading key if true, otherwise revoke'
},
type: {
type: 'string',
description: 'Type of trading key',
enum: ['User', 'API']
},
walletToken: {
type: 'string',
description: 'Login session token'
}
},
required: ['tkAddress', 'loginAddress', 'loginChainId', 'addKey', 'type', 'expiredDate', 'walletToken']
}
},
{
name: 'api_ultrade_wallet_add_key',
description: 'Add a trading key',
inputSchema: {
type: 'object',
properties: {
message: {
type: 'string',
description: 'The signed message in hex format'
},
signature: {
type: 'string',
description: 'The signature of the message'
},
walletToken: {
type: 'string',
description: 'Login session token'
},
tkAddress: {
type: 'string',
description: 'Trading key algorand address',
},
loginAddress: {
type: 'string',
description: 'Login wallet address',
},
loginChainId: {
type: 'number',
description: 'Wormhole chain id',
enum: [1, 8, 5, 4, 6, 23, 24, 30, 2, 10002, 10003, 10004, 10005, 10007]
},
expiredDate: {
type: 'number',
description: 'UTC timestamp in miliseconds; If not set then no expiration'
},
addKey: {
type: 'boolean',
description: 'Add a trading key if true, otherwise revoke'
},
type: {
type: 'string',
description: 'Type of trading key',
enum: ['User', 'API']
}
},
required: ['message', 'signature', 'walletToken', 'tkAddress', 'loginAddress', 'loginChainId', 'expiredDate', 'addKey', 'type']
}
},
{
name: 'api_ultrade_wallet_keys',
description: 'Get trading keys',
inputSchema: {
type: 'object',
properties: {
walletAddress: {
type: 'string',
description: 'Login wallet address'
},
walletToken: {
type: 'string',
description: 'Login session token'
}
},
required: ['walletAddress', 'walletToken']
}
},
{
name: 'api_ultrade_wallet_revoke_key',
description: 'Revoke a trading key',
inputSchema: {
type: 'object',
properties: {
message: {
type: 'string',
description: 'The signed message in hex format'
},
signature: {
type: 'string',
description: 'The signature of the message'
},
walletAddress: {
type: 'string',
description: 'Login wallet address'
},
walletToken: {
type: 'string',
description: 'Login session token'
}
},
required: ['message', 'signature', 'walletAddress', 'walletToken']
}
},
{
name: 'api_ultrade_wallet_withdraw',
description: 'Withdraw token',
inputSchema: {
type: 'object',
properties: {
message: {
type: 'string',
description: 'The signed message in hex format'
},
signature: {
type: 'string',
description: 'The signature of the message'
},
walletAddress: {
type: 'string',
description: 'Login wallet address'
},
walletToken: {
type: 'string',
description: 'Login session token'
}
},
required: ['message', 'signature', 'walletAddress', 'walletToken']
}
},
// Trades and Transactions
{
name: 'api_ultrade_wallet_trades',
description: 'Get filtered wallet trades',
inputSchema: {
type: 'object',
properties: {
walletAddress: {
type: 'string',
description: 'Login wallet address'
},
walletToken: {
type: 'string',
description: 'Login session token'
},
tradingKey: {
type: 'string',
description: 'Trading key address'
}
},
required: ['walletAddress']
}
},
{
name: 'api_ultrade_wallet_transactions',
description: 'Get filtered wallet transactions',
inputSchema: {
type: 'object',
properties: {
walletAddress: {
type: 'string',
description: 'Login wallet address'
},
walletToken: {
type: 'string',
description: 'Login session token'
},
tradingKey: {
type: 'string',
description: 'Trading key address'
}
},
required: ['walletAddress']
}
},
// Withdrawals
{
name: 'api_ultrade_wallet_withdraw_message',
description: 'Generate message from the withdrawal data',
inputSchema: {
type: 'object',
properties: {
data: {
type: 'object',
properties: {
loginAddress: { type: 'string' },
loginChainId: { type: 'number' },
tokenAmount: { type: 'string' },
tokenIndex: { type: 'string' },
tokenChainId: { type: 'number' },
recipient: { type: 'string' },
recipientChainId: { type: 'number' },
isNative: { type: 'boolean' },
fee: { type: 'number' }
},
required: ['loginAddress', 'loginChainId', 'tokenAmount', 'tokenIndex',
'tokenChainId', 'recipient', 'recipientChainId', 'isNative', 'fee']
},
customMessage: {
type: 'string',
description: 'The custom message visible to the user'
}
},
required: ['data']
}
}
];
interface RequestOptions {
method?: string;
headers?: Record<string, string>;
queryParams?: Record<string, any>;
body?: any;
}
async function makeRequest(endpoint: string, options: RequestOptions = {}): Promise<any> {
const { method = 'GET', headers = {}, queryParams = {}, body } = options;
try {
let url = `${env.ultrade_api_url}${endpoint}`;
// Add query parameters for GET requests
if (method === 'GET' && Object.keys(queryParams).length > 0) {
const params = new URLSearchParams();
for (const [key, value] of Object.entries(queryParams)) {
if (value !== undefined) {
params.append(key, String(value));
}
}
if (params.toString()) {
url += `?${params.toString()}`;
}
}
const requestOptions: RequestInit = {
method,
headers: {
'Content-Type': 'application/json',
...headers
}
};
if (body) {
requestOptions.body = JSON.stringify(body);
}
const response = await fetch(url, requestOptions);
if (!response.ok) {
throw new McpError(
ErrorCode.InternalError,
`Ultrade API error: ${response.status} ${response.statusText} ${await response.text()}`
);
}
let result: any;
const contentType = response.headers.get('Content-Type');
if (contentType && contentType.includes('application/json')) {
result = await response.json();
} else {
result = await response.text();
}
return result;
} catch (error) {
if (error instanceof McpError) {
throw error;
}
throw new McpError(
ErrorCode.InternalError,
`Failed to make request: ${error instanceof Error ? error.message : String(error)}`
);
}
}
async function getSigninMessage(data: { address: string; technology: string }, customMessage?: string): Promise<any> {
return makeRequest('/wallet/signin/message', {
method: 'POST',
body: { data, customMessage }
});
}
async function signin(message: string, signature: string, data: { address: string; technology: string }, referralToken?: string): Promise<any> {
return makeRequest('/wallet/signin', {
method: 'PUT',
headers: {
'companyId': '1'
},
body: { message, signature, data, referralToken }
});
}
async function getWalletKeys(auth: { walletAddress: string; walletToken: string }): Promise<any> {
return makeRequest('/wallet/keys', {
headers: {
'x-wallet-address': auth.walletAddress,
'x-wallet-token': auth.walletToken
}
});
}
async function getKeyMessage(params: {
tkAddress: string;
loginAddress: string;
loginChainId: number;
expiredDate?: number;
addKey: boolean;
type: 'User' | 'API';
walletToken: string;
}): Promise<any> {
let body = {
tkAddress: params.tkAddress,
loginAddress: params.loginAddress,
loginChainId:params.loginChainId || 8,
expiredDate: params.expiredDate,
addKey: params.addKey,
type: params.type
};
console.log( body)
const headers: Record<string, string> = {
'x-wallet-address': params.loginAddress,
'x-wallet-token': params.walletToken
};
return makeRequest('/wallet/key/message', {
method: 'POST',
body,
headers
});
}
async function addTradingKey(params: {
message: string;
signature: string;
walletToken: string;
tkAddress: string;
loginAddress: string;
loginChainId: number;
expiredDate?: number;
addKey: boolean;
type: 'User' | 'API';
}): Promise<any> {
console.log('public key: ', Buffer.from(algosdk.decodeAddress(params.loginAddress).publicKey).toString('hex'))
let body = {
message: params.message,
signature: params.signature,
data: {
tkAddress: params.tkAddress,
loginAddress: params.loginAddress,
expiredDate: params.expiredDate,
addKey: params.addKey,
type: params.type,
loginChainId: params.loginChainId || 8
},
}
console.log( body)
return makeRequest('/wallet/key', {
method: 'POST',
headers: {
'x-wallet-address': params.loginAddress,
'x-wallet-token': params.walletToken
},
body: body
});
}
async function revokeTradingKey(params: {
message: string;
signature: string;
walletAddress: string;
walletToken: string;
}): Promise<any> {
return makeRequest('/wallet/key', {
method: 'DELETE',
headers: {
'x-wallet-address': params.walletAddress,
'x-wallet-token': params.walletToken
},
body: {
message: params.message,
signature: params.signature
}
});
}
async function getWalletTrades(auth: { walletAddress: string; walletToken?: string; tradingKey?: string }): Promise<any> {
const headers: Record<string, string> = {
'x-wallet-address': auth.walletAddress
};
if (auth.walletToken) headers['x-wallet-token'] = auth.walletToken;
if (auth.tradingKey) headers['x-trading-key'] = auth.tradingKey;
return makeRequest('/wallet/trades', { headers });
}
async function getWalletTransactions(auth: { walletAddress: string; walletToken?: string; tradingKey?: string }): Promise<any> {
const headers: Record<string, string> = {
'x-wallet-address': auth.walletAddress
};
if (auth.walletToken) headers['x-wallet-token'] = auth.walletToken;
if (auth.tradingKey) headers['x-trading-key'] = auth.tradingKey;
return makeRequest('/wallet/transactions', { headers });
}
async function getWithdrawMessage(data: {
loginAddress: string;
loginChainId: number;
tokenAmount: string;
tokenIndex: string;
tokenChainId: number;
recipient: string;
recipientChainId: number;
isNative: boolean;
fee: number;
}, customMessage?: string): Promise<any> {
return makeRequest('/wallet/withdraw/message', {
method: 'POST',
body: { data, customMessage }
});
}
async function withdrawToken(params: {
message: string;
signature: string;
walletAddress: string;
walletToken: string;
}): Promise<any> {
return makeRequest('/wallet/withdraw', {
method: 'POST',
headers: {
'x-wallet-address': params.walletAddress,
'x-wallet-token': params.walletToken
},
body: {
message: params.message,
signature: params.signature
}
});
}
export async function handleWalletTools(args: any): Promise<any> {
switch (args.name) {
case 'api_ultrade_wallet_signin_message':
return await getSigninMessage(args.data, args.customMessage);
case 'api_ultrade_wallet_signin':
return await signin(args.message, args.signature, args.data, args.referralToken);
case 'api_ultrade_wallet_keys':
return await getWalletKeys({
walletAddress: args.walletAddress,
walletToken: args.walletToken
});
case 'api_ultrade_wallet_key_message':
return await getKeyMessage({
tkAddress: args.tkAddress,
loginAddress: args.loginAddress,
loginChainId: args.loginChainId,
expiredDate: args.expiredDate,
addKey: args.addKey,
type: args.type,
walletToken: args.walletToken
});
case 'api_ultrade_wallet_withdraw_message':
return await getWithdrawMessage(args.data, args.customMessage);
case 'api_ultrade_wallet_add_key':
return await addTradingKey(args);
case 'api_ultrade_wallet_trades':
return await getWalletTrades({
walletAddress: args.walletAddress,
walletToken: args.walletToken,
tradingKey: args.tradingKey
});
case 'api_ultrade_wallet_transactions':
return await getWalletTransactions({
walletAddress: args.walletAddress,
walletToken: args.walletToken,
tradingKey: args.tradingKey
});
case 'api_ultrade_wallet_revoke_key':
return await revokeTradingKey({
message: args.message,
signature: args.signature,
walletAddress: args.walletAddress,
walletToken: args.walletToken
});
case 'api_ultrade_wallet_withdraw':
return await withdrawToken({
message: args.message,
signature: args.signature,
walletAddress: args.walletAddress,
walletToken: args.walletToken
});
default:
throw new McpError(
ErrorCode.MethodNotFound,
`Unknown tool: ${args.name}`
);
}
}
```
--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/developer:docs:details:encoding.md:
--------------------------------------------------------------------------------
```markdown
title: Encoding and Decoding
When working with data from an algorand REST server or preparing transactions there is often a need to encode or decode fields.
## Encoding Types
### JSON
The encoding most often returned when querying the state of the chain is [JSON](https://www.json.org/json-en.html).
It is easy to visually inspect but may be relatively slow to parse.
All [byte arrays](#byte-arrays) are base 64 encoded strings
### MessagePack
The encoding used when transmitting transactions to a node is [MessagePack](https://msgpack.org/index.html)
To inspect a given msgpack file contents a convenience commandline tool is provided:
```sh
msgpacktool -d < file.msgp
```
### Base64
The encoding for byte arrays is [Base64](https://en.wikipedia.org/wiki/Base64).
This is to make it safe for the byte array to be transmitted as part of a json object.
### Base32
The encoding used for Addresses and Transaction Ids is [Base32](https://en.wikipedia.org/wiki/Base32)
## Individual Field encodings
### Address
In Algorand a [public key](../accounts/#transformation-public-key-to-algorand-address) is a 32 byte array.
The Address developers or users are typically shown is a 58 character long string corresponding to a base32 encoding of the byte array of the public key + a checksum.
Given an address `4H5UNRBJ2Q6JENAXQ6HNTGKLKINP4J4VTQBEPK5F3I6RDICMZBPGNH6KD4`, encoding to and from the public key format can be done as follows:
=== "JavaScript"
<!-- ===JSSDK_CODEC_ADDRESS=== -->
```javascript
const address = '4H5UNRBJ2Q6JENAXQ6HNTGKLKINP4J4VTQBEPK5F3I6RDICMZBPGNH6KD4';
const pk = algosdk.decodeAddress(address);
const addr = algosdk.encodeAddress(pk.publicKey);
console.log(address, addr);
```
[Snippet Source](https://github.com/algorand/js-algorand-sdk/blob/examples/examples/codec.ts#L16-L20)
<!-- ===JSSDK_CODEC_ADDRESS=== -->
=== "Python"
<!-- ===PYSDK_CODEC_ADDRESS=== -->
```python
address = "4H5UNRBJ2Q6JENAXQ6HNTGKLKINP4J4VTQBEPK5F3I6RDICMZBPGNH6KD4"
pk = encoding.decode_address(address)
addr = encoding.encode_address(pk)
assert addr == address
```
[Snippet Source](https://github.com/algorand/py-algorand-sdk/blob/examples/examples/codec.py#L8-L13)
<!-- ===PYSDK_CODEC_ADDRESS=== -->
=== "Go"
<!-- ===GOSDK_CODEC_ADDRESS=== -->
```go
address := "4H5UNRBJ2Q6JENAXQ6HNTGKLKINP4J4VTQBEPK5F3I6RDICMZBPGNH6KD4"
pk, _ := types.DecodeAddress(address)
addr := pk.String()
```
[Snippet Source](https://github.com/algorand/go-algorand-sdk/blob/examples/examples/codec/main.go#L69-L72)
<!-- ===GOSDK_CODEC_ADDRESS=== -->
=== "Java"
<!-- ===JAVASDK_CODEC_ADDRESS=== -->
```java
String addrAsStr = "4H5UNRBJ2Q6JENAXQ6HNTGKLKINP4J4VTQBEPK5F3I6RDICMZBPGNH6KD4";
// Instantiate a new Address object with string
Address addr = new Address(addrAsStr);
// Or with the bytes
Address addrAgain = new Address(addr.getBytes());
assert addrAgain.equals(addr);
```
[Snippet Source](https://github.com/algorand/java-algorand-sdk/blob/examples/examples/src/main/java/com/algorand/examples/CodecExamples.java#L26-L32)
<!-- ===JAVASDK_CODEC_ADDRESS=== -->
### Byte Arrays
When transmitting an array of bytes over the network, byte arrays are base64 encoded. The SDK will handle encoding from a byte array to base64 but may not decode some fields and you'll have to handle it yourself. For example compiled program results or the keys and values in a state delta in an application call will be returned as base64 encoded strings.
*Example:*
Given a base64 encoded byte array `SGksIEknbSBkZWNvZGVkIGZyb20gYmFzZTY0` it may be decoded as follows:
=== "JavaScript"
<!-- ===JSSDK_CODEC_BASE64=== -->
```javascript
const b64Encoded = 'SGksIEknbSBkZWNvZGVkIGZyb20gYmFzZTY0';
const b64Decoded = Buffer.from(b64Encoded, 'base64').toString();
console.log(b64Encoded, b64Decoded);
```
[Snippet Source](https://github.com/algorand/js-algorand-sdk/blob/examples/examples/codec.ts#L23-L26)
<!-- ===JSSDK_CODEC_BASE64=== -->
=== "Python"
<!-- ===PYSDK_CODEC_BASE64=== -->
```python
encoded_str = "SGksIEknbSBkZWNvZGVkIGZyb20gYmFzZTY0"
decoded_str = base64.b64decode(encoded_str).decode("utf-8")
print(decoded_str)
```
[Snippet Source](https://github.com/algorand/py-algorand-sdk/blob/examples/examples/codec.py#L24-L27)
<!-- ===PYSDK_CODEC_BASE64=== -->
=== "Go"
<!-- ===GOSDK_CODEC_BASE64=== -->
```go
encoded := "SGksIEknbSBkZWNvZGVkIGZyb20gYmFzZTY0"
decoded, _ := base64.StdEncoding.DecodeString(encoded)
reencoded := base64.StdEncoding.EncodeToString(decoded)
```
[Snippet Source](https://github.com/algorand/go-algorand-sdk/blob/examples/examples/codec/main.go#L84-L87)
<!-- ===GOSDK_CODEC_BASE64=== -->
=== "Java"
<!-- ===JAVASDK_CODEC_BASE64=== -->
```java
String encodedStr = "SGksIEknbSBkZWNvZGVkIGZyb20gYmFzZTY0";
byte[] decodedBytes = Encoder.decodeFromBase64(encodedStr);
String reEncodedStr = Encoder.encodeToBase64(decodedBytes);
assert encodedStr.equals(reEncodedStr);
```
[Snippet Source](https://github.com/algorand/java-algorand-sdk/blob/examples/examples/src/main/java/com/algorand/examples/CodecExamples.java#L35-L39)
<!-- ===JAVASDK_CODEC_BASE64=== -->
### Integers
Integers in algorand are almost always uint64, sometimes it's required to encode them as bytes. For example when passing them as application arguments in an ApplicationCallTransaction. When encoding an integer to pass as an application argument, the integer should be encoded as the big endian 8 byte representation of the integer value.
*Example:*
Given an integer `1337`, you may encode it as:
=== "JavaScript"
<!-- ===JSSDK_CODEC_UINT64=== -->
```javascript
const int = 1337;
const encoded = algosdk.encodeUint64(int);
const safeDecoded = algosdk.decodeUint64(encoded, 'safe');
const mixedDecoded = algosdk.decodeUint64(encoded, 'bigint');
console.log(int, encoded, safeDecoded, mixedDecoded);
```
[Snippet Source](https://github.com/algorand/js-algorand-sdk/blob/examples/examples/codec.ts#L29-L34)
<!-- ===JSSDK_CODEC_UINT64=== -->
=== "Python"
<!-- ===PYSDK_CODEC_UINT64=== -->
```python
val = 1337
encoded_uint = val.to_bytes(8, "big")
decoded_uint = int.from_bytes(encoded_uint, byteorder="big")
assert decoded_uint == val
```
[Snippet Source](https://github.com/algorand/py-algorand-sdk/blob/examples/examples/codec.py#L30-L34)
<!-- ===PYSDK_CODEC_UINT64=== -->
=== "Go"
<!-- ===GOSDK_CODEC_UINT64=== -->
```go
val := 1337
encodedInt := make([]byte, 8)
binary.BigEndian.PutUint64(encodedInt, uint64(val))
decodedInt := binary.BigEndian.Uint64(encodedInt)
// decodedInt == val
```
[Snippet Source](https://github.com/algorand/go-algorand-sdk/blob/examples/examples/codec/main.go#L91-L97)
<!-- ===GOSDK_CODEC_UINT64=== -->
=== "Java"
<!-- ===JAVASDK_CODEC_UINT64=== -->
```java
BigInteger val = BigInteger.valueOf(1337);
byte[] encodedVal = Encoder.encodeUint64(val);
BigInteger decodedVal = Encoder.decodeUint64(encodedVal);
assert val.equals(decodedVal);
```
[Snippet Source](https://github.com/algorand/java-algorand-sdk/blob/examples/examples/src/main/java/com/algorand/examples/CodecExamples.java#L42-L46)
<!-- ===JAVASDK_CODEC_UINT64=== -->
## Working with encoded structures
### Transaction
Sometimes an application needs to transmit a transaction or transaction group between the front end and back end. This can be done by msgpack encoding the transaction object on one side and msgpack decoding it on the other side. Often the msgpack'd bytes will be base64 encoded so that they can be safely transmitted in some json payload so we use that encoding here.
Essentially the encoding is:
`tx_byte_str = base64encode(msgpack_encode(tx_obj))`
and decoding is:
`tx_obj = msgpack_decode(base64decode(tx_byte_str))`
*Example*
Create a payment transaction from one account to another using suggested parameters and amount 10000, we write the msgpack encoded bytes
=== "JavaScript"
<!-- ===JSSDK_CODEC_TRANSACTION_UNSIGNED=== -->
```javascript
const txn = algosdk.makePaymentTxnWithSuggestedParamsFromObject({
from: sender.addr,
to: receiver.addr,
amount: 1e6,
suggestedParams,
});
const txnBytes = algosdk.encodeUnsignedTransaction(txn);
const txnB64 = Buffer.from(txnBytes).toString('base64');
// ...
const restoredTxn = algosdk.decodeUnsignedTransaction(
Buffer.from(txnB64, 'base64')
);
console.log(restoredTxn);
```
[Snippet Source](https://github.com/algorand/js-algorand-sdk/blob/examples/examples/codec.ts#L37-L51)
<!-- ===JSSDK_CODEC_TRANSACTION_UNSIGNED=== -->
<!-- ===JSSDK_CODEC_TRANSACTION_SIGNED=== -->
```javascript
const signedTxn = txn.signTxn(sender.privateKey);
const signedB64Txn = Buffer.from(signedTxn).toString('base64');
const restoredSignedTxn = algosdk.decodeSignedTransaction(
Buffer.from(signedB64Txn, 'base64')
);
console.log(restoredSignedTxn);
```
[Snippet Source](https://github.com/algorand/js-algorand-sdk/blob/examples/examples/codec.ts#L54-L60)
<!-- ===JSSDK_CODEC_TRANSACTION_SIGNED=== -->
=== "Python"
<!-- ===PYSDK_CODEC_TRANSACTION_UNSIGNED=== -->
```python
sp = algod_client.suggested_params()
pay_txn = transaction.PaymentTxn(acct.address, sp, acct.address, 10000)
# Write message packed transaction to disk
with open("pay.txn", "w") as f:
f.write(encoding.msgpack_encode(pay_txn))
# Read message packed transaction and decode it to a Transaction object
with open("pay.txn", "r") as f:
recovered_txn = encoding.msgpack_decode(f.read())
print(recovered_txn.dictify())
```
[Snippet Source](https://github.com/algorand/py-algorand-sdk/blob/examples/examples/codec.py#L40-L52)
<!-- ===PYSDK_CODEC_TRANSACTION_UNSIGNED=== -->
<!-- ===PYSDK_CODEC_TRANSACTION_SIGNED=== -->
```python
# Sign transaction
spay_txn = pay_txn.sign(acct.private_key)
# write message packed signed transaction to disk
with open("signed_pay.txn", "w") as f:
f.write(encoding.msgpack_encode(spay_txn))
# read message packed signed transaction into a SignedTransaction object
with open("signed_pay.txn", "r") as f:
recovered_signed_txn = encoding.msgpack_decode(f.read())
print(recovered_signed_txn.dictify())
```
[Snippet Source](https://github.com/algorand/py-algorand-sdk/blob/examples/examples/codec.py#L57-L68)
<!-- ===PYSDK_CODEC_TRANSACTION_SIGNED=== -->
=== "Go"
<!-- ===GOSDK_CODEC_TRANSACTION_UNSIGNED=== -->
```go
// Error handling omitted for brevity
sp, _ := algodClient.SuggestedParams().Do(context.Background())
ptxn, _ := transaction.MakePaymentTxn(
acct1.Address.String(), acct1.Address.String(), 10000, nil, "", sp,
)
// Encode the txn as bytes,
// if sending over the wire (like to a frontend) it should also be b64 encoded
encodedTxn := msgpack.Encode(ptxn)
os.WriteFile("pay.txn", encodedTxn, 0655)
var recoveredPayTxn = types.Transaction{}
msgpack.Decode(encodedTxn, &recoveredPayTxn)
log.Printf("%+v", recoveredPayTxn)
```
[Snippet Source](https://github.com/algorand/go-algorand-sdk/blob/examples/examples/codec/main.go#L28-L43)
<!-- ===GOSDK_CODEC_TRANSACTION_UNSIGNED=== -->
<!-- ===GOSDK_CODEC_TRANSACTION_SIGNED=== -->
```go
// Assuming we already have a pay transaction `ptxn`
// Sign the transaction
_, signedTxn, err := crypto.SignTransaction(acct1.PrivateKey, ptxn)
if err != nil {
log.Fatalf("failed to sign transaction: %s", err)
}
// Save the signed transaction to file
os.WriteFile("pay.stxn", signedTxn, 0644)
signedPayTxn := types.SignedTxn{}
err = msgpack.Decode(signedTxn, &signedPayTxn)
if err != nil {
log.Fatalf("failed to decode signed transaction: %s", err)
}
```
[Snippet Source](https://github.com/algorand/go-algorand-sdk/blob/examples/examples/codec/main.go#L46-L62)
<!-- ===GOSDK_CODEC_TRANSACTION_SIGNED=== -->
=== "Java"
<!-- ===JAVASDK_CODEC_TRANSACTION_UNSIGNED=== -->
```java
Response<TransactionParametersResponse> rsp = algodClient.TransactionParams().execute();
TransactionParametersResponse sp = rsp.body();
Transaction ptxn = Transaction.PaymentTransactionBuilder().suggestedParams(sp)
.sender(acct.getAddress()).receiver(acct.getAddress()).amount(100).build();
byte[] encodedTxn = Encoder.encodeToMsgPack(ptxn);
Transaction decodedTxn = Encoder.decodeFromMsgPack(encodedTxn, Transaction.class);
assert decodedTxn.equals(ptxn);
```
[Snippet Source](https://github.com/algorand/java-algorand-sdk/blob/examples/examples/src/main/java/com/algorand/examples/CodecExamples.java#L49-L58)
<!-- ===JAVASDK_CODEC_TRANSACTION_UNSIGNED=== -->
<!-- ===JAVASDK_CODEC_TRANSACTION_SIGNED=== -->
```java
SignedTransaction signedTxn = acct.signTransaction(ptxn);
byte[] encodedSignedTxn = Encoder.encodeToMsgPack(signedTxn);
SignedTransaction decodedSignedTransaction = Encoder.decodeFromMsgPack(encodedSignedTxn,
SignedTransaction.class);
assert decodedSignedTransaction.equals(signedTxn);
```
[Snippet Source](https://github.com/algorand/java-algorand-sdk/blob/examples/examples/src/main/java/com/algorand/examples/CodecExamples.java#L61-L67)
<!-- ===JAVASDK_CODEC_TRANSACTION_SIGNED=== -->
# ABI Encoding
All the SDKs support encoding and decoding of ABI values. The encoding is done using the [Algorand ABI specification](https://developer.algorand.org/docs/get-details/dapps/smart-contracts/ABI/).
=== "JavaScript"
<!-- ===JSSDK_CODEC_ABI==== -->
```javascript
const stringTupleCodec = algosdk.ABIType.from('(string,string)');
const stringTupleData = ['hello', 'world'];
const encodedTuple = stringTupleCodec.encode(stringTupleData);
console.log(Buffer.from(encodedTuple).toString('hex'));
const decodedTuple = stringTupleCodec.decode(encodedTuple);
console.log(decodedTuple); // ['hello', 'world']
const uintArrayCodec = algosdk.ABIType.from('uint64[]');
const uintArrayData = [1, 2, 3, 4, 5];
const encodedArray = uintArrayCodec.encode(uintArrayData);
console.log(Buffer.from(encodedArray).toString('hex'));
const decodeArray = uintArrayCodec.decode(encodedArray);
console.log(decodeArray); // [1, 2, 3, 4, 5]
```
[Snippet Source](https://github.com/algorand/js-algorand-sdk/blob/examples/examples/codec.ts#L63-L80)
<!-- ===JSSDK_CODEC_ABI==== -->
=== "Python"
<!-- ===PYSDK_CODEC_ABI==== -->
```python
from algosdk import abi
# generate a codec from the string representation of the ABI type
# in this case, a tuple of two strings
codec = abi.ABIType.from_string("(string,string)")
# encode the value to its ABI encoding with the codec
to_encode = ["hello", "world"]
encoded = codec.encode(to_encode)
print(encoded.hex())
# decode the value from its ABI encoding with the codec
decoded = codec.decode(encoded)
print(decoded) # prints ["hello", "world"]
# generate a codec for a uint64 array
uint_array_codec = abi.ABIType.from_string("uint64[]")
uint_array = [1, 2, 3, 4, 5]
encoded_array = uint_array_codec.encode(uint_array)
print(encoded_array.hex())
decoded_array = uint_array_codec.decode(encoded_array)
print(decoded_array) # prints [1, 2, 3, 4, 5]
```
[Snippet Source](https://github.com/algorand/py-algorand-sdk/blob/examples/examples/codec.py#L74-L97)
<!-- ===PYSDK_CODEC_ABI=== -->
=== "Go"
<!-- ===GOSDK_CODEC_ABI=== -->
```go
tupleCodec, _ := abi.TypeOf("(string,string)")
tupleVal := []string{"hello", "world"}
encodedTuple, _ := tupleCodec.Encode(tupleVal)
log.Printf("%x", encodedTuple)
decodedTuple, _ := tupleCodec.Decode(encodedTuple)
log.Printf("%v", decodedTuple) // [hello world]
arrCodec, _ := abi.TypeOf("uint64[]")
arrVal := []uint64{1, 2, 3, 4, 5}
encodedArr, _ := arrCodec.Encode(arrVal)
log.Printf("%x", encodedArr)
decodedArr, _ := arrCodec.Decode(encodedArr)
log.Printf("%v", decodedArr) // [1 2 3 4 5]
```
[Snippet Source](https://github.com/algorand/go-algorand-sdk/blob/examples/examples/codec/main.go#L101-L117)
<!-- ===GOSDK_CODEC_ABI=== -->
=== "Java"
<!-- ===JAVASDK_CODEC_ABI=== -->
```java
ABIType tupleCodec = ABIType.valueOf("(string,string)");
Object[] tupleData = new Object[] { "hello", "world" };
byte[] tupleEncoded = tupleCodec.encode(tupleData);
System.out.printf("Encoded: '%s'\n", Hex.encodeHexString(tupleEncoded));
Object tupleDecoded = tupleCodec.decode(tupleEncoded);
// prints [hello, world]
System.out.printf("Decoded: %s\n", Arrays.toString((Object[]) tupleDecoded));
ABIType arrCodec = ABIType.valueOf("uint64[]");
Object[] arrData = new Object[] { 1, 2, 3, 4, 5 };
byte[] arrEncoded = arrCodec.encode(arrData);
System.out.printf("Encoded: '%s'\n", Hex.encodeHexString(arrEncoded));
Object arrDecoded = arrCodec.decode(arrEncoded);
// prints [1, 2, 3, 4, 5]
System.out.printf("Decoded: %s\n", Arrays.toString((Object[]) arrDecoded));
```
[Snippet Source](https://github.com/algorand/java-algorand-sdk/blob/examples/examples/src/main/java/com/algorand/examples/CodecExamples.java#L70-L86)
<!-- ===JAVASDK_CODEC_ABI=== -->
```
--------------------------------------------------------------------------------
/packages/server/src/tools/transactionManager/assetTransactions.ts:
--------------------------------------------------------------------------------
```typescript
import {
Transaction,
makeAssetCreateTxnWithSuggestedParamsFromObject,
makeAssetConfigTxnWithSuggestedParamsFromObject,
makeAssetDestroyTxnWithSuggestedParamsFromObject,
makeAssetFreezeTxnWithSuggestedParamsFromObject,
makeAssetTransferTxnWithSuggestedParamsFromObject,
SuggestedParams
} from 'algosdk';
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
import { algodClient } from '../../algorand-client.js';
// Tool schemas
export const assetTransactionSchemas = {
makeAssetCreateTxn: {
type: 'object',
properties: {
from: { type: 'string', description: 'Sender address in standard Algorand format (58 characters)' },
total: { type: 'integer', description: 'Total number of base units of the asset to create' },
decimals: { type: 'integer', description: 'Number of decimals for display purposes (0-19)' },
defaultFrozen: { type: 'boolean', description: 'Whether accounts should be frozen by default' },
unitName: { type: 'string', optional: true, description: 'Short name for the asset (1-8 characters)' },
assetName: { type: 'string', optional: true, description: 'Full name of the asset (1-32 characters)' },
assetURL: { type: 'string', optional: true, description: 'URL where more information about the asset can be found' },
assetMetadataHash: { type: 'string', optional: true, description: 'Hash commitment of some sort of asset metadata (32-byte string)' },
manager: { type: 'string', optional: true, description: 'Address that can manage the asset configuration' },
reserve: { type: 'string', optional: true, description: 'Address holding reserve funds for the asset' },
freeze: { type: 'string', optional: true, description: 'Address that can freeze/unfreeze holder accounts' },
clawback: { type: 'string', optional: true, description: 'Address that can revoke the asset from holders' },
note: { type: 'string', optional: true, description: 'Transaction note field (up to 1000 bytes)' },
rekeyTo: { type: 'string', optional: true, description: 'Address to rekey the sender account to' }
},
required: ['from', 'total', 'decimals', 'defaultFrozen']
},
makeAssetConfigTxn: {
type: 'object',
properties: {
from: { type: 'string', description: 'Sender address in standard Algorand format (58 characters)' },
assetIndex: { type: 'integer', description: 'Index of the asset to reconfigure' },
manager: { type: 'string', optional: true, description: 'New address that can manage the asset configuration' },
reserve: { type: 'string', optional: true, description: 'New address holding reserve funds for the asset' },
freeze: { type: 'string', optional: true, description: 'New address that can freeze/unfreeze holder accounts' },
clawback: { type: 'string', optional: true, description: 'New address that can revoke the asset from holders' },
strictEmptyAddressChecking: { type: 'boolean', description: 'Whether to error if any provided address is empty' },
note: { type: 'string', optional: true, description: 'Transaction note field (up to 1000 bytes)' },
rekeyTo: { type: 'string', optional: true, description: 'Address to rekey the sender account to' }
},
required: ['from', 'assetIndex', 'strictEmptyAddressChecking']
},
makeAssetDestroyTxn: {
type: 'object',
properties: {
from: { type: 'string', description: 'Sender address in standard Algorand format (58 characters)' },
assetIndex: { type: 'integer', description: 'Index of the asset to destroy' },
note: { type: 'string', optional: true, description: 'Transaction note field (up to 1000 bytes)' },
rekeyTo: { type: 'string', optional: true, description: 'Address to rekey the sender account to' }
},
required: ['from', 'assetIndex']
},
makeAssetFreezeTxn: {
type: 'object',
properties: {
from: { type: 'string', description: 'Sender address in standard Algorand format (58 characters)' },
assetIndex: { type: 'integer', description: 'Index of the asset being frozen' },
freezeTarget: { type: 'string', description: 'Address of the account whose asset is being frozen/unfrozen' },
freezeState: { type: 'boolean', description: 'True to freeze the asset, false to unfreeze' },
note: { type: 'string', optional: true, description: 'Transaction note field (up to 1000 bytes)' },
rekeyTo: { type: 'string', optional: true, description: 'Address to rekey the sender account to' }
},
required: ['from', 'assetIndex', 'freezeTarget', 'freezeState']
},
makeAssetTransferTxn: {
type: 'object',
properties: {
from: { type: 'string', description: 'Sender address in standard Algorand format (58 characters)' },
to: { type: 'string', description: 'Recipient address in standard Algorand format (58 characters)' },
assetIndex: { type: 'integer', description: 'Index of the asset being transferred' },
amount: { type: 'integer', description: 'Amount of asset base units to transfer' },
note: { type: 'string', optional: true, description: 'Transaction note field (up to 1000 bytes)' },
closeRemainderTo: { type: 'string', optional: true, description: 'Address to send remaining asset balance to (close asset holding)' },
rekeyTo: { type: 'string', optional: true, description: 'Address to rekey the sender account to' }
},
required: ['from', 'to', 'assetIndex', 'amount']
}
};
// Tool definitions
export const assetTransactionTools = [
{
name: 'make_asset_create_txn',
description: 'Create an asset creation transaction',
inputSchema: assetTransactionSchemas.makeAssetCreateTxn,
},
{
name: 'make_asset_config_txn',
description: 'Create an asset configuration transaction',
inputSchema: assetTransactionSchemas.makeAssetConfigTxn,
},
{
name: 'make_asset_destroy_txn',
description: 'Create an asset destroy transaction',
inputSchema: assetTransactionSchemas.makeAssetDestroyTxn,
},
{
name: 'make_asset_freeze_txn',
description: 'Create an asset freeze transaction',
inputSchema: assetTransactionSchemas.makeAssetFreezeTxn,
},
{
name: 'make_asset_transfer_txn',
description: 'Create an asset transfer transaction',
inputSchema: assetTransactionSchemas.makeAssetTransferTxn,
}
];
export class AssetTransactionManager {
/**
* Creates an asset creation transaction
*/
static makeAssetCreateTxn(params: {
from: string;
note?: Uint8Array;
rekeyTo?: string;
suggestedParams: SuggestedParams;
total: number | bigint;
decimals: number;
defaultFrozen: boolean;
unitName?: string;
assetName?: string;
assetURL?: string;
assetMetadataHash?: string | Uint8Array;
manager?: string;
reserve?: string;
freeze?: string;
clawback?: string;
}): Transaction {
return makeAssetCreateTxnWithSuggestedParamsFromObject(params);
}
/**
* Creates an asset configuration transaction
*/
static makeAssetConfigTxn(params: {
from: string;
note?: Uint8Array;
rekeyTo?: string;
suggestedParams: SuggestedParams;
assetIndex: number;
manager?: string;
reserve?: string;
freeze?: string;
clawback?: string;
strictEmptyAddressChecking: boolean;
}): Transaction {
return makeAssetConfigTxnWithSuggestedParamsFromObject(params);
}
/**
* Creates an asset destroy transaction
*/
static makeAssetDestroyTxn(params: {
from: string;
note?: Uint8Array;
rekeyTo?: string;
suggestedParams: SuggestedParams;
assetIndex: number;
}): Transaction {
return makeAssetDestroyTxnWithSuggestedParamsFromObject(params);
}
/**
* Creates an asset freeze transaction
*/
static makeAssetFreezeTxn(params: {
from: string;
note?: Uint8Array;
rekeyTo?: string;
suggestedParams: SuggestedParams;
assetIndex: number;
freezeTarget: string;
freezeState: boolean;
}): Transaction {
return makeAssetFreezeTxnWithSuggestedParamsFromObject(params);
}
/**
* Creates an asset transfer transaction
*/
static makeAssetTransferTxn(params: {
from: string;
to: string;
closeRemainderTo?: string;
revocationTarget?: string;
amount: number | bigint;
note?: Uint8Array;
rekeyTo?: string;
suggestedParams: SuggestedParams;
assetIndex: number;
}): Transaction {
return makeAssetTransferTxnWithSuggestedParamsFromObject(params);
}
// Tool handlers
static async handleTool(name: string, args: Record<string, unknown>) {
const params = await algodClient.getTransactionParams().do();
const suggestedParams = { ...params, flatFee: true, fee: params.minFee };
switch (name) {
case 'make_asset_create_txn':
if (!args.from || typeof args.total !== 'number' || typeof args.decimals !== 'number' ||
typeof args.defaultFrozen !== 'boolean') {
throw new McpError(ErrorCode.InvalidParams, 'Invalid asset creation parameters');
}
// Create transaction with proper parameter handling
const createTxnParams: Record<string, any> = {
from: String(args.from),
total: Number(args.total),
decimals: Number(args.decimals),
defaultFrozen: Boolean(args.defaultFrozen),
fee: suggestedParams.fee,
firstRound: suggestedParams.firstRound,
lastRound: suggestedParams.lastRound,
genesisID: suggestedParams.genesisID,
genesisHash: suggestedParams.genesisHash,
type: 'acfg'
};
// Handle optional fields
if (typeof args.unitName === 'string') {
createTxnParams.unitName = args.unitName;
}
if (typeof args.assetName === 'string') {
createTxnParams.assetName = args.assetName;
}
if (typeof args.assetURL === 'string') {
createTxnParams.assetURL = args.assetURL;
}
if (typeof args.assetMetadataHash === 'string') {
const metadataBytes = new TextEncoder().encode(args.assetMetadataHash);
createTxnParams.assetMetadataHash = Buffer.from(metadataBytes).toString('base64');
}
if (typeof args.manager === 'string') {
createTxnParams.manager = args.manager;
}
if (typeof args.reserve === 'string') {
createTxnParams.reserve = args.reserve;
}
if (typeof args.freeze === 'string') {
createTxnParams.freeze = args.freeze;
}
if (typeof args.clawback === 'string') {
createTxnParams.clawback = args.clawback;
}
if (typeof args.note === 'string') {
const noteBytes = new TextEncoder().encode(args.note);
createTxnParams.note = Buffer.from(noteBytes).toString('base64');
}
if (typeof args.rekeyTo === 'string') {
createTxnParams.rekeyTo = args.rekeyTo;
}
return {
content: [{
type: 'text',
text: JSON.stringify(createTxnParams, null, 2),
}],
};
case 'make_asset_config_txn':
if (!args.from || typeof args.assetIndex !== 'number' || typeof args.strictEmptyAddressChecking !== 'boolean') {
throw new McpError(ErrorCode.InvalidParams, 'Invalid asset configuration parameters');
}
// Create transaction with proper parameter handling
const configTxnParams: Record<string, any> = {
from: String(args.from),
assetIndex: Number(args.assetIndex),
fee: suggestedParams.fee,
firstRound: suggestedParams.firstRound,
lastRound: suggestedParams.lastRound,
genesisID: suggestedParams.genesisID,
genesisHash: suggestedParams.genesisHash,
type: 'acfg',
strictEmptyAddressChecking: Boolean(args.strictEmptyAddressChecking)
};
// Handle optional fields
if (typeof args.manager === 'string') {
configTxnParams.manager = args.manager;
}
if (typeof args.reserve === 'string') {
configTxnParams.reserve = args.reserve;
}
if (typeof args.freeze === 'string') {
configTxnParams.freeze = args.freeze;
}
if (typeof args.clawback === 'string') {
configTxnParams.clawback = args.clawback;
}
if (typeof args.note === 'string') {
const noteBytes = new TextEncoder().encode(args.note);
configTxnParams.note = Buffer.from(noteBytes).toString('base64');
}
if (typeof args.rekeyTo === 'string') {
configTxnParams.rekeyTo = args.rekeyTo;
}
return {
content: [{
type: 'text',
text: JSON.stringify(configTxnParams, null, 2),
}],
};
case 'make_asset_destroy_txn':
if (!args.from || typeof args.assetIndex !== 'number') {
throw new McpError(ErrorCode.InvalidParams, 'Invalid asset destroy parameters');
}
// Create transaction with proper parameter handling
const destroyTxnParams: Record<string, any> = {
from: String(args.from),
assetIndex: Number(args.assetIndex),
fee: suggestedParams.fee,
firstRound: suggestedParams.firstRound,
lastRound: suggestedParams.lastRound,
genesisID: suggestedParams.genesisID,
genesisHash: suggestedParams.genesisHash,
type: 'acfg'
};
// Handle optional fields
if (typeof args.note === 'string') {
const noteBytes = new TextEncoder().encode(args.note);
destroyTxnParams.note = Buffer.from(noteBytes).toString('base64');
}
if (typeof args.rekeyTo === 'string') {
destroyTxnParams.rekeyTo = args.rekeyTo;
}
return {
content: [{
type: 'text',
text: JSON.stringify(destroyTxnParams, null, 2),
}],
};
case 'make_asset_freeze_txn':
if (!args.from || typeof args.assetIndex !== 'number' || !args.freezeTarget ||
typeof args.freezeState !== 'boolean') {
throw new McpError(ErrorCode.InvalidParams, 'Invalid asset freeze parameters');
}
// Create transaction with proper parameter handling
const freezeTxnParams: Record<string, any> = {
from: String(args.from),
assetIndex: Number(args.assetIndex),
freezeTarget: String(args.freezeTarget),
freezeState: Boolean(args.freezeState),
fee: suggestedParams.fee,
firstRound: suggestedParams.firstRound,
lastRound: suggestedParams.lastRound,
genesisID: suggestedParams.genesisID,
genesisHash: suggestedParams.genesisHash,
type: 'afrz'
};
// Handle optional fields
if (typeof args.note === 'string') {
const noteBytes = new TextEncoder().encode(args.note);
freezeTxnParams.note = Buffer.from(noteBytes).toString('base64');
}
if (typeof args.rekeyTo === 'string') {
freezeTxnParams.rekeyTo = args.rekeyTo;
}
return {
content: [{
type: 'text',
text: JSON.stringify(freezeTxnParams, null, 2),
}],
};
case 'make_asset_transfer_txn':
if (!args.from || !args.to || !args.assetIndex || typeof args.amount !== 'number') {
throw new McpError(ErrorCode.InvalidParams, 'Invalid asset transfer parameters');
}
// Create transaction with proper parameter handling
const transferTxnParams: Record<string, any> = {
from: String(args.from),
to: String(args.to),
assetIndex: Number(args.assetIndex),
amount: Number(args.amount),
fee: suggestedParams.fee,
firstRound: suggestedParams.firstRound,
lastRound: suggestedParams.lastRound,
genesisID: suggestedParams.genesisID,
genesisHash: suggestedParams.genesisHash,
type: 'axfer'
};
// Handle optional fields
if (typeof args.note === 'string') {
const noteBytes = new TextEncoder().encode(args.note);
transferTxnParams.note = Buffer.from(noteBytes).toString('base64');
}
if (typeof args.closeRemainderTo === 'string') {
transferTxnParams.closeRemainderTo = args.closeRemainderTo;
}
if (typeof args.rekeyTo === 'string') {
transferTxnParams.rekeyTo = args.rekeyTo;
}
return {
content: [{
type: 'text',
text: JSON.stringify(transferTxnParams, null, 2),
}],
};
default:
throw new McpError(
ErrorCode.MethodNotFound,
`Unknown asset transaction tool: ${name}`
);
}
}
}
```
--------------------------------------------------------------------------------
/packages/server/src/resources/knowledge/taxonomy/algokit-cli:README.md:
--------------------------------------------------------------------------------
```markdown
<div align="center">
<a href="https://github.com/algorandfoundation/algokit-cli"><img src="https://ipfs.algonode.xyz/ipfs/QmZqt55wHXrZzhBihSVzXDvwp9rguvLAvFhUm1qJR6GYeQ" width=60%></a>
</div>
<p align="center">
<a target="_blank" href="https://github.com/algorandfoundation/algokit-cli/blob/main/docs/algokit.md"><img src="https://img.shields.io/badge/docs-repository-00dc94?logo=github&style=flat.svg" /></a>
<a target="_blank" href="https://developer.algorand.org/algokit/"><img src="https://img.shields.io/badge/learn-AlgoKit-00dc94?logo=algorand&mac=flat.svg" /></a>
<a target="_blank" href="https://github.com/algorandfoundation/algokit-cli"><img src="https://img.shields.io/github/stars/algorandfoundation/algokit-cli?color=00dc94&logo=star&style=flat" /></a>
<a target="_blank" href="https://developer.algorand.org/algokit/"><img src="https://api.visitorbadge.io/api/visitors?path=https%3A%2F%2Fgithub.com%2Falgorandfoundation%2Falgokit-cli&countColor=%2300dc94&style=flat" /></a>
</p>
---
The Algorand AlgoKit CLI is the one-stop shop tool for developers building on the [Algorand network](https://www.algorand.com/).
AlgoKit gets developers of all levels up and running with a familiar, fun and productive development environment in minutes. The goal of AlgoKit is to help developers build and launch secure, automated production-ready applications rapidly.
[Install AlgoKit](#install) | [Quick Start Tutorial](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/tutorials/intro.md) | [Documentation](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/algokit.md)
## What is AlgoKit?
AlgoKit compromises of a number of components that make it the one-stop shop tool for developers building on the [Algorand network](https://www.algorand.com/).

AlgoKit can help you [**learn**](#learn), [**develop**](#develop) and [**operate**](#operate) Algorand solutions. It consists of [a number of repositories](https://github.com/search?q=org%3Aalgorandfoundation+algokit-&type=repositories), including this one.
### Learn
There are many learning resources on the [Algorand Developer Portal](https://developer.algorand.org/) and the [AlgoKit landing page](https://developer.algorand.org/algokit) has a range of links to more learning materials. In particular, check out the [quick start tutorial](https://developer.algorand.org/docs/get-started/algokit/) and the [AlgoKit detailed docs page](https://developer.algorand.org/docs/get-details/algokit/).
If you need help you can access both the [Algorand Discord](https://discord.gg/84AActu3at) (pro-tip: check out the algokit channel!) and the [Algorand Forum](https://forum.algorand.org/).
We have also developed an [AlgoKit video series](https://www.youtube.com/@algodevs/playlists).
### Develop
AlgoKit helps you develop Algorand solutions:
- **Interaction**: AlgoKit exposes a number of interaction methods, namely:
- [**AlgoKit CLI**](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/algokit.md): A Command Line Interface (CLI) so you can quickly access AlgoKit capabilities
- [VS Code](https://code.visualstudio.com/): All AlgoKit project templates include VS Code configurations so you have a smooth out-of-the-box development experience using VS Code
- [lora](https://lora.algokit.io/): AlgoKit has integrations with lora; a web-based user interface that let's you visualise and interact with an Algorand network
- **Getting Started**: AlgoKit helps you get started quickly when building new solutions:
- [**AlgoKit Templates**](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/init.md): Template libraries to get you started faster and quickly set up a productive dev experience
- **Development**: AlgoKit provides SDKs, tools and libraries that help you quickly and effectively build high quality Algorand solutions:
- **AlgoKit Utils** ([Python](https://github.com/algorandfoundation/algokit-utils-py#readme) | [TypeScript](https://github.com/algorandfoundation/algokit-utils-ts#readme)): A set of utility libraries so you can develop, test, build and deploy Algorand solutions quickly and easily
- [algosdk](https://developer.algorand.org/docs/sdks/) ([Python](https://github.com/algorand/py-algorand-sdk#readme) | [TypeScript](https://github.com/algorand/js-algorand-sdk#readme)) - The core Algorand SDK providing Algorand protocol API calls, which AlgoKit Utils wraps, but still exposes for advanced scenarios
- [**Algorand Python**](https://github.com/algorandfoundation/puya): A semantically and syntactically compatible, typed Python language that works with standard Python tooling and allows you to express smart contracts (apps) and smart signatures (logic signatures) for deployment on the Algorand Virtual Machine (AVM).
- [**TEALScript**](https://github.com/algorandfoundation/TEALScript): A subset of TypeScript that can be used to express smart contracts (apps) and smart signatures (logic signatures) for deployment on the Algorand Virtual Machine (AVM).
- [**AlgoKit LocalNet**](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/localnet.md): A local isolated Algorand network so you can simulate real transactions and workloads on your computer
### Operate
AlgoKit can help you deploy and operate Algorand solutions.
AlgoKit comes with out-of-the-box [Continuous Integration / Continuous Deployment (CI/CD) templates](https://github.com/algorandfoundation/algokit-python-template) that help you rapidly set up best-practice software delivery processes that ensure you build quality in and have a solution that can evolve
## What can AlgoKit help me do?
The set of capabilities supported by AlgoKit will evolve over time, but currently includes:
- Quickly run, explore and interact with an isolated local Algorand network (LocalNet)
- Building, testing, deploying and calling [Algorand Python](https://github.com/algorandfoundation/puya) / [TEALScript](https://github.com/algorandfoundation/TEALScript) smart contracts
For a user guide and guidance on how to use AlgoKit, please refer to the [docs](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/algokit.md).
Future capabilities are likely to include:
- Quickly deploy [standardised](https://github.com/algorandfoundation/ARCs/#arcs-algorand-requests-for-comments), audited smart contracts
- Building and deploying Algorand dApps
## Is this for me?
The target audience for this tool is software developers building applications on the Algorand network. A working knowledge of using a command line interfaces and experience using the supported programming languages is assumed.
## How can I contribute?
This is an open source project managed by the Algorand Foundation. See the [contributing page](https://github.com/algorandfoundation/algokit-cli/blob/main/CONTRIBUTING.md) to learn about making improvements to the CLI tool itself, including developer setup instructions.
# Install
> **Note** Refer to [Troubleshooting](#troubleshooting) for more details on mitigation of known edge cases when installing AlgoKit.
## Prerequisites
The key required dependency is Python 3.10+, but some of the installation options below will install that for you. We recommend using Python 3.12+, as the `algokit compile python` command requires this version.
> **Note**
> You can still install and use AlgoKit without these dependencies, and AlgoKit will tell you if you are missing one for a given command.
- **Git**: Essential for creating and updating projects from templates. Installation guide available at [Git Installation](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git).
- **Docker**: Necessary for running the AlgoKit LocalNet environment. Docker Compose version 2.5.0 or higher is required. See [Docker Installation](https://docs.docker.com/get-docker/).
- **Node.js**: For those working on frontend templates or building contracts using TEALScript. **Minimum required versions are Node.js `v18` and npm `v9`**. Instructions can be found at [Node.js Installation](https://nodejs.org/en/download/).
> **Note**
> If you have previously installed AlgoKit using `pipx` and would like to switch to a different installation method, please ensure that
> you first uninstall the existing version by running `pipx uninstall algokit`. Once uninstalled, you can follow the installation instructions for your preferred platform.
## Cross-platform installation
AlgoKit can be installed using OS specific package managers, or using the python tool [pipx](https://pypa.github.io/pipx/).
See below for specific installation instructions.
### Installation Methods
- [Windows](#install-algokit-on-windows)
- [Mac](#install-algokit-on-mac)
- [Linux](#install-algokit-on-linux)
- [pipx](#install-algokit-with-pipx-on-any-os)
## Install AlgoKit on Windows
> **Note**
> AlgoKit is supported on Windows 10 1709 (build 16299) and later.
> We only publish an x64 binary, however it also runs on ARM devices by default using the built in x64 emulation feature.
1. Ensure prerequisites are installed
- [WinGet](https://learn.microsoft.com/en-us/windows/package-manager/winget/) (should be installed by default on recent Windows 10 or later)
- [Git](https://github.com/git-guides/install-git#install-git-on-windows) (or `winget install git.git`)
- [Docker](https://docs.docker.com/desktop/install/windows-install/) (or `winget install docker.dockerdesktop`)
> **Note**
> See [our LocalNet documentation](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/localnet.md#prerequisites) for more tips on installing Docker on Windows
- [Microsoft C++ Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/)
2. Install using winget
```shell
winget install algokit
```
3. [Verify installation](#verify-installation)
### Maintenance
Some useful commands for updating or removing AlgoKit in the future.
- To update AlgoKit: `winget upgrade algokit`
- To remove AlgoKit: `winget uninstall algokit`
## Install AlgoKit on Mac
> **Note**
> AlgoKit is supported on macOS Big Sur (11) and later for both x64 and ARM (Apple Silicon)
1. Ensure prerequisites are installed
- [Homebrew](https://docs.brew.sh/Installation)
- [Git](https://github.com/git-guides/install-git#install-git-on-mac) (should already be available if `brew` is installed)
- [Docker](https://docs.docker.com/desktop/install/mac-install/), (or `brew install --cask docker`)
> **Note**
> Docker requires MacOS 11+
2. Install using Homebrew
```shell
brew install algorandfoundation/tap/algokit
```
3. Restart the terminal to ensure AlgoKit is available on the path
4. [Verify installation](#verify-installation)
### Maintenance
Some useful commands for updating or removing AlgoKit in the future.
- To update AlgoKit: `brew upgrade algokit`
- To remove AlgoKit: `brew uninstall algokit`
## Install AlgoKit on Linux
> **Note**
> AlgoKit is compatible with Ubuntu 16.04 and later, Debian, RedHat, and any distribution that supports [Snap](https://snapcraft.io/docs/installing-snapd), but it is only supported on x64 architecture; ARM is not supported.
1. Ensure prerequisites are installed
- [Snap](https://snapcraft.io/docs/installing-snapd) (should be installed by default on Ubuntu 16.04.4 LTS (Xenial Xerus) or later)
- [Git](https://github.com/git-guides/install-git#install-git-on-linux)
- [Docker](https://docs.docker.com/desktop/install/linux-install/)
2. Install using snap
```shell
sudo snap install algokit --classic
```
> For detailed guidelines per each supported linux distro, refer to [Snap Store](https://snapcraft.io/algokit).
3. [Verify installation](#verify-installation)
### Maintenance
Some useful commands for updating or removing AlgoKit in the future.
- To update AlgoKit: `snap refresh algokit`
- To remove AlgoKit: `snap remove --purge algokit`
## Install AlgoKit with pipx on any OS
1. Ensure desired prerequisites are installed
- [Python 3.10+](https://www.python.org/downloads/)
- [pipx](https://pypa.github.io/pipx/installation/)
- [Git](https://github.com/git-guides/install-git)
- [Docker](https://docs.docker.com/get-docker/)
2. Install using pipx
```shell
pipx install algokit
```
3. Restart the terminal to ensure AlgoKit is available on the path
4. [Verify installation](#verify-installation)
### Maintenance
Some useful commands for updating or removing AlgoKit in the future.
- To update AlgoKit: `pipx upgrade algokit`
- To remove AlgoKit: `pipx uninstall algokit`
## Verify installation
Verify AlgoKit is installed correctly by running `algokit --version` and you should see output similar to:
```
algokit, version 1.0.1
```
> **Note**
> If you get receive one of the following errors:
>
> - `command not found: algokit` (bash/zsh)
> - `The term 'algokit' is not recognized as the name of a cmdlet, function, script file, or operable program.` (PowerShell)
>
> Then ensure that `algokit` is available on the PATH by running `pipx ensurepath` and restarting the terminal.
It is also recommended that you run `algokit doctor` to verify there are no issues in your local environment and to diagnose any problems if you do have difficulties running AlgoKit. The output of this command will look similar to:
```
timestamp: 2023-03-27T01:23:45+00:00
AlgoKit: 1.0.1
AlgoKit Python: 3.11.1 (main, Dec 23 2022, 09:28:24) [Clang 14.0.0 (clang-1400.0.29.202)] (location: /Users/algokit/.local/pipx/venvs/algokit)
OS: macOS-13.1-arm64-arm-64bit
docker: 20.10.21
docker compose: 2.13.0
git: 2.37.1
python: 3.10.9 (location: /opt/homebrew/bin/python)
python3: 3.10.9 (location: /opt/homebrew/bin/python3)
pipx: 1.1.0
poetry: 1.3.2
node: 18.12.1
npm: 8.19.2
brew: 3.6.18
If you are experiencing a problem with AlgoKit, feel free to submit an issue via:
https://github.com/algorandfoundation/algokit-cli/issues/new
Please include this output, if you want to populate this message in your clipboard, run `algokit doctor -c`
```
Per the above output, the doctor command output is a helpful tool if you need to ask for support or [raise an issue](https://github.com/algorandfoundation/algokit-cli/issues/new).
## Troubleshooting
This section addresses specific edge cases and issues that some users might encounter when interacting with the CLI. The following table provides solutions to known edge cases:
| Issue Description | OS(s) with observed behaviour | Steps to mitigate | References |
| --------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- |
| This scenario may arise if installed `python` was build without `--with-ssl` flag enabled, causing pip to fail when trying to install dependencies. | Debian 12 | Run `sudo apt-get install -y libssl-dev` to install the required openssl dependency. Afterwards, ensure to reinstall python with `--with-ssl` flag enabled. This includes options like [building python from source code](https://medium.com/@enahwe/how-to-06bc8a042345) or using tools like [pyenv](https://github.com/pyenv/pyenv). | <https://github.com/actions/setup-python/issues/93> |
| `poetry install` invoked directly or via `algokit project bootstrap all` fails on `Could NOT find PkgConfig (missing: PKG_CONFIG_EXECUTABLE)`. | `MacOS` >=14 using `python` 3.13 installed via `homebrew` | Install dependencies deprecated in `3.13` and latest MacOS versions via `brew install pkg-config`, delete the virtual environment folder and retry the `poetry install` command invocation. | N/A |
```