This is page 20 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/developer:docs:details:parameter_tables.md: -------------------------------------------------------------------------------- ```markdown title: Algorand parameter tables [comment]: <> (generated from: https://docs.google.com/spreadsheets/d/12E_B6AYBfhrOoylO8NZysqKns4rHKklV8I0fejiwMXE) ## Minimum balance |Name|Current value|Developer doc|Consensus parameter name in (.go)|Note| |-|-|-|-|-| |Default|0.1 Algos|[reference](./accounts/index.md#minimum-balance)|MinBalance|| |Opt-in ASA|+ 0.1 Algos|[reference](./asa.md#assets-overview)|MinBalance|| |Created ASA|+ 0.1 Algos|[reference](./asa.md#assets-overview)|MinBalance|creator of ASA does not need to opt in| |Opt-in Application|(see below)|||creator of application only needs to opt in if they use local state| |Created Application|(see below)|||| ## Minimum balance for smart contract |Name|Current value|Developer doc|Consensus parameter name in (.go)|Note| |-|-|-|-|-| |Per page application creation fee|0.1 Algos|[reference](./dapps/smart-contracts/apps/index.md#minimum-balance-requirement-for-a-smart-contract)|AppFlatParamsMinBalance|| |Flat for application opt-in|0.1 Algos|[reference](./dapps/smart-contracts/apps/index.md#minimum-balance-requirement-for-a-smart-contract)|AppFlatOptInMinBalance|| |Per state entry|0.025 Algos|[reference](./dapps/smart-contracts/apps/index.md#minimum-balance-requirement-for-a-smart-contract)|SchemaMinBalancePerEntry|| |Addition per integer entry|0.0035 Algos|[reference](./dapps/smart-contracts/apps/index.md#minimum-balance-requirement-for-a-smart-contract)|SchemaUintMinBalance|| |Addition per byte slice entry|0.025 Algos|[reference](./dapps/smart-contracts/apps/index.md#minimum-balance-requirement-for-a-smart-contract)|SchemaBytesMinBalance|| |Per Box created|0.0025 Algos|[reference](./dapps/smart-contracts/apps/index.md#minimum-balance-requirement-for-a-smart-contract)|BoxFlatMinBalance|| |Per byte in box created|0.0004 Algos|[reference](./dapps/smart-contracts/apps/index.md#minimum-balance-requirement-for-a-smart-contract)|BoxByteMinBalance|Includes the length of the key| ## Transaction fee |Name|Current value|Developer doc|Consensus parameter name in (.go)|Note| |-|-|-|-|-| |Minimum transaction fee, in all cases|0.001 Algos|[reference](./transactions/index.md#fees)|MinTxnFee|| |Additional minimum constraint if congestion|additional fee per byte|[reference](./transactions/index.md#fees)|-|| ## Others |Name|Current value|Developer doc|Consensus parameter name in (.go)|Note| |-|-|-|-|-| |Max number transactions in a group / atomic transfer|16|[reference](./atomic_transfers.md)|MaxTxGroupSize|| |Max number of inner transactions|256|[reference](https://developer.algorand.org/docs/get-details/dapps/smart-contracts/apps/#inner-transactions)|MaxInnerTransactions|Whilst the actual value is 16, inner transaction pooling multiplies this value by MaxTxGroupSize.| |Maximum size of a block|5000000 bytes|-|MaxTxnBytesPerBlock|| |Maximum size of note|1024 bytes|-|MaxTxnNoteBytes|| |Maximum transaction life|1000 rounds|[reference](./transactions/index.md#setting-first-and-last-valid)|MaxTxnLife|| ## ASA constraints |Name|Current value|Developer doc|Consensus parameter name in (.go)|Note| |-|-|-|-|-| |Max number of ASAs (create and opt-in)|Unlimited|[reference](./asa.md)|MaxAssetsPerAccount|| |Max asset name size|32 bytes|[reference](./asa.md)|MaxAssetNameBytes|| |Max unit name size|8 bytes|[reference](./asa.md)|MaxAssetUnitNameBytes|| |Max URL size|96 bytes|[reference](./asa.md)|MaxAssetURLBytes|| |Metadata hash|32 bytes|[reference](./asa.md)||padded with zeros| ## Smart signature constraints |Name|Current value|Developer doc|Consensus parameter name in (.go)|Note| |-|-|-|-|-| |Max size of compiled TEAL code combined with arguments|1000 bytes|[reference](../dapps/avm/teal/specification#execution-environment-for-logicsigs)|LogicSigMaxSize|| |Max cost of TEAL code|20000|[reference](../dapps/avm/teal/specification#execution-environment-for-logicsigs)|LogicSigMaxCost|| ## Smart contract constraints |Name|Current value|Developer doc|Consensus parameter name in (.go)|Note| |-|-|-|-|-| |Page size of compiled approval + clear TEAL code|2048 bytes|[reference](./dapps/avm/teal/index.md#dynamic-operational-cost-of-teal-opcodes)|MaxAppProgramLen|by default, each application has a single page| |Max extra app pages |3|[reference](./dapps/smart-contracts/apps/index.md#creating-the-smart-contract)|MaxExtraAppProgramPages|an application can "pay" for additional pages via minimum balance| |Max cost of approval TEAL code|700|[reference](./dapps/avm/teal/index.md#dynamic-operational-cost-of-teal-opcodes)|MaxAppProgramCost|| |Max cost of clear TEAL code|700|[reference](./dapps/avm/teal/index.md#dynamic-operational-cost-of-teal-opcodes)|MaxAppProgramCost|| |Max number of scratch variables|256|[reference](../dapps/avm/teal/specification/#scratch-space)||| |Max depth of stack|1000|[reference](../dapps/avm/teal/specification/#the-stack)|MaxStackDepth|| |Max number of arguments|16|[reference](./dapps/smart-contracts/apps/index.md#passing-arguments-to-stateful-smart-contracts)|MaxAppArgs|| |Max combined size of arguments|2048 bytes|[reference](./dapps/smart-contracts/apps/index.md#passing-arguments-to-stateful-smart-contracts)|MaxAppTotalArgLen|| |Max number of global state keys|64|[reference](./dapps/smart-contracts/apps/index.md#creating-the-smart-contract)|MaxGlobalSchemaEntries|| |Max number of local state keys|16|[reference](./dapps/smart-contracts/apps/index.md#creating-the-smart-contract)|MaxLocalSchemaEntries|| |Max number of log messages|32|[reference](../dapps/avm/teal/opcodes/#log)|MaxLogCalls|| |Max size of log messages|1024|[reference](../dapps/avm/teal/opcodes/#log)|MaxLogSize|| |Max key size|64 bytes|[reference](./dapps/smart-contracts/apps/index.md#creating-the-smart-contract)|MaxAppKeyLen|| |Max []byte value size|128 bytes|[reference](./dapps/smart-contracts/apps/index.md#creating-the-smart-contract)|MaxAppBytesValueLen|| |Max key + value size|128 bytes|[reference](./dapps/smart-contracts/apps/index.md#creating-the-smart-contract)|MaxAppSumKeyValueLens|| |Max number of foreign accounts|4|[reference](./dapps/smart-contracts/apps/index.md#stateful-contract-arrays)|MaxAppTxnAccounts|| |Max number of foreign ASAs|8|[reference](./dapps/smart-contracts/apps/index.md#stateful-contract-arrays)|MaxAppTxnForeignAssets|| |Max number of foreign applications|8|[reference](./dapps/smart-contracts/apps/index.md#stateful-contract-arrays)|MaxAppTxnForeignApps|| |Max number of foreign accounts + ASAs + applications + box storage|8|[reference](./dapps/smart-contracts/apps/index.md#stateful-contract-arrays)|MaxAppTotalTxnReferences|| |Max number of created applications|Unlimited|[reference](./dapps/smart-contracts/apps/index.md#opt-into-the-smart-contract)|MaxAppsCreated|| |Max number of opt-in applications|Unlimited|[reference](./dapps/smart-contracts/apps/index.md#opt-into-the-smart-contract)|MaxAppsOptedIn|| ## Box Constraints |Name|Current value|Developer doc|Consensus parameter name in (.go)|Note| |-|-|-|-|-| |Max size of box | 32768 |[reference](./dapps/smart-contracts/apps/index.md#box-storage)|MaxBoxSize|Does not include name/key length. That is capped by MaxAppKeyLen| |Max box references | 8 |[reference](./dapps/smart-contracts/apps/index.md#smart-contract-arrays)|MaxAppBoxReferences|| |Bytes per Box reference | 1024 |[reference](./dapps/smart-contracts/apps/index.md#smart-contract-arrays)|BytesPerBoxReference|| ``` -------------------------------------------------------------------------------- /packages/server/src/resources/knowledge/taxonomy/puya:python:testing:docs:index.md: -------------------------------------------------------------------------------- ```markdown # Algorand Python Testing [](https://github.com/algorandfoundation/algorand-python-testing/) [](https://developer.algorand.org/algokit/) [](https://github.com/algorandfoundation/algorand-python-testing) [](https://developer.algorand.org/algokit/) `algorand-python-testing` is a companion package to [Algorand Python](https://github.com/algorandfoundation/puya) that enables efficient unit testing of Algorand Python smart contracts in an offline environment. This package emulates key AVM behaviors without requiring a network connection, offering fast and reliable testing capabilities with a familiar Pythonic interface. The `algorand-python-testing` package provides: - A simple interface for fast and reliable unit testing - An offline testing environment that simulates core AVM functionality - A familiar Pythonic experience, compatible with testing frameworks like [pytest](https://docs.pytest.org/en/latest/), [unittest](https://docs.python.org/3/library/unittest.html), and [hypothesis](https://hypothesis.readthedocs.io/en/latest/) ## Quick Start `algopy` is a prerequisite for `algorand-python-testing`, providing stubs and type annotations for Algorand Python syntax. It enhances code completion and type checking when writing smart contracts. Note that this code isn't directly executable in standard Python interpreters; it's compiled by `puya` into TEAL for Algorand Network deployment. Traditionally, testing Algorand smart contracts involved deployment on sandboxed networks and interacting with live instances. While robust, this approach can be inefficient and lacks versatility for testing Algorand Python code. Enter `algorand-python-testing`: it leverages Python's rich testing ecosystem for unit testing without network deployment. This enables rapid iteration and granular logic testing. > **NOTE**: While `algorand-python-testing` offers valuable unit testing capabilities, it's not a replacement for comprehensive testing. Use it alongside other test types, particularly those running against the actual Algorand Network, for thorough contract validation. ### Prerequisites - Python 3.12 or later - [Algorand Python](https://github.com/algorandfoundation/puya) ### Installation `algorand-python-testing` is distributed via [PyPI](https://pypi.org/project/algorand-python-testing/). Install the package using `pip`: ```bash pip install algorand-python-testing ``` or using `poetry`: ```bash poetry add algorand-python-testing ``` ### Testing your first contract Let's write a simple contract and test it using the `algorand-python-testing` framework. #### Contract Definition ```{testcode} import algopy from algopy import arc4 class VotingContract(algopy.ARC4Contract): def __init__(self) -> None: self.topic = algopy.GlobalState(algopy.Bytes(b"default_topic"), key="topic", description="Voting topic") self.votes = algopy.GlobalState( algopy.UInt64(0), key="votes", description="Votes for the option", ) self.voted = algopy.LocalState(algopy.UInt64, key="voted", description="Tracks if an account has voted") @arc4.abimethod def set_topic(self, topic: arc4.String) -> None: self.topic.value = topic.bytes @arc4.abimethod def vote(self, pay: algopy.gtxn.PaymentTransaction) -> arc4.Bool: assert algopy.op.Global.group_size == algopy.UInt64(2), "Expected 2 transactions" assert pay.amount == algopy.UInt64(10_000), "Incorrect payment amount" assert pay.sender == algopy.Txn.sender, "Payment sender must match transaction sender" _value, exists = self.voted.maybe(algopy.Txn.sender) if exists: return arc4.Bool(False) # Already voted self.votes.value += algopy.UInt64(1) self.voted[algopy.Txn.sender] = algopy.UInt64(1) return arc4.Bool(True) @arc4.abimethod(readonly=True) def get_votes(self) -> arc4.UInt64: return arc4.UInt64(self.votes.value) def clear_state_program(self) -> bool: return True ``` #### Test Definition ```{testcode} from collections.abc import Generator import pytest from algopy_testing import AlgopyTestContext, algopy_testing_context from algopy import arc4 # Create a test context with algopy_testing_context() as context: # Initialize the contract contract = VotingContract() # Test vote function voter = context.default_sender payment = context.any.txn.payment( sender=voter, amount=algopy.UInt64(10_000), ) result = contract.vote(payment) print(f"Vote result: {result.native}") print(f"Total votes: {contract.votes.value}") print(f"Voter {voter} voted: {contract.voted[voter]}") # Test set_topic function new_topic = context.any.arc4.string(10) contract.set_topic(new_topic) print(f"New topic: {new_topic.native}") print(f"Contract topic: {contract.topic.value}") # Test get_votes function contract.votes.value = algopy.UInt64(5) votes = contract.get_votes() print(f"Current votes: {votes.native}") ``` ```{testoutput} :hide: Vote result: True Total votes: 1 Voter ... voted: 1 New topic: ... Contract topic: ... Current votes: 5 ``` This example demonstrates key aspects of testing with `algorand-python-testing` for ARC4-based contracts: 1. ARC4 Contract Features: - Use of `algopy.ARC4Contract` as the base class for the contract. - ABI methods defined using the `@arc4.abimethod` decorator. - Use of ARC4-specific types like `arc4.String`, `arc4.Bool`, and `arc4.UInt64`. - Readonly method annotation with `@arc4.abimethod(readonly=True)`. 2. Testing ARC4 Contracts: - Creation of an `ARC4Contract` instance within the test context. - Use of `context.any.arc4` for generating ARC4-specific random test data. - Direct invocation of ABI methods on the contract instance. 3. Transaction Handling: - Use of `context.any.txn` to create test transactions. - Passing transaction objects as parameters to contract methods. 4. State Verification: - Checking global and local state changes after method execution. - Verifying return values from ABI methods using ARC4-specific types. > **NOTE**: Thorough testing is crucial in smart contract development due to their immutable nature post-deployment. Comprehensive unit and integration tests ensure contract validity and reliability. Optimizing for efficiency can significantly improve user experience by reducing transaction fees and simplifying interactions. Investing in robust testing and optimization practices is crucial and offers many benefits in the long run. ### Next steps To dig deeper into the capabilities of `algorand-python-testing`, continue with the following sections. ```{toctree} --- maxdepth: 2 caption: Contents hidden: true --- testing-guide/index examples coverage faq api algopy ``` ``` -------------------------------------------------------------------------------- /packages/server/src/resources/knowledge/taxonomy/algokit:utils:typescript:code:interfaces:types_asset_manager.AssetInformation.md: -------------------------------------------------------------------------------- ```markdown [@algorandfoundation/algokit-utils](../README.md) / [types/asset-manager](../modules/types_asset_manager.md) / AssetInformation # Interface: AssetInformation [types/asset-manager](../modules/types_asset_manager.md).AssetInformation Information about an asset. ## Table of contents ### Properties - [assetId](types_asset_manager.AssetInformation.md#assetid) - [assetName](types_asset_manager.AssetInformation.md#assetname) - [assetNameAsBytes](types_asset_manager.AssetInformation.md#assetnameasbytes) - [clawback](types_asset_manager.AssetInformation.md#clawback) - [creator](types_asset_manager.AssetInformation.md#creator) - [decimals](types_asset_manager.AssetInformation.md#decimals) - [defaultFrozen](types_asset_manager.AssetInformation.md#defaultfrozen) - [freeze](types_asset_manager.AssetInformation.md#freeze) - [manager](types_asset_manager.AssetInformation.md#manager) - [metadataHash](types_asset_manager.AssetInformation.md#metadatahash) - [reserve](types_asset_manager.AssetInformation.md#reserve) - [total](types_asset_manager.AssetInformation.md#total) - [unitName](types_asset_manager.AssetInformation.md#unitname) - [unitNameAsBytes](types_asset_manager.AssetInformation.md#unitnameasbytes) - [url](types_asset_manager.AssetInformation.md#url) - [urlAsBytes](types_asset_manager.AssetInformation.md#urlasbytes) ## Properties ### assetId • **assetId**: `bigint` The ID of the asset. #### Defined in [src/types/asset-manager.ts:19](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/asset-manager.ts#L19) ___ ### assetName • `Optional` **assetName**: `string` The optional name of the asset. Max size is 32 bytes. #### Defined in [src/types/asset-manager.ts:110](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/asset-manager.ts#L110) ___ ### assetNameAsBytes • `Optional` **assetNameAsBytes**: `Uint8Array` The optional name of the asset. Max size is 32 bytes. #### Defined in [src/types/asset-manager.ts:116](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/asset-manager.ts#L116) ___ ### clawback • `Optional` **clawback**: `string` The address of the optional account that can clawback holdings of this asset from any account. The clawback account has the ability to **unconditionally take assets from any account**. If empty, clawback is not permitted. If not set the field is permanently empty. #### Defined in [src/types/asset-manager.ts:92](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/asset-manager.ts#L92) ___ ### creator • **creator**: `string` The address of the account that created the asset. This is the address where the parameters for this asset can be found, and also the address where unwanted asset units can be sent when closing out an asset position and opting-out of the asset. #### Defined in [src/types/asset-manager.ts:27](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/asset-manager.ts#L27) ___ ### decimals • **decimals**: `number` The amount of decimal places the asset was created with. * If 0, the asset is not divisible; * If 1, the base unit of the asset is in tenths; * If 2, the base unit of the asset is in hundredths; * If 3, the base unit of the asset is in thousandths; * and so on up to 19 decimal places. #### Defined in [src/types/asset-manager.ts:43](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/asset-manager.ts#L43) ___ ### defaultFrozen • `Optional` **defaultFrozen**: `boolean` Whether the asset was frozen by default for all accounts. If `true` then for anyone apart from the creator to hold the asset it needs to be unfrozen per account using an asset freeze transaction from the `freeze` account. #### Defined in [src/types/asset-manager.ts:51](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/asset-manager.ts#L51) ___ ### freeze • `Optional` **freeze**: `string` The address of the optional account that can be used to freeze or unfreeze holdings of this asset for any account. If empty, freezing is not permitted. If not set the field is permanently empty. #### Defined in [src/types/asset-manager.ts:81](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/asset-manager.ts#L81) ___ ### manager • `Optional` **manager**: `string` The address of the optional account that can manage the configuration of the asset and destroy it. If not set the asset is permanently immutable. #### Defined in [src/types/asset-manager.ts:57](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/asset-manager.ts#L57) ___ ### metadataHash • `Optional` **metadataHash**: `Uint8Array` 32-byte hash of some metadata that is relevant to the asset and/or asset holders. The format of this metadata is up to the application. #### Defined in [src/types/asset-manager.ts:134](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/asset-manager.ts#L134) ___ ### reserve • `Optional` **reserve**: `string` The address of the optional account that holds the reserve (uncirculated supply) units of the asset. This address has no specific authority in the protocol itself and is informational only. Some standards like [ARC-19](https://github.com/algorandfoundation/ARCs/blob/main/ARCs/arc-0019.md) rely on this field to hold meaningful data. It can be used in the case where you want to signal to holders of your asset that the uncirculated units of the asset reside in an account that is different from the default creator account. If not set the field is permanently empty. #### Defined in [src/types/asset-manager.ts:72](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/asset-manager.ts#L72) ___ ### total • **total**: `bigint` The total amount of the smallest divisible (decimal) units that were created of the asset. For example, if `decimals` is, say, 2, then for every 100 `total` there is 1 whole unit. #### Defined in [src/types/asset-manager.ts:33](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/asset-manager.ts#L33) ___ ### unitName • `Optional` **unitName**: `string` The optional name of the unit of this asset (e.g. ticker name). Max size is 8 bytes. #### Defined in [src/types/asset-manager.ts:98](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/asset-manager.ts#L98) ___ ### unitNameAsBytes • `Optional` **unitNameAsBytes**: `Uint8Array` The optional name of the unit of this asset (e.g. ticker name). Max size is 8 bytes. #### Defined in [src/types/asset-manager.ts:104](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/asset-manager.ts#L104) ___ ### url • `Optional` **url**: `string` Optional URL where more information about the asset can be retrieved (e.g. metadata). Max size is 96 bytes. #### Defined in [src/types/asset-manager.ts:122](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/asset-manager.ts#L122) ___ ### urlAsBytes • `Optional` **urlAsBytes**: `Uint8Array` Optional URL where more information about the asset can be retrieved (e.g. metadata). Max size is 96 bytes. #### Defined in [src/types/asset-manager.ts:128](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/asset-manager.ts#L128) ``` -------------------------------------------------------------------------------- /packages/server/src/resources/knowledge/taxonomy/liquid-auth:ARCHITECTURE.md: -------------------------------------------------------------------------------- ```markdown ## Overview ### Components - Nest.js (Microservices/REST API) - Redis (Events/WebSockets) - MongoDB (SessionStore/Users) This service uses [FIDO2 REST API]() endpoints for credential creation and assertions. ## FIDO2 Endpoints Two main components, Assertion and Attestation. The purposed liquid extension is used to sign the FIDO2 responses with a different key pair and allow remote authentication ### Liquid FIDO2 Extension ```typescript // Authenticator Create Response interface LiquidClientAttestationExtensionResults { liquid: { type: string; // Currently only "algorand" supported address: string; // Wallet Address signature: string; // Base64URL Encoded Signature requestId?: string // Optional Request ID , authenticate a remote user simaltaneously device?: string // Optional Device Name } } // Authenticator Get Response interface LiquidClientAssertionExtensionResults { liquid: { requestId?: string; // Optional Request ID } } // Selector Options interface LiquidExtensionOptions { liquid: boolean; } ``` ### POST /attestation/request Returns the credential creation options supported by the service. It accepts the standard PublicKeyCreateOptions as the `body`. The response can be passed to an available authenticator which will generate the credentials. The request must enable the `liquid` extension in order to sign the response. #### BODY ```json { "username": "2SPDE6XLJNXFTOO7OIGNRNKSEDOHJWVD3HBSEAPHONZQ4IQEYOGYTP6LXA", "displayName": "Liquid Auth User", "authenticatorSelection": { "userVerification": "required" }, "extensions": { "liquid": true } } ``` #### Example CredentialCreateOptions Response ```json { "challenge": "35JYpoXGnM4s8IICakWSLllcXy3Z_lc3AaLSl872qXM", "rp": { "name": "Algorand Foundation FIDO2 Server", "id": "catfish-pro-wolf.ngrok-free.app" }, "user": { "id": "2SPDE6XLJNXFTOO7OIGNRNKSEDOHJWVD3HBSEAPHONZQ4IQEYOGYTP6LXA", "name": "2SPDE6XLJNXFTOO7OIGNRNKSEDOHJWVD3HBSEAPHONZQ4IQEYOGYTP6LXA", "displayName": "2SPDE6XLJNXFTOO7OIGNRNKSEDOHJWVD3HBSEAPHONZQ4IQEYOGYTP6LXA" }, "pubKeyCredParams": [ { "type": "public-key", "alg": -7 }, { "type": "public-key", "alg": -257 } ], "timeout": 1800000, "attestation": "none", "excludeCredentials": [], "authenticatorSelection": { "userVerification": "required" }, "extensions": { "liquid": true } } ``` ### POST /attestation/response Receives the PublicKeyCredential result from the authenticator and validates the credential signature. `body` uses base64URL encoding for keys. The authenticator must include the `liquid` extension in the response with the signature and address. This will associate the credential with the wallet address and the credential can be used for future assertions without the need for signing with the wallet keys #### BODY ```json { "id": "AYMPi2Rbhcnu2gSHOO1TNvzDJ38iU00rrlCqyH874XCIEoIotRc7eVRFpx0TvsQurg7BAnXy5KnWdKC8LeWs0k0", "type": "public-key", "rawId": "AYMPi2Rbhcnu2gSHOO1TNvzDJ38iU00rrlCqyH874XCIEoIotRc7eVRFpx0TvsQurg7BAnXy5KnWdKC8LeWs0k0", "clientExtensionResults": { "liquid": { "type": "algorand", "requestId": "019097ff-bb8c-7c42-9700-f11b9446fad7", "address": "2SPDE6XLJNXFTOO7OIGNRNKSEDOHJWVD3HBSEAPHONZQ4IQEYOGYTP6LXA", "signature": "QY31mdH8AwpJ9p4pCXBO2iA5WdU-BjG52xEtJNuSJNHJIaJ10uzqk3FdR0fvYVfb_rzXTuWn4k1PFFeg-vpEDw", "device": "Pixel 8 Pro" } }, "response": { "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiMzVKWXBvWEduTTRzOElJQ2FrV1NMbGxjWHkzWl9sYzNBYUxTbDg3MnFYTSIsIm9yaWdpbiI6ImFuZHJvaWQ6YXBrLWtleS1oYXNoOlI4eE83cmxRV2FXTDRCbEZ5Z3B0V1JiNXFjS1dkZmp6WklhU1JpdDlYVnciLCJhbmRyb2lkUGFja2FnZU5hbWUiOiJmb3VuZGF0aW9uLmFsZ29yYW5kLmRlbW8ifQ", "attestationObject": "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVjFlpPmT7RcYTDeFJdKhDtiKwzb05n-ojlcqqYw5SomXZBFAAAAAAAAAAAAAAAAAAAAAAAAAAAAQQGDD4tkW4XJ7toEhzjtUzb8wyd_IlNNK65Qqsh_O-FwiBKCKLUXO3lURacdE77ELq4OwQJ18uSp1nSgvC3lrNJNpQECAyYgASFYIB2dcp3wanhReRhgRIpJCUfRSwkCvyE9OdvEL_NlncSJIlggkSIz7h7O5nrAXGJrkCOmeolChSc09eHzniCFLFxaKH0" }, "device": "Pixel 8 Pro" } ``` ### POST /assertion/request/:credId Request a PublicKeyGetCredentialOptions from the service. This differs slightly from the FIDO2 API conformance in order to limit allowed credentials. #### BODY (Optional) ```json { "authenticatorSelection": { "userVerification": "required" }, "extensions": { "liquid": true } } ``` #### Example Response ```json { "challenge": "0TXu4G4iu3sbAQopheoPe_CpnLJOB-QlIUvwFBC317Q", "allowCredentials": [ { "id": "AYMPi2Rbhcnu2gSHOO1TNvzDJ38iU00rrlCqyH874XCIEoIotRc7eVRFpx0TvsQurg7BAnXy5KnWdKC8LeWs0k0", "type": "public-key" } ], "timeout": 1800000, "userVerification": "required", "rpId": "catfish-pro-wolf.ngrok-free.app", "extensions": { "liquid": true } } ``` ### POST /assertion/response Base64URL encoded response from the authenticator. Optionally add a `requestId` to also authenticate a remote session #### BODY ```json { "id": "AYMPi2Rbhcnu2gSHOO1TNvzDJ38iU00rrlCqyH874XCIEoIotRc7eVRFpx0TvsQurg7BAnXy5KnWdKC8LeWs0k0", "type": "public-key", "rawId": "AYMPi2Rbhcnu2gSHOO1TNvzDJ38iU00rrlCqyH874XCIEoIotRc7eVRFpx0TvsQurg7BAnXy5KnWdKC8LeWs0k0", "clientExtensionResults": { "liquid": { "requestId": "019097ff-bb8d-75d8-b950-33de977c2d3f" } }, "response": { "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiMFRYdTRHNGl1M3NiQVFvcGhlb1BlX0NwbkxKT0ItUWxJVXZ3RkJDMzE3USIsIm9yaWdpbiI6ImFuZHJvaWQ6YXBrLWtleS1oYXNoOlI4eE83cmxRV2FXTDRCbEZ5Z3B0V1JiNXFjS1dkZmp6WklhU1JpdDlYVnciLCJhbmRyb2lkUGFja2FnZU5hbWUiOiJmb3VuZGF0aW9uLmFsZ29yYW5kLmRlbW8ifQ", "authenticatorData": "lpPmT7RcYTDeFJdKhDtiKwzb05n-ojlcqqYw5SomXZAFAAAAAQ", "signature": "MEUCIQDcV2y6ub3Qh8pyTCCLdWKRH_cmR2xlFuNy1Fn1QsSUygIgTZh9b6mB77C-aQrBj7Evb8u3S4j3vjlnSPAKcR7Kld4" } } ``` #### Example Response ```json { "id": "M6RT4iT5FkNDM2i57MXzBhLDt9zl2CrLt2p4Ar03t2Q", "wallet": "2SPDE6XLJNXFTOO7OIGNRNKSEDOHJWVD3HBSEAPHONZQ4IQEYOGYTP6LXA", "credentials": [ { "device": "Pixel 8 Pro", "publicKey": "pQECAyYgASFYIB2dcp3wanhReRhgRIpJCUfRSwkCvyE9OdvEL_NlncSJIlggkSIz7h7O5nrAXGJrkCOmeolChSc09eHzniCFLFxaKH0", "credId": "AYMPi2Rbhcnu2gSHOO1TNvzDJ38iU00rrlCqyH874XCIEoIotRc7eVRFpx0TvsQurg7BAnXy5KnWdKC8LeWs0k0", "prevCounter": 0 } ] } ``` ## Signaling Service The signaling service is used to establish a WebRTC connection between the wallet and the website. ### Events #### microservice:auth Emits to the event bus when a client attests or asserts a credential with a requestId. #### wss:link Submit a request to link the current client to a remote wallet. The server will acknowledge the request when the `microservice:auth` event is received. ```typescript const response: LinkMessage = await client.link(requestId) ``` #### wss:offer-description | wss:answer-description Wait for the server to emit an offer or answer description to the client. ```typescript const response: string = await client.signal('offer' | 'answer') ``` #### wss:offer-candidate | wss:answer-candidate Emits the offer or answer ICE Candidates to connected clients. ```typescript client.peerClient.onicecandidate=(event)=>{ client.socket.emit('offer-candidate', event.candidate.toJSON()) } ``` ``` -------------------------------------------------------------------------------- /packages/server/src/resources/knowledge/taxonomy/algokit:utils:typescript:code:modules:testing.md: -------------------------------------------------------------------------------- ```markdown [@algorandfoundation/algokit-utils](../README.md) / testing # Module: testing ## Table of contents ### Classes - [TestLogger](../classes/testing.TestLogger.md) - [TransactionLogger](../classes/testing.TransactionLogger.md) ### Functions - [algoKitLogCaptureFixture](testing.md#algokitlogcapturefixture) - [algorandFixture](testing.md#algorandfixture) - [getTestAccount](testing.md#gettestaccount) - [runWhenIndexerCaughtUp](testing.md#runwhenindexercaughtup) ## Functions ### algoKitLogCaptureFixture ▸ **algoKitLogCaptureFixture**(): [`AlgoKitLogCaptureFixture`](../interfaces/types_testing.AlgoKitLogCaptureFixture.md) Creates a test fixture for capturing AlgoKit logs. #### Returns [`AlgoKitLogCaptureFixture`](../interfaces/types_testing.AlgoKitLogCaptureFixture.md) The fixture **`Example`** ```typescript const logs = algoKitLogCaptureFixture() beforeEach(logs.beforeEach) afterEach(logs.afterEach) test('My test', () => { const capturedLogs = logs.testLogger.capturedLogs }) ``` #### Defined in [src/testing/fixtures/algokit-log-capture-fixture.ts:22](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/testing/fixtures/algokit-log-capture-fixture.ts#L22) ___ ### algorandFixture ▸ **algorandFixture**(`fixtureConfig?`): [`AlgorandFixture`](../interfaces/types_testing.AlgorandFixture.md) Creates a test fixture for automated testing against Algorand. By default it tests against an environment variable specified client if the standard environment variables are specified, otherwise against a default LocalNet instance, but you can pass in an algod, indexer and/or kmd (or their respective config) if you want to test against an explicitly defined network. #### Parameters | Name | Type | Description | | :------ | :------ | :------ | | `fixtureConfig?` | [`AlgorandFixtureConfig`](../interfaces/types_testing.AlgorandFixtureConfig.md) | The fixture configuration | #### Returns [`AlgorandFixture`](../interfaces/types_testing.AlgorandFixture.md) The fixture **`Example`** ```typescript const algorand = algorandFixture() beforeEach(algorand.beforeEach, 10_000) test('My test', async () => { const {algod, indexer, testAccount, ...} = algorand.context // test things... }) ``` **`Example`** ```typescript const algorand = algorandFixture({ algod: new Algodv2('localhost', 12345, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'), // ... }) beforeEach(algorand.beforeEach, 10_000) test('My test', async () => { const {algod, indexer, testAccount, ...} = algorand.context // test things... }) ``` #### Defined in [src/testing/fixtures/algorand-fixture.ts:48](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/testing/fixtures/algorand-fixture.ts#L48) ▸ **algorandFixture**(`fixtureConfig`, `config`): [`AlgorandFixture`](../interfaces/types_testing.AlgorandFixture.md) #### Parameters | Name | Type | Description | | :------ | :------ | :------ | | `fixtureConfig` | `undefined` \| [`AlgorandFixtureConfig`](../interfaces/types_testing.AlgorandFixtureConfig.md) | The fixture configuration | | `config` | [`AlgoConfig`](../interfaces/types_network_client.AlgoConfig.md) | The fixture configuration | #### Returns [`AlgorandFixture`](../interfaces/types_testing.AlgorandFixture.md) The fixture **`Deprecated`** Config can be passed in directly to fixture config now. Creates a test fixture for automated testing against Algorand. By default it tests against an environment variable specified client if the standard environment variables are specified, otherwise against a default LocalNet instance, but you can pass in an algod, indexer and/or kmd if you want to test against an explicitly defined network. **`Example`** ```typescript const algorand = algorandFixture(undefined, getConfigFromEnvOrDefaults()) beforeEach(algorand.beforeEach, 10_000) test('My test', async () => { const {algod, indexer, testAccount, ...} = algorand.context // test things... }) ``` #### Defined in [src/testing/fixtures/algorand-fixture.ts:75](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/testing/fixtures/algorand-fixture.ts#L75) ___ ### getTestAccount ▸ **getTestAccount**(`params`, `algod`, `kmd?`): `Promise`\<`Address` & `Account` & [`TransactionSignerAccount`](../interfaces/types_account.TransactionSignerAccount.md)\> #### Parameters | Name | Type | Description | | :------ | :------ | :------ | | `params` | [`GetTestAccountParams`](../interfaces/types_testing.GetTestAccountParams.md) | The config for the test account to generate | | `algod` | `AlgodClient` | An algod client | | `kmd?` | `KmdClient` | A KMD client, if not specified then a default KMD client will be loaded from environment variables and if not found fallback to the default LocalNet KMD client | #### Returns `Promise`\<`Address` & `Account` & [`TransactionSignerAccount`](../interfaces/types_account.TransactionSignerAccount.md)\> The account, with private key loaded **`Deprecated`** Use `getTestAccount(params, algorandClient)` instead. The `algorandClient` object can be created using `AlgorandClient.fromClients({ algod, kmd })`. Creates an ephemeral Algorand account for the purposes of testing. Returns a newly created random test account that is funded from the dispenser DO NOT USE THIS TO CREATE A MAINNET ACCOUNT! Note: By default this will log the mnemonic of the account. #### Defined in [src/testing/account.ts:21](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/testing/account.ts#L21) ▸ **getTestAccount**(`params`, `algorand`): `Promise`\<`Address` & `Account` & [`TransactionSignerAccount`](../interfaces/types_account.TransactionSignerAccount.md)\> Creates an ephemeral Algorand account for the purposes of testing. Returns a newly created random test account that is funded from the dispenser DO NOT USE THIS TO CREATE A MAINNET ACCOUNT! Note: By default this will log the mnemonic of the account. #### Parameters | Name | Type | Description | | :------ | :------ | :------ | | `params` | [`GetTestAccountParams`](../interfaces/types_testing.GetTestAccountParams.md) | The config for the test account to generate | | `algorand` | [`AlgorandClient`](../classes/types_algorand_client.AlgorandClient.md) | An AlgorandClient client | #### Returns `Promise`\<`Address` & `Account` & [`TransactionSignerAccount`](../interfaces/types_account.TransactionSignerAccount.md)\> The account, with private key loaded #### Defined in [src/testing/account.ts:35](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/testing/account.ts#L35) ___ ### runWhenIndexerCaughtUp ▸ **runWhenIndexerCaughtUp**\<`T`\>(`run`): `Promise`\<`T`\> Runs the given indexer call until a 404 error is no longer returned. Tried every 200ms up to 100 times. Very rudimentary implementation designed for automated testing. #### Type parameters | Name | | :------ | | `T` | #### Parameters | Name | Type | Description | | :------ | :------ | :------ | | `run` | () => `Promise`\<`T`\> | The code to run | #### Returns `Promise`\<`T`\> The result (as a promise), or throws if the indexer didn't catch up in time **`Example`** ```typescript const transaction = await runWhenIndexerCaughtUp(() => indexer.lookupTransactionByID(txnId).do()) ``` #### Defined in [src/testing/indexer.ts:12](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/testing/indexer.ts#L12) ``` -------------------------------------------------------------------------------- /packages/server/tests/resources/indexer/application.test.ts: -------------------------------------------------------------------------------- ```typescript import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js'; import { applicationResources, applicationResourceSchemas, lookupApplications, lookupApplicationLogs, searchForApplications, handleApplicationResources } from '../../../src/resources/indexer/application.js'; import { indexerClient } from '../../../src/algorand-client.js'; // Mock algosdk client jest.mock('../../../src/algorand-client.js', () => ({ indexerClient: { lookupApplications: jest.fn(), lookupApplicationLogs: jest.fn(), searchForApplications: jest.fn() }, API_URIS: { APPLICATION_STATE: 'algorand://app/{app-id}/state' } })); describe('Indexer Application Resources', () => { beforeEach(() => { jest.clearAllMocks(); }); describe('Resource Definitions', () => { it('should define application resources', () => { expect(applicationResources).toHaveLength(1); expect(applicationResources[0].name).toBe('Application State'); }); it('should define resource schemas', () => { expect(Object.keys(applicationResourceSchemas)).toHaveLength(1); expect(applicationResourceSchemas).toHaveProperty('algorand://app/{app-id}/state'); }); }); describe('Application Information', () => { const mockAppId = 123; const mockResponse = { application: { id: mockAppId, params: { creator: 'MOCK_ADDRESS', approvalProgram: 'base64...', clearStateProgram: 'base64...', globalState: [] } }, currentRound: 1234 }; beforeEach(() => { (indexerClient.lookupApplications as jest.Mock).mockReturnValue({ do: jest.fn().mockResolvedValue(mockResponse) }); }); it('should fetch application information', async () => { const result = await lookupApplications(mockAppId); expect(result).toEqual(mockResponse); expect(indexerClient.lookupApplications).toHaveBeenCalledWith(mockAppId); }); it('should handle errors', async () => { const error = new Error('Network error'); (indexerClient.lookupApplications as jest.Mock).mockReturnValue({ do: jest.fn().mockRejectedValue(error) }); await expect(lookupApplications(mockAppId)) .rejects .toThrow('Failed to get application info: Network error'); }); }); describe('Application Logs', () => { const mockAppId = 123; const mockResponse = { logs: [{ txid: 'txn1', log: 'base64...' }], currentRound: 1234 }; beforeEach(() => { (indexerClient.lookupApplicationLogs as jest.Mock).mockReturnValue({ limit: jest.fn().mockReturnThis(), minRound: jest.fn().mockReturnThis(), maxRound: jest.fn().mockReturnThis(), txid: jest.fn().mockReturnThis(), sender: jest.fn().mockReturnThis(), nextToken: jest.fn().mockReturnThis(), do: jest.fn().mockResolvedValue(mockResponse) }); }); it('should fetch application logs', async () => { const result = await lookupApplicationLogs(mockAppId); expect(result).toEqual(mockResponse); expect(indexerClient.lookupApplicationLogs).toHaveBeenCalledWith(mockAppId); }); it('should handle search parameters', async () => { const params = { limit: 10, minRound: 1000, maxRound: 2000, txid: 'txn1', sender: 'addr1', nextToken: 'token123' }; await lookupApplicationLogs(mockAppId, params); const mock = indexerClient.lookupApplicationLogs as jest.Mock; const chain = mock.mock.results[0].value; expect(chain.limit).toHaveBeenCalledWith(params.limit); expect(chain.minRound).toHaveBeenCalledWith(params.minRound); expect(chain.maxRound).toHaveBeenCalledWith(params.maxRound); expect(chain.txid).toHaveBeenCalledWith(params.txid); expect(chain.sender).toHaveBeenCalledWith(params.sender); expect(chain.nextToken).toHaveBeenCalledWith(params.nextToken); }); it('should handle errors', async () => { const error = new Error('Network error'); (indexerClient.lookupApplicationLogs as jest.Mock).mockReturnValue({ do: jest.fn().mockRejectedValue(error) }); await expect(lookupApplicationLogs(mockAppId)) .rejects .toThrow('Failed to get application logs: Network error'); }); }); describe('Search Applications', () => { const mockResponse = { applications: [{ id: 1, params: { creator: 'addr1' } }], currentRound: 1234 }; beforeEach(() => { (indexerClient.searchForApplications as jest.Mock).mockReturnValue({ limit: jest.fn().mockReturnThis(), creator: jest.fn().mockReturnThis(), nextToken: jest.fn().mockReturnThis(), do: jest.fn().mockResolvedValue(mockResponse) }); }); it('should search applications', async () => { const result = await searchForApplications(); expect(result).toEqual(mockResponse); expect(indexerClient.searchForApplications).toHaveBeenCalled(); }); it('should handle search parameters', async () => { const params = { limit: 10, creator: 'addr1', nextToken: 'token123' }; await searchForApplications(params); const mock = indexerClient.searchForApplications as jest.Mock; const chain = mock.mock.results[0].value; expect(chain.limit).toHaveBeenCalledWith(params.limit); expect(chain.creator).toHaveBeenCalledWith(params.creator); expect(chain.nextToken).toHaveBeenCalledWith(params.nextToken); }); it('should handle errors', async () => { const error = new Error('Network error'); (indexerClient.searchForApplications as jest.Mock).mockReturnValue({ do: jest.fn().mockRejectedValue(error) }); await expect(searchForApplications()) .rejects .toThrow('Failed to search applications: Network error'); }); }); describe('Resource Handler', () => { const mockAppId = 123; const mockResponse = { application: { id: mockAppId, params: { creator: 'MOCK_ADDRESS', globalState: [] } }, currentRound: 1234 }; beforeEach(() => { (indexerClient.lookupApplications as jest.Mock).mockReturnValue({ do: jest.fn().mockResolvedValue(mockResponse) }); }); it('should handle application state URI', async () => { const uri = `algorand://app/${mockAppId}/state`; const result = await handleApplicationResources(uri); expect(result).toHaveLength(1); expect(JSON.parse(result[0].text)).toHaveProperty('application'); expect(JSON.parse(result[0].text)).toHaveProperty('currentRound'); }); it('should return empty array for unknown URI', async () => { const uri = 'algorand://unknown'; const result = await handleApplicationResources(uri); expect(result).toHaveLength(0); }); it('should handle errors with McpError', async () => { const error = new Error('Network error'); (indexerClient.lookupApplications as jest.Mock).mockReturnValue({ do: jest.fn().mockRejectedValue(error) }); const uri = `algorand://app/${mockAppId}/state`; await expect(handleApplicationResources(uri)) .rejects .toThrow(new McpError(ErrorCode.InternalError, 'Network error')); }); }); }); ``` -------------------------------------------------------------------------------- /packages/server/src/resources/knowledge/taxonomy/developer:docs:details:dapps:smart-contracts:ABI:index.md: -------------------------------------------------------------------------------- ```markdown title: ABI details The ABI (Application Binary Interface) is a specification that defines the encoding/decoding of data types and a standard for exposing and invoking methods in a smart contract. The specification is defined in [ARC4](https://github.com/algorandfoundation/ARCs/blob/main/ARCs/arc-0004.md). At a high level, the ABI allows contracts to define an API with rich types and offer an interface description so clients know exactly what the contract is expecting to be passed. To encode or decode ABI types with the SDKs, see the [ABI encoding and decoding](../../../encoding.md#abi-encoding) documentation. !!! note When constructing Application Call transactions that are expected to encode arguments, using the [Atomic Transaction Composer](../../../atc.md) is recommended. # Data Types Encoding for the data types is specified [here](https://github.com/algorandfoundation/ARCs/blob/main/ARCs/arc-0004.md#encoding). The data types specified are: | Type | Description | | ---- | ----------- | |uintN| An N-bit unsigned integer, where 8 <= N <= 512 and N % 8 = 0| |byte| An alias for uint8| |bool| A boolean value that is restricted to either 0 or 1. When encoded, up to 8 consecutive bool values will be packed into a single byte| |ufixedNxM| An N-bit unsigned fixed-point decimal number with precision M, where 8 <= N <= 512, N % 8 = 0, and 0 < M <= 160, which denotes a value v as v / (10^M)| |type[N]| A fixed-length array of length N, where N >= 0. type can be any other type| |address| Used to represent a 32-byte Algorand address. This is equivalent to byte[32]| |type[]| A variable-length array. type can be any other type| |string| A variable-length byte array (byte[]) assumed to contain UTF-8 encoded content| |(T1,T2,...,TN)| A tuple of the types T1, T2, …, TN, N >= 0| |reference type | account, asset, application only for arguments, in which case they are an alias for uint8. See section "Reference Types" below| The encoding and decoding of these types should be handled by the SDKs for calling methods and reading out return values. Because stack types in the AVM are limited to uint64 and bytes, a smart contract may rely on ABI types defined in PyTeal to encode or decode the data passed in the application args. ## Reference Types Reference types may be specified in the method signature referring to some transaction parameters that must be passed. The value encoded is a uint8 reference to the index of element in the relevant array (i.e. for account, the index in the foreign accounts array). # Methods Methods may be exposed by the smart contract and called by submitting an ApplicationCall transaction to the existing application id. A *method signature* is defined as a name, argument types, and return type. The stringified version is then hashed and the first 4 bytes are taken as a *method selector*. For example: A *method signature* for an `add` method that takes 2 uint64s and returns 1 uint128: ``` Method signature: add(uint64,uint64)uint128 ``` The string version of the *method signature* is hashed and the first 4 bytes are its *method selector*: ``` SHA-512/256 hash (in hex): 8aa3b61f0f1965c3a1cbfa91d46b24e54c67270184ff89dc114e877b1753254a Method selector (in hex): 8aa3b61f ``` Once the method selector is known, it is used in the smart contract logic to route to the appropriate logic that implements the `add` method. The `method` pseudo-opcode can be used in a contract to do the above work and produce a *method selector* given the *method signature* string. ``` method "add(uint64,uint64)uint128" ``` ## Implementing a method [Implementing a method](https://github.com/algorandfoundation/ARCs/blob/main/ARCs/arc-0004.md#implementing-a-method) is done by handling an ApplicationCall transaction where the first element matches its method selector and the subsequent elements are used by the logic in the method body. The initial handling logic of the contract should route to the correct method given a match against the method selector passed and the known method selector of the application method. The return value of the method _must_ be logged with the prefix `151f7c75` which is the result of `sha256("return")[:4]`. Only the last logged element with this prefix is considered the return value of this method call. # API The API of a smart contract can be published as an [interface description object](https://github.com/algorandfoundation/ARCs/blob/main/ARCs/arc-0004.md#interface-description). A user may read this object and instantiate a client that handles the encoding/decoding of the arguments and returns values using one of the SDKs. A full example of a contract json file might look like: ```json { "name":"super-awesome-contract", "networks":{ "MainNet":{ "appID": 123456 } }, "methods":[ { "name":"add", "desc":"Add 2 integers", "args":[ { "type":"uint64" }, { "type":"uint64" } ], "returns": {"type":"uint64"} }, { "name":"sub", "desc":"Subtract 2 integers", "args":[ { "type":"uint64" }, { "type":"uint64" } ], "returns": {"type":"uint64"} }, { "name":"mul", "desc":"Multiply 2 integers", "args":[ { "type":"uint64" }, { "type":"uint64" } ], "returns": {"type":"uint64"} }, { "name":"div", "desc":"Divide 2 integers, throw away the remainder", "args":[ { "type":"uint64" }, { "type":"uint64" } ], "returns": {"type":"uint64"} }, { "name":"qrem", "desc":"Divide 2 integers, return both the quotient and remainder", "args":[ { "type":"uint64" }, { "type":"uint64" } ], "returns": {"type":"(uint64,uint64)"} }, { "name":"reverse", "desc":"Reverses a string", "args":[ { "type":"string" } ], "returns": {"type":"string"} }, { "name":"txntest", "desc":"just check it", "args":[{"type":"uint64"}, {"type": "pay"}, {"type":"uint64"}], "returns":{"type": "uint64"} }, { "name":"concat_strings", "desc":"concat some strings", "args":[{"type":"string[]"}], "returns":{"type": "string"} }, { "name":"manyargs", "desc":"Try to send 20 arguments", "args":[ {"type":"uint64"}, {"type": "uint64"}, {"type":"uint64"},{"type":"uint64"}, {"type":"uint64"}, {"type": "uint64"}, {"type":"uint64"},{"type":"uint64"}, {"type":"uint64"}, {"type": "uint64"}, {"type":"uint64"},{"type":"uint64"}, {"type":"uint64"}, {"type": "uint64"}, {"type":"uint64"},{"type":"uint64"}, {"type":"uint64"}, {"type": "uint64"}, {"type":"uint64"},{"type":"uint64"} ], "returns":{"type": "uint64"} }, { "name":"min_bal", "desc":"Get the minimum balance for given account", "args":[ {"type":"account"} ], "returns":{"type":"uint64"} }, { "name":"tupler", "desc":"", "args":[ {"type":"(string,uint64,string)"} ], "returns":{"type":"uint64"} } ] } ``` ``` -------------------------------------------------------------------------------- /packages/server/src/resources/knowledge/taxonomy/SDKs:javascript:interfaces:EncodedTransaction.md: -------------------------------------------------------------------------------- ```markdown [algosdk](../README.md) / [Exports](../modules.md) / EncodedTransaction # Interface: EncodedTransaction A rough structure for the encoded transaction object. Every property is labelled with its associated Transaction type property ## Table of contents ### Properties - [aamt](EncodedTransaction.md#aamt) - [aclose](EncodedTransaction.md#aclose) - [afrz](EncodedTransaction.md#afrz) - [amt](EncodedTransaction.md#amt) - [apaa](EncodedTransaction.md#apaa) - [apan](EncodedTransaction.md#apan) - [apap](EncodedTransaction.md#apap) - [apar](EncodedTransaction.md#apar) - [apas](EncodedTransaction.md#apas) - [apat](EncodedTransaction.md#apat) - [apbx](EncodedTransaction.md#apbx) - [apep](EncodedTransaction.md#apep) - [apfa](EncodedTransaction.md#apfa) - [apgs](EncodedTransaction.md#apgs) - [apid](EncodedTransaction.md#apid) - [apls](EncodedTransaction.md#apls) - [apsu](EncodedTransaction.md#apsu) - [arcv](EncodedTransaction.md#arcv) - [asnd](EncodedTransaction.md#asnd) - [caid](EncodedTransaction.md#caid) - [close](EncodedTransaction.md#close) - [fadd](EncodedTransaction.md#fadd) - [faid](EncodedTransaction.md#faid) - [fee](EncodedTransaction.md#fee) - [fv](EncodedTransaction.md#fv) - [gen](EncodedTransaction.md#gen) - [gh](EncodedTransaction.md#gh) - [grp](EncodedTransaction.md#grp) - [lv](EncodedTransaction.md#lv) - [lx](EncodedTransaction.md#lx) - [nonpart](EncodedTransaction.md#nonpart) - [note](EncodedTransaction.md#note) - [rcv](EncodedTransaction.md#rcv) - [rekey](EncodedTransaction.md#rekey) - [selkey](EncodedTransaction.md#selkey) - [snd](EncodedTransaction.md#snd) - [sp](EncodedTransaction.md#sp) - [spmsg](EncodedTransaction.md#spmsg) - [sprfkey](EncodedTransaction.md#sprfkey) - [sptype](EncodedTransaction.md#sptype) - [type](EncodedTransaction.md#type) - [votefst](EncodedTransaction.md#votefst) - [votekd](EncodedTransaction.md#votekd) - [votekey](EncodedTransaction.md#votekey) - [votelst](EncodedTransaction.md#votelst) - [xaid](EncodedTransaction.md#xaid) ## Properties ### aamt • `Optional` **aamt**: `number` \| `bigint` amount (but for asset transfers) #### Defined in types/transactions/encoded.ts:162 ___ ### aclose • `Optional` **aclose**: `Buffer` closeRemainderTo (but for asset transfers) #### Defined in types/transactions/encoded.ts:172 ___ ### afrz • `Optional` **afrz**: `boolean` freezeState #### Defined in types/transactions/encoded.ts:242 ___ ### amt • `Optional` **amt**: `number` \| `bigint` amount #### Defined in types/transactions/encoded.ts:157 ___ ### apaa • `Optional` **apaa**: `Buffer`[] appArgs #### Defined in types/transactions/encoded.ts:302 ___ ### apan • `Optional` **apan**: `number` appOnComplete #### Defined in types/transactions/encoded.ts:267 ___ ### apap • `Optional` **apap**: `Buffer` appApprovalProgram #### Defined in types/transactions/encoded.ts:292 ___ ### apar • `Optional` **apar**: [`EncodedAssetParams`](EncodedAssetParams.md) See EncodedAssetParams type #### Defined in types/transactions/encoded.ts:257 ___ ### apas • `Optional` **apas**: `number`[] appForeignAssets #### Defined in types/transactions/encoded.ts:287 ___ ### apat • `Optional` **apat**: `Buffer`[] appAccounts #### Defined in types/transactions/encoded.ts:307 ___ ### apbx • `Optional` **apbx**: [`EncodedBoxReference`](EncodedBoxReference.md)[] boxes #### Defined in types/transactions/encoded.ts:317 ___ ### apep • `Optional` **apep**: `number` extraPages #### Defined in types/transactions/encoded.ts:312 ___ ### apfa • `Optional` **apfa**: `number`[] appForeignApps #### Defined in types/transactions/encoded.ts:282 ___ ### apgs • `Optional` **apgs**: [`EncodedGlobalStateSchema`](EncodedGlobalStateSchema.md) See EncodedGlobalStateSchema type #### Defined in types/transactions/encoded.ts:277 ___ ### apid • `Optional` **apid**: `number` appIndex #### Defined in types/transactions/encoded.ts:262 ___ ### apls • `Optional` **apls**: [`EncodedLocalStateSchema`](EncodedLocalStateSchema.md) See EncodedLocalStateSchema type #### Defined in types/transactions/encoded.ts:272 ___ ### apsu • `Optional` **apsu**: `Buffer` appClearProgram #### Defined in types/transactions/encoded.ts:297 ___ ### arcv • `Optional` **arcv**: `Buffer` to (but for asset transfers) #### Defined in types/transactions/encoded.ts:187 ___ ### asnd • `Optional` **asnd**: `Buffer` assetRevocationTarget #### Defined in types/transactions/encoded.ts:252 ___ ### caid • `Optional` **caid**: `number` assetIndex #### Defined in types/transactions/encoded.ts:227 ___ ### close • `Optional` **close**: `Buffer` closeRemainderTo #### Defined in types/transactions/encoded.ts:167 ___ ### fadd • `Optional` **fadd**: `Buffer` freezeAccount #### Defined in types/transactions/encoded.ts:247 ___ ### faid • `Optional` **faid**: `number` assetIndex (but for asset freezing/unfreezing) #### Defined in types/transactions/encoded.ts:237 ___ ### fee • `Optional` **fee**: `number` fee #### Defined in types/transactions/encoded.ts:107 ___ ### fv • `Optional` **fv**: `number` firstRound #### Defined in types/transactions/encoded.ts:112 ___ ### gen • **gen**: `string` genesisID #### Defined in types/transactions/encoded.ts:137 ___ ### gh • **gh**: `Buffer` genesisHash #### Defined in types/transactions/encoded.ts:142 ___ ### grp • `Optional` **grp**: `Buffer` group #### Defined in types/transactions/encoded.ts:152 ___ ### lv • **lv**: `number` lastRound #### Defined in types/transactions/encoded.ts:117 ___ ### lx • `Optional` **lx**: `Buffer` lease #### Defined in types/transactions/encoded.ts:147 ___ ### nonpart • `Optional` **nonpart**: `boolean` nonParticipation #### Defined in types/transactions/encoded.ts:222 ___ ### note • `Optional` **note**: `Buffer` note #### Defined in types/transactions/encoded.ts:122 ___ ### rcv • `Optional` **rcv**: `Buffer` to #### Defined in types/transactions/encoded.ts:182 ___ ### rekey • `Optional` **rekey**: `Buffer` reKeyTo #### Defined in types/transactions/encoded.ts:177 ___ ### selkey • `Optional` **selkey**: `Buffer` selectionKey #### Defined in types/transactions/encoded.ts:197 ___ ### snd • **snd**: `Buffer` from #### Defined in types/transactions/encoded.ts:127 ___ ### sp • `Optional` **sp**: `Buffer` stateProof #### Defined in types/transactions/encoded.ts:327 ___ ### spmsg • `Optional` **spmsg**: `Buffer` stateProofMessage #### Defined in types/transactions/encoded.ts:332 ___ ### sprfkey • `Optional` **sprfkey**: `Buffer` stateProofKey #### Defined in types/transactions/encoded.ts:202 ___ ### sptype • `Optional` **sptype**: `number` \| `bigint` #### Defined in types/transactions/encoded.ts:322 ___ ### type • **type**: `string` type #### Defined in types/transactions/encoded.ts:132 ___ ### votefst • `Optional` **votefst**: `number` voteFirst #### Defined in types/transactions/encoded.ts:207 ___ ### votekd • `Optional` **votekd**: `number` voteKeyDilution #### Defined in types/transactions/encoded.ts:217 ___ ### votekey • `Optional` **votekey**: `Buffer` voteKey #### Defined in types/transactions/encoded.ts:192 ___ ### votelst • `Optional` **votelst**: `number` voteLast #### Defined in types/transactions/encoded.ts:212 ___ ### xaid • `Optional` **xaid**: `number` assetIndex (but for asset transfers) #### Defined in types/transactions/encoded.ts:232 ``` -------------------------------------------------------------------------------- /packages/server/src/resources/knowledge/taxonomy/algokit:utils:typescript:code:interfaces:types_app.CreateAppParams.md: -------------------------------------------------------------------------------- ```markdown [@algorandfoundation/algokit-utils](../README.md) / [types/app](../modules/types_app.md) / CreateAppParams # Interface: CreateAppParams [types/app](../modules/types_app.md).CreateAppParams **`Deprecated`** Use `TransactionComposer` to construct create app transactions instead. Parameters that are passed in when creating an app. ## Hierarchy - `CreateOrUpdateAppParams` ↳ **`CreateAppParams`** ## Table of contents ### Properties - [approvalProgram](types_app.CreateAppParams.md#approvalprogram) - [args](types_app.CreateAppParams.md#args) - [atc](types_app.CreateAppParams.md#atc) - [clearStateProgram](types_app.CreateAppParams.md#clearstateprogram) - [fee](types_app.CreateAppParams.md#fee) - [from](types_app.CreateAppParams.md#from) - [maxFee](types_app.CreateAppParams.md#maxfee) - [maxRoundsToWaitForConfirmation](types_app.CreateAppParams.md#maxroundstowaitforconfirmation) - [note](types_app.CreateAppParams.md#note) - [onCompleteAction](types_app.CreateAppParams.md#oncompleteaction) - [populateAppCallResources](types_app.CreateAppParams.md#populateappcallresources) - [schema](types_app.CreateAppParams.md#schema) - [skipSending](types_app.CreateAppParams.md#skipsending) - [skipWaiting](types_app.CreateAppParams.md#skipwaiting) - [suppressLog](types_app.CreateAppParams.md#suppresslog) - [transactionParams](types_app.CreateAppParams.md#transactionparams) ## Properties ### approvalProgram • **approvalProgram**: `string` \| `Uint8Array` The approval program as raw teal (string) or compiled teal, base 64 encoded as a byte array (Uint8Array) #### Inherited from CreateOrUpdateAppParams.approvalProgram #### Defined in [src/types/app.ts:135](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L135) ___ ### args • `Optional` **args**: [`AppCallArgs`](../modules/types_app.md#appcallargs) The arguments passed in to the app call #### Inherited from CreateOrUpdateAppParams.args #### Defined in [src/types/app.ts:143](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L143) ___ ### atc • `Optional` **atc**: `AtomicTransactionComposer` An optional `AtomicTransactionComposer` to add the transaction to, if specified then `skipSending: undefined` has the same effect as `skipSending: true` #### Inherited from CreateOrUpdateAppParams.atc #### Defined in [src/types/transaction.ts:36](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transaction.ts#L36) ___ ### clearStateProgram • **clearStateProgram**: `string` \| `Uint8Array` The clear state program as raw teal (string) or compiled teal, base 64 encoded as a byte array (Uint8Array) #### Inherited from CreateOrUpdateAppParams.clearStateProgram #### Defined in [src/types/app.ts:137](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L137) ___ ### fee • `Optional` **fee**: [`AlgoAmount`](../classes/types_amount.AlgoAmount.md) The flat fee you want to pay, useful for covering extra fees in a transaction group or app call #### Inherited from CreateOrUpdateAppParams.fee #### Defined in [src/types/transaction.ts:40](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transaction.ts#L40) ___ ### from • **from**: [`SendTransactionFrom`](../modules/types_transaction.md#sendtransactionfrom) The account (with private key loaded) that will send the transaction #### Inherited from CreateOrUpdateAppParams.from #### Defined in [src/types/app.ts:133](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L133) ___ ### maxFee • `Optional` **maxFee**: [`AlgoAmount`](../classes/types_amount.AlgoAmount.md) The maximum fee that you are happy to pay (default: unbounded) - if this is set it's possible the transaction could get rejected during network congestion #### Inherited from CreateOrUpdateAppParams.maxFee #### Defined in [src/types/transaction.ts:42](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transaction.ts#L42) ___ ### maxRoundsToWaitForConfirmation • `Optional` **maxRoundsToWaitForConfirmation**: `number` The maximum number of rounds to wait for confirmation, only applies if `skipWaiting` is `undefined` or `false`, default: wait up to 5 rounds #### Inherited from CreateOrUpdateAppParams.maxRoundsToWaitForConfirmation #### Defined in [src/types/transaction.ts:44](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transaction.ts#L44) ___ ### note • `Optional` **note**: [`TransactionNote`](../modules/types_transaction.md#transactionnote) The (optional) transaction note #### Inherited from CreateOrUpdateAppParams.note #### Defined in [src/types/app.ts:141](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L141) ___ ### onCompleteAction • `Optional` **onCompleteAction**: ``"no_op"`` \| ``"opt_in"`` \| ``"close_out"`` \| ``"update_application"`` \| ``"delete_application"`` \| `NoOpOC` \| `OptInOC` \| `CloseOutOC` \| `UpdateApplicationOC` \| `DeleteApplicationOC` Override the on-completion action for the create call; defaults to NoOp #### Defined in [src/types/app.ts:154](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L154) ___ ### populateAppCallResources • `Optional` **populateAppCallResources**: `boolean` Whether to use simulate to automatically populate app call resources in the txn objects. Defaults to true when there are app calls in the group. #### Inherited from CreateOrUpdateAppParams.populateAppCallResources #### Defined in [src/types/transaction.ts:46](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transaction.ts#L46) ___ ### schema • **schema**: [`AppStorageSchema`](types_app.AppStorageSchema.md) The storage schema to request for the created app #### Defined in [src/types/app.ts:152](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L152) ___ ### skipSending • `Optional` **skipSending**: `boolean` Whether to skip signing and sending the transaction to the chain (default: transaction signed and sent to chain, unless `atc` specified) and instead just return the raw transaction, e.g. so you can add it to a group of transactions #### Inherited from CreateOrUpdateAppParams.skipSending #### Defined in [src/types/transaction.ts:32](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transaction.ts#L32) ___ ### skipWaiting • `Optional` **skipWaiting**: `boolean` Whether to skip waiting for the submitted transaction (only relevant if `skipSending` is `false` or unset) #### Inherited from CreateOrUpdateAppParams.skipWaiting #### Defined in [src/types/transaction.ts:34](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transaction.ts#L34) ___ ### suppressLog • `Optional` **suppressLog**: `boolean` Whether to suppress log messages from transaction send, default: do not suppress #### Inherited from CreateOrUpdateAppParams.suppressLog #### Defined in [src/types/transaction.ts:38](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/transaction.ts#L38) ___ ### transactionParams • `Optional` **transactionParams**: `SuggestedParams` Optional transaction parameters #### Inherited from CreateOrUpdateAppParams.transactionParams #### Defined in [src/types/app.ts:139](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/app.ts#L139) ``` -------------------------------------------------------------------------------- /packages/server/src/resources/knowledge/taxonomy/puya:python:testing:docs:testing-guide:avm-types.md: -------------------------------------------------------------------------------- ```markdown # AVM Types These types are available directly under the `algopy` namespace. They represent the basic AVM primitive types and can be instantiated directly or via _value generators_: ```{note} For 'primitive `algopy` types such as `Account`, `Application`, `Asset`, `UInt64`, `BigUint`, `Bytes`, `Sting` with and without respective _value generator_, instantiation can be performed directly. If you have a suggestion for a new _value generator_ implementation, please open an issue in the [`algorand-python-testing`](https://github.com/algorandfoundation/algorand-python-testing) repository or contribute by following the [contribution guide](https://github.com/algorandfoundation/algorand-python-testing/blob/main/CONTRIBUTING.md). ``` ```{testsetup} import algopy from algopy_testing import algopy_testing_context # Create the context manager for snippets below ctx_manager = algopy_testing_context() # Enter the context context = ctx_manager.__enter__() ``` ## UInt64 ```{testcode} # Direct instantiation uint64_value = algopy.UInt64(100) # Instantiate test context ... # Generate a random UInt64 value random_uint64 = context.any.uint64() # Specify a range random_uint64 = context.any.uint64(min_value=1000, max_value=9999) ``` ## Bytes ```{testcode} # Direct instantiation bytes_value = algopy.Bytes(b"Hello, Algorand!") # Instantiate test context ... # Generate random byte sequences random_bytes = context.any.bytes() # Specify the length random_bytes = context.any.bytes(length=32) ``` ## String ```{testcode} # Direct instantiation string_value = algopy.String("Hello, Algorand!") # Generate random strings random_string = context.any.string() # Specify the length random_string = context.any.string(length=16) ``` ## BigUInt ```{testcode} # Direct instantiation biguint_value = algopy.BigUInt(100) # Generate a random BigUInt value random_biguint = context.any.biguint() ``` ## Asset ```{testcode} # Direct instantiation asset = algopy.Asset(asset_id=1001) # Instantiate test context ... # Generate a random asset random_asset = context.any.asset( creator=..., # Optional: Creator account name=..., # Optional: Asset name unit_name=..., # Optional: Unit name total=..., # Optional: Total supply decimals=..., # Optional: Number of decimals default_frozen=..., # Optional: Default frozen state url=..., # Optional: Asset URL metadata_hash=..., # Optional: Metadata hash manager=..., # Optional: Manager address reserve=..., # Optional: Reserve address freeze=..., # Optional: Freeze address clawback=... # Optional: Clawback address ) # Get an asset by ID asset = context.ledger.get_asset(asset_id=random_asset.id) # Update an asset context.ledger.update_asset( random_asset, name=..., # Optional: New asset name total=..., # Optional: New total supply decimals=..., # Optional: Number of decimals default_frozen=..., # Optional: Default frozen state url=..., # Optional: New asset URL metadata_hash=..., # Optional: New metadata hash manager=..., # Optional: New manager address reserve=..., # Optional: New reserve address freeze=..., # Optional: New freeze address clawback=... # Optional: New clawback address ) ``` ## Account ```{testcode} # Direct instantiation raw_address = 'PUYAGEGVCOEBP57LUKPNOCSMRWHZJSU4S62RGC2AONDUEIHC6P7FOPJQ4I' account = algopy.Account(raw_address) # zero address by default # Instantiate test context ... # Generate a random account random_account = context.any.account( address=str(raw_address), # Optional: Specify a custom address, defaults to a random address opted_asset_balances={}, # Optional: Specify opted asset balances as dict of assets to balance opted_apps=[], # Optional: Specify opted apps as sequence of algopy.Application objects balance=..., # Optional: Specify an initial balance min_balance=..., # Optional: Specify a minimum balance auth_address=..., # Optional: Specify an auth address total_assets=..., # Optional: Specify the total number of assets total_assets_created=..., # Optional: Specify the total number of created assets total_apps_created=..., # Optional: Specify the total number of created applications total_apps_opted_in=..., # Optional: Specify the total number of applications opted into total_extra_app_pages=..., # Optional: Specify the total number of extra ) # Generate a random account that is opted into a specific asset mock_asset = context.any.asset() mock_account = context.any.account( opted_asset_balances={mock_asset: 123} ) # Get an account by address account = context.ledger.get_account(str(mock_account)) # Update an account context.ledger.update_account( mock_account, balance=..., # Optional: New balance min_balance=..., # Optional: New minimum balance auth_address=context.any.account(), # Optional: New auth address total_assets=..., # Optional: New total number of assets total_created_assets=..., # Optional: New total number of created assets total_apps_created=..., # Optional: New total number of created applications total_apps_opted_in=..., # Optional: New total number of applications opted into total_extra_app_pages=..., # Optional: New total number of extra application pages rewards=..., # Optional: New rewards status=... # Optional: New account status ) # Check if an account is opted into a specific asset opted_in = account.is_opted_in(mock_asset) ``` ## Application ```{testcode} # Direct instantiation application = algopy.Application() # Instantiate test context ... # Generate a random application random_app = context.any.application( approval_program=algopy.Bytes(b''), # Optional: Specify a custom approval program clear_state_program=algopy.Bytes(b''), # Optional: Specify a custom clear state program global_num_uint=algopy.UInt64(1), # Optional: Number of global uint values global_num_bytes=algopy.UInt64(1), # Optional: Number of global byte values local_num_uint=algopy.UInt64(1), # Optional: Number of local uint values local_num_bytes=algopy.UInt64(1), # Optional: Number of local byte values extra_program_pages=algopy.UInt64(1), # Optional: Number of extra program pages creator=context.default_sender # Optional: Specify the creator account ) # Get an application by ID app = context.ledger.get_app(app_id=random_app.id) # Update an application context.ledger.update_app( random_app, approval_program=..., # Optional: New approval program clear_state_program=..., # Optional: New clear state program global_num_uint=..., # Optional: New number of global uint values global_num_bytes=..., # Optional: New number of global byte values local_num_uint=..., # Optional: New number of local uint values local_num_bytes=..., # Optional: New number of local byte values extra_program_pages=..., # Optional: New number of extra program pages creator=... # Optional: New creator account ) # Patch logs for an application. When accessing via transactions or inner transaction related opcodes, will return the patched logs unless new logs where added into the transaction during execution. test_app = context.any.application(logs=b"log entry" or [b"log entry 1", b"log entry 2"]) # Get app associated with the active contract class MyContract(algopy.ARC4Contract): ... contract = MyContract() active_app = context.ledger.get_app(contract) ``` ```{testcleanup} ctx_manager.__exit__(None, None, None) ``` ``` -------------------------------------------------------------------------------- /packages/server/src/tools/transactionManager/accountTransactions.ts: -------------------------------------------------------------------------------- ```typescript import { Transaction, makePaymentTxnWithSuggestedParamsFromObject, makeKeyRegistrationTxnWithSuggestedParamsFromObject, SuggestedParams } from 'algosdk'; import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js'; import { algodClient } from '../../algorand-client.js'; // Tool schemas export const accountTransactionSchemas = { makePaymentTxn: { type: 'object', description: 'Create a payment transaction with proper Algorand address strings', properties: { from: { type: 'string', description: 'Sender address in standard Algorand format (58 characters)' }, to: { type: 'string', description: 'Receiver address in standard Algorand format (58 characters)' }, amount: { type: 'integer', description: 'Amount in microAlgos' }, note: { type: 'string', optional: true, description: 'Optional transaction note' }, closeRemainderTo: { type: 'string', optional: true, description: 'Optional close remainder to address in standard Algorand format' }, rekeyTo: { type: 'string', optional: true, description: 'Optional rekey to address in standard Algorand format' } }, required: ['from', 'to', 'amount'] }, makeKeyRegTxn: { type: 'object', properties: { from: { type: 'string', description: 'Sender address in standard Algorand format (58 characters)' }, voteKey: { type: 'string', description: 'The root participation public key (58 bytes base64 encoded)' }, selectionKey: { type: 'string', description: 'VRF public key (32 bytes base64 encoded)' }, stateProofKey: { type: 'string', description: 'State proof public key (64 bytes base64 encoded)' }, voteFirst: { type: 'integer', description: 'First round this participation key is valid' }, voteLast: { type: 'integer', description: 'Last round this participation key is valid' }, voteKeyDilution: { type: 'integer', description: 'Dilution for the 2-level participation key' }, nonParticipation: { type: 'boolean', optional: true, description: 'Mark account as nonparticipating for rewards' }, note: { type: 'string', optional: true, description: 'Transaction note field (up to 1000 bytes)' }, rekeyTo: { type: 'string', optional: true, description: 'Address to rekey the sender account to' } }, required: ['from', 'voteKey', 'selectionKey', 'stateProofKey', 'voteFirst', 'voteLast', 'voteKeyDilution'] } }; // Tool definitions export const accountTransactionTools = [ { name: 'make_payment_txn', description: 'Create a payment transaction', inputSchema: accountTransactionSchemas.makePaymentTxn, }, { name: 'make_keyreg_txn', description: 'Create a key registration transaction', inputSchema: accountTransactionSchemas.makeKeyRegTxn, } ]; export class AccountTransactionManager { /** * Creates a payment transaction */ static makePaymentTxn(txn: { from: string; to: string; amount: number; closeRemainderTo?: string; note?: Uint8Array; rekeyTo?: string; suggestedParams: SuggestedParams; }): Transaction { return makePaymentTxnWithSuggestedParamsFromObject(txn); } /** * Creates a key registration transaction */ static makeKeyRegTxn(txn: { from: string; note?: Uint8Array; rekeyTo?: string; suggestedParams: SuggestedParams; voteKey: string; selectionKey: string; stateProofKey: string; voteFirst: number; voteLast: number; voteKeyDilution: number; nonParticipation?: boolean; }): Transaction { return makeKeyRegistrationTxnWithSuggestedParamsFromObject(txn); } // Tool handlers static async handleTool(name: string, args: Record<string, unknown>) { const params = await algodClient.getTransactionParams().do(); const suggestedParams = { ...params, flatFee: true, fee: params.minFee }; switch (name) { case 'make_payment_txn': if (!args.from || !args.to || typeof args.amount !== 'number') { throw new McpError(ErrorCode.InvalidParams, 'Invalid payment transaction parameters'); } try { // Create payment transaction using SDK's maker function const txn = AccountTransactionManager.makePaymentTxn({ from: String(args.from), to: String(args.to), amount: Number(args.amount), note: typeof args.note === 'string' ? new TextEncoder().encode(args.note) : undefined, closeRemainderTo: typeof args.closeRemainderTo === 'string' ? args.closeRemainderTo : undefined, rekeyTo: typeof args.rekeyTo === 'string' ? args.rekeyTo : undefined, suggestedParams }); // Create a clean transaction object for JSON serialization const cleanTxn: Record<string, any> = { from: String(args.from), to: String(args.to), amount: Number(args.amount), fee: suggestedParams.fee, firstRound: suggestedParams.firstRound, lastRound: suggestedParams.lastRound, genesisID: suggestedParams.genesisID, genesisHash: suggestedParams.genesisHash, type: 'pay' }; // Add note if provided if (typeof args.note === 'string') { const noteBytes = new TextEncoder().encode(args.note); cleanTxn['note'] = Buffer.from(noteBytes).toString('base64'); } // Add optional parameters if they exist if (args.closeRemainderTo) { cleanTxn['closeRemainderTo'] = String(args.closeRemainderTo); } if (args.rekeyTo) { cleanTxn['rekeyTo'] = String(args.rekeyTo); } return { content: [{ type: 'text', text: JSON.stringify(cleanTxn, null, 2), }], }; } catch (error) { throw new McpError( ErrorCode.InvalidParams, `Failed to create payment transaction: ${error instanceof Error ? error.message : String(error)}` ); } case 'make_keyreg_txn': if (!args.from || !args.voteKey || !args.selectionKey || !args.stateProofKey || typeof args.voteFirst !== 'number' || typeof args.voteLast !== 'number' || typeof args.voteKeyDilution !== 'number') { throw new McpError(ErrorCode.InvalidParams, 'Invalid key registration parameters'); } const keyRegTxn = AccountTransactionManager.makeKeyRegTxn({ from: String(args.from), voteKey: String(args.voteKey), selectionKey: String(args.selectionKey), stateProofKey: String(args.stateProofKey), voteFirst: Number(args.voteFirst), voteLast: Number(args.voteLast), voteKeyDilution: Number(args.voteKeyDilution), nonParticipation: typeof args.nonParticipation === 'boolean' ? args.nonParticipation : undefined, note: typeof args.note === 'string' ? new TextEncoder().encode(args.note) : undefined, rekeyTo: typeof args.rekeyTo === 'string' ? args.rekeyTo : undefined, suggestedParams, }); return { content: [{ type: 'text', text: JSON.stringify(keyRegTxn, null, 2), }], }; default: throw new McpError( ErrorCode.MethodNotFound, `Unknown account transaction tool: ${name}` ); } } } ``` -------------------------------------------------------------------------------- /packages/server/src/tools/transactionManager/generalTransaction.ts: -------------------------------------------------------------------------------- ```typescript import algosdk, { Transaction, SignedTransaction, encodeUnsignedTransaction, TransactionType } from 'algosdk'; import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js'; // Tool schemas export const generalTransactionSchemas = { assignGroupId: { type: 'object', properties: { transactions: { type: 'array', items: { type: 'object' }, description: 'Array of transaction objects to be assigned a group ID' } }, required: ['transactions'] }, signTransaction: { type: 'object', properties: { transaction: { type: 'object', description: 'Transaction object to be signed' }, sk: { type: 'string', description: 'Secret key in hexadecimal format to sign the transaction with' } }, required: ['transaction', 'sk'] }, signBytes: { type: 'object', properties: { bytes: { type: 'string', description: 'Base64-encoded bytes to be signed' }, sk: { type: 'string', description: 'Secret key in hexadecimal format to sign the bytes with' } }, required: ['bytes', 'sk'] }, encodeObj: { type: 'object', properties: { obj: { type: 'object', description: 'Object to be encoded into msgpack format' } }, required: ['obj'] }, decodeObj: { type: 'object', properties: { bytes: { type: 'string', description: 'Base64-encoded msgpack bytes to be decoded into an object' } }, required: ['bytes'] } }; // Tool definitions export const generalTransactionTools = [ { name: 'assign_group_id', description: 'Assign a group ID to a list of transactions', inputSchema: generalTransactionSchemas.assignGroupId, }, { name: 'sign_transaction', description: 'Sign a transaction with a secret key', inputSchema: generalTransactionSchemas.signTransaction, }, { name: 'sign_bytes', description: 'Sign arbitrary bytes with a secret key', inputSchema: generalTransactionSchemas.signBytes, }, { name: 'encode_obj', description: 'Encode an object to msgpack format', inputSchema: generalTransactionSchemas.encodeObj, }, { name: 'decode_obj', description: 'Decode msgpack bytes to an object', inputSchema: generalTransactionSchemas.decodeObj, } ]; export class GeneralTransactionManager { /** * Assigns a group ID to a list of transactions */ // Tool handlers static async handleTool(name: string, args: Record<string, unknown>) { switch (name) { case 'assign_group_id': { if (!args.transactions || !Array.isArray(args.transactions)) { throw new McpError(ErrorCode.InvalidParams, 'Transactions array is required'); } // Validate each transaction object for (const txn of args.transactions) { if (typeof txn !== 'object' || txn === null) { throw new McpError(ErrorCode.InvalidParams, 'Each transaction must be a valid transaction object'); } } // Create all transactions first let txns; try { txns = args.transactions.map(txn => new algosdk.Transaction(txn)); } catch (error) { throw new McpError( ErrorCode.InvalidParams, `Failed to assign group ID: ${error instanceof Error ? error.message : String(error)}` ); } // Then try to assign group ID try { const groupedTxns = algosdk.assignGroupID(txns); return { content: [{ type: 'text', text: JSON.stringify(groupedTxns, null, 2) }] }; } catch (error) { throw new McpError( ErrorCode.InvalidParams, `Failed to assign group ID: ${error instanceof Error ? error.message : String(error)}` ); } } case 'sign_transaction': { if (!args.transaction || typeof args.transaction !== 'object' || !args.sk || typeof args.sk !== 'string') { throw new McpError(ErrorCode.InvalidParams, 'Invalid sign transaction parameters'); } try { const transaction = args.transaction as any; // Create a new transaction object with proper fields // const txn: any = { // from: transaction.from, // fee: transaction.fee, // firstRound: transaction.firstRound, // lastRound: transaction.lastRound, // genesisID: transaction.genesisID, // genesisHash: transaction.genesisHash, // type: transaction.type, // appIndex: transaction.appIndex || 0, // onComplete: transaction.onComplete, // }; // Convert base64 fields if (transaction.note) { transaction.note = new Uint8Array(Buffer.from(transaction.note, 'base64')); } // Handle application-specific fields if (transaction.type === 'appl') { // Set approval program if (transaction.approvalProgram) { const approvalBytes = Buffer.from(transaction.approvalProgram, 'base64'); transaction.appApprovalProgram = new Uint8Array(approvalBytes); } // Set clear program if (transaction.clearProgram) { const clearBytes = Buffer.from(transaction.clearProgram, 'base64'); transaction.appClearProgram = new Uint8Array(clearBytes); } // Set schema if (transaction.numGlobalInts !== undefined) { transaction.appGlobalInts = transaction.numGlobalInts; } if (transaction.numGlobalByteSlices !== undefined) { transaction.appGlobalByteSlices = transaction.numGlobalByteSlices; } if (transaction.numLocalInts !== undefined) { transaction.appLocalInts = transaction.numLocalInts; } if (transaction.numLocalByteSlices !== undefined) { transaction.appLocalByteSlices = transaction.numLocalByteSlices; } if(transaction.onComplete)transaction.appOnComplete = transaction.onComplete; // Set optional arrays if (transaction.appArgs) { transaction.appArgs = transaction.appArgs.map((arg: string) => new Uint8Array(Buffer.from(arg, 'base64')) ); } if (transaction.accounts) { transaction.appAccounts = transaction.accounts; } if (transaction.foreignApps) { transaction.appForeignApps = transaction.foreignApps; } if (transaction.foreignAssets) { transaction.appForeignAssets = transaction.foreignAssets; } } // Convert hex string secret key to Uint8Array const sk = new Uint8Array(Buffer.from(args.sk, 'hex')); const signedTxn = algosdk.signTransaction(new algosdk.Transaction(transaction), sk); return { content: [{ type: 'text', text: JSON.stringify({ txID: signedTxn.txID, blob: Buffer.from(signedTxn.blob).toString('base64') }, null, 2) }] }; } catch (error) { throw new McpError( ErrorCode.InvalidParams, `Failed to sign transaction: ${error instanceof Error ? error.message : String(error)}` ); } } default: throw new McpError( ErrorCode.MethodNotFound, `Unknown general transaction tool: ${name}` ); } } } ``` -------------------------------------------------------------------------------- /packages/server/tests/tools/transactionManager/accountTransactionManager.test.ts: -------------------------------------------------------------------------------- ```typescript import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js'; import { AccountTransactionManager, accountTransactionTools } from '../../../src/tools/transactionManager/accountTransactions.js'; import { algodClient } from '../../../src/algorand-client.js'; import algosdk from 'algosdk'; // Mock algosdk jest.mock('algosdk', () => ({ makePaymentTxnWithSuggestedParamsFromObject: jest.fn(), makeKeyRegistrationTxnWithSuggestedParamsFromObject: jest.fn(), })); // Mock algodClient jest.mock('../../../src/algorand-client.js', () => ({ algodClient: { getTransactionParams: jest.fn().mockReturnValue({ do: jest.fn().mockResolvedValue({ firstRound: 1000, lastRound: 2000, genesisHash: 'hash', genesisID: 'testnet-v1.0', fee: 1000, flatFee: true, }), }), }, })); describe('AccountTransactionManager', () => { const mockSuggestedParams = { firstRound: 1000, lastRound: 2000, genesisHash: 'hash', genesisID: 'testnet-v1.0', fee: 1000, flatFee: true, }; beforeEach(() => { jest.clearAllMocks(); (algodClient.getTransactionParams as jest.Mock)().do.mockResolvedValue(mockSuggestedParams); }); describe('Tool Schemas', () => { it('should have valid tool schemas', () => { expect(accountTransactionTools).toHaveLength(2); expect(accountTransactionTools.map((t: { name: string }) => t.name)).toEqual([ 'make_payment_txn', 'make_keyreg_txn', ]); }); }); describe('Payment Transactions', () => { const mockPaymentTxn = { type: 'pay', from: 'sender', to: 'receiver' }; beforeEach(() => { (algosdk.makePaymentTxnWithSuggestedParamsFromObject as jest.Mock).mockReturnValue(mockPaymentTxn); }); it('should create a basic payment transaction', async () => { const args = { from: 'sender', to: 'receiver', amount: 1000, }; const result = await AccountTransactionManager.handleTool('make_payment_txn', args); expect(result).toEqual({ content: [{ type: 'text', text: JSON.stringify(mockPaymentTxn, null, 2), }], }); expect(algosdk.makePaymentTxnWithSuggestedParamsFromObject).toHaveBeenCalledWith( expect.objectContaining({ from: 'sender', to: 'receiver', amount: 1000, suggestedParams: expect.objectContaining(mockSuggestedParams), }) ); }); it('should create a payment transaction with optional parameters', async () => { const args = { from: 'sender', to: 'receiver', amount: 1000, note: 'test note', closeRemainderTo: 'close-to', rekeyTo: 'rekey-to', }; const result = await AccountTransactionManager.handleTool('make_payment_txn', args); expect(result).toEqual({ content: [{ type: 'text', text: JSON.stringify(mockPaymentTxn, null, 2), }], }); expect(algosdk.makePaymentTxnWithSuggestedParamsFromObject).toHaveBeenCalledWith( expect.objectContaining({ from: 'sender', to: 'receiver', amount: 1000, note: new TextEncoder().encode('test note'), closeRemainderTo: 'close-to', rekeyTo: 'rekey-to', suggestedParams: expect.objectContaining(mockSuggestedParams), }) ); }); it('should throw error for missing required parameters', async () => { await expect(AccountTransactionManager.handleTool('make_payment_txn', {})) .rejects .toThrow(new McpError(ErrorCode.InvalidParams, 'Invalid payment transaction parameters')); }); }); describe('Key Registration Transactions', () => { const mockKeyRegTxn = { type: 'keyreg', from: 'sender' }; beforeEach(() => { (algosdk.makeKeyRegistrationTxnWithSuggestedParamsFromObject as jest.Mock).mockReturnValue(mockKeyRegTxn); }); it('should create a basic key registration transaction', async () => { const args = { from: 'sender', voteKey: 'vote-key', selectionKey: 'selection-key', stateProofKey: 'stateproof-key', voteFirst: 1000, voteLast: 2000, voteKeyDilution: 10, }; const result = await AccountTransactionManager.handleTool('make_keyreg_txn', args); expect(result).toEqual({ content: [{ type: 'text', text: JSON.stringify(mockKeyRegTxn, null, 2), }], }); expect(algosdk.makeKeyRegistrationTxnWithSuggestedParamsFromObject).toHaveBeenCalledWith( expect.objectContaining({ from: 'sender', voteKey: 'vote-key', selectionKey: 'selection-key', stateProofKey: 'stateproof-key', voteFirst: 1000, voteLast: 2000, voteKeyDilution: 10, suggestedParams: expect.objectContaining(mockSuggestedParams), }) ); }); it('should create a key registration transaction with optional parameters', async () => { const args = { from: 'sender', voteKey: 'vote-key', selectionKey: 'selection-key', stateProofKey: 'stateproof-key', voteFirst: 1000, voteLast: 2000, voteKeyDilution: 10, nonParticipation: true, note: 'test note', rekeyTo: 'rekey-to', }; const result = await AccountTransactionManager.handleTool('make_keyreg_txn', args); expect(result).toEqual({ content: [{ type: 'text', text: JSON.stringify(mockKeyRegTxn, null, 2), }], }); expect(algosdk.makeKeyRegistrationTxnWithSuggestedParamsFromObject).toHaveBeenCalledWith( expect.objectContaining({ from: 'sender', voteKey: 'vote-key', selectionKey: 'selection-key', stateProofKey: 'stateproof-key', voteFirst: 1000, voteLast: 2000, voteKeyDilution: 10, nonParticipation: true, note: new TextEncoder().encode('test note'), rekeyTo: 'rekey-to', suggestedParams: expect.objectContaining(mockSuggestedParams), }) ); }); it('should throw error for missing required parameters', async () => { await expect(AccountTransactionManager.handleTool('make_keyreg_txn', {})) .rejects .toThrow(new McpError(ErrorCode.InvalidParams, 'Invalid key registration parameters')); }); }); describe('Error Handling', () => { it('should throw error for unknown tool', async () => { await expect(AccountTransactionManager.handleTool('unknown_tool', {})) .rejects .toThrow(new McpError(ErrorCode.MethodNotFound, 'Unknown account transaction tool: unknown_tool')); }); it('should handle algod client errors', async () => { const error = new Error('Network error'); (algodClient.getTransactionParams as jest.Mock)().do.mockRejectedValue(error); await expect(AccountTransactionManager.handleTool('make_payment_txn', { from: 'sender', to: 'receiver', amount: 1000, })) .rejects .toThrow(error); }); it('should handle transaction creation errors', async () => { const error = new Error('Invalid parameters'); (algosdk.makePaymentTxnWithSuggestedParamsFromObject as jest.Mock).mockImplementation(() => { throw error; }); await expect(AccountTransactionManager.handleTool('make_payment_txn', { from: 'sender', to: 'receiver', amount: 1000, })) .rejects .toThrow(error); }); }); }); ``` -------------------------------------------------------------------------------- /packages/server/src/resources/knowledge/taxonomy/developer:docs:details:algorand_consensus.md: -------------------------------------------------------------------------------- ```markdown title: Algorand consensus The Algorand blockchain uses a decentralized Byzantine Agreement protocol that leverages pure proof of stake (Pure POS). This means that it can tolerate malicious users, achieving consensus without a central authority, as long as a supermajority of the stake is in non-malicious hands. This protocol is very fast and requires minimal computational power per node, giving it the ability to finalize transactions efficiently. Before getting into detail on the protocol, we discuss two functional concepts that Algorand uses. This is a simplified version of the protocol that covers the ideal conditions. For all technical details see the white paper<LINK> or the source code<LINK>. # Verifiable Random Function Recently we released the source code<LINK> for our implementation of a Verifiable Random Function (VRF). The VRF takes a secret key and a value and produces a pseudorandom output, with a proof that anyone can use to verify the result. The VRF functions similar to a lottery and is used to choose leaders to propose a block and committee members to vote on a block. This VRF output, when executed for an account, is used to sample from a binomial distribution<LINK> to emulate a call for every algo in a user’s account. The more algos in an account, the greater chance the account has of being selected -- it’s as if every algo in an account participates in its own lottery. This method ensures that a user does not gain any advantage by creating multiple accounts. # Participation Keys A user account must be online to participate in the consensus protocol. To reduce exposure, online users do not use their spending keys (i.e., the keys they use to sign transactions) for consensus. Instead, a user generates and registers a participation key for a certain number of rounds. It also generates a collection of ephemeral keys, one for each round, signs these keys with the participation key, and then deletes the participation key. Each ephemeral key is used to sign messages for the corresponding round, and is deleted after the round is over. Using participation keys ensures that a user's tokens are secure even if their participating node is compromised. Deleting the participation and ephemeral keys after they are used ensures that the blockchain is forward-secure and cannot be compromised by attacks on old blocks using old keys. # State Proof Keys As of go-algorand 3.4.2 (released March 2022), users also generate a state proof key, with associated ephemeral keys, alongside their participation keys. State proof keys will be used to generate Post-Quantum secure state proofs that attest to the state of the blockchain at different points in time. These will be useful for applications that want a portable, lightweight way to cryptographically verify Algorand state without running a full participation node. # The Algorand Consensus Protocol Consensus refers to the way blocks are selected and written to the blockchain. Algorand uses the VRF described above to select leaders to propose blocks for a given round. When a block is proposed to the blockchain, a committee of voters is selected to vote on the block proposal. If a super majority of the votes are from honest participants, the block can be certified. What makes this algorithm a Pure Proof of Stake is that users are chosen for committees based on the number of algos in their accounts. Committees are made up of pseudorandomly selected accounts with voting power dependent on their online stake. It is as if every token gets an execution of the VRF. Users with more tokens are likely to be selected more. For a committee membership this means higher stake accounts will most likely have more votes than a selected account with less tokens. Using randomly selected committees allows the protocol to still have good performance while allowing anyone in the network to participate. Consensus requires three steps to propose, confirm and write the block to the blockchain. These steps are: 1) propose, 2) soft vote and 3) certify vote. Each is described below, assuming the ideal case when there are no malicious users and the network is not partitioned (i.e., none of the network is down due to technical issues or from DDoS attacks). Note that all messages are cryptographically signed with the user’s participation key and committee membership is verified using the VRF in these steps. # Block Proposal In the block proposal phase, accounts are selected to propose new blocks to the network. This phase starts with every node in the network looping through each online account for which it has valid participation keys, running Algorand’s VRF to determine if the account is selected to propose the block. The VRF acts similar to a weighted lottery where the number of Algos that the account has participating online determines the account’s chance of being selected. Once an account is selected by the VRF, the node propagates the proposed block along with the VRF output, which proves that the account is a valid proposer. We then move from the propose step to the soft vote step.  <center>*Block Proposal*</center> # Soft Vote The purpose of this phase is to filter the number of proposals down to one, guaranteeing that only one block gets certified. Each node in the network will get many proposal messages from other nodes. Nodes will verify the signature of the message and then validate the selection using the VRF proof. Next, the node will compare the hash from each validated winner’s VRF proof to determine which is the lowest and will only propagate the block proposal with the lowest VRF hash. This process continues for a fixed amount of time to allow votes to be propagated across the network.  <center>*Soft Vote Part 1*</center> Each node will then run the VRF for every participating account it manages to see if they have been chosen to participate in the soft vote committee. If any account is chosen it will have a weighted vote based on the number of Algos the account has, and these votes will be propagated to the network. These votes will be for the lowest VRF block proposal calculated at the timeout and will be sent out to the other nodes along with the VRF Proof.  <center>*Soft Vote Part 2*</center> A new committee is selected for every step in the process and each step has a different committee size. This committee size is quantified in algos. A quorum of votes is needed to move to the next step and must be a certain percentage of the expected committee size. These votes will be received from other nodes on the network and each node will validate the committee membership VRF proof before adding to the vote tally. Once a quorum is reached for the soft vote the process moves to the certify vote step. # Certify Vote A new committee checks the block proposal that was voted on in the soft vote stage for overspending, double-spending, or any other problems. If valid, the new committee votes again to certify the block. This is done in a similar manner as the soft vote where each node iterates through its managed accounts to select a committee and to send votes. These votes are collected and validated by each node until a quorum is reached, triggering an end to the round and prompting the node to create a certificate for the block and write it to the ledger. At that point, a new round is initiated and the process starts over.  <center>*Certify Vote*</center> If a quorum is not reached in a certifying committee vote by a certain timeout then the network will enter recovery mode. ```