This is page 22 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:utils:typescript:capabilities:transfer.md: -------------------------------------------------------------------------------- ```markdown # Algo transfers (payments) Algo transfers, or [payments](https://developer.algorand.org/docs/get-details/transactions/#payment-transaction), is a higher-order use case capability provided by AlgoKit Utils that builds on top of the core capabilities, particularly [Algo amount handling](./amount.md) and [Transaction management](./transaction.md). It allows you to easily initiate Algo transfers between accounts, including dispenser management and idempotent account funding. To see some usage examples check out the [automated tests](../../src/types/algorand-client.transfer.spec.ts). ## `payment` The key function to facilitate Algo transfers is `algorand.send.payment(params)` (immediately send a single payment transaction), `algorand.createTransaction.payment(params)` (construct a payment transaction), or `algorand.newGroup().addPayment(params)` (add payment to a group of transactions) per [`AlgorandClient`](./algorand-client.md) [transaction semantics](./algorand-client.md#creating-and-issuing-transactions). The base type for specifying a payment transaction is [`PaymentParams`](../code/modules/types_composer.md#paymentparams), which has the following parameters in addition to the [common transaction parameters](./algorand-client.md#transaction-parameters): - `receiver: string` - The address of the account that will receive the Algo - `amount: AlgoAmount` - The amount of Algo to send - `closeRemainderTo?: string` - If given, close the sender account and send the remaining balance to this address (**warning:** use this carefully as it can result in loss of funds if used incorrectly) ```typescript // Minimal example const result = await algorand.send.payment({ sender: 'SENDERADDRESS', receiver: 'RECEIVERADDRESS', amount: (4).algo(), }) // Advanced example const result2 = await algorand.send.payment({ sender: 'SENDERADDRESS', receiver: 'RECEIVERADDRESS', amount: (4).algo(), closeRemainderTo: 'CLOSEREMAINDERTOADDRESS', lease: 'lease', note: 'note', // Use this with caution, it's generally better to use algorand.account.rekeyAccount rekeyTo: 'REKEYTOADDRESS', // You wouldn't normally set this field firstValidRound: 1000n, validityWindow: 10, extraFee: (1000).microAlgo(), staticFee: (1000).microAlgo(), // Max fee doesn't make sense with extraFee AND staticFee // already specified, but here for completeness maxFee: (3000).microAlgo(), // Signer only needed if you want to provide one, // generally you'd register it with AlgorandClient // against the sender and not need to pass it in signer: transactionSigner, maxRoundsToWaitForConfirmation: 5, suppressLog: true, }) ``` ## `ensureFunded` The `ensureFunded` function automatically funds an account to maintain a minimum amount of [disposable Algo](https://developer.algorand.org/docs/get-details/accounts/#minimum-balance). This is particularly useful for automation and deployment scripts that get run multiple times and consume Algo when run. There are 3 variants of this function: - [`algorand.account.ensureFunded(accountToFund, dispenserAccount, minSpendingBalance, options?)`](../code/classes/types_account_manager.AccountManager.md#ensurefunded) - Funds a given account using a dispenser account as a funding source such that the given account has a certain amount of Algo free to spend (accounting for Algo locked in minimum balance requirement). - [`algorand.account.ensureFundedFromEnvironment(accountToFund, minSpendingBalance, options?)`](../code/classes/types_account_manager.AccountManager.md#ensurefundedfromenvironment) - Funds a given account using a dispenser account retrieved from the environment, per the [`dispenserFromEnvironment`](#dispenser) method, as a funding source such that the given account has a certain amount of Algo free to spend (accounting for Algo locked in minimum balance requirement). - **Note:** requires a Node.js environment to execute. - The dispenser account is retrieved from the account mnemonic stored in `process.env.DISPENSER_MNEMONIC` and optionally `process.env.DISPENSER_SENDER` if it's a rekeyed account, or against default LocalNet if no environment variables present. - [`algorand.account.ensureFundedFromTestNetDispenserApi(accountToFund, dispenserClient, minSpendingBalance, options)`](../code/classes/types_account_manager.AccountManager.md#ensurefundedfromtestnetdispenserapi) - Funds a given account using the [TestNet Dispenser API](https://github.com/algorandfoundation/algokit/blob/main/docs/testnet_api.md) as a funding source such that the account has a certain amount of Algo free to spend (accounting for Algo locked in minimum balance requirement). The general structure of these calls is similar, they all take: - `accountToFund: string | TransactionSignerAccount` - Address or signing account of the account to fund - The source (dispenser): - In `ensureFunded`: `dispenserAccount: string | TransactionSignerAccount` - the address or signing account of the account to use as a dispenser - In `ensureFundedFromEnvironment`: Not specified, loaded automatically from the ephemeral environment - In `ensureFundedFromTestNetDispenserApi`: `dispenserClient: TestNetDispenserApiClient` - a client instance of the [TestNet dispenser API](./dispenser-client.md) - `minSpendingBalance: AlgoAmount` - The minimum balance of Algo that the account should have available to spend (i.e., on top of the minimum balance requirement) - An `options` object, which has: - [Common transaction parameters](./algorand-client.md#transaction-parameters) (not for TestNet Dispenser API) - [Execution parameters](./algorand-client.md#sending-a-single-transaction) (not for TestNet Dispenser API) - `minFundingIncrement?: AlgoAmount` - When issuing a funding amount, the minimum amount to transfer; this avoids many small transfers if this function gets called often on an active account ### Examples ```typescript // From account // Basic example await algorand.account.ensureFunded('ACCOUNTADDRESS', 'DISPENSERADDRESS', (1).algo()) // With configuration await algorand.account.ensureFunded('ACCOUNTADDRESS', 'DISPENSERADDRESS', (1).algo(), { minFundingIncrement: (2).algo(), fee: (1000).microAlgo(), suppressLog: true, }) // From environment // Basic example await algorand.account.ensureFundedFromEnvironment('ACCOUNTADDRESS', (1).algo()) // With configuration await algorand.account.ensureFundedFromEnvironment('ACCOUNTADDRESS', (1).algo(), { minFundingIncrement: (2).algo(), fee: (1000).microAlgo(), suppressLog: true, }) // TestNet Dispenser API // Basic example await algorand.account.ensureFundedUsingDispenserAPI('ACCOUNTADDRESS', algorand.client.getTestNetDispenserFromEnvironment(), (1).algo()) // With configuration await algorand.account.ensureFundedUsingDispenserAPI('ACCOUNTADDRESS', algorand.client.getTestNetDispenserFromEnvironment(), (1).algo(), { minFundingIncrement: (2).algo(), }) ``` All 3 variants return an [`EnsureFundedReturnType`](../code/modules/types_account_manager.md#) (and the first two also return a [single transaction result](./algorand-client.md#sending-a-single-transaction)) if a funding transaction was needed, or `undefined` if no transaction was required: - `amountFunded: AlgoAmount` - The number of Algo that was paid - `transactionId: string` - The ID of the transaction that funded the account If you are using the TestNet Dispenser API then the `transactionId` is useful if you want to use the [refund functionality](./dispenser-client.md#registering-a-refund). ## Dispenser If you want to programmatically send funds to an account so it can transact then you will often need a "dispenser" account that has a store of Algo that can be sent and a private key available for that dispenser account. There's a number of ways to get a dispensing account in AlgoKit Utils: - Get a dispenser via [account manager](./account.md#dispenser) - either automatically from [LocalNet](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/localnet.md) or from the environment - By programmatically creating one of the many account types via [account manager](./account.md#accounts) - By programmatically interacting with [KMD](./account.md#kmd-account-management) if running against LocalNet - By using the [AlgoKit TestNet Dispenser API client](./dispenser-client.md) which can be used to fund accounts on TestNet via a dedicated API service ``` -------------------------------------------------------------------------------- /packages/server/src/resources/knowledge/taxonomy/developer:docs:sdks:python:index.md: -------------------------------------------------------------------------------- ```markdown title: Python SDK: Your first transaction This section is a quick start guide for interacting with the Algorand network using Python. This guide will help to install [Algorand sandbox](https://github.com/algorand/sandbox){target=blank}, which provides a node for testing and development. This guide will also help to install the Python SDK, create an account and submit your first transaction on Algorand. # Install Sandbox !!! info This step is only required if you are not using AlgoKit. If you are using AlgoKit, you can spin up a sandbox using the LocalNet, see [AlgoKit getting started guide](/docs/get-started/algokit/#start-a-localnet) for more information. !!! Prerequisites - Docker Compose ([install guide](https://docs.docker.com/compose/install/){target=_blank}) - Git ([install guide](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git){target=_blank}) Algorand provides a docker instance for setting up a node, which can be used to get started developing quickly. To install and use this instance, follow these instructions. ```bash git clone https://github.com/algorand/sandbox.git cd sandbox ./sandbox up dev ``` This will install and start private network. To read more about Algorand networks see [Algorand Networks](../../get-details/algorand-networks/index.md){target=_blank}. [More Information about the sandbox](https://developer.algorand.org/articles/introducing-sandbox-20/) and [how to use](https://developer.algorand.org/tutorials/exploring-the-algorand-sandbox/) it. # Install Python SDK Algorand provides an SDK for Python which is available as a pip package. To install the Python SDK, open a terminal and run the following command: ``` bash pip3 install py-algorand-sdk ``` The [GitHub repository](https://github.com/algorand/py-algorand-sdk){target=_blank} contains additional documentation and examples. See the Python SDK [reference documentation](https://py-algorand-sdk.readthedocs.io/en/latest/){target=_blank} for more information on methods. The SDK is installed and can now interact with the Sandbox created earlier. # Create an Account In order to interact with the Algorand blockchain, you must have a funded account. To quickly create a test account use the following code. <!-- ===PYSDK_ACCOUNT_GENERATE=== --> ```python private_key, address = account.generate_account() print(f"address: {address}") print(f"private key: {private_key}") print(f"mnemonic: {mnemonic.from_private_key(private_key)}") ``` [Snippet Source](https://github.com/algorand/py-algorand-sdk/blob/examples/examples/account.py#L5-L9) <!-- ===PYSDK_ACCOUNT_GENERATE=== --> [`More Information`](../../get-details/accounts/create.md#standalone){target=_blank} !!! Warning Never share mnemonic and private key. Production environments require stringent private key management. For more information on key management in community Wallets, click [here](https://developer.algorand.org/docs/community/#wallets){target=_blank}. For the [Algorand open source wallet](https://developer.algorand.org/articles/algorand-wallet-now-open-source/){target=_blank}, click [here](https://github.com/algorand/algorand-wallet){target=_blank}. # Fund the Account Before sending transactions to the Algorand network, the account must be funded to cover the minimal transaction fees that exist on Algorand. In this example, we'll be using prefunded accounts available in the Sandbox. To fund an account on Testnet account use the [Algorand faucet](https://dispenser.testnet.aws.algodev.network/){target=_blank}. !!! Info All Algorand accounts require a minimum balance to be registered in the ledger. To read more about Algorand minimum balance, see [Account Overview](../../get-details/accounts/index.md#minimum-balance){target=_blank}. # Connect Your Client An Algod client must be instantiated prior to making calls to the API endpoints. You must provide values for `<algod-address>` and `<algod-token>`. The CLI tools implement the client natively. By default, the `algod_token` for each [sandbox](https://github.com/algorand/sandbox) is set to its `aaa...` value and the `algod_address` corresponds to `http://localhost:4001`. <!-- ===PYSDK_ALGOD_CREATE_CLIENT=== --> ```python # Create a new algod client, configured to connect to our local sandbox algod_address = "http://localhost:4001" algod_token = "a" * 64 algod_client = algod.AlgodClient(algod_token, algod_address) # Or, if necessary, pass alternate headers # Create a new client with an alternate api key header special_algod_client = algod.AlgodClient( "", algod_address, headers={"X-API-Key": algod_token} ) ``` [Snippet Source](https://github.com/algorand/py-algorand-sdk/blob/examples/examples/overview.py#L10-L21) <!-- ===PYSDK_ALGOD_CREATE_CLIENT=== --> !!! Info The example code connects to the sandbox Algod client. If you want to connect to a public API client, change the host, port, and token parameters to match the API service. See some service available [here](https://developer.algorand.org/ecosystem-projects/?tags=api-services) !!! Info If you are connecting to the Testnet, a dispenser is available [here](https://dispenser.testnet.aws.algodev.network/){target=_blank} # Check Your Balance Before moving on to the next step, make sure your account has been funded. <!-- ===PYSDK_ALGOD_FETCH_ACCOUNT_INFO=== --> ```python account_info: Dict[str, Any] = algod_client.account_info(address) print(f"Account balance: {account_info.get('amount')} microAlgos") ``` [Snippet Source](https://github.com/algorand/py-algorand-sdk/blob/examples/examples/overview.py#L33-L35) <!-- ===PYSDK_ALGOD_FETCH_ACCOUNT_INFO=== --> # Build First Transaction Transactions are used to interact with the Algorand network. To create a payment transaction use the following code. <!-- ===PYSDK_TRANSACTION_PAYMENT_CREATE=== --> ```python # grab suggested params from algod using client # includes things like suggested fee and first/last valid rounds params = algod_client.suggested_params() unsigned_txn = transaction.PaymentTxn( sender=address, sp=params, receiver=address2, amt=1000000, note=b"Hello World", ) ``` [Snippet Source](https://github.com/algorand/py-algorand-sdk/blob/examples/examples/overview.py#L39-L49) <!-- ===PYSDK_TRANSACTION_PAYMENT_CREATE=== --> !!! Info Algorand supports many transaction types. To see what types are supported see [Transactions](../../get-details/transactions/index.md#transaction-types){target=_blank}. # Sign First Transaction Before the transaction is considered valid, it must be signed by a private key. Use the following code to sign the transaction. <!-- ===PYSDK_TRANSACTION_PAYMENT_SIGN=== --> ```python # sign the transaction signed_txn = unsigned_txn.sign(private_key) ``` [Snippet Source](https://github.com/algorand/py-algorand-sdk/blob/examples/examples/overview.py#L52-L54) <!-- ===PYSDK_TRANSACTION_PAYMENT_SIGN=== --> !!! Info Algorand provides many ways to sign transactions. To see other ways see [Authorization](../../get-details/transactions/signatures.md#single-signatures){target=_blank}. # Submit the Transaction The signed transaction can now be submitted to the network. `wait_for_confirmation` SDK Method is called after the transaction is submitted to wait until the transaction is broadcast to the Algorand blockchain and is confirmed. <!-- ===PYSDK_TRANSACTION_PAYMENT_SUBMIT=== --> ```python # submit the transaction and get back a transaction id txid = algod_client.send_transaction(signed_txn) print("Successfully submitted transaction with txID: {}".format(txid)) # wait for confirmation txn_result = transaction.wait_for_confirmation(algod_client, txid, 4) print(f"Transaction information: {json.dumps(txn_result, indent=4)}") print(f"Decoded note: {b64decode(txn_result['txn']['txn']['note'])}") ``` [Snippet Source](https://github.com/algorand/py-algorand-sdk/blob/examples/examples/overview.py#L57-L66) <!-- ===PYSDK_TRANSACTION_PAYMENT_SUBMIT=== --> # View the Transaction To view the transaction we submitted to the sandbox Algod, open [Lora](https://lora.algokit.io/localnet){target=_blank} and choose `LocalNet` configuration option, then search for the transaction ID. To view a transaction submitted to public network like testnet, open [Lora](https://lora.algokit.io/testnet){target=_blank} or [Pera Explorer](https://testnet.explorer.perawallet.app/){target=blank} and paste the transaction ID into the search bar. ``` -------------------------------------------------------------------------------- /packages/server/src/resources/knowledge/taxonomy-categories/algokit-utils.json: -------------------------------------------------------------------------------- ```json { "name": "AlgoKit Utils", "description": "Utility libraries for Algorand development", "path": "algokit:utils", "subcategories": { "python": { "name": "Python Utils", "description": "Python utility libraries for Algorand development", "path": "algokit:utils:python", "documents": [ {"name": "README", "path": "algokit:utils:python:README.md"} ], "subcategories": { "markdown": { "name": "Documentation", "description": "Python utils documentation", "path": "algokit:utils:python:markdown", "documents": [ {"name": "Index", "path": "algokit:utils:python:markdown:index.md"} ], "subcategories": { "capabilities": { "name": "Capabilities", "description": "Core functionality documentation", "path": "algokit:utils:python:markdown:capabilities", "documents": [ {"name": "Account", "path": "algokit:utils:python:markdown:capabilities:account.md"}, {"name": "App Client", "path": "algokit:utils:python:markdown:capabilities:app-client.md"}, {"name": "App Deploy", "path": "algokit:utils:python:markdown:capabilities:app-deploy.md"}, {"name": "Client", "path": "algokit:utils:python:markdown:capabilities:client.md"}, {"name": "Debugger", "path": "algokit:utils:python:markdown:capabilities:debugger.md"}, {"name": "Dispenser Client", "path": "algokit:utils:python:markdown:capabilities:dispenser-client.md"}, {"name": "Transfer", "path": "algokit:utils:python:markdown:capabilities:transfer.md"} ] } } }, "source": { "name": "Source Documentation", "description": "Source code documentation", "path": "algokit:utils:python:source", "documents": [ {"name": "Index", "path": "algokit:utils:python:source:index.md"} ], "subcategories": { "capabilities": { "name": "Capabilities", "description": "Source code documentation for core functionality", "path": "algokit:utils:python:source:capabilities", "documents": [ {"name": "Account", "path": "algokit:utils:python:source:capabilities:account.md"}, {"name": "App Client", "path": "algokit:utils:python:source:capabilities:app-client.md"}, {"name": "App Deploy", "path": "algokit:utils:python:source:capabilities:app-deploy.md"}, {"name": "Client", "path": "algokit:utils:python:source:capabilities:client.md"}, {"name": "Debugger", "path": "algokit:utils:python:source:capabilities:debugger.md"}, {"name": "Dispenser Client", "path": "algokit:utils:python:source:capabilities:dispenser-client.md"}, {"name": "Transfer", "path": "algokit:utils:python:source:capabilities:transfer.md"} ] } } } } }, "typescript": { "name": "TypeScript Utils", "description": "TypeScript utility libraries for Algorand development", "path": "algokit:utils:typescript", "documents": [ {"name": "README", "path": "algokit:utils:typescript:README.md"}, {"name": "V7 Migration", "path": "algokit:utils:typescript:v7-migration.md"}, {"name": "V8 Migration", "path": "algokit:utils:typescript:v8-migration.md"} ], "subcategories": { "capabilities": { "name": "Capabilities", "description": "Core functionality documentation", "path": "algokit:utils:typescript:capabilities", "documents": [ {"name": "Account", "path": "algokit:utils:typescript:capabilities:account.md"}, {"name": "Algorand Client", "path": "algokit:utils:typescript:capabilities:algorand-client.md"}, {"name": "Amount", "path": "algokit:utils:typescript:capabilities:amount.md"}, {"name": "App Client", "path": "algokit:utils:typescript:capabilities:app-client.md"}, {"name": "App Deploy", "path": "algokit:utils:typescript:capabilities:app-deploy.md"}, {"name": "App", "path": "algokit:utils:typescript:capabilities:app.md"}, {"name": "Asset", "path": "algokit:utils:typescript:capabilities:asset.md"}, {"name": "Client", "path": "algokit:utils:typescript:capabilities:client.md"}, {"name": "Debugging", "path": "algokit:utils:typescript:capabilities:debugging.md"}, {"name": "Dispenser Client", "path": "algokit:utils:typescript:capabilities:dispenser-client.md"}, {"name": "Event Emitter", "path": "algokit:utils:typescript:capabilities:event-emitter.md"}, {"name": "Indexer", "path": "algokit:utils:typescript:capabilities:indexer.md"}, {"name": "Testing", "path": "algokit:utils:typescript:capabilities:testing.md"}, {"name": "Transaction Composer", "path": "algokit:utils:typescript:capabilities:transaction-composer.md"}, {"name": "Transaction", "path": "algokit:utils:typescript:capabilities:transaction.md"}, {"name": "Transfer", "path": "algokit:utils:typescript:capabilities:transfer.md"}, {"name": "Typed App Clients", "path": "algokit:utils:typescript:capabilities:typed-app-clients.md"} ] }, "code": { "name": "API Reference", "description": "Detailed API documentation", "path": "algokit:utils:typescript:code", "documents": [ {"name": "README", "path": "algokit:utils:typescript:code:README.md"} ], "subcategories": { "classes": { "name": "Classes", "description": "Class documentation", "path": "algokit:utils:typescript:code:classes", "documents": [ {"name": "AccountManager", "path": "algokit:utils:typescript:code:classes:types_account_manager.AccountManager.md"}, {"name": "AlgoAmount", "path": "algokit:utils:typescript:code:classes:types_amount.AlgoAmount.md"}, {"name": "AlgorandClient", "path": "algokit:utils:typescript:code:classes:types_algorand_client.AlgorandClient.md"}, {"name": "ApplicationClient", "path": "algokit:utils:typescript:code:classes:types_app_client.ApplicationClient.md"}, {"name": "AsyncEventEmitter", "path": "algokit:utils:typescript:code:classes:types_async_event_emitter.AsyncEventEmitter.md"}, {"name": "LogicError", "path": "algokit:utils:typescript:code:classes:types_logic_error.LogicError.md"}, {"name": "TestLogger", "path": "algokit:utils:typescript:code:classes:testing.TestLogger.md"}, {"name": "TransactionLogger", "path": "algokit:utils:typescript:code:classes:testing.TransactionLogger.md"} ] }, "interfaces": { "name": "Interfaces", "description": "Interface documentation", "path": "algokit:utils:typescript:code:interfaces", "documents": [ {"name": "AlgorandFixture", "path": "algokit:utils:typescript:code:interfaces:types_testing.AlgorandFixture.md"}, {"name": "AppClientParams", "path": "algokit:utils:typescript:code:interfaces:types_app_client.AppClientParams.md"}, {"name": "AppDeploymentParams", "path": "algokit:utils:typescript:code:interfaces:types_app.AppDeploymentParams.md"}, {"name": "Config", "path": "algokit:utils:typescript:code:interfaces:types_config.Config.md"}, {"name": "TransactionParams", "path": "algokit:utils:typescript:code:interfaces:types_transaction.SendTransactionParams.md"} ] }, "enums": { "name": "Enums", "description": "Enum documentation", "path": "algokit:utils:typescript:code:enums", "documents": [ {"name": "EventType", "path": "algokit:utils:typescript:code:enums:types_lifecycle_events.EventType.md"}, {"name": "OnSchemaBreak", "path": "algokit:utils:typescript:code:enums:types_app.OnSchemaBreak.md"}, {"name": "OnUpdate", "path": "algokit:utils:typescript:code:enums:types_app.OnUpdate.md"} ] } } } } } } } ``` -------------------------------------------------------------------------------- /packages/server/src/tools/apiManager/indexer/account.ts: -------------------------------------------------------------------------------- ```typescript import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js'; import { indexerClient } from '../../../algorand-client.js'; import { ResponseProcessor } from '../../../utils/responseProcessor.js'; import type { AccountResponse, AccountsResponse, ApplicationLocalStatesResponse, AssetHoldingsResponse, ApplicationsResponse, TransactionsResponse } from 'algosdk/dist/types/client/v2/indexer/models/types'; export const accountTools = [ { name: 'api_indexer_lookup_account_by_id', description: 'Get account information from indexer', inputSchema: { type: 'object', properties: { address: { type: 'string', description: 'Account address' } }, required: ['address'] } }, { name: 'api_indexer_lookup_account_assets', description: 'Get account assets', inputSchema: { type: 'object', properties: { address: { type: 'string', description: 'Account address' }, limit: { type: 'integer', description: 'Maximum number of assets to return' }, assetId: { type: 'integer', description: 'Filter by asset ID' }, nextToken: { type: 'string', description: 'Token for retrieving the next page of results' } }, required: ['address'] } }, { name: 'api_indexer_lookup_account_app_local_states', description: 'Get account application local states', inputSchema: { type: 'object', properties: { address: { type: 'string', description: 'Account address' } }, required: ['address'] } }, { name: 'api_indexer_lookup_account_created_applications', description: 'Get applications created by this account', inputSchema: { type: 'object', properties: { address: { type: 'string', description: 'Account address' } }, required: ['address'] } }, { name: 'api_indexer_search_for_accounts', description: 'Search for accounts with various criteria', inputSchema: { type: 'object', properties: { limit: { type: 'integer', description: 'Maximum number of accounts to return' }, assetId: { type: 'integer', description: 'Filter by asset ID' }, applicationId: { type: 'integer', description: 'Filter by application ID' }, currencyGreaterThan: { type: 'integer', description: 'Filter by minimum balance' }, currencyLessThan: { type: 'integer', description: 'Filter by maximum balance' }, nextToken: { type: 'string', description: 'Token for retrieving the next page of results' } } } } ]; export async function lookupAccountByID(address: string): Promise<AccountResponse> { try { console.log(`Looking up account info for address ${address}`); const response = await indexerClient.lookupAccountByID(address).do() as AccountResponse; console.log('Account response:', JSON.stringify(response, null, 2)); return response; } catch (error) { console.error('Account lookup error:', error); if (error instanceof McpError) { throw error; } throw new McpError( ErrorCode.InternalError, `Failed to get account info: ${error instanceof Error ? error.message : String(error)}` ); } } export async function lookupAccountAssets(address: string, params?: { limit?: number; assetId?: number; nextToken?: string; }): Promise<AssetHoldingsResponse> { try { console.log(`Looking up assets for address ${address}`); let search = indexerClient.lookupAccountAssets(address); if (params?.limit) { search = search.limit(params.limit); } if (params?.assetId) { search = search.assetId(params.assetId); } if (params?.nextToken) { search = search.nextToken(params.nextToken); } const response = await search.do() as AssetHoldingsResponse; console.log('Assets response:', JSON.stringify(response, null, 2)); return response; } catch (error) { console.error('Assets lookup error:', error); if (error instanceof McpError) { throw error; } throw new McpError( ErrorCode.InternalError, `Failed to get account assets: ${error instanceof Error ? error.message : String(error)}` ); } } export async function lookupAccountAppLocalStates(address: string): Promise<ApplicationLocalStatesResponse> { try { console.log(`Looking up app local states for address ${address}`); const response = await indexerClient.lookupAccountAppLocalStates(address).do() as ApplicationLocalStatesResponse; console.log('App local states response:', JSON.stringify(response, null, 2)); return response; } catch (error) { console.error('App local states lookup error:', error); if (error instanceof McpError) { throw error; } throw new McpError( ErrorCode.InternalError, `Failed to get account application local states: ${error instanceof Error ? error.message : String(error)}` ); } } export async function lookupAccountCreatedApplications(address: string): Promise<ApplicationsResponse> { try { console.log(`Looking up created applications for address ${address}`); const response = await indexerClient.lookupAccountCreatedApplications(address).do() as ApplicationsResponse; console.log('Created applications response:', JSON.stringify(response, null, 2)); return response; } catch (error) { console.error('Created applications lookup error:', error); if (error instanceof McpError) { throw error; } throw new McpError( ErrorCode.InternalError, `Failed to get account created applications: ${error instanceof Error ? error.message : String(error)}` ); } } export async function searchAccounts(params?: { limit?: number; assetId?: number; applicationId?: number; currencyGreaterThan?: number; currencyLessThan?: number; nextToken?: string; }): Promise<AccountsResponse> { try { console.log('Searching accounts with params:', params); let search = indexerClient.searchAccounts(); if (params?.limit) { search = search.limit(params.limit); } if (params?.assetId) { search = search.assetID(params.assetId); } if (params?.applicationId) { search = search.applicationID(params.applicationId); } if (params?.currencyGreaterThan) { search = search.currencyGreaterThan(params.currencyGreaterThan); } if (params?.currencyLessThan) { search = search.currencyLessThan(params.currencyLessThan); } if (params?.nextToken) { search = search.nextToken(params.nextToken); } const response = await search.do() as AccountsResponse; console.log('Search accounts response:', JSON.stringify(response, null, 2)); return response; } catch (error) { console.error('Search accounts error:', error); if (error instanceof McpError) { throw error; } throw new McpError( ErrorCode.InternalError, `Failed to search accounts: ${error instanceof Error ? error.message : String(error)}` ); } } export const handleAccountTools = ResponseProcessor.wrapResourceHandler(async function handleAccountTools(args: any): Promise<any> { const name = args.name; switch (name) { case 'api_indexer_lookup_account_by_id': { const { address } = args; const info = await lookupAccountByID(address); return info; } case 'api_indexer_lookup_account_app_local_states': { const { address } = args; const info = await lookupAccountAppLocalStates(address); return info; } case 'api_indexer_lookup_account_created_applications': { const { address } = args; const info = await lookupAccountCreatedApplications(address); return info.applications; } case 'api_indexer_search_for_accounts': { const info = await searchAccounts(args); return info.accounts; } case 'api_indexer_lookup_account_assets': { const { address, ...params } = args; const info = await lookupAccountAssets(address, params); return info.assets; } default: throw new McpError( ErrorCode.MethodNotFound, `Unknown tool: ${name}` ); } }); ``` -------------------------------------------------------------------------------- /packages/server/src/resources/knowledge/taxonomy/developer:docs:run-a-node:reference:artifacts.md: -------------------------------------------------------------------------------- ```markdown title: Node artifacts These files run as part of the Algorand node or are CLI utilities that will help to diagnose or interact with a currently running node. The primary files are described below. # goal Goal is the command line utility used to interact with the Algorand node. It communicates with algod and the kmd process to do things like: create an account, list the ledger, examine the status of the network, or create a transaction. Goal documentation is available in the [Goal](../../../clis/goal/goal) guide. # algod Algod is the main Algorand process for handling the blockchain. Messages between nodes are processed, the protocol steps are executed, and the blocks are written to disk. The algod process also exposes a REST API server that developers can use to communicate with the node and the network. Algod uses the data directory for storage and configuration information. # algoh Algoh is an optional hosting process for algod, whose use is encouraged to help catch fatal runtime errors and proactively report with logs. Algoh also monitors for stalls and proactively reports them with diagnostics data in case the problem is local to the instance. We’ll be adding optional layer-2 telemetry to some nodes running algoh, but it will be disabled for most nodes (and will be configurable). # kmd Kmd is the key management daemon. This process handles interacting with clients’ private keys for Algorand accounts. The process is responsible for generating and importing spending keys, signing transactions, and interacting with key storage mechanisms like hardware wallets. This process can also be executed on a separate machine, isolating the spending keys from the network. This process also uses a data directory for wallet configurations. In the default configuration, this will be in the data directory for algod but will contain its own folder labeled `kmd-version`. The kmd process also hosts a REST endpoint for integration. # algokey algokey is a command line utility for generating, exporting and importing keys. The tool can be used to sign single and multi-signature transactions as well. See [algokey](../../../clis/algokey/algokey) documentation for more details. # carpenter Carpenter is a debug tool that helps to visualize the protocol and how it is proceeding. The tool reads the node log file and formats the output. Generally, every entry displayed in the tool starts with the round number, with the period and step. Each line displayed in the tool will have a message that is relative to the step and will display when a proposal or a vote is accepted or rejected. When accepted votes are displayed, the number of votes is also included in parentheses. When the threshold for the vote is reached a message will be displayed letting the user know the next step in the protocol is about to start. Messages are color-coded by round and user. When running carpenter, just specify the latest.log file from the data directory. ``` ./carpenter -file data/latest.log ``` Or use the standard data directory specifier syntax: ``` ./carpenter -d data ``` If you have the `ALGORAND_DATA` environment variable set, you can just run: ``` ./carpenter -D ``` # update.sh, updater, and updatekey.json These are the primary files used for installing and updating the node software. They can be executed manually or put them in a CRON job and have it execute more regularly. The process for doing this is explained in the installation guide. # Node Data files As part of the installation process, a data directory is created. The node stores its local copy of the blockchain in this directory. Log files and configuration files are also stored here. Each of the configuration files is described below. # config.json.example This file is just an example configuration file that lets you configure a node with specific parameters. If this file is renamed to config.json, the settings in this file will take effect on the node when it is started. Each of the settings is defined in the Node configuration settings guide. # phonebook.json As discussed in [Algorand Node Types](../../setup/types) there are two types of nodes; relay and non-relay. Any node can function as either but it is not good practice for nodes that are relays to run the kmd process or manage accounts. Relay nodes have higher requirements and open more ports than standard non-relay nodes. Non-relay nodes only connect to relay nodes. They never connect to other non-relay nodes. The relay nodes are published in Algorand SRV records. You can create a relay node that is not in a SRV record. You can specify one or more of these non-published relays to be placed in a pool of available relay nodes for a node starting up. The node will randomly pick from this pool of nodes to open connections to communicate with the network. Before specifying how to change the relay pool, note that setting some options will replace the default SRV records from the pool. This means that if you intend to connect to the Algorand MainNet or TestNet network, the relays in your pool must connect to a published Algorand SRV relay. One method for replacing the pool entirely is to use the goal node start -p command. The -p parameter expects a list of relays that will be added to a pool. Note that this does away with the default pool. Here is an example of using the -p option to connect to TestNet. ``` ./goal node start -d data -p "r1.algorand.network:4161;r2.algorand.network:4161" ``` In this example, the two specified relays are the only ones used. Another option is to create a file named phonebook.json in your binary directory and add a list of relays similar to the following: ``` { "Include": [ "r1.algorand.network:4161", "r2.algorand.network:4161" ] } ``` In this case, the entries are added to the default pool. If you want these entries to override the default pool set the `DNSBootstrapID` in config.json to "". Setting a configuration value for a node is described in the Node Configuration Settings guide. # node.archive.log and node.log The node.log file is the log file of the current node. This file contains a set of JSON entries for various steps processed by the node. The carpenter utility can be used to view these entries in a much more digestible format. Once the node log file has reached its maximum size, it is copied to node.archive.log and a new version of node.log is created. # algod-err.log, algod-out.log When started through goal, algod redirects the error and output streams to algod-err.log and algod-out.log respectively. algod.net, algod.pid and algod.token, algod-listen.net The algod.net, algo.pid and algod.token files are created in the node’s data folder when the node starts. The algod.net file contains the IP and port the node is serving REST API calls on. The algod.pid file contains the process id of the algod daemon of the running node. The algod.token file contains the API token that must be used to communicate with the node’s REST APIs. This is passed to the REST API using the `X-Algo-API-Token` header. algod-listen.net contains the IP and port that the node is listening on for incoming connections if any. # host.log Contains logging output from algoh. # wallet-genesis.id and genesis.json These files are associated with the genesis block and the associated wallet ids at creation of the network. The wallet-genesis.id file contains the unique id for the genesis block that was most recently installed. This is also the name of the directory in which the blockchain’s SQLite file is stored. The genesis.json file specifies the initial state of the blockchain - its ‘genesis block’. This is a JSON formatted file with the schema for the blockchain. It contains the network name and id, the protocol version and list of allocated addresses to start the chain with. Each address contains a list of things like their status and the amount of Algos they own. # Nested Directories The data directory will contain a couple of sub-directories depending on what has been done with that instance. One directory, named after the specific Algorand network and genesis version, will contain the SQLite files associated with the blockchain ledger and any wallets. There may be additional directories if the node has been updated. The backup directory contains a backup of the data directory. This allows the node to revert to the previous version in case of a failure during an update. A kmd directory may also exist with a SQLite instance for that process. It will also contain REST endpoint and API token files, similar to the algod files. ``` -------------------------------------------------------------------------------- /packages/server/src/resources/knowledge/taxonomy/SDKs:javascript:classes:indexerModels.Block.md: -------------------------------------------------------------------------------- ```markdown [algosdk](../README.md) / [Exports](../modules.md) / [indexerModels](../modules/indexerModels.md) / Block # Class: Block [indexerModels](../modules/indexerModels.md).Block Block information. Definition: data/bookkeeping/block.go : Block ## Hierarchy - `default` ↳ **`Block`** ## Table of contents ### Constructors - [constructor](indexerModels.Block.md#constructor) ### Properties - [attribute\_map](indexerModels.Block.md#attribute_map) - [bonus](indexerModels.Block.md#bonus) - [feesCollected](indexerModels.Block.md#feescollected) - [genesisHash](indexerModels.Block.md#genesishash) - [genesisId](indexerModels.Block.md#genesisid) - [participationUpdates](indexerModels.Block.md#participationupdates) - [previousBlockHash](indexerModels.Block.md#previousblockhash) - [proposer](indexerModels.Block.md#proposer) - [proposerPayout](indexerModels.Block.md#proposerpayout) - [rewards](indexerModels.Block.md#rewards) - [round](indexerModels.Block.md#round) - [seed](indexerModels.Block.md#seed) - [stateProofTracking](indexerModels.Block.md#stateprooftracking) - [timestamp](indexerModels.Block.md#timestamp) - [transactions](indexerModels.Block.md#transactions) - [transactionsRoot](indexerModels.Block.md#transactionsroot) - [transactionsRootSha256](indexerModels.Block.md#transactionsrootsha256) - [txnCounter](indexerModels.Block.md#txncounter) - [upgradeState](indexerModels.Block.md#upgradestate) - [upgradeVote](indexerModels.Block.md#upgradevote) ### Methods - [get\_obj\_for\_encoding](indexerModels.Block.md#get_obj_for_encoding) - [from\_obj\_for\_encoding](indexerModels.Block.md#from_obj_for_encoding) ## Constructors ### constructor • **new Block**(`«destructured»`) Creates a new `Block` object. #### Parameters | Name | Type | | :------ | :------ | | `«destructured»` | `Object` | | › `bonus?` | `number` \| `bigint` | | › `feesCollected?` | `number` \| `bigint` | | › `genesisHash` | `string` \| `Uint8Array` | | › `genesisId` | `string` | | › `participationUpdates?` | [`ParticipationUpdates`](indexerModels.ParticipationUpdates.md) | | › `previousBlockHash` | `string` \| `Uint8Array` | | › `proposer?` | `string` | | › `proposerPayout?` | `number` \| `bigint` | | › `rewards?` | [`BlockRewards`](indexerModels.BlockRewards.md) | | › `round` | `number` \| `bigint` | | › `seed` | `string` \| `Uint8Array` | | › `stateProofTracking?` | [`StateProofTracking`](indexerModels.StateProofTracking.md)[] | | › `timestamp` | `number` \| `bigint` | | › `transactions?` | [`Transaction`](indexerModels.Transaction.md)[] | | › `transactionsRoot` | `string` \| `Uint8Array` | | › `transactionsRootSha256` | `string` \| `Uint8Array` | | › `txnCounter?` | `number` \| `bigint` | | › `upgradeState?` | [`BlockUpgradeState`](indexerModels.BlockUpgradeState.md) | | › `upgradeVote?` | [`BlockUpgradeVote`](indexerModels.BlockUpgradeVote.md) | #### Overrides BaseModel.constructor #### Defined in client/v2/indexer/models/types.ts:2292 ## Properties ### attribute\_map • **attribute\_map**: `Record`\<`string`, `string`\> #### Inherited from BaseModel.attribute\_map #### Defined in client/v2/basemodel.ts:56 ___ ### bonus • `Optional` **bonus**: `number` \| `bigint` the potential bonus payout for this block. #### Defined in client/v2/indexer/models/types.ts:2202 ___ ### feesCollected • `Optional` **feesCollected**: `number` \| `bigint` the sum of all fees paid by transactions in this block. #### Defined in client/v2/indexer/models/types.ts:2207 ___ ### genesisHash • **genesisHash**: `Uint8Array` (gh) hash to which this block belongs. #### Defined in client/v2/indexer/models/types.ts:2154 ___ ### genesisId • **genesisId**: `string` (gen) ID to which this block belongs. #### Defined in client/v2/indexer/models/types.ts:2159 ___ ### participationUpdates • `Optional` **participationUpdates**: [`ParticipationUpdates`](indexerModels.ParticipationUpdates.md) Participation account data that needs to be checked/acted on by the network. #### Defined in client/v2/indexer/models/types.ts:2212 ___ ### previousBlockHash • **previousBlockHash**: `Uint8Array` (prev) Previous block hash. #### Defined in client/v2/indexer/models/types.ts:2164 ___ ### proposer • `Optional` **proposer**: `string` the proposer of this block. #### Defined in client/v2/indexer/models/types.ts:2217 ___ ### proposerPayout • `Optional` **proposerPayout**: `number` \| `bigint` the actual amount transferred to the proposer from the fee sink. #### Defined in client/v2/indexer/models/types.ts:2222 ___ ### rewards • `Optional` **rewards**: [`BlockRewards`](indexerModels.BlockRewards.md) Fields relating to rewards, #### Defined in client/v2/indexer/models/types.ts:2227 ___ ### round • **round**: `number` \| `bigint` (rnd) Current round on which this block was appended to the chain. #### Defined in client/v2/indexer/models/types.ts:2169 ___ ### seed • **seed**: `Uint8Array` (seed) Sortition seed. #### Defined in client/v2/indexer/models/types.ts:2174 ___ ### stateProofTracking • `Optional` **stateProofTracking**: [`StateProofTracking`](indexerModels.StateProofTracking.md)[] Tracks the status of state proofs. #### Defined in client/v2/indexer/models/types.ts:2232 ___ ### timestamp • **timestamp**: `number` \| `bigint` (ts) Block creation timestamp in seconds since eposh #### Defined in client/v2/indexer/models/types.ts:2179 ___ ### transactions • `Optional` **transactions**: [`Transaction`](indexerModels.Transaction.md)[] (txns) list of transactions corresponding to a given round. #### Defined in client/v2/indexer/models/types.ts:2237 ___ ### transactionsRoot • **transactionsRoot**: `Uint8Array` (txn) TransactionsRoot authenticates the set of transactions appearing in the block. More specifically, it's the root of a merkle tree whose leaves are the block's Txids, in lexicographic order. For the empty block, it's 0. Note that the TxnRoot does not authenticate the signatures on the transactions, only the transactions themselves. Two blocks with the same transactions but in a different order and with different signatures will have the same TxnRoot. #### Defined in client/v2/indexer/models/types.ts:2189 ___ ### transactionsRootSha256 • **transactionsRootSha256**: `Uint8Array` (txn256) TransactionsRootSHA256 is an auxiliary TransactionRoot, built using a vector commitment instead of a merkle tree, and SHA256 hash function instead of the default SHA512_256. This commitment can be used on environments where only the SHA256 function exists. #### Defined in client/v2/indexer/models/types.ts:2197 ___ ### txnCounter • `Optional` **txnCounter**: `number` \| `bigint` (tc) TxnCounter counts the number of transactions committed in the ledger, from the time at which support for this feature was introduced. Specifically, TxnCounter is the number of the next transaction that will be committed after this block. It is 0 when no transactions have ever been committed (since TxnCounter started being supported). #### Defined in client/v2/indexer/models/types.ts:2246 ___ ### upgradeState • `Optional` **upgradeState**: [`BlockUpgradeState`](indexerModels.BlockUpgradeState.md) Fields relating to a protocol upgrade. #### Defined in client/v2/indexer/models/types.ts:2251 ___ ### upgradeVote • `Optional` **upgradeVote**: [`BlockUpgradeVote`](indexerModels.BlockUpgradeVote.md) Fields relating to voting for a protocol upgrade. #### Defined in client/v2/indexer/models/types.ts:2256 ## Methods ### get\_obj\_for\_encoding ▸ **get_obj_for_encoding**(`binary?`): `Record`\<`string`, `any`\> Get an object ready for encoding to either JSON or msgpack. #### Parameters | Name | Type | Default value | Description | | :------ | :------ | :------ | :------ | | `binary` | `boolean` | `false` | Use true to indicate that the encoding can handle raw binary objects (Uint8Arrays). Use false to indicate that raw binary objects should be converted to base64 strings. True should be used for objects that will be encoded with msgpack, and false should be used for objects that will be encoded with JSON. | #### Returns `Record`\<`string`, `any`\> #### Inherited from BaseModel.get\_obj\_for\_encoding #### Defined in client/v2/basemodel.ts:65 ___ ### from\_obj\_for\_encoding ▸ `Static` **from_obj_for_encoding**(`data`): [`Block`](indexerModels.Block.md) #### Parameters | Name | Type | | :------ | :------ | | `data` | `Record`\<`string`, `any`\> | #### Returns [`Block`](indexerModels.Block.md) #### Defined in client/v2/indexer/models/types.ts:2393 ``` -------------------------------------------------------------------------------- /packages/server/src/resources/knowledge/taxonomy/algokit:cli:features:generate.md: -------------------------------------------------------------------------------- ```markdown # AlgoKit Generate The `algokit generate` [command](../cli/index.md#generate) is used to generate components used in an AlgoKit project. It also allows for custom generate commands which are loaded from the .algokit.toml file in your project directory. ## 1. Typed clients The `algokit generate client` [command](../cli/index.md#client) can be used to generate a typed client from an [ARC-0032](https://arc.algorand.foundation/ARCs/arc-0032) or [ARC-0056](https://github.com/algorandfoundation/ARCs/pull/258) application specification with both Python and TypeScript available as target languages. ### Prerequisites To generate Python clients an installation of pip and pipx is required. To generate TypeScript clients an installation of Node.js and npx is also required. Each generated client will also have a dependency on `algokit-utils` libraries for the target language. ### Input file / directory You can either specify a path to an ARC-0032 JSON file, an ARC-0056 JSON file or to a directory that is recursively scanned for `application.json`, `*.arc32.json`, `*.arc56.json` file(s). ### Output tokens The output path is interpreted as relative to the current working directory, however an absolute path may also be specified e.g. `algokit generate client application.json --output /absolute/path/to/client.py` There are two tokens available for use with the `-o`, `--output` [option](../cli/index.md#-o---output-): - `{contract_name}`: This will resolve to a name based on the ARC-0032/ARC-0056 contract name, formatted appropriately for the target language. - `{app_spec_dir}`: This will resolve to the parent directory of the `application.json`, `*.arc32.json`, `*.arc56.json` file which can be useful to output a client relative to its source file. ### Version Pinning If you want to ensure typed client output stability across different environments and additionally protect yourself from any potential breaking changes introduced in the client generator packages, you can specify a version you'd like to pin to. To make use of this feature, pass `-v`, `--version`, for example `algokit generate client --version 1.2.3 path/to/application.json`. Alternatively, you can achieve output stability by installing the underlying [Python](https://github.com/algorandfoundation/algokit-client-generator-py) or [TypeScript](https://github.com/algorandfoundation/algokit-client-generator-ts) client generator package either locally in your project (via `poetry` or `npm` respectively) or globally on your system (via `pipx` or `npm` respectively). AlgoKit will search for a matching installed version before dynamically resolving. ### Usage Usage examples of using a generated client are below, typed clients allow your favourite IDE to provide better intellisense to provide better discoverability of available operations and parameters. #### Python ```python # A similar working example can be seen in the algokit python template, when using Python deployment from smart_contracts.artifacts.HelloWorldApp.client import ( HelloWorldAppClient, ) app_client = HelloWorldAppClient( algod_client, creator=deployer, indexer_client=indexer_client, ) deploy_response = app_client.deploy( on_schema_break=OnSchemaBreak.ReplaceApp, on_update=OnUpdate.UpdateApp, allow_delete=True, allow_update=True, ) response = app_client.hello(name="World") ``` #### TypeScript ```typescript // A similar working example can be seen in the algokit python template with typescript deployer, when using TypeScript deployment import { HelloWorldAppClient } from "./artifacts/HelloWorldApp/client"; const appClient = new HelloWorldAppClient( { resolveBy: "creatorAndName", findExistingUsing: indexer, sender: deployer, creatorAddress: deployer.addr, }, algod ); const app = await appClient.deploy({ allowDelete: isLocal, allowUpdate: isLocal, onSchemaBreak: isLocal ? "replace" : "fail", onUpdate: isLocal ? "update" : "fail", }); const response = await appClient.hello({ name: "world" }); ``` ### Examples To output a single application.json to a python typed client: `algokit generate client path/to/application.json --output client.py` To process multiple application.json in a directory structure and output to a typescript client for each in the current directory: `algokit generate client smart_contracts/artifacts --output {contract_name}.ts` To process multiple application.json in a directory structure and output to a python client alongside each application.json: `algokit generate client smart_contracts/artifacts --output {app_spec_path}/client.py` ## 2. Using Custom Generate Commands Custom generate commands are defined in the `.algokit.toml` file within the project directory, typically supplied by community template builders or official AlgoKit templates. These commands are specified under the `generate` key and serve to execute a generator at a designated path with provided answer key/value pairs. ### Understanding `Generators` A `generator` is essentially a compact, self-sufficient `copier` template. This template can optionally be defined within the primary `algokit templates` to offer supplementary functionality after a project is initialized from the template. For instance, the official [`algokit-python-template`](https://github.com/algorandfoundation/algokit-python-template/tree/main/template_content) provides a generator within the `.algokit/generators` directory. This generator can be employed for executing extra tasks on AlgoKit projects that have been initiated from this template, such as adding new smart contracts to an existing project. For a comprehensive explanation, please refer to the [`architecture decision record`](../architecture-decisions/2023-07-19_advanced_generate_command.md). ### Requirements To utilize custom generate commands, you must have `copier` installed. This installation is included by default in the AlgoKit CLI. Therefore, no additional installation is necessary if you have already installed the `algokit cli`. ### How to Use A custom command can be defined in the `.algokit.toml` as shown: ```toml [generate.my_generator] path = "path/to/my_generator" description = "A brief description of the function of my_generator" ``` Following this, you can execute the command as follows: `algokit generate my_generator --answer key value --path path/to/my_generator` If no `path` is given, the command will use the path specified in the `.algokit.toml`. If no `answer` is provided, the command will initiate an interactive `copier` prompt to request answers (similar to `algokit init`). The custom command employs the `copier` library to duplicate the files from the generator's path to the current working directory, substituting any values from the `answers` dictionary. ### Examples As an example, let's use the `smart-contract` generator from the `algokit-python-template` to add new contract to an existing project based on that template. The `smart-contract` generator is defined as follows: ```toml [algokit] min_version = "v1.3.1" ... # other keys [generate.smart_contract] description = "Adds a new smart contract to the existing project" path = ".algokit/generators/create_contract" ``` To execute this generator, ensure that you are operating from the same directory as the `.algokit.toml` file, and then run: ```bash $ algokit generate # The output will be as follows: # Note how algokit dynamically injects a new `smart-contract` command based # on the `.algokit.toml` file Usage: algokit generate [OPTIONS] COMMAND [ARGS]... Generate code for an Algorand project. Options: -h, --help Show this message and exit. Commands: client Create a typed ApplicationClient from an ARC-32 application.json smart-contract Adds a new smart contract to the existing project ``` To execute the `smart-contract` generator, run: ```bash $ algokit generate smart-contract # or $ algokit generate smart-contract -a contract_name "MyCoolContract" ``` #### Third Party Generators It is important to understand that by default, AlgoKit will always prompt you before executing a generator to ensure it's from a trusted source. If you are confident about the source of the generator, you can use the `--force` or `-f` option to execute the generator without this confirmation prompt. Be cautious while using this option and ensure the generator is from a trusted source. At the moment, a trusted source for a generator is defined as _a generator that is included in the official AlgoKit templates (e.g. `smart-contract` generator in `algokit-python-template`)_ ``` -------------------------------------------------------------------------------- /packages/server/src/resources/knowledge/taxonomy/algokit:cli:features:init.md: -------------------------------------------------------------------------------- ```markdown # AlgoKit Init The `algokit init` [command](../cli/index.md#init) is used to quickly initialize new projects using official Algorand Templates or community provided templates. It supports a fully guided command line wizard experience, as well as fully scriptable / non-interactive functionality via command options. ## Quick start For a quick start template with all of the defaults you can run: `algokit init` which will interactively guide you through picking the right stack to build your AlgoKit project. Afterwards, you should immediately be able to hit F5 to compile the hello world smart contract to the `smart_contracts/artifacts` folder (with breakpoint debugging - try setting a breakpoint in `smart_contracts/helloworld.py`) and open the `smart_contracts/helloworld.py` file and get linting, automatic formatting and syntax highlighting. ## Prerequisites Git is a prerequisite for the init command as it is used to clone templates and initialize git repos. Please consult the [README](../../README.md#prerequisites) for installation instructions. ## Functionality As outlined in [quick start](#quick-start), the simplest use of the command is to just run `algokit init` and you will then be guided through selecting a template and configuring options for that template. e.g. ``` $ ~ algokit init ? Which of these options best describes the project you want to start? `Smart Contract` | `Dapp Frontend` | `Smart Contract & Dapp Frontend` | `Custom` ? Name of project / directory to create the project in: my-cool-app ``` Once above 2 questions are answered, the `cli` will start instantiating the project and will start asking questions specific to the template you are instantiating. By default official templates such as `python`, `fullstack`, `react`, `python` include a notion of a `preset`. If you want to skip all questions and let the tool preset the answers tailored for a starter project you can pick `Starter`, for a more advanced project that includes unit tests, CI automation and other advanced features, pick `Production`. Lastly, if you prefer to modify the experience and tailor the template to your needs, pick the `Custom` preset. If you want to accept the default for each option simply hit [enter] or alternatively to speed things up you can run `algokit init --defaults` and they will be auto-accepted. ### Workspaces vs Standalone Projects AlgoKit supports two distinct project structures: Workspaces and Standalone Projects. This flexibility allows developers to choose the most suitable approach for their project's needs. To initialize a project within a workspace, use the `--workspace` flag. If a workspace does not already exist, AlgoKit will create one for you by default (unless you disable it via `--no-workspace` flag). Once established, new projects can be added to this workspace, allowing for centralized management. To create a standalone project, use the `--no-workspace` flag during initialization. This instructs AlgoKit to bypass the workspace structure and set up the project as an isolated entity. For more details on workspaces and standalone projects, refer to the [AlgoKit Project documentation](./project.md#workspaces-vs-standalone-projects). ## Bootstrapping You will also be prompted if you wish to run the [bootstrap](../cli/index.md#bootstrap) command, this is useful if you plan to immediately begin developing in the new project. If you passed in `--defaults` or `--bootstrap` then it will automatically run bootstrapping unless you passed in `--no-bootstrap`. ``` ? Do you want to run `algokit bootstrap` to bootstrap dependencies for this new project so it can be run immediately? Yes Installing Python dependencies and setting up Python virtual environment via Poetry poetry: Creating virtualenv my-smart-contract in /Users/algokit/algokit-init/my-smart-contract/.venv poetry: Updating dependencies poetry: Resolving dependencies... poetry: poetry: Writing lock file poetry: poetry: Package operations: 53 installs, 0 updates, 0 removals poetry: poetry: • Installing pycparser (2.21) ---- other output omitted for brevity ---- poetry: • Installing ruff (0.0.171) Copying /Users/algokit/algokit-init/my-smart-contract/smart_contracts/.env.template to /Users/algokit/algokit-init/my-smart-contract/smart_contracts/.env and prompting for empty values ? Would you like to initialise a git repository and perform an initial commit? Yes 🎉 Performed initial git commit successfully! 🎉 🙌 Project initialized at `my-smart-contract`! For template specific next steps, consult the documentation of your selected template 🧐 Your selected template comes from: ➡️ https://github.com/algorandfoundation/algokit-python-template As a suggestion, if you wanted to open the project in VS Code you could execute: > cd my-smart-contract && code . ``` After bootstrapping you are also given the opportunity to initialize a git repo, upon successful completion of the init command the project is ready to be used. If you pass in `--git` it will automatically initialise the git repository and if you pass in `--no-git` it won't. > Please note, when using `--no-workspaces`, algokit init will assume a max lookup depth of 1 for a fresh template based project. Otherwise it will assume a max depth of 2, since default algokit workspace structure is at most 2 levels deep. ## Options There are a number of options that can be used to provide answers to the template prompts. Some of the options requiring further explanation are detailed below, but consult the CLI reference for all available [options](../cli/index.md#init). ## Community Templates As well as the official Algorand templates shown when running the init command, community templates can also be provided by providing a URL via the prompt or the `--template-url` option. e.g. `algokit init --template-url https://github.com/algorandfoundation/algokit-python-template` (that being the url of the official python template, the same as `algokit init -t python`). The `--template-url` option can be combined with `--template-url-ref` to specify a specific commit, branch or tag e.g. `algokit init --template-url https://github.com/algorandfoundation/algokit-python-template --template-url-ref 0232bb68a2f5628e910ee52f62bf13ded93fe672` If the URL is not an official template there is a potential security risk and so to continue you must either acknowledge this prompt, or if you are in a non-interactive environment you can pass the `--UNSAFE-SECURITY-accept-template-url` option (but we generally don't recommend this option so users can review the warning message first) e.g. ``` Community templates have not been reviewed, and can execute arbitrary code. Please inspect the template repository, and pay particular attention to the values of \_tasks, \_migrations and \_jinja_extensions in copier.yml ? Continue anyway? Yes ``` If you want to create a community template, you can use the [AlgoKit guidelines on template building](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/tutorials/algokit-template.md#creating-algokit-templates) and [Copier documentation](https://copier.readthedocs.io/en/stable/) as a starting point. ## Template Answers Answers to specific template prompts can be provided with the `--answer {key} {value}` option, which can be used multiple times for each prompt. Quotes can be used for values with spaces e.g. `--answer author_name "Algorand Foundation"`. To find out the key for a specific answer you can either look at `.algokit/.copier-answers.yml` in the root folder of a project created via `algokit init` or in the `copier.yaml` file of a template repo e.g. for the [python template](https://github.com/algorandfoundation/algokit-python-template/blob/main/copier.yaml). ## Non-interactive project initialization By combining a number of options, it is possible to initialize a new project without any interaction. For example, to create a project named `my-smart-contract` using the `python` template with no git, no bootstrapping, the author name of `Algorand Foundation`, and defaults for all other values, you could execute the following: ``` $ ~ algokit init -n my-smart-contract -t python --no-git --no-bootstrap --answer author_name "Algorand Foundation" --defaults 🙌 Project initialized at `my-smart-contract`! For template specific next steps, consult the documentation of your selected template 🧐 Your selected template comes from: ➡️ https://github.com/algorandfoundation/algokit-python-template As a suggestion, if you wanted to open the project in VS Code you could execute: > cd my-smart-contract && code . ``` For more details about the `AlgoKit init` command, please refer to the [AlgoKit CLI reference documentation](../cli/index.md#init). ``` -------------------------------------------------------------------------------- /packages/server/src/resources/knowledge/taxonomy/developer:docs:sdks:javascript:index.md: -------------------------------------------------------------------------------- ```markdown title: JS SDK: Your First Transaction This section is a quick start guide for interacting with the Algorand network using JavaScript. This guide will help to install the [Algorand sandbox](https://github.com/algorand/sandbox){target=blank}, which provides a node for testing and development. This guide will also help to install the JavaScript SDK, create an account and submit your first transaction using different JavaScript Runtimes. # Install Sandbox !!! info This step is only required if you are not using AlgoKit. If you are using AlgoKit, you can spin up a sandbox using the LocalNet, see [AlgoKit getting started guide](/docs/get-started/algokit/#start-a-localnet) for more information. !!! Prerequisites - Docker Compose ([install guide](https://docs.docker.com/compose/install/)) - Git ([install guide](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)) Algorand provides a docker instance for setting up a node, which can be used to get started developing quickly. To install and use this instance, follow these instructions. ```bash git clone https://github.com/algorand/sandbox.git cd sandbox ./sandbox up dev ``` This will install and start private network. To read more about Algorand networks see [Algorand Networks](../../get-details/algorand-networks/index.md){target=_blank}. [More Information about the sandbox](https://developer.algorand.org/articles/introducing-sandbox-20/) and [how to use](https://developer.algorand.org/tutorials/exploring-the-algorand-sandbox/) it. # Install JavaScript SDK Algorand provides an [SDK for JavaScript](https://github.com/algorand/js-algorand-sdk). The instructions for installing the SDK will depend on what runtime you plan on using. !!! Prerequisites - Install [Node.js](https://nodejs.org/download) ```bash # initialize project npm init # install Algorand sdk npm install algosdk # list the version npm list algosdk # This package provides TypeScript types, but you will need TypeScript version 4.2 or higher to use them properly. ``` The [GitHub repository](https://github.com/algorand/js-algorand-sdk){target=_blank} contains additional documentation and examples. See the JavaScript SDK [reference documentation](https://algorand.github.io/js-algorand-sdk/){target=_blank} for more information on methods. The SDK is installed and can now interact with the running Algorand Sandbox environment, as configured above. !!! Info Using a Web Runtime requires the AlgoSigner extension or other web-based private key management software. For more information see [community wallets](https://developer.algorand.org/docs/community/#wallets). # Create an Account In order to interact with the Algorand blockchain, you must have a funded account. To quickly create a test account use the following code. <!-- ===JSSDK_ACCOUNT_GENERATE=== --> ```javascript const generatedAccount = algosdk.generateAccount(); const passphrase = algosdk.secretKeyToMnemonic(generatedAccount.sk); console.log(`My address: ${generatedAccount.addr}`); console.log(`My passphrase: ${passphrase}`); ``` [Snippet Source](https://github.com/algorand/js-algorand-sdk/blob/examples/examples/accounts.ts#L80-L84) <!-- ===JSSDK_ACCOUNT_GENERATE=== --> [`More Information`](../../get-details/accounts/create.md#standalone){target=_blank} !!! Warning Never share mnemonic private keys. Production environments require stringent private key management. For more information on key management in community wallets, click [here](https://developer.algorand.org/docs/community/#wallets). For the [Algorand open source wallet](https://developer.algorand.org/articles/algorand-wallet-now-open-source/), click [here](https://github.com/algorand/algorand-wallet). # Fund the Account Before sending transactions to the Algorand network, the account must be funded to cover the minimal transaction fees that exist on Algorand. In this example, we'll be using prefunded accounts available in the Sandbox. To fund an account on Testnet account use the [Algorand faucet](https://dispenser.testnet.aws.algodev.network/){target=_blank}. !!! Info All Algorand accounts require a minimum balance to be registered in the ledger. To read more about Algorand minimum balance see [Account Overview](https://developer.algorand.org/docs/features/accounts/#minimum-balance) # Connect Your Client An Algod client must be instantiated prior to making calls to the API endpoints. You must provide values for `<algod-address>` and `<algod-token>`. The CLI tools implement the client natively. By default, the `algodToken` for each [sandbox](https://github.com/algorand/sandbox) is set to its `aaa...` value and the `algodAddress` corresponds to `http://localhost:4001`. <!-- ===JSSDK_ALGOD_CREATE_CLIENT=== --> ```javascript const algodToken = 'a'.repeat(64); const algodServer = 'http://localhost'; const algodPort = 4001; const algodClient = new algosdk.Algodv2(algodToken, algodServer, algodPort); ``` [Snippet Source](https://github.com/algorand/js-algorand-sdk/blob/examples/examples/overview.ts#L7-L12) <!-- ===JSSDK_ALGOD_CREATE_CLIENT=== --> !!! Info The example code connects to the sandbox Algod client. If you want to connect to a public API client, change the host, port, and token parameters to match the API service. See some service available [here](https://developer.algorand.org/ecosystem-projects/?tags=api-services) !!! Info If you are connecting to the Testnet, a dispenser is available [here](https://dispenser.testnet.aws.algodev.network/){target=_blank} # Check Your Balance Before moving on to the next step, make sure your account has been funded by the faucet. <!-- ===JSSDK_ALGOD_FETCH_ACCOUNT_INFO=== --> ```javascript const acctInfo = await algodClient.accountInformation(acct.addr).do(); console.log(`Account balance: ${acctInfo.amount} microAlgos`); ``` [Snippet Source](https://github.com/algorand/js-algorand-sdk/blob/examples/examples/overview.ts#L46-L48) <!-- ===JSSDK_ALGOD_FETCH_ACCOUNT_INFO=== --> # Build First Transaction Transactions are used to interact with the Algorand network. To create a payment transaction use the following code. <!-- ===JSSDK_TRANSACTION_PAYMENT_CREATE=== --> ```javascript const suggestedParams = await algodClient.getTransactionParams().do(); const ptxn = algosdk.makePaymentTxnWithSuggestedParamsFromObject({ from: acct.addr, suggestedParams, to: acct2.addr, amount: 10000, note: new Uint8Array(Buffer.from('hello world')), }); ``` [Snippet Source](https://github.com/algorand/js-algorand-sdk/blob/examples/examples/overview.ts#L23-L31) <!-- ===JSSDK_TRANSACTION_PAYMENT_CREATE=== --> !!! Info Algorand supports many transaction types. To see what types are supported see [Transactions](https://developer.algorand.org/docs/get-details/transactions/). # Sign First Transaction Before the transaction is considered valid, it must be signed by a private key. Use the following code to sign the transaction. <!-- ===JSSDK_TRANSACTION_PAYMENT_SIGN=== --> ```javascript const signedTxn = ptxn.signTxn(acct.privateKey); ``` [Snippet Source](https://github.com/algorand/js-algorand-sdk/blob/examples/examples/overview.ts#L34-L35) <!-- ===JSSDK_TRANSACTION_PAYMENT_SIGN=== --> !!! Info Algorand provides many ways to sign transactions. To see other ways see [Authorization](https://developer.algorand.org/docs/features/transactions/signatures/#single-signatures). # Submit the Transaction The signed transaction can now be submitted to the network.`waitForConfirmation` is called after the transaction is submitted to wait until the transaction is broadcast to the Algorand blockchain and is confirmed. The below snippet also shows how you can decode the data in the node field again to make it readable. <!-- ===JSSDK_TRANSACTION_PAYMENT_SUBMIT=== --> ```javascript const { txId } = await algodClient.sendRawTransaction(signedTxn).do(); const result = await algosdk.waitForConfirmation(algodClient, txId, 4); console.log(result); console.log(`Transaction Information: ${result.txn}`); console.log(`Decoded Note: ${Buffer.from(result.txn.txn.note).toString()}`); ``` [Snippet Source](https://github.com/algorand/js-algorand-sdk/blob/examples/examples/overview.ts#L38-L43) <!-- ===JSSDK_TRANSACTION_PAYMENT_SUBMIT=== --> # View the Transaction To view the transaction we submitted to the sandbox Algod, open [Lora](https://lora.algokit.io/localnet){target=_blank} and choose `LocalNet` configuration option, then search for the transaction ID. To view a transaction submitted to public network like testnet, open [Lora](https://lora.algokit.io/testnet){target=_blank} or [Pera Explorer](https://testnet.explorer.perawallet.app/){target=blank} and paste the transaction ID into the search bar. ``` -------------------------------------------------------------------------------- /packages/server/src/resources/knowledge/taxonomy/developer:docs:details:dapps:smart-contracts:smartsigs:walkthrough.md: -------------------------------------------------------------------------------- ```markdown title: CLI smart signatures This guide covers working with the `goal` command-line tool with smart signatures. TEAL programs can be written with any editor and are compiled using the `goal` command-line tool. They can also be built using python with the [PyTeal Library](/docs/get-details/dapps/writing-contracts/pyteal). The command-line tool provides the ability to use these compiled programs within transactions. # Simple TEAL example The simplest program you can write in TEAL is probably the following: ```go // simple.teal // Do not use this in a real application int 0 ``` This simplistic example always returns false and should never be used in a real transaction. The following command illustrates compiling this program: ``` goal clerk compile simple.teal // Compile output simple.teal: 6Z3C3LDVWGMX23BMSYMANACQOSINPFIRF77H7N3AWJZYV6OH6GWTJKVMXY ``` The compilation returns an Algorand Address. This is the contract account address if the TEAL program is used as a contract account. If the TEAL program is intended to be used as a delegated signature, the logic should be signed with a private key. This is done using the `-s` option with the `goal clerk compile` command. The following example shows using goal to compile and sign the TEAL program in one operation. ``` goal clerk compile simple.teal -o mydelegatedsig.lsig -s -a C3MKH24QL3GHSD5CDQ47ZNQZMNZRX4MUTV6LVPAXMWAXMIISYSOWPGH674 -d ~/node/data ``` Logic is signed with a specific address specified with the `-a` option. If no default wallet is assigned, the `-w` option is used to specify the wallet that contains the account that is signing the logic. The `-o` option specifies the name of the logic signature file. In this example, the file mydelegatedsig.lsig is created. This file can be shared to let others submit transactions with the authority of the original signer. When this logic signature is used in a transaction the logic will determine if the transaction is approved. The following example shows how the logic signature is used in a transaction with `goal` ``` goal clerk send -f C3MKH24QL3GHSD5CDQ47ZNQZMNZRX4MUTV6LVPAXMWAXMIISYSOWPGH674 -a 1000000 -t STF6TH6PKINM4CDIQHNSC7QEA4DM5OJKKSACAPWGTG776NWSQOMAYVGOQE -L mydelegatedsig.lsig -d ~/node/data ``` The `-f` option specifies the account that signed the logic signature and the -t option specifies the receiver of the transaction. The transaction fee is paid by the account that signed the logic signature. # Compiling TEAL options Compiling a teal program using the `goal clerk compile` compiles and writes the binary raw bytes to a file with the same name as the source file with a `.tok` extension. Specifying the `-n` option will compile the TEAL program, but not write out the binary. The console will display the compiled TEAL's address. ``` $ goal clerk compile -n simple.teal simple.teal: KI4DJG2OOFJGUERJGSWCYGFZWDNEU2KWTU56VRJHITP62PLJ5VYMBFDBFE ``` Removing the `-n` option writes the binary to a file named simple.teal.tok. Supplying the `-o` option allows the binary to be written to a specific location and filename. ``` goal clerk compile simple.teal -o /tmp/mytealbinary.tealc ``` The raw binary TEAL program can be disassembled using the `-D` option. ``` $ goal clerk compile -D /tmp/mytealbinary.tealc // Terminal Output // version 1 intcblock 0 intc_0 ``` In the above examples, the TEAL program is compiled and can be used as a contract account as discussed in the [Usage Modes](../modes) documentation. To use TEAL for account [delegation](../modes#delegated-account), the program must be signed by an account or a multi-signature account. This can be done with `goal` using the `-s` option. The following will produce a LogicSig file. ``` goal clerk compile simple.teal -o /tmp/simple.lsig -s -d ~/node/data ``` In the example above, the `-o` option is used to produce the logic signature file, which contains the raw program binary and the signature as discussed in the [Logic Signature](../modes#logic-signatures) documentation. Using the `-a` option allows the TEAL program to be signed by a specific account. ``` goal clerk compile simple.teal -o /tmp/simple.lsig -s -a LSJY4JD5J626BMJY2NMODBP64WDQP5OS4M6YF2F5BWQUS22I3YJYCXHHIA -d ~/node/data ``` A logic signature file can be disassembled in the same way as the standard binary. ``` goal clerk compile -D /tmp/simple.lsig // Console Output // version 1 intcblock 0 intc_0 LogicSig: { "sig": "45on5JUofgMjxL9e7IiPzCwutMHj3hFS1bKnCpxjgQ06dhikUgQSadqxcSOMKlcpN31W88hzkv3AeUUDLc4qAg==" } ``` # Creating a multi-signature delegated logic sig In the previous section, a logic signature was created using a single account. As discussed in the [Logic Signature](../modes#logic-signatures) documentation, LogicSigs can also be created using a multi-signature account. For example, a three account multi-signature account with a threshold level of 2 can be created using the following command. ``` goal account multisig new -T 2 DFPKC2SJP3OTFVJFMCD356YB7BOT4SJZTGWLIPPFEWL3ZABUFLTOY6ILYE LSJY4JD5J626BMJY2NMODBP64WDQP5OS4M6YF2F5BWQUS22I3YJYCXHHIA YYKRMERAFXMXCDWMBNR6BUUWQXDCUR53FPUGXLUYS7VNASRTJW2ENQ7BMQ -d ~/node/data ``` This creates a multi-sig account that requires at least two signatures to authorize a transaction. To create a logic signature, any one of the three accounts can sign the logic and create a logic signature file. This is done using the `goal clerk multisig signprogram` command. ``` goal clerk multisig signprogram -p /tmp/simple.teal -a YYKRMERAFXMXCDWMBNR6BUUWQXDCUR53FPUGXLUYS7VNASRTJW2ENQ7BMQ -A 5DLEJBZHDG4XTIILEEJ6HSLG2YFGHNDAKIUAFASMFV234CJGEDQYMJ6LMI -o /tmp/simple.lsig -d ~/node/data ``` In the above example, the `-p` option specifies the TEAL program file. The TEAL program bytes can also be passed directly using the `-P` option. The `-a` option specifies which account is signing the logic and the `-A` specifies the multi-signature address. At this point the logic signature file only contains one signature and the threshold is set to two. This means that in order for the logic signature to be used, one of the two remaining accounts must also sign the logic signature file. This is done using the `-L` option with the `goal clerk multisig signprogram` command. ``` goal clerk multisig signprogram -L /tmp/simple.lsig -a LSJY4JD5J626BMJY2NMODBP64WDQP5OS4M6YF2F5BWQUS22I3YJYCXHHIA -A 5DLEJBZHDG4XTIILEEJ6HSLG2YFGHNDAKIUAFASMFV234CJGEDQYMJ6LMI -d ~/node/data ``` Decompiling the logic signature shows the number of current signatures. ``` $ goal clerk compile -D /tmp/simple.lsig // Console Output // version 1 intcblock 0 intc_0 LogicSig: { "msig": { "subsig": [ { "pk": "YYKRMERAFXMXCDWMBNR6BUUWQXDCUR53FPUGXLUYS7VNASRTJW2ENQ7BMQ", "s": "h7/CyM7aiJnDnXOjyNeY2DlOZhqieaWafO0n2Hi4d9IfyFozjKQL9/kB2x7QQV+bPRTORdbYCXpL2x6c5razAw==" }, { "pk": "LSJY4JD5J626BMJY2NMODBP64WDQP5OS4M6YF2F5BWQUS22I3YJYCXHHIA", "s": "/s/BsHGK+RThEmrc2Wre/VVBX6jtqcMS/pZQTA0iBE3S5d+D4BFeD2JXRSAW/oD78V9SlLXSfOYGAfEnianaDw==" } ], "thr": 2, "v": 1 } } ``` # Passing parameters to TEAL with goal Parameters can be passed to a TEAL program using `goal`. The parameters must be passed as base64 encoded strings. For example, to pass “mystringargument” to a stateless TEAL program, the argument can be encoded using an `echo` command with base64. The `-w0` argument disables wrapping that defaults to 76 characters. ``` $ echo -n mystringargument | base64 -w0 bXlzdHJpbmdhcmd1bWVudA== ``` The base64 encoded string is passed to the TEAL program using the `--argb64` option. The `goal` command line can be passed multiple parameters using the `--argb64` option multiple times. The parameter order is specific and will directly map to the TEAL parameters array. ``` goal clerk send -a 1000 -c closeaccountotaddress --to toaddr --from-program myteal.teal --argb64 "bXlzdHJpbmdhcmd1bWVudA==" -d ~/node/data ``` The example above also illustrates using the `--from-program` option. This option instructs the compiler to compile a specific TEAL program and set it as the sender of the transaction. Because the `-s` option is not used, this account must be a contract account. Passing an integer to a TEAL program requires that it must be converted to a base64 encoded string as well when using `goal`. This can be done in many ways. The following example illustrates the conversion using a simple python command. ``` python $ python3 -c "import base64;print(base64.b64encode((123).to_bytes(8,'big')).decode('ascii'))" ``` The example above converts the integer value of 123 to a base64 encoded string. TEAL currently does not support negative numbers. Each SDK provides facilities for passing parameters as well. These processes are described in the [Interact with smart signatures](../frontend/smartsigs.md) Usage documentation. ``` -------------------------------------------------------------------------------- /packages/server/src/resources/knowledge/taxonomy/developer:docs:sdks:go:index.md: -------------------------------------------------------------------------------- ```markdown title: Go SDK: Your First Transaction This section is a quick start guide for interacting with the Algorand network using Go. This guide will help to install [Algorand sandbox](https://github.com/algorand/sandbox){target=blank}, which provides a node for testing and development. This guide will also help to install the Go SDK, create an account and submit your first transaction on Algorand. # Install Sandbox !!! info This step is only required if you are not using AlgoKit. If you are using AlgoKit, you can spin up a sandbox using the LocalNet, see [AlgoKit getting started guide](/docs/get-started/algokit/#start-a-localnet) for more information. !!! Prerequisites - Docker Compose ([install guide](https://docs.docker.com/compose/install/)) - Git ([install guide](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)) Algorand provides a docker instance for setting up a node, which can be used to get started developing quickly. To install and use this instance, follow these instructions. ```bash git clone https://github.com/algorand/sandbox.git cd sandbox ./sandbox up dev ``` This will install and start private network. To read more about Algorand networks see [Algorand Networks](../../get-details/algorand-networks/index.md){target=_blank}. [More Information about the sandbox](https://developer.algorand.org/articles/introducing-sandbox-20/) and [how to use](https://developer.algorand.org/tutorials/exploring-the-algorand-sandbox/) it. # Install Go SDK Algorand provides an SDK for Go. !!! Prerequisites - Go programming language ([install guide](https://golang.org/doc/install)) From a terminal window, install the Go SDK: ```bash go get -u github.com/algorand/go-algorand-sdk/v2 ``` The [GitHub repository](https://github.com/algorand/go-algorand-sdk){target=_blank} contains additional documentation and examples. See the JavaScript SDK [reference documentation](https://pkg.go.dev/github.com/algorand/go-algorand-sdk/v2){target=_blank} for more information on methods. The SDK is installed and can now interact with the running Algorand Sandbox environment, as configured above. # Create an account In order to interact with the Algorand blockchain, you must have a funded account on the network. To quickly create a test account use the following code. <!-- ===GOSDK_ACCOUNT_GENERATE=== --> ```go account := crypto.GenerateAccount() mn, err := mnemonic.FromPrivateKey(account.PrivateKey) if err != nil { log.Fatalf("failed to generate account: %s", err) } log.Printf("Address: %s\n", account.Address) log.Printf("Mnemonic: %s\n", mn) ``` [Snippet Source](https://github.com/algorand/go-algorand-sdk/blob/examples/examples/account/main.go#L16-L25) <!-- ===GOSDK_ACCOUNT_GENERATE=== --> [`More Information`](../../get-details/accounts/create.md#standalone){target=_blank} !!! Warning Never share your mnemonic passphrase or private keys. Production environments require stringent private key management. For more information on key management in community Wallets, click [here](https://developer.algorand.org/docs/community/#wallets). For the open source [Algorand Wallet](https://developer.algorand.org/articles/algorand-wallet-now-open-source/), click [here](https://github.com/algorand/algorand-wallet). # Fund the account Before sending transactions to the Algorand network, the account must be funded to cover the minimal transaction fees that exist on Algorand. In this example, we'll be using prefunded accounts available in the Sandbox. To fund an account on Testnet account use the [Algorand faucet](https://dispenser.testnet.aws.algodev.network/){target=_blank}. !!! Info All Algorand accounts require a minimum balance to be registered in the ledger. To read more about Algorand minimum balance see [Account Overview](https://developer.algorand.org/docs/features/accounts/#minimum-balance) # Connect Your Client An Algod client must be instantiated prior to making calls to the API endpoints. You must provide values for `<algod-address>` and `<algod-token>`. The CLI tools implement the client natively. By default, the `algodToken` for each [sandbox](https://github.com/algorand/sandbox) is set to its `aaa...` value and the `algodAddress` corresponds to `http://localhost:4001`. <!-- ===GOSDK_ALGOD_CREATE_CLIENT=== --> ```go // Create a new algod client, configured to connect to out local sandbox var algodAddress = "http://localhost:4001" var algodToken = strings.Repeat("a", 64) algodClient, _ := algod.MakeClient( algodAddress, algodToken, ) // Or, if necessary, pass alternate headers var algodHeader common.Header algodHeader.Key = "X-API-Key" algodHeader.Value = algodToken algodClientWithHeaders, _ := algod.MakeClientWithHeaders( algodAddress, algodToken, []*common.Header{&algodHeader}, ) ``` [Snippet Source](https://github.com/algorand/go-algorand-sdk/blob/examples/examples/overview/main.go#L18-L36) <!-- ===GOSDK_ALGOD_CREATE_CLIENT=== --> !!! Info The example code connects to the sandbox Algod client. If you want to connect to a public API client, change the host, port, and token parameters to match the API service. See some service available [here](https://developer.algorand.org/ecosystem-projects/?tags=api-services) !!! Info If you are connecting to the Testnet, a dispenser is available [here](https://dispenser.testnet.aws.algodev.network/){target=_blank} # Check Your Balance Before moving on to the next step, make sure your account has been funded. <!-- ===GOSDK_ALGOD_FETCH_ACCOUNT_INFO=== --> ```go acctInfo, err := algodClient.AccountInformation(acct.Address.String()).Do(context.Background()) if err != nil { log.Fatalf("failed to fetch account info: %s", err) } log.Printf("Account balance: %d microAlgos", acctInfo.Amount) ``` [Snippet Source](https://github.com/algorand/go-algorand-sdk/blob/examples/examples/overview/main.go#L51-L56) <!-- ===GOSDK_ALGOD_FETCH_ACCOUNT_INFO=== --> # Build First Transaction Transactions are used to interact with the Algorand network. To create a payment transaction use the following code. <!-- ===GOSDK_TRANSACTION_PAYMENT_CREATE=== --> ```go sp, err := algodClient.SuggestedParams().Do(context.Background()) if err != nil { log.Fatalf("failed to get suggested params: %s", err) } // payment from account to itself ptxn, err := transaction.MakePaymentTxn(acct.Address.String(), acct.Address.String(), 100000, nil, "", sp) if err != nil { log.Fatalf("failed creating transaction: %s", err) } ``` [Snippet Source](https://github.com/algorand/go-algorand-sdk/blob/examples/examples/overview/main.go#L59-L68) <!-- ===GOSDK_TRANSACTION_PAYMENT_CREATE=== --> !!! Info Algorand supports many transaction types. To see what types are supported see [Transactions](https://developer.algorand.org/docs/features/transactions/). # Sign First transaction Before the transaction is considered valid, it must be signed by a private key. Use the following code to sign the transaction. <!-- ===GOSDK_TRANSACTION_PAYMENT_SIGN=== --> ```go _, sptxn, err := crypto.SignTransaction(acct.PrivateKey, ptxn) if err != nil { fmt.Printf("Failed to sign transaction: %s\n", err) return } ``` [Snippet Source](https://github.com/algorand/go-algorand-sdk/blob/examples/examples/overview/main.go#L71-L76) <!-- ===GOSDK_TRANSACTION_PAYMENT_SIGN=== --> !!! Info Algorand provides many ways to sign transactions. To see other ways see [Authorization](https://developer.algorand.org/docs/features/transactions/signatures/#single-signatures). # Submit transaction The signed transaction can now be broadcast to the network for validation and inclusion in a future block. The `waitForConfirmation` SDK method polls the `algod` node for the transaction ID to ensure it succeeded. <!-- ===GOSDK_TRANSACTION_PAYMENT_SUBMIT=== --> ```go pendingTxID, err := algodClient.SendRawTransaction(sptxn).Do(context.Background()) if err != nil { fmt.Printf("failed to send transaction: %s\n", err) return } confirmedTxn, err := transaction.WaitForConfirmation(algodClient, pendingTxID, 4, context.Background()) if err != nil { fmt.Printf("Error waiting for confirmation on txID: %s\n", pendingTxID) return } fmt.Printf("Confirmed Transaction: %s in Round %d\n", pendingTxID, confirmedTxn.ConfirmedRound) ``` [Snippet Source](https://github.com/algorand/go-algorand-sdk/blob/examples/examples/overview/main.go#L79-L90) <!-- ===GOSDK_TRANSACTION_PAYMENT_SUBMIT=== --> # Viewing the Transaction To view the transaction we submitted to the sandbox Algod, open [Lora](https://lora.algokit.io/localnet){target=_blank} and choose `LocalNet` configuration option, then search for the transaction ID. To view a transaction submitted to public network like testnet, open [Lora](https://lora.algokit.io/testnet){target=_blank} or [Pera Explorer](https://testnet.explorer.perawallet.app/){target=blank} and paste the transaction ID into the search bar. ``` -------------------------------------------------------------------------------- /packages/server/src/resources/knowledge/taxonomy/algokit:cli:architecture-decisions:2024-03-06_local_dev_ui_packaging.md: -------------------------------------------------------------------------------- ```markdown # Local dev UI packaging - **Status**: Draft - **Owner:** Patrick Dinh (MakerX), Negar Abbasi (MakerX) - **Deciders**: Alessandro (Algorand Foundation), Rob Moore (MakerX), MakerX team - **Date created**: 2024-03-06 ## Context We are building a web-based local development interface to support: - Exploring transactions, assets and accounts - Visualising transactions - Launching a VS Code debug session from an application call transaction - Integrating and using a dev wallet via KMD - Network switching between LocalNet, TestNet and MainNet - Calling deployed ABI apps - Integration with the AlgoKit CLI to perform any relevant actions - Launching the interface from the AlgoKit CLI ## Requirements The local development interface should have: - Support for a wide variety of Linux distributions, macOS (both Apple Silicon and Intel architectures), and Windows 10+. - Local system access to: - The user home directory on the file system. - Launch child processes. - Launch the UI from the AlgoKit CLI. - Launch shell commands. - The ability for the explorer portion to be deployed to a static web host. - The ability to be installed via the following channels: - Winget for Windows. - Homebrew for macOS. - Snapcraft for Linux. - The ability for users to see a notification when a new version is available and can update. ## Out of scope - Support for ARM processors on Linux or Windows. ## Options ### Option 1 - Electron [Electron](https://www.electronjs.org/) is a framework for creating native applications with web technologies like JavaScript, HTML, and CSS. It allows developers to build cross-platform desktop apps using their existing web development skills. Link to PoC is here: [Electron PoC](https://github.com/negar-abbasi/electron-poc). **Pros** - Electron is a mature framework with a large community and a lot of resources available. - Uses standard JavaScript and Node APIs, which most developers are very familiar with. - It supports all the local system access requirements via [icpMain](https://www.electronjs.org/docs/latest/api/ipc-main), allowing asynchronous communication from the main process to renderer processes. - File system access is enabled using the Node.js `fs` module. See [Node.js File System (fs) module docs](https://nodejs.org/api/fs.html). - Launching processes is enabled using the Node.js `child_process` module to spawn new processes. [Node.js Child Processes](https://nodejs.org/api/child_process.html). Specifically, well use the `spawn` or `exec` functions. - Running shell commands is enabled via the Node.js `child_process` module's `exec` function. - Electron supports an [auto update](https://www.electronjs.org/docs/latest/api/auto-updater) for windows and macOS only. For Linux, if the explorer is distributed via Snapcraft, it should get auto updated. - Electron does not have any built in tooling for packaging and distribution. There are however several third-party tools available for packaging and distribution, such as [electron-builder](https://www.electron.build/), [electron-packager](https://www.npmjs.com/package/electron-packager), and [electron-forge](https://www.electronforge.io/). - Electron Forge is an all-in-one tool that handles the packaging and distribution of Electron apps. Under the hood, it combines a lot of existing Electron tools (e.g. @electron/packager, @electron/osx-sign, electron-winstaller, etc.) into a single interface so we do not have to worry about wiring them all together. [docs](https://www.electronjs.org/docs/latest/tutorial/tutorial-packaging#using-electron-forge) - It can package the app into format that we are interested in: - `.deb`, `.snap` for Linux - `.msi` for Windows - `.dmg` for macOS **Cons** - Electron is resource hungry, for a small test app (Hello World) it uses 146.0 MB of memory and 0.47% of CPU (running on macOS M2 CPU with 12 cores and 16GB RAM) - When built on a local dev machine, the package size for macOS is ~250MB. ### Option 2 - Tauri [Tauri](https://tauri.app/about/intro) is a toolkit that helps developers make applications for the major desktop platforms - using virtually any frontend framework in existence. The core is built with Rust, and the CLI leverages Node.js making Tauri a genuinely polyglot approach to creating and maintaining great apps. **Pros** - Tauri supports all requirements for the local development interface via their JavaScript API without the need to write any Rust. - It can manage the [file systems](https://tauri.app/v1/api/js/fs), launch another [process](https://tauri.app/v1/api/js/process), run a [shell command](https://tauri.app/v1/api/js/shell). - Tauri integrates well with major web frameworks. [`create-tauri-app`](https://github.com/tauri-apps/create-tauri-app) and a good template project can be bootstrapped and working within minutes. - Once bootstrapped, the web app can be bundled individually and deployed as a website. Below is the `npm script` Tauri generates for a Vite project, we can see that it supports `vite build` ```json "scripts": { "dev": "vite", "build": "tsc && vite build", "preview": "vite preview", "tauri": "tauri" }, ``` - For [compiling binaries](https://tauri.app/v1/guides/building/), the Tauri Bundler supports - Windows: setup.exe, .msi - macOS: .app, .dmg - Linux: .deb, .appimage - The Tauri Bundler supports code signing for: - [Windows](https://tauri.app/v1/guides/distribution/sign-windows) - [Linux](https://tauri.app/v1/guides/distribution/sign-linux) - [macOS](https://tauri.app/v1/guides/distribution/sign-macos) - Tauri offers a [built-in updater](https://tauri.app/v1/guides/distribution/updater) for the NSIS (Windows), MSI (Windows), AppImage (Linux) and App bundle (macOS) distribution formats. - Tauri is reasonably efficient, for a small test app (Hello World) it uses 30 MB of RAM and 0.1% CPU (running on macOS M1 CPU and 32GB RAM). - When built on a local dev machine, the package size for macOS is ~5MB. **Cons** - If we need to extend the functionality beyond the support of Tauri's JavaScript API, we will need to write the code in Rust, which would be a new language in the AlgoKit ecosystem and a less common skill in the team. - At the point of writing, building with `snap` (for Linux) isn't officially supported by Tauri. There is a open [PR](https://github.com/tauri-apps/tauri/pull/6532). We can however support snap by packaging the Linux build output ourselves. - Tauri relies on [Webview](https://tauri.app/v1/references/webview-versions/) which are not the same across platforms. This means that we'll need to perform more testing on the styling and rendering, to ensure a consistent experience across the different platform Webviews and the supported versions. - For reference, [here](https://github.com/tauri-apps/tauri/issues?q=is%3Aissue+webview+css) are Tauri's issues related to CSS. - For some versions of Windows 10, WebView2 needs to be installed. This process requires internet connection whilst installing. ### Option 3 - Wails [Wails](https://wails.io/) is similar to Tauri but the core is written in Go. **Pros** - Wails has init templates for major web framework. React + TypeScript + Vite is supported. - Wails has an auto codegen to generate the contract between the main process and the renderer process. - Wails doesn't have built-in code signing for Windows and Mac. However, the document on how to do code signing with GitHub actions is very detailed. - Wails is reasonably efficient, for a small test app (Hello World) it uses 30 MB of RAM and 0.1% CPU (running on macOS M1 CPU and 32GB RAM). - When built on a local dev machine, the package size for macOS is ~5MB. **Cons** - Documentation isn't as comprehensive as Electron and Tauri. Because of this, I didn't investigate much further into Wails. Tauri seems to be a more supported project, Wails doesn't give us anything additional. - The code to interact with file systems, shell and child processes will be written in Go, which would be a new language in the AlgoKit ecosystem and a less common skill in the team. - No built-in updater. It is tracked in this [issue](https://github.com/wailsapp/wails/issues/1178). - Wails is based on WebView, therefore, it has the same cross-platform issues with Tauri. - Wails supports building for Windows, Mac and Linux. The documentation however isn't super clear: - I could build Windows binaries from Mac. - I couldn't build Linux binaries from Mac. - The document doesn't mention options to build installers. ## Preferred option - **Option2** Tauri is the preferred option because it is well documented and has a big community behind it. Tauri supports all of our use cases and is less resource hungry than Electron. ## Selected option Option 2 Given the good community support, great docs, low resource consumption and not needing to write much (if any) Rust, Tauri (Option 2) appears to fit our needs very well. ``` -------------------------------------------------------------------------------- /packages/server/tests/tools/utilityManager.test.ts: -------------------------------------------------------------------------------- ```typescript import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js'; import { UtilityManager } from '../../src/tools/utilityManager'; import algosdk from 'algosdk'; // Rest of the file remains the same... // Mock algosdk jest.mock('algosdk', () => ({ isValidAddress: jest.fn(), encodeAddress: jest.fn(), decodeAddress: jest.fn(), getApplicationAddress: jest.fn(), })); describe('UtilityManager', () => { beforeEach(() => { jest.clearAllMocks(); }); describe('Tool Schemas', () => { it('should have valid tool schemas', () => { expect(UtilityManager.utilityTools).toHaveLength(8); expect(UtilityManager.utilityTools.map((t: { name: string; }) => t.name)).toEqual([ 'validate_address', 'encode_address', 'decode_address', 'get_application_address', 'bytes_to_bigint', 'bigint_to_bytes', 'encode_uint64', 'decode_uint64', ]); }); }); describe('Address Operations', () => { const testAddress = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'; const testPublicKey = Buffer.from('0'.repeat(64), 'hex'); it('should validate address', () => { (algosdk.isValidAddress as jest.Mock).mockReturnValue(true); const result = UtilityManager.isValidAddress(testAddress); expect(result).toBe(true); expect(algosdk.isValidAddress).toHaveBeenCalledWith(testAddress); }); it('should encode address', () => { (algosdk.encodeAddress as jest.Mock).mockReturnValue(testAddress); const result = UtilityManager.encodeAddress(testPublicKey); expect(result).toBe(testAddress); expect(algosdk.encodeAddress).toHaveBeenCalledWith(testPublicKey); }); it('should decode address', () => { (algosdk.decodeAddress as jest.Mock).mockReturnValue({ publicKey: testPublicKey }); const result = UtilityManager.decodeAddress(testAddress); expect(result).toBe(testPublicKey); expect(algosdk.decodeAddress).toHaveBeenCalledWith(testAddress); }); it('should get application address', () => { const appId = 123; const appAddress = 'APP_ADDRESS'; (algosdk.getApplicationAddress as jest.Mock).mockReturnValue(appAddress); const result = UtilityManager.getApplicationAddress(appId); expect(result).toBe(appAddress); expect(algosdk.getApplicationAddress).toHaveBeenCalledWith(appId); }); }); describe('BigInt Operations', () => { it('should convert bytes to BigInt', () => { const bytes = Buffer.from('0001', 'hex'); const result = UtilityManager.bytesToBigInt(bytes); expect(result.toString()).toBe('1'); }); it('should convert BigInt to bytes', () => { const value = BigInt(1); const size = 2; const result = UtilityManager.bigIntToBytes(value, size); expect(Buffer.from(result).toString('hex')).toBe('0001'); }); it('should encode uint64', () => { const value = BigInt(1); const result = UtilityManager.encodeUint64(value); expect(Buffer.from(result).toString('hex')).toBe('0000000000000001'); }); it('should decode uint64', () => { const bytes = Buffer.from('0000000000000001', 'hex'); const result = UtilityManager.decodeUint64(bytes); expect(result.toString()).toBe('1'); }); }); describe('handleTool', () => { it('should handle validate_address', async () => { (algosdk.isValidAddress as jest.Mock).mockReturnValue(true); const result = await UtilityManager.handleTool('validate_address', { address: 'test-address', }); expect(result).toEqual({ content: [{ type: 'text', text: JSON.stringify({ isValid: true }, null, 2), }], }); }); it('should handle encode_address', async () => { const testAddress = 'encoded-address'; (algosdk.encodeAddress as jest.Mock).mockReturnValue(testAddress); const result = await UtilityManager.handleTool('encode_address', { publicKey: '00', }); expect(result).toEqual({ content: [{ type: 'text', text: JSON.stringify({ address: testAddress }, null, 2), }], }); }); it('should handle decode_address', async () => { const testPublicKey = Buffer.from('00', 'hex'); (algosdk.decodeAddress as jest.Mock).mockReturnValue({ publicKey: testPublicKey }); const result = await UtilityManager.handleTool('decode_address', { address: 'test-address', }); expect(result).toEqual({ content: [{ type: 'text', text: JSON.stringify({ publicKey: '00' }, null, 2), }], }); }); it('should handle get_application_address', async () => { const appAddress = 'app-address'; (algosdk.getApplicationAddress as jest.Mock).mockReturnValue(appAddress); const result = await UtilityManager.handleTool('get_application_address', { appId: 123, }); expect(result).toEqual({ content: [{ type: 'text', text: JSON.stringify({ address: appAddress }, null, 2), }], }); }); it('should handle bytes_to_bigint', async () => { const result = await UtilityManager.handleTool('bytes_to_bigint', { bytes: '0001', }); expect(result).toEqual({ content: [{ type: 'text', text: JSON.stringify({ value: '1' }, null, 2), }], }); }); it('should handle bigint_to_bytes', async () => { const result = await UtilityManager.handleTool('bigint_to_bytes', { value: '1', size: 2, }); expect(result).toEqual({ content: [{ type: 'text', text: JSON.stringify({ bytes: '0001' }, null, 2), }], }); }); it('should handle encode_uint64', async () => { const result = await UtilityManager.handleTool('encode_uint64', { value: '1', }); expect(result).toEqual({ content: [{ type: 'text', text: JSON.stringify({ bytes: '0000000000000001' }, null, 2), }], }); }); it('should handle decode_uint64', async () => { const result = await UtilityManager.handleTool('decode_uint64', { bytes: '0000000000000001', }); expect(result).toEqual({ content: [{ type: 'text', text: JSON.stringify({ value: '1' }, null, 2), }], }); }); describe('Error Handling', () => { it('should throw error for unknown tool', async () => { await expect(UtilityManager.handleTool('unknown_tool', {})) .rejects .toThrow(new McpError(ErrorCode.MethodNotFound, 'Unknown tool: unknown_tool')); }); it('should throw error for missing address in validate_address', async () => { await expect(UtilityManager.handleTool('validate_address', {})) .rejects .toThrow(new McpError(ErrorCode.InvalidParams, 'Address is required')); }); it('should throw error for missing public key in encode_address', async () => { await expect(UtilityManager.handleTool('encode_address', {})) .rejects .toThrow(new McpError(ErrorCode.InvalidParams, 'Public key is required')); }); it('should throw error for missing address in decode_address', async () => { await expect(UtilityManager.handleTool('decode_address', {})) .rejects .toThrow(new McpError(ErrorCode.InvalidParams, 'Address is required')); }); it('should throw error for missing app ID in get_application_address', async () => { await expect(UtilityManager.handleTool('get_application_address', {})) .rejects .toThrow(new McpError(ErrorCode.InvalidParams, 'Application ID is required')); }); it('should throw error for missing bytes in bytes_to_bigint', async () => { await expect(UtilityManager.handleTool('bytes_to_bigint', {})) .rejects .toThrow(new McpError(ErrorCode.InvalidParams, 'Bytes are required')); }); it('should throw error for missing value or size in bigint_to_bytes', async () => { await expect(UtilityManager.handleTool('bigint_to_bytes', {})) .rejects .toThrow(new McpError(ErrorCode.InvalidParams, 'Value and size are required')); }); it('should throw error for missing value in encode_uint64', async () => { await expect(UtilityManager.handleTool('encode_uint64', {})) .rejects .toThrow(new McpError(ErrorCode.InvalidParams, 'Value is required')); }); it('should throw error for missing bytes in decode_uint64', async () => { await expect(UtilityManager.handleTool('decode_uint64', {})) .rejects .toThrow(new McpError(ErrorCode.InvalidParams, 'Bytes are required')); }); }); }); }); ```