From 6dacc1c7f7703d14c7e43ceefddda3efc5f53013 Mon Sep 17 00:00:00 2001 From: Neil Campbell Date: Fri, 31 Oct 2025 11:51:55 +0800 Subject: [PATCH 01/10] feat: add algod generator --- .gitignore | 9 + .../openapi-converter/specs/algod.oas3.json | 7595 +++++++++++++++++ .../openapi-converter/specs/compatibility.md | 79 + .../openapi-converter/specs/indexer.oas3.json | 5779 +++++++++++++ .../openapi-converter/specs/kmd.oas3.json | 1953 +++++ oas-generator/README.md | 0 oas-generator/pyproject.toml | 22 + oas-generator/src/oas_generator/__init__.py | 11 + oas-generator/src/oas_generator/cli.py | 173 + oas-generator/src/oas_generator/constants.py | 219 + .../src/oas_generator/generator/__init__.py | 5 + .../src/oas_generator/generator/filters.py | 459 + .../src/oas_generator/generator/models.py | 150 + .../generator/template_engine.py | 845 ++ .../src/oas_generator/parser/__init__.py | 5 + .../src/oas_generator/parser/oas_parser.py | 46 + .../oas_generator/templates/apis/index.ts.j2 | 2 + .../templates/apis/service.ts.j2 | 166 + .../templates/base/src/core/api-error.ts.j2 | 12 + .../base/src/core/base-http-request.ts.j2 | 22 + .../base/src/core/cancelable-promise.ts.j2 | 58 + .../base/src/core/client-config.ts.j2 | 22 + .../templates/base/src/core/codecs.ts.j2 | 42 + .../base/src/core/fetch-http-request.ts.j2 | 120 + .../base/src/core/model-runtime.ts.j2 | 308 + .../templates/base/src/core/request.ts.j2 | 127 + .../base/src/core/serialization.ts.j2 | 26 + .../templates/base/src/index.ts.j2 | 12 + .../src/oas_generator/templates/client.ts.j2 | 10 + .../models/block/application-eval-delta.ts.j2 | 37 + .../block/block-account-state-delta.ts.j2 | 22 + .../models/block/block-eval-delta.ts.j2 | 26 + .../models/block/block-state-delta.ts.j2 | 16 + .../block-state-proof-tracking-data.ts.j2 | 26 + .../block/block-state-proof-tracking.ts.j2 | 17 + .../templates/models/block/block.ts.j2 | 120 + .../templates/models/block/get-block.ts.j2 | 22 + .../models/block/signed-txn-in-block.ts.j2 | 63 + .../templates/models/index.ts.j2 | 4 + .../templates/models/model.ts.j2 | 99 + .../src/oas_generator/utils/__init__.py | 5 + .../src/oas_generator/utils/file_utils.py | 18 + oas-generator/uv.lock | 89 + package.json | 3 +- 44 files changed, 18843 insertions(+), 1 deletion(-) create mode 100644 algokit-configs/openapi-converter/specs/algod.oas3.json create mode 100644 algokit-configs/openapi-converter/specs/compatibility.md create mode 100644 algokit-configs/openapi-converter/specs/indexer.oas3.json create mode 100644 algokit-configs/openapi-converter/specs/kmd.oas3.json create mode 100644 oas-generator/README.md create mode 100644 oas-generator/pyproject.toml create mode 100644 oas-generator/src/oas_generator/__init__.py create mode 100644 oas-generator/src/oas_generator/cli.py create mode 100644 oas-generator/src/oas_generator/constants.py create mode 100644 oas-generator/src/oas_generator/generator/__init__.py create mode 100644 oas-generator/src/oas_generator/generator/filters.py create mode 100644 oas-generator/src/oas_generator/generator/models.py create mode 100644 oas-generator/src/oas_generator/generator/template_engine.py create mode 100644 oas-generator/src/oas_generator/parser/__init__.py create mode 100644 oas-generator/src/oas_generator/parser/oas_parser.py create mode 100644 oas-generator/src/oas_generator/templates/apis/index.ts.j2 create mode 100644 oas-generator/src/oas_generator/templates/apis/service.ts.j2 create mode 100644 oas-generator/src/oas_generator/templates/base/src/core/api-error.ts.j2 create mode 100644 oas-generator/src/oas_generator/templates/base/src/core/base-http-request.ts.j2 create mode 100644 oas-generator/src/oas_generator/templates/base/src/core/cancelable-promise.ts.j2 create mode 100644 oas-generator/src/oas_generator/templates/base/src/core/client-config.ts.j2 create mode 100644 oas-generator/src/oas_generator/templates/base/src/core/codecs.ts.j2 create mode 100644 oas-generator/src/oas_generator/templates/base/src/core/fetch-http-request.ts.j2 create mode 100644 oas-generator/src/oas_generator/templates/base/src/core/model-runtime.ts.j2 create mode 100644 oas-generator/src/oas_generator/templates/base/src/core/request.ts.j2 create mode 100644 oas-generator/src/oas_generator/templates/base/src/core/serialization.ts.j2 create mode 100644 oas-generator/src/oas_generator/templates/base/src/index.ts.j2 create mode 100644 oas-generator/src/oas_generator/templates/client.ts.j2 create mode 100644 oas-generator/src/oas_generator/templates/models/block/application-eval-delta.ts.j2 create mode 100644 oas-generator/src/oas_generator/templates/models/block/block-account-state-delta.ts.j2 create mode 100644 oas-generator/src/oas_generator/templates/models/block/block-eval-delta.ts.j2 create mode 100644 oas-generator/src/oas_generator/templates/models/block/block-state-delta.ts.j2 create mode 100644 oas-generator/src/oas_generator/templates/models/block/block-state-proof-tracking-data.ts.j2 create mode 100644 oas-generator/src/oas_generator/templates/models/block/block-state-proof-tracking.ts.j2 create mode 100644 oas-generator/src/oas_generator/templates/models/block/block.ts.j2 create mode 100644 oas-generator/src/oas_generator/templates/models/block/get-block.ts.j2 create mode 100644 oas-generator/src/oas_generator/templates/models/block/signed-txn-in-block.ts.j2 create mode 100644 oas-generator/src/oas_generator/templates/models/index.ts.j2 create mode 100644 oas-generator/src/oas_generator/templates/models/model.ts.j2 create mode 100644 oas-generator/src/oas_generator/utils/__init__.py create mode 100644 oas-generator/src/oas_generator/utils/file_utils.py create mode 100644 oas-generator/uv.lock diff --git a/.gitignore b/.gitignore index b3c24599c..f877f0b06 100644 --- a/.gitignore +++ b/.gitignore @@ -57,3 +57,12 @@ out/ .env .env.* !.env.template + +# Python +__pycache__/ +*.pyc +*.pyo +*.pyd +env/ +venv/ +ENV/ diff --git a/algokit-configs/openapi-converter/specs/algod.oas3.json b/algokit-configs/openapi-converter/specs/algod.oas3.json new file mode 100644 index 000000000..804c5fb03 --- /dev/null +++ b/algokit-configs/openapi-converter/specs/algod.oas3.json @@ -0,0 +1,7595 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "Algod REST API.", + "description": "API endpoint for algod operations.", + "contact": { + "name": "algorand", + "url": "https://www.algorand.com/get-in-touch/contact", + "email": "contact@algorand.com" + }, + "version": "0.0.1" + }, + "servers": [ + { + "url": "http://localhost/" + }, + { + "url": "https://localhost/" + } + ], + "security": [ + { + "api_key": [] + } + ], + "tags": [ + { + "name": "private" + } + ], + "paths": { + "/health": { + "get": { + "tags": [ + "public", + "common" + ], + "summary": "Returns OK if healthy.", + "operationId": "HealthCheck", + "responses": { + "200": { + "description": "OK.", + "content": {} + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/ready": { + "get": { + "tags": [ + "public", + "common" + ], + "summary": "Returns OK if healthy and fully caught up.", + "operationId": "GetReady", + "responses": { + "200": { + "description": "OK.", + "content": {} + }, + "500": { + "description": "Internal Error", + "content": {} + }, + "503": { + "description": "Node not ready yet", + "content": {} + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/metrics": { + "get": { + "tags": [ + "public", + "common" + ], + "summary": "Return metrics about algod functioning.", + "operationId": "Metrics", + "responses": { + "200": { + "description": "text with \\#-comments and key:value lines", + "content": {} + }, + "404": { + "description": "metrics were compiled out", + "content": {} + } + } + } + }, + "/genesis": { + "get": { + "tags": [ + "public", + "common" + ], + "summary": "Gets the genesis information.", + "description": "Returns the entire genesis file in json.", + "operationId": "GetGenesis", + "responses": { + "200": { + "description": "The genesis file in json.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Genesis" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/swagger.json": { + "get": { + "tags": [ + "public", + "common" + ], + "summary": "Gets the current swagger spec.", + "description": "Returns the entire swagger spec in json.", + "operationId": "SwaggerJSON", + "responses": { + "200": { + "description": "The current swagger spec", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/versions": { + "get": { + "tags": [ + "public", + "common" + ], + "description": "Retrieves the supported API versions, binary build versions, and genesis information.", + "operationId": "GetVersion", + "responses": { + "200": { + "description": "VersionsResponse is the response to 'GET /versions'", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Version" + } + } + } + } + } + } + }, + "/debug/settings/pprof": { + "get": { + "tags": [ + "private" + ], + "description": "Retrieves the current settings for blocking and mutex profiles", + "operationId": "GetDebugSettingsProf", + "responses": { + "200": { + "description": "DebugPprof is the response to the /debug/extra/pprof endpoint", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DebugSettingsProf" + } + } + } + } + } + }, + "put": { + "tags": [ + "private" + ], + "description": "Enables blocking and mutex profiles, and returns the old settings", + "operationId": "PutDebugSettingsProf", + "responses": { + "200": { + "description": "DebugPprof is the response to the /debug/extra/pprof endpoint", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DebugSettingsProf" + } + } + } + } + } + } + }, + "/debug/settings/config": { + "get": { + "tags": [ + "private" + ], + "summary": "Gets the merged config file.", + "description": "Returns the merged (defaults + overrides) config file in json.", + "operationId": "GetConfig", + "responses": { + "200": { + "description": "The merged config file in json.", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v2/accounts/{address}": { + "get": { + "tags": [ + "public", + "nonparticipating" + ], + "summary": "Get account information.", + "description": "Given a specific account public key, this call returns the account's status, balance and spendable amounts", + "operationId": "AccountInformation", + "parameters": [ + { + "name": "address", + "in": "path", + "description": "An account public key.", + "required": true, + "schema": { + "pattern": "[A-Z0-9]{58}", + "type": "string", + "x-go-type": "basics.Address" + }, + "x-go-type": "basics.Address" + }, + { + "name": "exclude", + "in": "query", + "description": "When set to `all` will exclude asset holdings, application local state, created asset parameters, any created application parameters. Defaults to `none`.", + "schema": { + "type": "string", + "enum": [ + "all", + "none" + ] + } + }, + { + "name": "format", + "in": "query", + "description": "Configures whether the response object is JSON or MessagePack encoded. If not provided, defaults to JSON.", + "schema": { + "type": "string", + "enum": [ + "json" + ], + "default": "json" + } + } + ], + "responses": { + "200": { + "description": "AccountResponse wraps the Account type in a response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Account" + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v2/accounts/{address}/assets/{asset-id}": { + "get": { + "tags": [ + "public", + "nonparticipating" + ], + "summary": "Get account information about a given asset.", + "description": "Given a specific account public key and asset ID, this call returns the account's asset holding and asset parameters (if either exist). Asset parameters will only be returned if the provided address is the asset's creator.", + "operationId": "AccountAssetInformation", + "parameters": [ + { + "name": "address", + "in": "path", + "description": "An account public key.", + "required": true, + "schema": { + "pattern": "[A-Z0-9]{58}", + "type": "string", + "x-go-type": "basics.Address" + }, + "x-go-type": "basics.Address" + }, + { + "name": "asset-id", + "in": "path", + "description": "An asset identifier.", + "required": true, + "schema": { + "minimum": 0, + "type": "integer", + "x-go-type": "basics.AssetIndex" + }, + "x-go-type": "basics.AssetIndex" + }, + { + "name": "format", + "in": "query", + "description": "Configures whether the response object is JSON or MessagePack encoded. If not provided, defaults to JSON.", + "schema": { + "type": "string", + "enum": [ + "json" + ], + "default": "json" + } + } + ], + "responses": { + "200": { + "description": "AccountAssetResponse describes the account's asset holding and asset parameters (if either exist) for a specific asset ID. Asset parameters will only be returned if the provided address is the asset's creator.", + "content": { + "application/json": { + "schema": { + "required": [ + "round" + ], + "type": "object", + "properties": { + "round": { + "type": "integer", + "description": "The round for which this information is relevant.", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + }, + "asset-holding": { + "$ref": "#/components/schemas/AssetHolding" + }, + "created-asset": { + "$ref": "#/components/schemas/AssetParams" + } + } + } + } + } + }, + "400": { + "description": "Malformed address or asset ID", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v2/accounts/{address}/assets": { + "get": { + "tags": [ + "public", + "experimental" + ], + "summary": "Get a list of assets held by an account, inclusive of asset params.", + "description": "Lookup an account's asset holdings.", + "operationId": "AccountAssetsInformation", + "parameters": [ + { + "name": "address", + "in": "path", + "description": "An account public key.", + "required": true, + "schema": { + "pattern": "[A-Z0-9]{58}", + "type": "string", + "x-go-type": "basics.Address" + }, + "x-go-type": "basics.Address" + }, + { + "name": "limit", + "in": "query", + "description": "Maximum number of results to return.", + "schema": { + "type": "integer", + "x-algokit-bigint": true + }, + "x-algokit-bigint": true + }, + { + "name": "next", + "in": "query", + "description": "The next page of results. Use the next token provided by the previous results.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "AccountAssetsInformationResponse contains a list of assets held by an account.", + "content": { + "application/json": { + "schema": { + "required": [ + "round" + ], + "type": "object", + "properties": { + "round": { + "type": "integer", + "description": "The round for which this information is relevant.", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + }, + "next-token": { + "type": "string", + "description": "Used for pagination, when making another request provide this token with the next parameter." + }, + "asset-holdings": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AccountAssetHolding" + } + } + } + } + } + } + }, + "400": { + "description": "Malformed address", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v2/accounts/{address}/applications/{application-id}": { + "get": { + "tags": [ + "public", + "nonparticipating" + ], + "summary": "Get account information about a given app.", + "description": "Given a specific account public key and application ID, this call returns the account's application local state and global state (AppLocalState and AppParams, if either exists). Global state will only be returned if the provided address is the application's creator.", + "operationId": "AccountApplicationInformation", + "parameters": [ + { + "name": "address", + "in": "path", + "description": "An account public key.", + "required": true, + "schema": { + "pattern": "[A-Z0-9]{58}", + "type": "string", + "x-go-type": "basics.Address" + }, + "x-go-type": "basics.Address" + }, + { + "name": "application-id", + "in": "path", + "description": "An application identifier.", + "required": true, + "schema": { + "minimum": 0, + "type": "integer", + "x-go-type": "basics.AppIndex" + }, + "x-go-type": "basics.AppIndex" + }, + { + "name": "format", + "in": "query", + "description": "Configures whether the response object is JSON or MessagePack encoded. If not provided, defaults to JSON.", + "schema": { + "type": "string", + "enum": [ + "json", + "msgpack" + ] + } + } + ], + "responses": { + "200": { + "description": "AccountApplicationResponse describes the account's application local state and global state (AppLocalState and AppParams, if either exists) for a specific application ID. Global state will only be returned if the provided address is the application's creator.", + "content": { + "application/json": { + "schema": { + "required": [ + "round" + ], + "type": "object", + "properties": { + "round": { + "type": "integer", + "description": "The round for which this information is relevant.", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + }, + "app-local-state": { + "$ref": "#/components/schemas/ApplicationLocalState" + }, + "created-app": { + "$ref": "#/components/schemas/ApplicationParams" + } + } + } + }, + "application/msgpack": { + "schema": { + "required": [ + "round" + ], + "type": "object", + "properties": { + "round": { + "type": "integer", + "description": "The round for which this information is relevant.", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + }, + "app-local-state": { + "$ref": "#/components/schemas/ApplicationLocalState" + }, + "created-app": { + "$ref": "#/components/schemas/ApplicationParams" + } + } + } + } + } + }, + "400": { + "description": "Malformed address or application ID", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + }, + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + }, + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + }, + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v2/accounts/{address}/transactions/pending": { + "get": { + "tags": [ + "public", + "participating" + ], + "summary": "Get a list of unconfirmed transactions currently in the transaction pool by address.", + "description": "Get the list of pending transactions by address, sorted by priority, in decreasing order, truncated at the end at MAX. If MAX = 0, returns all pending transactions.\n", + "operationId": "GetPendingTransactionsByAddress", + "parameters": [ + { + "name": "address", + "in": "path", + "description": "An account public key.", + "required": true, + "schema": { + "pattern": "[A-Z0-9]{58}", + "type": "string", + "x-go-type": "basics.Address" + }, + "x-go-type": "basics.Address" + }, + { + "name": "max", + "in": "query", + "description": "Truncated number of transactions to display. If max=0, returns all pending txns.", + "schema": { + "type": "integer", + "x-algokit-bigint": true + }, + "x-algokit-bigint": true + }, + { + "name": "format", + "in": "query", + "description": "Configures whether the response object is JSON or MessagePack encoded. If not provided, defaults to JSON.", + "schema": { + "type": "string", + "enum": [ + "msgpack" + ], + "default": "msgpack" + } + } + ], + "responses": { + "200": { + "description": "A potentially truncated list of transactions currently in the node's transaction pool. You can compute whether or not the list is truncated if the number of elements in the **top-transactions** array is fewer than **total-transactions**.", + "content": { + "application/msgpack": { + "schema": { + "required": [ + "top-transactions", + "total-transactions" + ], + "type": "object", + "properties": { + "top-transactions": { + "type": "array", + "description": "An array of signed transaction objects.", + "items": { + "type": "object", + "properties": {}, + "x-algokit-signed-txn": true + } + }, + "total-transactions": { + "type": "integer", + "description": "Total number of transactions in the pool." + } + }, + "description": "PendingTransactions is an array of signed transactions exactly as they were submitted." + } + } + } + }, + "400": { + "description": "Max must be a non-negative integer", + "content": { + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service Temporarily Unavailable", + "content": { + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v2/blocks/{round}": { + "get": { + "tags": [ + "public", + "nonparticipating" + ], + "summary": "Get the block for the given round.", + "operationId": "GetBlock", + "parameters": [ + { + "name": "round", + "in": "path", + "description": "A round number.", + "required": true, + "schema": { + "minimum": 0, + "type": "integer", + "x-go-type": "basics.Round" + }, + "x-go-type": "basics.Round" + }, + { + "name": "header-only", + "in": "query", + "description": "If true, only the block header (exclusive of payset or certificate) may be included in response.", + "schema": { + "type": "boolean" + } + }, + { + "name": "format", + "in": "query", + "description": "Configures whether the response object is JSON or MessagePack encoded. If not provided, defaults to JSON.", + "schema": { + "type": "string", + "enum": [ + "msgpack" + ], + "default": "msgpack" + } + } + ], + "responses": { + "200": { + "description": "Encoded block object.", + "content": { + "application/msgpack": { + "schema": { + "required": [ + "block" + ], + "type": "object", + "properties": { + "block": { + "type": "object", + "properties": {}, + "description": "Block header data.", + "x-algorand-format": "BlockHeader" + }, + "cert": { + "type": "object", + "properties": {}, + "description": "Optional certificate object. This is only included when the format is set to message pack.", + "x-algorand-format": "BlockCertificate" + } + } + } + } + } + }, + "400": { + "description": "Bad Request - Non integer number", + "content": { + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "None existing block ", + "content": { + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v2/blocks/{round}/txids": { + "get": { + "tags": [ + "public", + "nonparticipating" + ], + "summary": "Get the top level transaction IDs for the block on the given round.", + "operationId": "GetBlockTxids", + "parameters": [ + { + "name": "round", + "in": "path", + "description": "A round number.", + "required": true, + "schema": { + "minimum": 0, + "type": "integer", + "x-go-type": "basics.Round" + }, + "x-go-type": "basics.Round" + } + ], + "responses": { + "200": { + "description": "Top level transaction IDs in a block.", + "content": { + "application/json": { + "schema": { + "required": [ + "blockTxids" + ], + "type": "object", + "properties": { + "blockTxids": { + "type": "array", + "description": "Block transaction IDs.", + "items": { + "type": "string" + } + } + } + } + } + } + }, + "400": { + "description": "Bad Request - Non integer number", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Non existing block", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v2/blocks/{round}/hash": { + "get": { + "tags": [ + "public", + "nonparticipating" + ], + "summary": "Get the block hash for the block on the given round.", + "operationId": "GetBlockHash", + "parameters": [ + { + "name": "round", + "in": "path", + "description": "A round number.", + "required": true, + "schema": { + "minimum": 0, + "type": "integer", + "x-go-type": "basics.Round" + }, + "x-go-type": "basics.Round" + } + ], + "responses": { + "200": { + "description": "Hash of a block header.", + "content": { + "application/json": { + "schema": { + "required": [ + "blockHash" + ], + "type": "object", + "properties": { + "blockHash": { + "type": "string", + "description": "Block header hash." + } + } + } + } + } + }, + "400": { + "description": "Bad Request - Non integer number", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "None existing block ", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v2/blocks/{round}/transactions/{txid}/proof": { + "get": { + "tags": [ + "public", + "nonparticipating" + ], + "summary": "Get a proof for a transaction in a block.", + "operationId": "GetTransactionProof", + "parameters": [ + { + "name": "round", + "in": "path", + "description": "A round number.", + "required": true, + "schema": { + "minimum": 0, + "type": "integer", + "x-go-type": "basics.Round" + }, + "x-go-type": "basics.Round" + }, + { + "name": "txid", + "in": "path", + "description": "The transaction ID for which to generate a proof.", + "required": true, + "schema": { + "pattern": "[A-Z0-9]+", + "type": "string" + } + }, + { + "name": "hashtype", + "in": "query", + "description": "The type of hash function used to create the proof, must be one of: \n* sha512_256 \n* sha256", + "schema": { + "type": "string", + "enum": [ + "sha512_256", + "sha256" + ] + } + }, + { + "name": "format", + "in": "query", + "description": "Configures whether the response object is JSON or MessagePack encoded. If not provided, defaults to JSON.", + "schema": { + "type": "string", + "enum": [ + "json", + "msgpack" + ] + } + } + ], + "responses": { + "200": { + "description": "Proof of transaction in a block.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TransactionProof" + } + } + } + }, + "400": { + "description": "Malformed round number or transaction ID", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Non-existent block or transaction", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal error, including protocol not supporting proofs.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown error", + "content": {} + } + } + } + }, + "/v2/blocks/{round}/logs": { + "get": { + "tags": [ + "public", + "nonparticipating" + ], + "summary": "Get all of the logs from outer and inner app calls in the given round", + "description": "Get all of the logs from outer and inner app calls in the given round", + "operationId": "GetBlockLogs", + "parameters": [ + { + "name": "round", + "in": "path", + "description": "A round number.", + "required": true, + "schema": { + "minimum": 0, + "type": "integer", + "x-go-type": "basics.Round" + }, + "x-go-type": "basics.Round" + } + ], + "responses": { + "200": { + "description": "All logs emitted in the given round. Each app call, whether top-level or inner, that contains logs results in a separate AppCallLogs object. Therefore there may be multiple AppCallLogs with the same application ID and outer transaction ID in the event of multiple inner app calls to the same app. App calls with no logs are not included in the response. AppCallLogs are returned in the same order that their corresponding app call appeared in the block (pre-order traversal of inner app calls)", + "content": { + "application/json": { + "schema": { + "required": [ + "logs" + ], + "type": "object", + "properties": { + "logs": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AppCallLogs" + } + } + } + } + } + } + }, + "400": { + "description": "Bad Request - Non integer number", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Nonexistent block ", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/v2/ledger/supply": { + "get": { + "tags": [ + "public", + "nonparticipating" + ], + "summary": "Get the current supply reported by the ledger.", + "operationId": "GetSupply", + "responses": { + "200": { + "description": "Supply represents the current supply of MicroAlgos in the system.", + "content": { + "application/json": { + "schema": { + "required": [ + "current_round", + "online-money", + "total-money" + ], + "type": "object", + "properties": { + "current_round": { + "type": "integer", + "description": "Round", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + }, + "online-money": { + "type": "integer", + "description": "OnlineMoney", + "x-algokit-bigint": true + }, + "total-money": { + "type": "integer", + "description": "TotalMoney", + "x-algokit-bigint": true + } + }, + "description": "Supply represents the current supply of MicroAlgos in the system" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v2/participation": { + "get": { + "tags": [ + "private", + "participating" + ], + "summary": "Return a list of participation keys", + "description": "Return a list of participation keys", + "operationId": "GetParticipationKeys", + "responses": { + "200": { + "description": "A list of participation keys", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ParticipationKey" + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Participation Key Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + }, + "post": { + "tags": [ + "private", + "participating" + ], + "summary": "Add a participation key to the node", + "operationId": "AddParticipationKey", + "requestBody": { + "description": "The participation key to add to the node", + "content": { + "application/msgpack": { + "schema": { + "type": "string", + "format": "binary" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Participation ID of the submission", + "content": { + "application/json": { + "schema": { + "required": [ + "partId" + ], + "type": "object", + "properties": { + "partId": { + "type": "string", + "description": "encoding of the participation ID." + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Participation Key Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service Temporarily Unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + }, + "x-codegen-request-body-name": "participationkey" + } + }, + "/v2/participation/generate/{address}": { + "post": { + "tags": [ + "private", + "participating" + ], + "summary": "Generate and install participation keys to the node.", + "operationId": "GenerateParticipationKeys", + "parameters": [ + { + "name": "address", + "in": "path", + "description": "An account public key.", + "required": true, + "schema": { + "pattern": "[A-Z0-9]{58}", + "type": "string", + "x-go-type": "basics.Address" + }, + "x-go-type": "basics.Address" + }, + { + "name": "dilution", + "in": "query", + "description": "Key dilution for two-level participation keys (defaults to sqrt of validity window).", + "schema": { + "type": "integer", + "format": "uint64", + "x-algokit-bigint": true + } + }, + { + "name": "first", + "in": "query", + "description": "First round for participation key.", + "required": true, + "schema": { + "type": "integer", + "format": "uint64", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + }, + "x-go-type": "basics.Round" + }, + { + "name": "last", + "in": "query", + "description": "Last round for participation key.", + "required": true, + "schema": { + "type": "integer", + "format": "uint64", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + }, + "x-go-type": "basics.Round" + } + ], + "responses": { + "200": { + "description": "An empty JSON object is returned if the generation process was started. Currently no status is available.", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service Temporarily Unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v2/participation/{participation-id}": { + "get": { + "tags": [ + "private", + "participating" + ], + "summary": "Get participation key info given a participation ID", + "description": "Given a participation ID, return information about that participation key", + "operationId": "GetParticipationKeyByID", + "parameters": [ + { + "name": "participation-id", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "A detailed description of a participation ID", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ParticipationKey" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Participation Key Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + }, + "post": { + "tags": [ + "private", + "participating" + ], + "summary": "Append state proof keys to a participation key", + "description": "Given a participation ID, append state proof keys to a particular set of participation keys", + "operationId": "AppendKeys", + "parameters": [ + { + "name": "participation-id", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "The state proof keys to add to an existing participation ID", + "content": { + "application/msgpack": { + "schema": { + "type": "string", + "format": "binary" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "A detailed description of a participation ID", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ParticipationKey" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Participation Key Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + }, + "x-codegen-request-body-name": "keymap" + }, + "delete": { + "tags": [ + "private", + "participating" + ], + "summary": "Delete a given participation key by ID", + "description": "Delete a given participation key by ID", + "operationId": "DeleteParticipationKeyByID", + "parameters": [ + { + "name": "participation-id", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Participation key got deleted by ID", + "content": {} + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Participation Key Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v2/shutdown": { + "post": { + "tags": [ + "private", + "nonparticipating" + ], + "description": "Special management endpoint to shutdown the node. Optionally provide a timeout parameter to indicate that the node should begin shutting down after a number of seconds.", + "operationId": "ShutdownNode", + "parameters": [ + { + "name": "timeout", + "in": "query", + "schema": { + "type": "integer", + "default": 0 + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + }, + "description": "Node shutdown initiated successfully" + } + } + } + }, + "/v2/status": { + "get": { + "tags": [ + "public", + "nonparticipating" + ], + "summary": "Gets the current node status.", + "operationId": "GetStatus", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "required": [ + "catchup-time", + "last-round", + "last-version", + "next-version", + "next-version-round", + "next-version-supported", + "stopped-at-unsupported-round", + "time-since-last-round" + ], + "type": "object", + "properties": { + "catchup-time": { + "type": "integer", + "description": "CatchupTime in nanoseconds", + "x-go-type": "int64", + "x-algokit-bigint": true + }, + "last-round": { + "type": "integer", + "description": "LastRound indicates the last round seen", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + }, + "last-version": { + "type": "string", + "description": "LastVersion indicates the last consensus version supported" + }, + "next-version": { + "type": "string", + "description": "NextVersion of consensus protocol to use" + }, + "next-version-round": { + "type": "integer", + "description": "NextVersionRound is the round at which the next consensus version will apply", + "x-go-type": "basics.Round" + }, + "next-version-supported": { + "type": "boolean", + "description": "NextVersionSupported indicates whether the next consensus version is supported by this node" + }, + "stopped-at-unsupported-round": { + "type": "boolean", + "description": "StoppedAtUnsupportedRound indicates that the node does not support the new rounds and has stopped making progress" + }, + "time-since-last-round": { + "type": "integer", + "description": "TimeSinceLastRound in nanoseconds", + "x-go-type": "int64", + "x-algokit-bigint": true + }, + "last-catchpoint": { + "type": "string", + "description": "The last catchpoint seen by the node" + }, + "catchpoint": { + "type": "string", + "description": "The current catchpoint that is being caught up to" + }, + "catchpoint-total-accounts": { + "type": "integer", + "description": "The total number of accounts included in the current catchpoint", + "x-algokit-bigint": true + }, + "catchpoint-processed-accounts": { + "type": "integer", + "description": "The number of accounts from the current catchpoint that have been processed so far as part of the catchup", + "x-algokit-bigint": true + }, + "catchpoint-verified-accounts": { + "type": "integer", + "description": "The number of accounts from the current catchpoint that have been verified so far as part of the catchup", + "x-algokit-bigint": true + }, + "catchpoint-total-kvs": { + "type": "integer", + "description": "The total number of key-values (KVs) included in the current catchpoint", + "x-algokit-bigint": true + }, + "catchpoint-processed-kvs": { + "type": "integer", + "description": "The number of key-values (KVs) from the current catchpoint that have been processed so far as part of the catchup", + "x-algokit-bigint": true + }, + "catchpoint-verified-kvs": { + "type": "integer", + "description": "The number of key-values (KVs) from the current catchpoint that have been verified so far as part of the catchup", + "x-algokit-bigint": true + }, + "catchpoint-total-blocks": { + "type": "integer", + "description": "The total number of blocks that are required to complete the current catchpoint catchup", + "x-algokit-bigint": true + }, + "catchpoint-acquired-blocks": { + "type": "integer", + "description": "The number of blocks that have already been obtained by the node as part of the catchup", + "x-algokit-bigint": true + }, + "upgrade-delay": { + "type": "integer", + "description": "Upgrade delay", + "x-go-type": "basics.Round" + }, + "upgrade-node-vote": { + "type": "boolean", + "description": "This node's upgrade vote" + }, + "upgrade-votes-required": { + "type": "integer", + "description": "Yes votes required for consensus upgrade", + "x-go-type": "basics.Round" + }, + "upgrade-votes": { + "type": "integer", + "description": "Total votes cast for consensus upgrade", + "x-go-type": "basics.Round" + }, + "upgrade-yes-votes": { + "type": "integer", + "description": "Yes votes cast for consensus upgrade", + "x-go-type": "basics.Round" + }, + "upgrade-no-votes": { + "type": "integer", + "description": "No votes cast for consensus upgrade", + "x-go-type": "basics.Round" + }, + "upgrade-next-protocol-vote-before": { + "type": "integer", + "description": "Next protocol round", + "x-go-type": "basics.Round" + }, + "upgrade-vote-rounds": { + "type": "integer", + "description": "Total voting rounds for current upgrade", + "x-go-type": "basics.Round" + } + }, + "description": "NodeStatus contains the information about a node status" + } + } + }, + "description": "Returns the current node status including sync status, version, and latest round" + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v2/status/wait-for-block-after/{round}": { + "get": { + "tags": [ + "public", + "nonparticipating" + ], + "summary": "Gets the node status after waiting for a round after the given round.", + "description": "Waits for a block to appear after round {round} and returns the node's status at the time. There is a 1 minute timeout, when reached the current status is returned regardless of whether or not it is the round after the given round.", + "operationId": "WaitForBlock", + "parameters": [ + { + "name": "round", + "in": "path", + "description": "A round number.", + "required": true, + "schema": { + "minimum": 0, + "type": "integer", + "x-go-type": "basics.Round" + }, + "x-go-type": "basics.Round" + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "required": [ + "catchup-time", + "last-round", + "last-version", + "next-version", + "next-version-round", + "next-version-supported", + "stopped-at-unsupported-round", + "time-since-last-round" + ], + "type": "object", + "properties": { + "catchup-time": { + "type": "integer", + "description": "CatchupTime in nanoseconds", + "x-go-type": "int64", + "x-algokit-bigint": true + }, + "last-round": { + "type": "integer", + "description": "LastRound indicates the last round seen", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + }, + "last-version": { + "type": "string", + "description": "LastVersion indicates the last consensus version supported" + }, + "next-version": { + "type": "string", + "description": "NextVersion of consensus protocol to use" + }, + "next-version-round": { + "type": "integer", + "description": "NextVersionRound is the round at which the next consensus version will apply", + "x-go-type": "basics.Round" + }, + "next-version-supported": { + "type": "boolean", + "description": "NextVersionSupported indicates whether the next consensus version is supported by this node" + }, + "stopped-at-unsupported-round": { + "type": "boolean", + "description": "StoppedAtUnsupportedRound indicates that the node does not support the new rounds and has stopped making progress" + }, + "time-since-last-round": { + "type": "integer", + "description": "TimeSinceLastRound in nanoseconds", + "x-go-type": "int64", + "x-algokit-bigint": true + }, + "last-catchpoint": { + "type": "string", + "description": "The last catchpoint seen by the node" + }, + "catchpoint": { + "type": "string", + "description": "The current catchpoint that is being caught up to" + }, + "catchpoint-total-accounts": { + "type": "integer", + "description": "The total number of accounts included in the current catchpoint", + "x-algokit-bigint": true + }, + "catchpoint-processed-accounts": { + "type": "integer", + "description": "The number of accounts from the current catchpoint that have been processed so far as part of the catchup", + "x-algokit-bigint": true + }, + "catchpoint-verified-accounts": { + "type": "integer", + "description": "The number of accounts from the current catchpoint that have been verified so far as part of the catchup", + "x-algokit-bigint": true + }, + "catchpoint-total-kvs": { + "type": "integer", + "description": "The total number of key-values (KVs) included in the current catchpoint", + "x-algokit-bigint": true + }, + "catchpoint-processed-kvs": { + "type": "integer", + "description": "The number of key-values (KVs) from the current catchpoint that have been processed so far as part of the catchup", + "x-algokit-bigint": true + }, + "catchpoint-verified-kvs": { + "type": "integer", + "description": "The number of key-values (KVs) from the current catchpoint that have been verified so far as part of the catchup", + "x-algokit-bigint": true + }, + "catchpoint-total-blocks": { + "type": "integer", + "description": "The total number of blocks that are required to complete the current catchpoint catchup", + "x-algokit-bigint": true + }, + "catchpoint-acquired-blocks": { + "type": "integer", + "description": "The number of blocks that have already been obtained by the node as part of the catchup", + "x-algokit-bigint": true + }, + "upgrade-delay": { + "type": "integer", + "description": "Upgrade delay", + "x-go-type": "basics.Round" + }, + "upgrade-node-vote": { + "type": "boolean", + "description": "This node's upgrade vote" + }, + "upgrade-votes-required": { + "type": "integer", + "description": "Yes votes required for consensus upgrade", + "x-go-type": "basics.Round" + }, + "upgrade-votes": { + "type": "integer", + "description": "Total votes cast for consensus upgrade", + "x-go-type": "basics.Round" + }, + "upgrade-yes-votes": { + "type": "integer", + "description": "Yes votes cast for consensus upgrade", + "x-go-type": "basics.Round" + }, + "upgrade-no-votes": { + "type": "integer", + "description": "No votes cast for consensus upgrade", + "x-go-type": "basics.Round" + }, + "upgrade-next-protocol-vote-before": { + "type": "integer", + "description": "Next protocol round", + "x-go-type": "basics.Round" + }, + "upgrade-vote-rounds": { + "type": "integer", + "description": "Total voting rounds for current upgrade", + "x-go-type": "basics.Round" + } + }, + "description": "NodeStatus contains the information about a node status" + } + } + }, + "description": "Returns node status after the specified round is reached" + }, + "400": { + "description": "Bad Request -- number must be non-negative integer", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service Temporarily Unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v2/transactions": { + "post": { + "tags": [ + "public", + "participating" + ], + "summary": "Broadcasts a raw transaction or transaction group to the network.", + "operationId": "RawTransaction", + "requestBody": { + "description": "The byte encoded signed transaction to broadcast to network", + "content": { + "application/x-binary": { + "schema": { + "type": "string", + "format": "binary" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Transaction ID of the submission.", + "content": { + "application/json": { + "schema": { + "required": [ + "txId" + ], + "type": "object", + "properties": { + "txId": { + "type": "string", + "description": "encoding of the transaction hash." + } + } + } + } + } + }, + "400": { + "description": "Bad Request - Malformed Algorand transaction ", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service Temporarily Unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + }, + "x-codegen-request-body-name": "rawtxn" + } + }, + "/v2/transactions/async": { + "post": { + "tags": [ + "public", + "experimental" + ], + "summary": "Fast track for broadcasting a raw transaction or transaction group to the network through the tx handler without performing most of the checks and reporting detailed errors. Should be only used for development and performance testing.", + "operationId": "RawTransactionAsync", + "requestBody": { + "description": "The byte encoded signed transaction to broadcast to network", + "content": { + "application/x-binary": { + "schema": { + "type": "string", + "format": "binary" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": {}, + "description": "Transaction successfully submitted for asynchronous processing" + }, + "400": { + "description": "Bad Request - Malformed Algorand transaction ", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Developer or Experimental API not enabled", + "content": {} + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service Temporarily Unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + }, + "x-codegen-request-body-name": "rawtxn" + } + }, + "/v2/transactions/simulate": { + "post": { + "tags": [ + "public", + "nonparticipating" + ], + "summary": "Simulates a raw transaction or transaction group as it would be evaluated on the network. The simulation will use blockchain state from the latest committed round.", + "operationId": "SimulateTransaction", + "parameters": [ + { + "name": "format", + "in": "query", + "description": "Configures whether the response object is JSON or MessagePack encoded. If not provided, defaults to JSON.", + "schema": { + "type": "string", + "enum": [ + "json", + "msgpack" + ] + } + } + ], + "requestBody": { + "description": "The transactions to simulate, along with any other inputs.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SimulateRequest" + } + }, + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/SimulateRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Result of a transaction group simulation.", + "content": { + "application/json": { + "schema": { + "required": [ + "last-round", + "txn-groups", + "version" + ], + "type": "object", + "properties": { + "version": { + "type": "integer", + "description": "The version of this response object.", + "x-algokit-bigint": true + }, + "last-round": { + "type": "integer", + "description": "The round immediately preceding this simulation. State changes through this round were used to run this simulation.", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + }, + "txn-groups": { + "type": "array", + "description": "A result object for each transaction group that was simulated.", + "items": { + "$ref": "#/components/schemas/SimulateTransactionGroupResult" + } + }, + "eval-overrides": { + "$ref": "#/components/schemas/SimulationEvalOverrides" + }, + "exec-trace-config": { + "$ref": "#/components/schemas/SimulateTraceConfig" + }, + "initial-states": { + "$ref": "#/components/schemas/SimulateInitialStates" + } + } + } + }, + "application/msgpack": { + "schema": { + "required": [ + "last-round", + "txn-groups", + "version" + ], + "type": "object", + "properties": { + "version": { + "type": "integer", + "description": "The version of this response object.", + "x-algokit-bigint": true + }, + "last-round": { + "type": "integer", + "description": "The round immediately preceding this simulation. State changes through this round were used to run this simulation.", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + }, + "txn-groups": { + "type": "array", + "description": "A result object for each transaction group that was simulated.", + "items": { + "$ref": "#/components/schemas/SimulateTransactionGroupResult" + } + }, + "eval-overrides": { + "$ref": "#/components/schemas/SimulationEvalOverrides" + }, + "exec-trace-config": { + "$ref": "#/components/schemas/SimulateTraceConfig" + }, + "initial-states": { + "$ref": "#/components/schemas/SimulateInitialStates" + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + }, + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + }, + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + }, + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service Temporarily Unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + }, + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + }, + "x-codegen-request-body-name": "request" + } + }, + "/v2/transactions/params": { + "get": { + "tags": [ + "public", + "nonparticipating" + ], + "summary": "Get parameters for constructing a new transaction", + "operationId": "TransactionParams", + "responses": { + "200": { + "description": "TransactionParams contains the parameters that help a client construct a new transaction.", + "content": { + "application/json": { + "schema": { + "required": [ + "consensus-version", + "fee", + "genesis-hash", + "genesis-id", + "last-round", + "min-fee" + ], + "type": "object", + "properties": { + "consensus-version": { + "type": "string", + "description": "ConsensusVersion indicates the consensus protocol version\nas of LastRound." + }, + "fee": { + "type": "integer", + "description": "Fee is the suggested transaction fee\nFee is in units of micro-Algos per byte.\nFee may fall to zero but transactions must still have a fee of\nat least MinTxnFee for the current network protocol.", + "x-algokit-bigint": true + }, + "genesis-hash": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "GenesisHash is the hash of the genesis block.", + "format": "byte" + }, + "genesis-id": { + "type": "string", + "description": "GenesisID is an ID listed in the genesis block." + }, + "last-round": { + "type": "integer", + "description": "LastRound indicates the last round seen", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + }, + "min-fee": { + "type": "integer", + "description": "The minimum transaction fee (not per byte) required for the\ntxn to validate for the current network protocol.", + "x-algokit-bigint": true + } + }, + "description": "TransactionParams contains the parameters that help a client construct\na new transaction." + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service Temporarily Unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v2/transactions/pending": { + "get": { + "tags": [ + "public", + "participating" + ], + "summary": "Get a list of unconfirmed transactions currently in the transaction pool.", + "description": "Get the list of pending transactions, sorted by priority, in decreasing order, truncated at the end at MAX. If MAX = 0, returns all pending transactions.\n", + "operationId": "GetPendingTransactions", + "parameters": [ + { + "name": "max", + "in": "query", + "description": "Truncated number of transactions to display. If max=0, returns all pending txns.", + "schema": { + "type": "integer", + "x-algokit-bigint": true + }, + "x-algokit-bigint": true + }, + { + "name": "format", + "in": "query", + "description": "Configures whether the response object is JSON or MessagePack encoded. If not provided, defaults to JSON.", + "schema": { + "type": "string", + "enum": [ + "msgpack" + ], + "default": "msgpack" + } + } + ], + "responses": { + "200": { + "description": "A potentially truncated list of transactions currently in the node's transaction pool. You can compute whether or not the list is truncated if the number of elements in the **top-transactions** array is fewer than **total-transactions**.", + "content": { + "application/msgpack": { + "schema": { + "required": [ + "top-transactions", + "total-transactions" + ], + "type": "object", + "properties": { + "top-transactions": { + "type": "array", + "description": "An array of signed transaction objects.", + "items": { + "type": "object", + "properties": {}, + "x-algokit-signed-txn": true + } + }, + "total-transactions": { + "type": "integer", + "description": "Total number of transactions in the pool." + } + }, + "description": "PendingTransactions is an array of signed transactions exactly as they were submitted." + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service Temporarily Unavailable", + "content": { + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v2/transactions/pending/{txid}": { + "get": { + "tags": [ + "public", + "participating" + ], + "summary": "Get a specific pending transaction.", + "description": "Given a transaction ID of a recently submitted transaction, it returns information about it. There are several cases when this might succeed:\n- transaction committed (committed round > 0)\n- transaction still in the pool (committed round = 0, pool error = \"\")\n- transaction removed from pool due to error (committed round = 0, pool error != \"\")\nOr the transaction may have happened sufficiently long ago that the node no longer remembers it, and this will return an error.\n", + "operationId": "PendingTransactionInformation", + "parameters": [ + { + "name": "txid", + "in": "path", + "description": "A transaction ID", + "required": true, + "schema": { + "pattern": "[A-Z0-9]+", + "type": "string" + } + }, + { + "name": "format", + "in": "query", + "description": "Configures whether the response object is JSON or MessagePack encoded. If not provided, defaults to JSON.", + "schema": { + "type": "string", + "enum": [ + "msgpack" + ], + "default": "msgpack" + } + } + ], + "responses": { + "200": { + "description": "Given a transaction ID of a recently submitted transaction, it returns information about it. There are several cases when this might succeed:\n- transaction committed (committed round > 0)\n- transaction still in the pool (committed round = 0, pool error = \"\")\n- transaction removed from pool due to error (committed round = 0, pool error != \"\")\n\nOr the transaction may have happened sufficiently long ago that the node no longer remembers it, and this will return an error.", + "content": { + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/PendingTransactionResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Transaction Not Found", + "content": { + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v2/deltas/{round}": { + "get": { + "tags": [ + "public", + "nonparticipating" + ], + "summary": "Get a LedgerStateDelta object for a given round", + "description": "Get ledger deltas for a round.", + "operationId": "GetLedgerStateDelta", + "parameters": [ + { + "name": "round", + "in": "path", + "description": "A round number.", + "required": true, + "schema": { + "minimum": 0, + "type": "integer", + "x-go-type": "basics.Round" + }, + "x-go-type": "basics.Round" + }, + { + "name": "format", + "in": "query", + "description": "Configures whether the response object is JSON or MessagePack encoded. If not provided, defaults to JSON.", + "schema": { + "type": "string", + "enum": [ + "msgpack" + ], + "default": "msgpack" + } + } + ], + "responses": { + "200": { + "description": "Contains ledger deltas", + "content": { + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/LedgerStateDelta" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Could not find a delta for round", + "content": { + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "408": { + "description": "timed out on request", + "content": { + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service Temporarily Unavailable", + "content": { + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v2/deltas/{round}/txn/group": { + "get": { + "tags": [ + "public", + "nonparticipating" + ], + "summary": "Get LedgerStateDelta objects for all transaction groups in a given round", + "description": "Get ledger deltas for transaction groups in a given round.", + "operationId": "GetTransactionGroupLedgerStateDeltasForRound", + "parameters": [ + { + "name": "round", + "in": "path", + "description": "A round number.", + "required": true, + "schema": { + "minimum": 0, + "type": "integer", + "x-go-type": "basics.Round" + }, + "x-go-type": "basics.Round" + }, + { + "name": "format", + "in": "query", + "description": "Configures whether the response object is JSON or MessagePack encoded. If not provided, defaults to JSON.", + "schema": { + "type": "string", + "enum": [ + "msgpack" + ], + "default": "msgpack" + } + } + ], + "responses": { + "200": { + "description": "Response containing all ledger state deltas for transaction groups, with their associated Ids, in a single round.", + "content": { + "application/msgpack": { + "schema": { + "required": [ + "Deltas" + ], + "type": "object", + "properties": { + "Deltas": { + "type": "array", + "items": { + "$ref": "#/components/schemas/LedgerStateDeltaForTransactionGroup" + } + } + } + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Could not find deltas for round", + "content": { + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "408": { + "description": "timed out on request", + "content": { + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "501": { + "description": "Not Implemented", + "content": { + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v2/deltas/txn/group/{id}": { + "get": { + "tags": [ + "public", + "nonparticipating" + ], + "summary": "Get a LedgerStateDelta object for a given transaction group", + "description": "Get a ledger delta for a given transaction group.", + "operationId": "GetLedgerStateDeltaForTransactionGroup", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "A transaction ID, or transaction group ID", + "required": true, + "schema": { + "pattern": "[A-Z0-9]+", + "type": "string" + } + }, + { + "name": "format", + "in": "query", + "description": "Configures whether the response object is JSON or MessagePack encoded. If not provided, defaults to JSON.", + "schema": { + "type": "string", + "enum": [ + "msgpack" + ], + "default": "msgpack" + } + } + ], + "responses": { + "200": { + "description": "Response containing a ledger state delta for a single transaction group.", + "content": { + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/LedgerStateDelta" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Could not find a delta for transaction ID or group ID", + "content": { + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "408": { + "description": "timed out on request", + "content": { + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "501": { + "description": "Not Implemented", + "content": { + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v2/stateproofs/{round}": { + "get": { + "tags": [ + "public", + "nonparticipating" + ], + "summary": "Get a state proof that covers a given round", + "operationId": "GetStateProof", + "parameters": [ + { + "name": "round", + "in": "path", + "description": "A round number.", + "required": true, + "schema": { + "minimum": 0, + "type": "integer", + "x-go-type": "basics.Round" + }, + "x-go-type": "basics.Round" + } + ], + "responses": { + "200": { + "description": "StateProofResponse wraps the StateProof type in a response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StateProof" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Could not find a state proof that covers a given round", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "408": { + "description": "timed out on request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service Temporarily Unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v2/blocks/{round}/lightheader/proof": { + "get": { + "tags": [ + "public", + "nonparticipating" + ], + "summary": "Gets a proof for a given light block header inside a state proof commitment", + "operationId": "GetLightBlockHeaderProof", + "parameters": [ + { + "name": "round", + "in": "path", + "description": "A round number.", + "required": true, + "schema": { + "minimum": 0, + "type": "integer", + "x-go-type": "basics.Round" + }, + "x-go-type": "basics.Round" + } + ], + "responses": { + "200": { + "description": "Proof of a light block header.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LightBlockHeaderProof" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Could not create proof since some data is missing", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "408": { + "description": "timed out on request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service Temporarily Unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v2/applications/{application-id}": { + "get": { + "tags": [ + "public", + "nonparticipating" + ], + "summary": "Get application information.", + "description": "Given a application ID, it returns application information including creator, approval and clear programs, global and local schemas, and global state.", + "operationId": "GetApplicationByID", + "parameters": [ + { + "name": "application-id", + "in": "path", + "description": "An application identifier.", + "required": true, + "schema": { + "minimum": 0, + "type": "integer", + "x-go-type": "basics.AppIndex" + }, + "x-go-type": "basics.AppIndex" + } + ], + "responses": { + "200": { + "description": "Application information", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Application" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Application Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v2/applications/{application-id}/boxes": { + "get": { + "tags": [ + "public", + "nonparticipating" + ], + "summary": "Get all box names for a given application.", + "description": "Given an application ID, return all Box names. No particular ordering is guaranteed. Request fails when client or server-side configured limits prevent returning all Box names.", + "operationId": "GetApplicationBoxes", + "parameters": [ + { + "name": "application-id", + "in": "path", + "description": "An application identifier.", + "required": true, + "schema": { + "minimum": 0, + "type": "integer", + "x-go-type": "basics.AppIndex" + }, + "x-go-type": "basics.AppIndex" + }, + { + "name": "max", + "in": "query", + "description": "Max number of box names to return. If max is not set, or max == 0, returns all box-names.", + "schema": { + "type": "integer", + "x-algokit-bigint": true + }, + "x-algokit-bigint": true + } + ], + "responses": { + "200": { + "description": "Box names of an application", + "content": { + "application/json": { + "schema": { + "required": [ + "boxes" + ], + "type": "object", + "properties": { + "boxes": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BoxDescriptor" + } + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v2/applications/{application-id}/box": { + "get": { + "tags": [ + "public", + "nonparticipating" + ], + "summary": "Get box information for a given application.", + "description": "Given an application ID and box name, it returns the round, box name, and value (each base64 encoded). Box names must be in the goal app call arg encoding form 'encoding:value'. For ints, use the form 'int:1234'. For raw bytes, use the form 'b64:A=='. For printable strings, use the form 'str:hello'. For addresses, use the form 'addr:XYZ...'.", + "operationId": "GetApplicationBoxByName", + "parameters": [ + { + "name": "application-id", + "in": "path", + "description": "An application identifier.", + "required": true, + "schema": { + "minimum": 0, + "type": "integer", + "x-go-type": "basics.AppIndex" + }, + "x-go-type": "basics.AppIndex" + }, + { + "name": "name", + "in": "query", + "description": "A box name, in the goal app call arg form 'encoding:value'. For ints, use the form 'int:1234'. For raw bytes, use the form 'b64:A=='. For printable strings, use the form 'str:hello'. For addresses, use the form 'addr:XYZ...'.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Box information", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Box" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Box Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v2/assets/{asset-id}": { + "get": { + "tags": [ + "public", + "nonparticipating" + ], + "summary": "Get asset information.", + "description": "Given a asset ID, it returns asset information including creator, name, total supply and special addresses.", + "operationId": "GetAssetByID", + "parameters": [ + { + "name": "asset-id", + "in": "path", + "description": "An asset identifier.", + "required": true, + "schema": { + "minimum": 0, + "type": "integer", + "x-go-type": "basics.AssetIndex" + }, + "x-go-type": "basics.AssetIndex" + } + ], + "responses": { + "200": { + "description": "Asset information", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Asset" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Application Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v2/ledger/sync": { + "get": { + "tags": [ + "public", + "data" + ], + "summary": "Returns the minimum sync round the ledger is keeping in cache.", + "description": "Gets the minimum sync round for the ledger.", + "operationId": "GetSyncRound", + "responses": { + "200": { + "description": "Response containing the ledger's minimum sync round", + "content": { + "application/json": { + "schema": { + "required": [ + "round" + ], + "type": "object", + "properties": { + "round": { + "type": "integer", + "description": "The minimum sync round for the ledger.", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + } + } + } + } + } + }, + "400": { + "description": "Sync round not set.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service Temporarily Unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + }, + "delete": { + "tags": [ + "public", + "data" + ], + "summary": "Removes minimum sync round restriction from the ledger.", + "description": "Unset the ledger sync round.", + "operationId": "UnsetSyncRound", + "responses": { + "200": { + "content": {}, + "description": "Ledger sync operation stopped successfully" + }, + "400": { + "description": "Sync round not set.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service Temporarily Unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v2/ledger/sync/{round}": { + "post": { + "tags": [ + "public", + "data" + ], + "summary": "Given a round, tells the ledger to keep that round in its cache.", + "description": "Sets the minimum sync round on the ledger.", + "operationId": "SetSyncRound", + "parameters": [ + { + "name": "round", + "in": "path", + "description": "A round number.", + "required": true, + "schema": { + "minimum": 0, + "type": "integer", + "x-go-type": "basics.Round" + }, + "x-go-type": "basics.Round" + } + ], + "responses": { + "200": { + "content": {}, + "description": "Ledger sync to specified round initiated successfully" + }, + "400": { + "description": "Can not set sync round to an earlier round than the current round.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service Temporarily Unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v2/teal/compile": { + "post": { + "tags": [ + "public", + "nonparticipating" + ], + "summary": "Compile TEAL source code to binary, produce its hash", + "description": "Given TEAL source code in plain text, return base64 encoded program bytes and base32 SHA512_256 hash of program bytes (Address style). This endpoint is only enabled when a node's configuration file sets EnableDeveloperAPI to true.", + "operationId": "TealCompile", + "parameters": [ + { + "name": "sourcemap", + "in": "query", + "description": "When set to `true`, returns the source map of the program as a JSON. Defaults to `false`.", + "schema": { + "type": "boolean" + } + } + ], + "requestBody": { + "description": "TEAL source code to be compiled", + "content": { + "text/plain": { + "schema": { + "type": "string", + "format": "binary" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Teal compile Result", + "content": { + "application/json": { + "schema": { + "required": [ + "hash", + "result" + ], + "type": "object", + "properties": { + "hash": { + "type": "string", + "description": "base32 SHA512_256 of program bytes (Address style)" + }, + "result": { + "type": "string", + "description": "base64 encoded program bytes" + }, + "sourcemap": { + "type": "object", + "properties": {}, + "description": "JSON of the source map" + } + } + } + } + } + }, + "400": { + "description": "Bad Request - Teal Compile Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Developer API not enabled", + "content": {} + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + }, + "x-codegen-request-body-name": "source" + } + }, + "/v2/teal/disassemble": { + "post": { + "tags": [ + "public", + "nonparticipating" + ], + "summary": "Disassemble program bytes into the TEAL source code.", + "description": "Given the program bytes, return the TEAL source code in plain text. This endpoint is only enabled when a node's configuration file sets EnableDeveloperAPI to true.", + "operationId": "TealDisassemble", + "requestBody": { + "description": "TEAL program binary to be disassembled", + "content": { + "application/x-binary": { + "schema": { + "type": "string", + "format": "byte" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Teal disassembly Result", + "content": { + "application/json": { + "schema": { + "required": [ + "result" + ], + "type": "object", + "properties": { + "result": { + "type": "string", + "description": "disassembled Teal code" + } + } + } + } + } + }, + "400": { + "description": "Bad Request - Teal Compile Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Developer API not enabled", + "content": {} + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + }, + "x-codegen-request-body-name": "source" + } + }, + "/v2/catchup/{catchpoint}": { + "post": { + "tags": [ + "private", + "nonparticipating" + ], + "summary": "Starts a catchpoint catchup.", + "description": "Given a catchpoint, it starts catching up to this catchpoint", + "operationId": "StartCatchup", + "parameters": [ + { + "name": "catchpoint", + "in": "path", + "description": "A catch point", + "required": true, + "schema": { + "pattern": "[0-9]{1,10}#[A-Z0-9]{1,53}", + "type": "string", + "format": "catchpoint", + "x-algorand-format": "Catchpoint String" + }, + "x-algorand-format": "Catchpoint String" + }, + { + "name": "min", + "in": "query", + "description": "Specify the minimum number of blocks which the ledger must be advanced by in order to start the catchup. This is useful for simplifying tools which support fast catchup, they can run the catchup unconditionally and the node will skip the catchup if it is not needed.", + "schema": { + "type": "integer", + "x-go-type": "basics.Round" + }, + "x-go-type": "basics.Round" + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "required": [ + "catchup-message" + ], + "type": "object", + "properties": { + "catchup-message": { + "type": "string", + "description": "Catchup start response string" + } + }, + "description": "An catchpoint start response." + } + } + }, + "description": "Catchpoint operation started successfully" + }, + "201": { + "content": { + "application/json": { + "schema": { + "required": [ + "catchup-message" + ], + "type": "object", + "properties": { + "catchup-message": { + "type": "string", + "description": "Catchup start response string" + } + }, + "description": "An catchpoint start response." + } + } + }, + "description": "Catchpoint operation created and started successfully" + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "408": { + "description": "Request Timeout", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + }, + "delete": { + "tags": [ + "private", + "nonparticipating" + ], + "summary": "Aborts a catchpoint catchup.", + "description": "Given a catchpoint, it aborts catching up to this catchpoint", + "operationId": "AbortCatchup", + "parameters": [ + { + "name": "catchpoint", + "in": "path", + "description": "A catch point", + "required": true, + "schema": { + "pattern": "[0-9]{1,10}#[A-Z0-9]{1,53}", + "type": "string", + "format": "catchpoint", + "x-algorand-format": "Catchpoint String" + }, + "x-algorand-format": "Catchpoint String" + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "required": [ + "catchup-message" + ], + "type": "object", + "properties": { + "catchup-message": { + "type": "string", + "description": "Catchup abort response string" + } + }, + "description": "An catchpoint abort response." + } + } + }, + "description": "Catchpoint operation aborted successfully" + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v2/teal/dryrun": { + "post": { + "tags": [ + "public", + "nonparticipating" + ], + "summary": "Provide debugging information for a transaction (or group).", + "description": "Executes TEAL program(s) in context and returns debugging information about the execution. This endpoint is only enabled when a node's configuration file sets EnableDeveloperAPI to true.", + "operationId": "TealDryrun", + "requestBody": { + "description": "Transaction (or group) and any accompanying state-simulation data.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DryrunRequest" + } + }, + "application/msgpack": { + "schema": { + "$ref": "#/components/schemas/DryrunRequest" + } + } + }, + "required": false + }, + "responses": { + "200": { + "description": "DryrunResponse contains per-txn debug information from a dryrun.", + "content": { + "application/json": { + "schema": { + "required": [ + "error", + "protocol-version", + "txns" + ], + "type": "object", + "properties": { + "txns": { + "type": "array", + "items": { + "$ref": "#/components/schemas/DryrunTxnResult" + } + }, + "error": { + "type": "string" + }, + "protocol-version": { + "type": "string", + "description": "Protocol version is the protocol version Dryrun was operated under." + } + } + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Developer API not enabled", + "content": {} + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + }, + "x-codegen-request-body-name": "request" + } + }, + "/v2/experimental": { + "get": { + "tags": [ + "public", + "experimental" + ], + "summary": "Returns OK if experimental API is enabled.", + "operationId": "ExperimentalCheck", + "responses": { + "200": { + "description": "Experimental API enabled", + "content": {} + }, + "404": { + "description": "Experimental API not enabled", + "content": {} + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v2/devmode/blocks/offset": { + "get": { + "tags": [ + "public", + "nonparticipating" + ], + "summary": "Returns the timestamp offset. Timestamp offsets can only be set in dev mode.", + "description": "Gets the current timestamp offset.", + "operationId": "GetBlockTimeStampOffset", + "responses": { + "200": { + "description": "Response containing the timestamp offset in seconds", + "content": { + "application/json": { + "schema": { + "required": [ + "offset" + ], + "type": "object", + "properties": { + "offset": { + "type": "integer", + "description": "Timestamp offset in seconds.", + "x-algokit-bigint": true + } + } + } + } + } + }, + "400": { + "description": "TimeStamp offset not set.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v2/devmode/blocks/offset/{offset}": { + "post": { + "tags": [ + "public", + "nonparticipating" + ], + "summary": "Given a timestamp offset in seconds, adds the offset to every subsequent block header's timestamp.", + "description": "Sets the timestamp offset (seconds) for blocks in dev mode. Providing an offset of 0 will unset this value and try to use the real clock for the timestamp.", + "operationId": "SetBlockTimeStampOffset", + "parameters": [ + { + "name": "offset", + "in": "path", + "description": "The timestamp offset for blocks in dev mode.", + "required": true, + "schema": { + "minimum": 0, + "type": "integer", + "x-algokit-bigint": true + }, + "x-algokit-bigint": true + } + ], + "responses": { + "200": { + "description": "OK", + "content": {} + }, + "400": { + "description": "Cannot set timestamp offset to a negative integer.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Invalid API Token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + } + }, + "components": { + "schemas": { + "GenesisAllocation": { + "title": "Allocations for Genesis File", + "required": [ + "addr", + "comment", + "state" + ], + "type": "object", + "properties": { + "addr": { + "type": "string" + }, + "comment": { + "type": "string" + }, + "state": { + "required": [ + "algo", + "onl" + ], + "type": "object", + "properties": { + "algo": { + "type": "integer", + "format": "uint64", + "x-algokit-bigint": true + }, + "onl": { + "type": "integer" + }, + "sel": { + "type": "string" + }, + "stprf": { + "type": "string" + }, + "vote": { + "type": "string" + }, + "voteKD": { + "type": "integer", + "format": "uint64", + "x-algokit-bigint": true + }, + "voteFst": { + "type": "integer", + "format": "uint64", + "x-algokit-bigint": true + }, + "voteLst": { + "type": "integer", + "format": "uint64", + "x-algokit-bigint": true + } + } + } + } + }, + "Genesis": { + "title": "Genesis File in JSON", + "required": [ + "alloc", + "fees", + "id", + "network", + "proto", + "rwd", + "timestamp" + ], + "type": "object", + "properties": { + "alloc": { + "type": "array", + "items": { + "$ref": "#/components/schemas/GenesisAllocation" + } + }, + "comment": { + "type": "string" + }, + "devmode": { + "type": "boolean" + }, + "fees": { + "type": "string" + }, + "id": { + "type": "string" + }, + "network": { + "type": "string" + }, + "proto": { + "type": "string" + }, + "rwd": { + "type": "string" + }, + "timestamp": { + "type": "integer", + "format": "int64" + } + } + }, + "LedgerStateDelta": { + "type": "object", + "description": "Ledger StateDelta object", + "x-algorand-format": "StateDelta" + }, + "LedgerStateDeltaForTransactionGroup": { + "required": [ + "Delta", + "Ids" + ], + "type": "object", + "properties": { + "Delta": { + "$ref": "#/components/schemas/LedgerStateDelta" + }, + "Ids": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "description": "Contains a ledger delta for a single transaction group" + }, + "Account": { + "required": [ + "address", + "amount", + "amount-without-pending-rewards", + "min-balance", + "pending-rewards", + "rewards", + "round", + "status", + "total-apps-opted-in", + "total-assets-opted-in", + "total-created-apps", + "total-created-assets" + ], + "type": "object", + "properties": { + "address": { + "type": "string", + "description": "the account public key" + }, + "amount": { + "type": "integer", + "description": "\\[algo\\] total number of MicroAlgos in the account", + "format": "uint64", + "x-algokit-bigint": true + }, + "min-balance": { + "type": "integer", + "description": "MicroAlgo balance required by the account.\n\nThe requirement grows based on asset and application usage.", + "format": "uint64", + "x-algokit-bigint": true + }, + "amount-without-pending-rewards": { + "type": "integer", + "description": "specifies the amount of MicroAlgos in the account, without the pending rewards.", + "format": "uint64", + "x-algokit-bigint": true + }, + "apps-local-state": { + "type": "array", + "description": "\\[appl\\] applications local data stored in this account.\n\nNote the raw object uses `map[int] -> AppLocalState` for this type.", + "items": { + "$ref": "#/components/schemas/ApplicationLocalState" + } + }, + "total-apps-opted-in": { + "type": "integer", + "description": "The count of all applications that have been opted in, equivalent to the count of application local data (AppLocalState objects) stored in this account.", + "format": "uint64", + "x-algokit-bigint": true + }, + "apps-total-schema": { + "$ref": "#/components/schemas/ApplicationStateSchema" + }, + "apps-total-extra-pages": { + "type": "integer", + "description": "\\[teap\\] the sum of all extra application program pages for this account.", + "format": "uint64", + "x-algokit-bigint": true + }, + "assets": { + "type": "array", + "description": "\\[asset\\] assets held by this account.\n\nNote the raw object uses `map[int] -> AssetHolding` for this type.", + "items": { + "$ref": "#/components/schemas/AssetHolding" + } + }, + "total-assets-opted-in": { + "type": "integer", + "description": "The count of all assets that have been opted in, equivalent to the count of AssetHolding objects held by this account.", + "format": "uint64", + "x-algokit-bigint": true + }, + "created-apps": { + "type": "array", + "description": "\\[appp\\] parameters of applications created by this account including app global data.\n\nNote: the raw account uses `map[int] -> AppParams` for this type.", + "items": { + "$ref": "#/components/schemas/Application" + } + }, + "total-created-apps": { + "type": "integer", + "description": "The count of all apps (AppParams objects) created by this account.", + "format": "uint64", + "x-algokit-bigint": true + }, + "created-assets": { + "type": "array", + "description": "\\[apar\\] parameters of assets created by this account.\n\nNote: the raw account uses `map[int] -> Asset` for this type.", + "items": { + "$ref": "#/components/schemas/Asset" + } + }, + "total-created-assets": { + "type": "integer", + "description": "The count of all assets (AssetParams objects) created by this account.", + "format": "uint64", + "x-algokit-bigint": true + }, + "total-boxes": { + "type": "integer", + "description": "\\[tbx\\] The number of existing boxes created by this account's app.", + "format": "uint64", + "x-algokit-bigint": true + }, + "total-box-bytes": { + "type": "integer", + "description": "\\[tbxb\\] The total number of bytes used by this account's app's box keys and values.", + "format": "uint64", + "x-algokit-bigint": true + }, + "participation": { + "$ref": "#/components/schemas/AccountParticipation" + }, + "incentive-eligible": { + "type": "boolean", + "description": "Whether or not the account can receive block incentives if its balance is in range at proposal time." + }, + "pending-rewards": { + "type": "integer", + "description": "amount of MicroAlgos of pending rewards in this account.", + "format": "uint64", + "x-algokit-bigint": true + }, + "reward-base": { + "type": "integer", + "description": "\\[ebase\\] used as part of the rewards computation. Only applicable to accounts which are participating.", + "format": "uint64", + "x-algokit-bigint": true + }, + "rewards": { + "type": "integer", + "description": "\\[ern\\] total rewards of MicroAlgos the account has received, including pending rewards.", + "format": "uint64", + "x-algokit-bigint": true + }, + "round": { + "type": "integer", + "description": "The round for which this information is relevant.", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + }, + "status": { + "type": "string", + "description": "\\[onl\\] delegation status of the account's MicroAlgos\n* Offline - indicates that the associated account is delegated.\n* Online - indicates that the associated account used as part of the delegation pool.\n* NotParticipating - indicates that the associated account is neither a delegator nor a delegate." + }, + "sig-type": { + "type": "string", + "description": "Indicates what type of signature is used by this account, must be one of:\n* sig\n* msig\n* lsig", + "enum": [ + "sig", + "msig", + "lsig" + ] + }, + "auth-addr": { + "type": "string", + "description": "\\[spend\\] the address against which signing should be checked. If empty, the address of the current account is used. This field can be updated in any transaction by setting the RekeyTo field.", + "x-algorand-format": "Address" + }, + "last-proposed": { + "type": "integer", + "description": "The round in which this account last proposed the block.", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + }, + "last-heartbeat": { + "type": "integer", + "description": "The round in which this account last went online, or explicitly renewed their online status.", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + } + }, + "description": "Account information at a given round.\n\nDefinition:\ndata/basics/userBalance.go : AccountData\n" + }, + "AccountAssetHolding": { + "required": [ + "asset-holding" + ], + "type": "object", + "properties": { + "asset-holding": { + "$ref": "#/components/schemas/AssetHolding" + }, + "asset-params": { + "$ref": "#/components/schemas/AssetParams" + } + }, + "description": "AccountAssetHolding describes the account's asset holding and asset parameters (if either exist) for a specific asset ID." + }, + "AccountParticipation": { + "required": [ + "selection-participation-key", + "vote-first-valid", + "vote-key-dilution", + "vote-last-valid", + "vote-participation-key" + ], + "type": "object", + "properties": { + "selection-participation-key": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[sel\\] Selection public key (if any) currently registered for this round.", + "format": "byte" + }, + "vote-first-valid": { + "type": "integer", + "description": "\\[voteFst\\] First round for which this participation is valid.", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + }, + "vote-key-dilution": { + "type": "integer", + "description": "\\[voteKD\\] Number of subkeys in each batch of participation keys.", + "x-algokit-bigint": true + }, + "vote-last-valid": { + "type": "integer", + "description": "\\[voteLst\\] Last round for which this participation is valid.", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + }, + "vote-participation-key": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[vote\\] root participation public key (if any) currently registered for this round.", + "format": "byte" + }, + "state-proof-key": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[stprf\\] Root of the state proof key (if any)", + "format": "byte" + } + }, + "description": "AccountParticipation describes the parameters used by this account in consensus protocol." + }, + "Asset": { + "required": [ + "index", + "params" + ], + "type": "object", + "properties": { + "index": { + "type": "integer", + "description": "unique asset identifier", + "x-go-type": "basics.AssetIndex", + "x-algokit-bigint": true + }, + "params": { + "$ref": "#/components/schemas/AssetParams" + } + }, + "description": "Specifies both the unique identifier and the parameters for an asset" + }, + "AssetHolding": { + "required": [ + "amount", + "asset-id", + "is-frozen" + ], + "type": "object", + "properties": { + "amount": { + "type": "integer", + "description": "\\[a\\] number of units held.", + "format": "uint64", + "x-algokit-bigint": true + }, + "asset-id": { + "type": "integer", + "description": "Asset ID of the holding.", + "x-go-name": "AssetID", + "x-go-type": "basics.AssetIndex", + "x-algokit-bigint": true + }, + "is-frozen": { + "type": "boolean", + "description": "\\[f\\] whether or not the holding is frozen." + } + }, + "description": "Describes an asset held by an account.\n\nDefinition:\ndata/basics/userBalance.go : AssetHolding" + }, + "AssetParams": { + "required": [ + "creator", + "decimals", + "total" + ], + "type": "object", + "properties": { + "clawback": { + "type": "string", + "description": "\\[c\\] Address of account used to clawback holdings of this asset. If empty, clawback is not permitted." + }, + "creator": { + "type": "string", + "description": "The address that created this 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 in the worst case." + }, + "decimals": { + "maximum": 19, + "minimum": 0, + "type": "integer", + "description": "\\[dc\\] The number of digits to use after the decimal point when displaying this asset. 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, and so on. This value must be between 0 and 19 (inclusive).", + "format": "uint64", + "x-algokit-bigint": true + }, + "default-frozen": { + "type": "boolean", + "description": "\\[df\\] Whether holdings of this asset are frozen by default." + }, + "freeze": { + "type": "string", + "description": "\\[f\\] Address of account used to freeze holdings of this asset. If empty, freezing is not permitted." + }, + "manager": { + "type": "string", + "description": "\\[m\\] Address of account used to manage the keys of this asset and to destroy it." + }, + "metadata-hash": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[am\\] A commitment to some unspecified asset metadata. The format of this metadata is up to the application.", + "format": "byte" + }, + "name": { + "type": "string", + "description": "\\[an\\] Name of this asset, as supplied by the creator. Included only when the asset name is composed of printable utf-8 characters." + }, + "name-b64": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "Base64 encoded name of this asset, as supplied by the creator.", + "format": "byte" + }, + "reserve": { + "type": "string", + "description": "\\[r\\] Address of account holding reserve (non-minted) units of this asset." + }, + "total": { + "type": "integer", + "description": "\\[t\\] The total number of units of this asset.", + "format": "uint64", + "x-algokit-bigint": true + }, + "unit-name": { + "type": "string", + "description": "\\[un\\] Name of a unit of this asset, as supplied by the creator. Included only when the name of a unit of this asset is composed of printable utf-8 characters." + }, + "unit-name-b64": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "Base64 encoded name of a unit of this asset, as supplied by the creator.", + "format": "byte" + }, + "url": { + "type": "string", + "description": "\\[au\\] URL where more information about the asset can be retrieved. Included only when the URL is composed of printable utf-8 characters." + }, + "url-b64": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "Base64 encoded URL where more information about the asset can be retrieved.", + "format": "byte" + } + }, + "description": "AssetParams specifies the parameters for an asset.\n\n\\[apar\\] when part of an AssetConfig transaction.\n\nDefinition:\ndata/transactions/asset.go : AssetParams" + }, + "AssetHoldingReference": { + "required": [ + "account", + "asset" + ], + "type": "object", + "properties": { + "account": { + "type": "string", + "description": "Address of the account holding the asset.", + "x-algorand-format": "Address" + }, + "asset": { + "type": "integer", + "description": "Asset ID of the holding.", + "x-go-type": "basics.AssetIndex", + "x-algokit-bigint": true + } + }, + "description": "References an asset held by an account." + }, + "ApplicationLocalReference": { + "required": [ + "account", + "app" + ], + "type": "object", + "properties": { + "account": { + "type": "string", + "description": "Address of the account with the local state.", + "x-algorand-format": "Address" + }, + "app": { + "type": "integer", + "description": "Application ID of the local state application.", + "x-go-type": "basics.AppIndex", + "x-algokit-bigint": true + } + }, + "description": "References an account's local state for an application." + }, + "ApplicationStateSchema": { + "required": [ + "num-byte-slice", + "num-uint" + ], + "type": "object", + "properties": { + "num-uint": { + "type": "integer", + "description": "\\[nui\\] num of uints.", + "minimum": 0, + "maximum": 64 + }, + "num-byte-slice": { + "type": "integer", + "description": "\\[nbs\\] num of byte slices.", + "minimum": 0, + "maximum": 64 + } + }, + "description": "Specifies maximums on the number of each type that may be stored." + }, + "ApplicationLocalState": { + "required": [ + "id", + "schema" + ], + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The application which this local state is for.", + "x-go-type": "basics.AppIndex", + "x-algokit-bigint": true + }, + "schema": { + "$ref": "#/components/schemas/ApplicationStateSchema" + }, + "key-value": { + "$ref": "#/components/schemas/TealKeyValueStore" + } + }, + "description": "Stores local state associated with an application." + }, + "ParticipationKey": { + "required": [ + "address", + "id", + "key" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The key's ParticipationID." + }, + "address": { + "type": "string", + "description": "Address the key was generated for.", + "x-algorand-format": "Address" + }, + "effective-first-valid": { + "type": "integer", + "description": "When registered, this is the first round it may be used.", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + }, + "effective-last-valid": { + "type": "integer", + "description": "When registered, this is the last round it may be used.", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + }, + "last-vote": { + "type": "integer", + "description": "Round when this key was last used to vote.", + "x-go-type": "basics.Round" + }, + "last-block-proposal": { + "type": "integer", + "description": "Round when this key was last used to propose a block.", + "x-go-type": "basics.Round" + }, + "last-state-proof": { + "type": "integer", + "description": "Round when this key was last used to generate a state proof.", + "x-go-type": "basics.Round" + }, + "key": { + "$ref": "#/components/schemas/AccountParticipation" + } + }, + "description": "Represents a participation key used by the node." + }, + "TealKeyValueStore": { + "type": "array", + "description": "Represents a key-value store for use in an application.", + "items": { + "$ref": "#/components/schemas/TealKeyValue" + } + }, + "TealKeyValue": { + "required": [ + "key", + "value" + ], + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "value": { + "$ref": "#/components/schemas/TealValue" + } + }, + "description": "Represents a key-value pair in an application store." + }, + "TealValue": { + "required": [ + "bytes", + "type", + "uint" + ], + "type": "object", + "properties": { + "type": { + "type": "integer", + "description": "\\[tt\\] value type. Value `1` refers to **bytes**, value `2` refers to **uint**", + "x-algokit-bigint": true + }, + "bytes": { + "type": "string", + "description": "\\[tb\\] bytes value.", + "x-algokit-bytes-base64": true + }, + "uint": { + "type": "integer", + "description": "\\[ui\\] uint value.", + "format": "uint64", + "x-algokit-bigint": true + } + }, + "description": "Represents a TEAL value." + }, + "AvmValue": { + "required": [ + "type" + ], + "type": "object", + "properties": { + "type": { + "type": "integer", + "description": "value type. Value `1` refers to **bytes**, value `2` refers to **uint64**", + "x-algokit-bigint": true + }, + "bytes": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "bytes value." + }, + "uint": { + "type": "integer", + "description": "uint value.", + "format": "uint64", + "x-algokit-bigint": true + } + }, + "description": "Represents an AVM value." + }, + "AvmKeyValue": { + "required": [ + "key", + "value" + ], + "type": "object", + "properties": { + "key": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "format": "byte" + }, + "value": { + "$ref": "#/components/schemas/AvmValue" + } + }, + "description": "Represents an AVM key-value pair in an application store." + }, + "StateDelta": { + "type": "array", + "description": "Application state delta.", + "items": { + "$ref": "#/components/schemas/EvalDeltaKeyValue" + } + }, + "AccountStateDelta": { + "required": [ + "address", + "delta" + ], + "type": "object", + "properties": { + "address": { + "type": "string" + }, + "delta": { + "$ref": "#/components/schemas/StateDelta" + } + }, + "description": "Application state delta." + }, + "EvalDeltaKeyValue": { + "required": [ + "key", + "value" + ], + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "value": { + "$ref": "#/components/schemas/EvalDelta" + } + }, + "description": "Key-value pairs for StateDelta." + }, + "EvalDelta": { + "required": [ + "action" + ], + "type": "object", + "properties": { + "action": { + "type": "integer", + "description": "\\[at\\] delta action." + }, + "bytes": { + "type": "string", + "description": "\\[bs\\] bytes value." + }, + "uint": { + "type": "integer", + "description": "\\[ui\\] uint value.", + "format": "uint64", + "x-algokit-bigint": true + } + }, + "description": "Represents a TEAL value delta." + }, + "Application": { + "required": [ + "id", + "params" + ], + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "\\[appidx\\] application index.", + "x-go-type": "basics.AppIndex", + "x-algokit-bigint": true + }, + "params": { + "$ref": "#/components/schemas/ApplicationParams" + } + }, + "description": "Application index and its parameters" + }, + "ApplicationParams": { + "required": [ + "approval-program", + "clear-state-program", + "creator" + ], + "type": "object", + "properties": { + "creator": { + "type": "string", + "description": "The address that created this application. This is the address where the parameters and global state for this application can be found.", + "x-algorand-format": "Address" + }, + "approval-program": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[approv\\] approval program.", + "format": "byte", + "x-algorand-format": "TEALProgram" + }, + "clear-state-program": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[clearp\\] approval program.", + "format": "byte", + "x-algorand-format": "TEALProgram" + }, + "extra-program-pages": { + "type": "integer", + "description": "\\[epp\\] the amount of extra program pages available to this app.", + "minimum": 0, + "maximum": 3 + }, + "local-state-schema": { + "$ref": "#/components/schemas/ApplicationStateSchema" + }, + "global-state-schema": { + "$ref": "#/components/schemas/ApplicationStateSchema" + }, + "global-state": { + "$ref": "#/components/schemas/TealKeyValueStore" + }, + "version": { + "type": "integer", + "description": "\\[v\\] the number of updates to the application programs", + "x-algokit-bigint": true + } + }, + "description": "Stores the global information associated with an application." + }, + "DryrunState": { + "required": [ + "line", + "pc", + "stack" + ], + "type": "object", + "properties": { + "line": { + "type": "integer", + "description": "Line number" + }, + "pc": { + "type": "integer", + "description": "Program counter" + }, + "stack": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TealValue" + } + }, + "scratch": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TealValue" + } + }, + "error": { + "type": "string", + "description": "Evaluation error if any" + } + }, + "description": "Stores the TEAL eval step data" + }, + "DryrunTxnResult": { + "required": [ + "disassembly" + ], + "type": "object", + "properties": { + "disassembly": { + "type": "array", + "description": "Disassembled program line by line.", + "items": { + "type": "string" + } + }, + "logic-sig-disassembly": { + "type": "array", + "description": "Disassembled lsig program line by line.", + "items": { + "type": "string" + } + }, + "logic-sig-trace": { + "type": "array", + "items": { + "$ref": "#/components/schemas/DryrunState" + } + }, + "logic-sig-messages": { + "type": "array", + "items": { + "type": "string" + } + }, + "app-call-trace": { + "type": "array", + "items": { + "$ref": "#/components/schemas/DryrunState" + } + }, + "app-call-messages": { + "type": "array", + "items": { + "type": "string" + } + }, + "global-delta": { + "$ref": "#/components/schemas/StateDelta" + }, + "local-deltas": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AccountStateDelta" + } + }, + "logs": { + "type": "array", + "items": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "format": "byte" + } + }, + "budget-added": { + "type": "integer", + "description": "Budget added during execution of app call transaction." + }, + "budget-consumed": { + "type": "integer", + "description": "Budget consumed during execution of app call transaction." + } + }, + "description": "DryrunTxnResult contains any LogicSig or ApplicationCall program debug information and state updates from a dryrun." + }, + "ErrorResponse": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + }, + "description": "An error response with optional data field." + }, + "DryrunRequest": { + "required": [ + "accounts", + "apps", + "latest-timestamp", + "protocol-version", + "round", + "sources", + "txns" + ], + "type": "object", + "properties": { + "txns": { + "type": "array", + "items": { + "type": "string", + "description": "SignedTxn object. Must be canonically encoded.", + "format": "json", + "x-algokit-signed-txn": true + } + }, + "accounts": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Account" + } + }, + "apps": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Application" + } + }, + "protocol-version": { + "type": "string", + "description": "ProtocolVersion specifies a specific version string to operate under, otherwise whatever the current protocol of the network this algod is running in." + }, + "round": { + "type": "integer", + "description": "Round is available to some TEAL scripts. Defaults to the current round on the network this algod is attached to.", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + }, + "latest-timestamp": { + "minimum": 0, + "type": "integer", + "description": "LatestTimestamp is available to some TEAL scripts. Defaults to the latest confirmed timestamp this algod is attached to.", + "x-go-type": "int64" + }, + "sources": { + "type": "array", + "items": { + "$ref": "#/components/schemas/DryrunSource" + } + } + }, + "description": "Request data type for dryrun endpoint. Given the Transactions and simulated ledger state upload, run TEAL scripts and return debugging information." + }, + "DryrunSource": { + "required": [ + "app-index", + "field-name", + "source", + "txn-index" + ], + "type": "object", + "properties": { + "field-name": { + "type": "string", + "description": "FieldName is what kind of sources this is. If lsig then it goes into the transactions[this.TxnIndex].LogicSig. If approv or clearp it goes into the Approval Program or Clear State Program of application[this.AppIndex]." + }, + "source": { + "type": "string" + }, + "txn-index": { + "type": "integer", + "x-algokit-bigint": true + }, + "app-index": { + "type": "integer", + "x-go-type": "basics.AppIndex", + "x-algokit-bigint": true + } + }, + "description": "DryrunSource is TEAL source text that gets uploaded, compiled, and inserted into transactions or application state." + }, + "SimulateRequest": { + "required": [ + "txn-groups" + ], + "type": "object", + "properties": { + "txn-groups": { + "type": "array", + "description": "The transaction groups to simulate.", + "items": { + "$ref": "#/components/schemas/SimulateRequestTransactionGroup" + } + }, + "round": { + "type": "integer", + "description": "If provided, specifies the round preceding the simulation. State changes through this round will be used to run this simulation. Usually only the 4 most recent rounds will be available (controlled by the node config value MaxAcctLookback). If not specified, defaults to the latest available round.", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + }, + "allow-empty-signatures": { + "type": "boolean", + "description": "Allows transactions without signatures to be simulated as if they had correct signatures." + }, + "allow-more-logging": { + "type": "boolean", + "description": "Lifts limits on log opcode usage during simulation." + }, + "allow-unnamed-resources": { + "type": "boolean", + "description": "Allows access to unnamed resources during simulation." + }, + "extra-opcode-budget": { + "type": "integer", + "description": "Applies extra opcode budget during simulation for each transaction group." + }, + "exec-trace-config": { + "$ref": "#/components/schemas/SimulateTraceConfig" + }, + "fix-signers": { + "type": "boolean", + "description": "If true, signers for transactions that are missing signatures will be fixed during evaluation." + } + }, + "description": "Request type for simulation endpoint." + }, + "SimulateRequestTransactionGroup": { + "required": [ + "txns" + ], + "type": "object", + "properties": { + "txns": { + "type": "array", + "description": "An atomic transaction group.", + "items": { + "type": "string", + "description": "SignedTxn object. Must be canonically encoded.", + "format": "json", + "x-algokit-signed-txn": true + } + } + }, + "description": "A transaction group to simulate." + }, + "SimulateTraceConfig": { + "type": "object", + "properties": { + "enable": { + "type": "boolean", + "description": "A boolean option for opting in execution trace features simulation endpoint." + }, + "stack-change": { + "type": "boolean", + "description": "A boolean option enabling returning stack changes together with execution trace during simulation." + }, + "scratch-change": { + "type": "boolean", + "description": "A boolean option enabling returning scratch slot changes together with execution trace during simulation." + }, + "state-change": { + "type": "boolean", + "description": "A boolean option enabling returning application state changes (global, local, and box changes) with the execution trace during simulation." + } + }, + "description": "An object that configures simulation execution trace." + }, + "Box": { + "required": [ + "name", + "round", + "value" + ], + "type": "object", + "properties": { + "round": { + "type": "integer", + "description": "The round for which this information is relevant", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + }, + "name": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "The box name, base64 encoded", + "format": "byte" + }, + "value": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "The box value, base64 encoded.", + "format": "byte" + } + }, + "description": "Box name and its content." + }, + "BoxDescriptor": { + "required": [ + "name" + ], + "type": "object", + "properties": { + "name": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "Base64 encoded box name", + "format": "byte" + } + }, + "description": "Box descriptor describes a Box." + }, + "BoxReference": { + "required": [ + "app", + "name" + ], + "type": "object", + "properties": { + "app": { + "type": "integer", + "description": "Application ID which this box belongs to", + "x-go-type": "basics.AppIndex" + }, + "name": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "Base64 encoded box name", + "format": "byte" + } + }, + "description": "References a box of an application." + }, + "Version": { + "title": "Version contains the current algod version.", + "required": [ + "build", + "genesis_hash_b64", + "genesis_id", + "versions" + ], + "type": "object", + "properties": { + "build": { + "$ref": "#/components/schemas/BuildVersion" + }, + "genesis_hash_b64": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "format": "byte" + }, + "genesis_id": { + "type": "string" + }, + "versions": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "description": "algod version information." + }, + "DebugSettingsProf": { + "title": "algod mutex and blocking profiling state.", + "type": "object", + "properties": { + "block-rate": { + "type": "integer", + "description": "The rate of blocking events. The profiler aims to sample an average of one blocking event per rate nanoseconds spent blocked. To turn off profiling entirely, pass rate 0.", + "format": "uint64", + "example": 1000, + "x-algokit-bigint": true + }, + "mutex-rate": { + "type": "integer", + "description": "The rate of mutex events. On average 1/rate events are reported. To turn off profiling entirely, pass rate 0", + "format": "uint64", + "example": 1000, + "x-algokit-bigint": true + } + }, + "description": "algod mutex and blocking profiling state." + }, + "BuildVersion": { + "title": "BuildVersion contains the current algod build version information.", + "required": [ + "branch", + "build_number", + "channel", + "commit_hash", + "major", + "minor" + ], + "type": "object", + "properties": { + "branch": { + "type": "string" + }, + "build_number": { + "type": "integer" + }, + "channel": { + "type": "string" + }, + "commit_hash": { + "type": "string" + }, + "major": { + "type": "integer" + }, + "minor": { + "type": "integer" + } + } + }, + "PendingTransactionResponse": { + "required": [ + "pool-error", + "txn" + ], + "type": "object", + "properties": { + "asset-index": { + "type": "integer", + "description": "The asset index if the transaction was found and it created an asset.", + "x-go-type": "basics.AssetIndex", + "x-algokit-field-rename": "asset_id", + "x-algokit-bigint": true + }, + "application-index": { + "type": "integer", + "description": "The application index if the transaction was found and it created an application.", + "x-go-type": "basics.AppIndex", + "x-algokit-field-rename": "app_id", + "x-algokit-bigint": true + }, + "close-rewards": { + "type": "integer", + "description": "Rewards in microalgos applied to the close remainder to account." + }, + "closing-amount": { + "type": "integer", + "description": "Closing amount for the transaction.", + "x-algokit-bigint": true + }, + "asset-closing-amount": { + "type": "integer", + "description": "The number of the asset's unit that were transferred to the close-to address.", + "x-algokit-bigint": true + }, + "confirmed-round": { + "type": "integer", + "description": "The round where this transaction was confirmed, if present.", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + }, + "pool-error": { + "type": "string", + "description": "Indicates that the transaction was kicked out of this node's transaction pool (and specifies why that happened). An empty string indicates the transaction wasn't kicked out of this node's txpool due to an error.\n" + }, + "receiver-rewards": { + "type": "integer", + "description": "Rewards in microalgos applied to the receiver account.", + "x-algokit-bigint": true + }, + "sender-rewards": { + "type": "integer", + "description": "Rewards in microalgos applied to the sender account.", + "x-algokit-bigint": true + }, + "local-state-delta": { + "type": "array", + "description": "Local state key/value changes for the application being executed by this transaction.", + "items": { + "$ref": "#/components/schemas/AccountStateDelta" + } + }, + "global-state-delta": { + "$ref": "#/components/schemas/StateDelta" + }, + "logs": { + "type": "array", + "description": "Logs for the application being executed by this transaction.", + "items": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "format": "byte" + } + }, + "inner-txns": { + "type": "array", + "description": "Inner transactions produced by application execution.", + "items": { + "$ref": "#/components/schemas/PendingTransactionResponse" + } + }, + "txn": { + "type": "object", + "properties": {}, + "description": "The raw signed transaction.", + "x-algokit-signed-txn": true + } + }, + "description": "Details about a pending transaction. If the transaction was recently confirmed, includes confirmation details like the round and reward details." + }, + "SimulateTransactionGroupResult": { + "required": [ + "txn-results" + ], + "type": "object", + "properties": { + "txn-results": { + "type": "array", + "description": "Simulation result for individual transactions", + "items": { + "$ref": "#/components/schemas/SimulateTransactionResult" + } + }, + "failure-message": { + "type": "string", + "description": "If present, indicates that the transaction group failed and specifies why that happened" + }, + "failed-at": { + "type": "array", + "description": "If present, indicates which transaction in this group caused the failure. This array represents the path to the failing transaction. Indexes are zero based, the first element indicates the top-level transaction, and successive elements indicate deeper inner transactions.", + "items": { + "type": "integer" + } + }, + "app-budget-added": { + "type": "integer", + "description": "Total budget added during execution of app calls in the transaction group." + }, + "app-budget-consumed": { + "type": "integer", + "description": "Total budget consumed during execution of app calls in the transaction group." + }, + "unnamed-resources-accessed": { + "$ref": "#/components/schemas/SimulateUnnamedResourcesAccessed" + } + }, + "description": "Simulation result for an atomic transaction group" + }, + "SimulateTransactionResult": { + "required": [ + "txn-result" + ], + "type": "object", + "properties": { + "txn-result": { + "$ref": "#/components/schemas/PendingTransactionResponse" + }, + "app-budget-consumed": { + "type": "integer", + "description": "Budget used during execution of an app call transaction. This value includes budged used by inner app calls spawned by this transaction." + }, + "logic-sig-budget-consumed": { + "type": "integer", + "description": "Budget used during execution of a logic sig transaction." + }, + "exec-trace": { + "$ref": "#/components/schemas/SimulationTransactionExecTrace" + }, + "unnamed-resources-accessed": { + "$ref": "#/components/schemas/SimulateUnnamedResourcesAccessed" + }, + "fixed-signer": { + "type": "string", + "description": "The account that needed to sign this transaction when no signature was provided and the provided signer was incorrect.", + "x-algorand-format": "Address" + } + }, + "description": "Simulation result for an individual transaction" + }, + "StateProof": { + "required": [ + "Message", + "StateProof" + ], + "type": "object", + "properties": { + "Message": { + "$ref": "#/components/schemas/StateProofMessage" + }, + "StateProof": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "The encoded StateProof for the message.", + "format": "byte" + } + }, + "description": "Represents a state proof and its corresponding message" + }, + "LightBlockHeaderProof": { + "required": [ + "index", + "proof", + "treedepth" + ], + "type": "object", + "properties": { + "index": { + "type": "integer", + "description": "The index of the light block header in the vector commitment tree", + "x-algokit-bigint": true + }, + "treedepth": { + "type": "integer", + "description": "Represents the depth of the tree that is being proven, i.e. the number of edges from a leaf to the root." + }, + "proof": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "The encoded proof.", + "format": "byte" + } + }, + "description": "Proof of membership and position of a light block header." + }, + "StateProofMessage": { + "required": [ + "BlockHeadersCommitment", + "FirstAttestedRound", + "LastAttestedRound", + "LnProvenWeight", + "VotersCommitment" + ], + "type": "object", + "properties": { + "BlockHeadersCommitment": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "The vector commitment root on all light block headers within a state proof interval.", + "format": "byte" + }, + "VotersCommitment": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "The vector commitment root of the top N accounts to sign the next StateProof.", + "format": "byte" + }, + "LnProvenWeight": { + "type": "integer", + "description": "An integer value representing the natural log of the proven weight with 16 bits of precision. This value would be used to verify the next state proof.", + "format": "uint64", + "x-algokit-bigint": true + }, + "FirstAttestedRound": { + "type": "integer", + "description": "The first round the message attests to.", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + }, + "LastAttestedRound": { + "type": "integer", + "description": "The last round the message attests to.", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + } + }, + "description": "Represents the message that the state proofs are attesting to." + }, + "SimulationEvalOverrides": { + "type": "object", + "properties": { + "allow-empty-signatures": { + "type": "boolean", + "description": "If true, transactions without signatures are allowed and simulated as if they were properly signed." + }, + "allow-unnamed-resources": { + "type": "boolean", + "description": "If true, allows access to unnamed resources during simulation." + }, + "max-log-calls": { + "type": "integer", + "description": "The maximum log calls one can make during simulation" + }, + "max-log-size": { + "type": "integer", + "description": "The maximum byte number to log during simulation" + }, + "extra-opcode-budget": { + "type": "integer", + "description": "The extra opcode budget added to each transaction group during simulation" + }, + "fix-signers": { + "type": "boolean", + "description": "If true, signers for transactions that are missing signatures will be fixed during evaluation." + } + }, + "description": "The set of parameters and limits override during simulation. If this set of parameters is present, then evaluation parameters may differ from standard evaluation in certain ways." + }, + "ScratchChange": { + "required": [ + "new-value", + "slot" + ], + "type": "object", + "properties": { + "slot": { + "type": "integer", + "description": "The scratch slot written." + }, + "new-value": { + "$ref": "#/components/schemas/AvmValue" + } + }, + "description": "A write operation into a scratch slot." + }, + "ApplicationStateOperation": { + "required": [ + "app-state-type", + "key", + "operation" + ], + "type": "object", + "properties": { + "operation": { + "type": "string", + "description": "Operation type. Value `w` is **write**, `d` is **delete**." + }, + "app-state-type": { + "type": "string", + "description": "Type of application state. Value `g` is **global state**, `l` is **local state**, `b` is **boxes**." + }, + "key": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "The key (name) of the global/local/box state.", + "format": "byte" + }, + "new-value": { + "$ref": "#/components/schemas/AvmValue" + }, + "account": { + "type": "string", + "description": "For local state changes, the address of the account associated with the local state.", + "x-algorand-format": "Address" + } + }, + "description": "An operation against an application's global/local/box state." + }, + "ApplicationKVStorage": { + "required": [ + "kvs" + ], + "type": "object", + "properties": { + "kvs": { + "type": "array", + "description": "Key-Value pairs representing application states.", + "items": { + "$ref": "#/components/schemas/AvmKeyValue" + } + }, + "account": { + "type": "string", + "description": "The address of the account associated with the local state.", + "x-algorand-format": "Address" + } + }, + "description": "An application's global/local/box state." + }, + "ApplicationInitialStates": { + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "Application index.", + "x-go-type": "basics.AppIndex", + "x-algokit-bigint": true + }, + "app-locals": { + "type": "array", + "description": "An application's initial local states tied to different accounts.", + "items": { + "$ref": "#/components/schemas/ApplicationKVStorage" + } + }, + "app-globals": { + "$ref": "#/components/schemas/ApplicationKVStorage" + }, + "app-boxes": { + "$ref": "#/components/schemas/ApplicationKVStorage" + } + }, + "description": "An application's initial global/local/box states that were accessed during simulation." + }, + "SimulationOpcodeTraceUnit": { + "required": [ + "pc" + ], + "type": "object", + "properties": { + "pc": { + "type": "integer", + "description": "The program counter of the current opcode being evaluated." + }, + "scratch-changes": { + "type": "array", + "description": "The writes into scratch slots.", + "items": { + "$ref": "#/components/schemas/ScratchChange" + } + }, + "state-changes": { + "type": "array", + "description": "The operations against the current application's states.", + "items": { + "$ref": "#/components/schemas/ApplicationStateOperation" + } + }, + "spawned-inners": { + "type": "array", + "description": "The indexes of the traces for inner transactions spawned by this opcode, if any.", + "items": { + "type": "integer" + } + }, + "stack-pop-count": { + "type": "integer", + "description": "The number of deleted stack values by this opcode." + }, + "stack-additions": { + "type": "array", + "description": "The values added by this opcode to the stack.", + "items": { + "$ref": "#/components/schemas/AvmValue" + } + } + }, + "description": "The set of trace information and effect from evaluating a single opcode." + }, + "SimulationTransactionExecTrace": { + "type": "object", + "properties": { + "approval-program-trace": { + "type": "array", + "description": "Program trace that contains a trace of opcode effects in an approval program.", + "items": { + "$ref": "#/components/schemas/SimulationOpcodeTraceUnit" + } + }, + "approval-program-hash": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "SHA512_256 hash digest of the approval program executed in transaction.", + "format": "byte" + }, + "clear-state-program-trace": { + "type": "array", + "description": "Program trace that contains a trace of opcode effects in a clear state program.", + "items": { + "$ref": "#/components/schemas/SimulationOpcodeTraceUnit" + } + }, + "clear-state-program-hash": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "SHA512_256 hash digest of the clear state program executed in transaction.", + "format": "byte" + }, + "clear-state-rollback": { + "type": "boolean", + "description": "If true, indicates that the clear state program failed and any persistent state changes it produced should be reverted once the program exits." + }, + "clear-state-rollback-error": { + "type": "string", + "description": "The error message explaining why the clear state program failed. This field will only be populated if clear-state-rollback is true and the failure was due to an execution error." + }, + "logic-sig-trace": { + "type": "array", + "description": "Program trace that contains a trace of opcode effects in a logic sig.", + "items": { + "$ref": "#/components/schemas/SimulationOpcodeTraceUnit" + } + }, + "logic-sig-hash": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "SHA512_256 hash digest of the logic sig executed in transaction.", + "format": "byte" + }, + "inner-trace": { + "type": "array", + "description": "An array of SimulationTransactionExecTrace representing the execution trace of any inner transactions executed.", + "items": { + "$ref": "#/components/schemas/SimulationTransactionExecTrace" + } + } + }, + "description": "The execution trace of calling an app or a logic sig, containing the inner app call trace in a recursive way." + }, + "SimulateUnnamedResourcesAccessed": { + "type": "object", + "properties": { + "accounts": { + "type": "array", + "description": "The unnamed accounts that were referenced. The order of this array is arbitrary.", + "items": { + "type": "string", + "x-algorand-format": "Address" + } + }, + "assets": { + "type": "array", + "description": "The unnamed assets that were referenced. The order of this array is arbitrary.", + "items": { + "type": "integer", + "x-go-type": "basics.AssetIndex", + "x-algokit-bigint": true + } + }, + "apps": { + "type": "array", + "description": "The unnamed applications that were referenced. The order of this array is arbitrary.", + "items": { + "type": "integer", + "x-go-type": "basics.AppIndex", + "x-algokit-bigint": true + } + }, + "boxes": { + "type": "array", + "description": "The unnamed boxes that were referenced. The order of this array is arbitrary.", + "items": { + "$ref": "#/components/schemas/BoxReference" + } + }, + "extra-box-refs": { + "type": "integer", + "description": "The number of extra box references used to increase the IO budget. This is in addition to the references defined in the input transaction group and any referenced to unnamed boxes." + }, + "asset-holdings": { + "type": "array", + "description": "The unnamed asset holdings that were referenced. The order of this array is arbitrary.", + "items": { + "$ref": "#/components/schemas/AssetHoldingReference" + } + }, + "app-locals": { + "type": "array", + "description": "The unnamed application local states that were referenced. The order of this array is arbitrary.", + "items": { + "$ref": "#/components/schemas/ApplicationLocalReference" + } + } + }, + "description": "These are resources that were accessed by this group that would normally have caused failure, but were allowed in simulation. Depending on where this object is in the response, the unnamed resources it contains may or may not qualify for group resource sharing. If this is a field in SimulateTransactionGroupResult, the resources do qualify, but if this is a field in SimulateTransactionResult, they do not qualify. In order to make this group valid for actual submission, resources that qualify for group sharing can be made available by any transaction of the group; otherwise, resources must be placed in the same transaction which accessed them." + }, + "SimulateInitialStates": { + "type": "object", + "properties": { + "app-initial-states": { + "type": "array", + "description": "The initial states of accessed application before simulation. The order of this array is arbitrary.", + "items": { + "$ref": "#/components/schemas/ApplicationInitialStates" + } + } + }, + "description": "Initial states of resources that were accessed during simulation." + }, + "AppCallLogs": { + "required": [ + "application-index", + "logs", + "txId" + ], + "type": "object", + "properties": { + "logs": { + "type": "array", + "description": "An array of logs", + "items": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "format": "byte" + } + }, + "application-index": { + "type": "integer", + "description": "The application from which the logs were generated", + "x-go-type": "basics.AppIndex", + "x-algokit-field-rename": "app_id", + "x-algokit-bigint": true + }, + "txId": { + "type": "string", + "description": "The transaction ID of the outer app call that lead to these logs" + } + }, + "description": "The logged messages from an app call along with the app ID and outer transaction ID. Logs appear in the same order that they were emitted." + }, + "TransactionProof": { + "required": [ + "hashtype", + "idx", + "proof", + "stibhash", + "treedepth" + ], + "type": "object", + "properties": { + "proof": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "Proof of transaction membership.", + "format": "byte" + }, + "stibhash": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "Hash of SignedTxnInBlock for verifying proof.", + "format": "byte" + }, + "treedepth": { + "type": "integer", + "description": "Represents the depth of the tree that is being proven, i.e. the number of edges from a leaf to the root.", + "x-algokit-bigint": true + }, + "idx": { + "type": "integer", + "description": "Index of the transaction in the block's payset.", + "x-algokit-bigint": true + }, + "hashtype": { + "type": "string", + "description": "The type of hash function used to create the proof, must be one of: \n* sha512_256 \n* sha256", + "enum": [ + "sha512_256", + "sha256" + ] + } + }, + "description": "Proof of transaction in a block." + } + }, + "responses": { + "GetBlockTimeStampOffsetResponse": { + "description": "Response containing the timestamp offset in seconds", + "content": { + "application/json": { + "schema": { + "required": [ + "offset" + ], + "type": "object", + "properties": { + "offset": { + "type": "integer", + "description": "Timestamp offset in seconds.", + "x-algokit-bigint": true + } + } + } + } + } + }, + "GetSyncRoundResponse": { + "description": "Response containing the ledger's minimum sync round", + "content": { + "application/json": { + "schema": { + "required": [ + "round" + ], + "type": "object", + "properties": { + "round": { + "type": "integer", + "description": "The minimum sync round for the ledger.", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + } + } + } + } + } + }, + "LedgerStateDeltaForTransactionGroupResponse": { + "description": "Response containing a ledger state delta for a single transaction group.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LedgerStateDelta" + } + } + } + }, + "TransactionGroupLedgerStateDeltasForRoundResponse": { + "description": "Response containing all ledger state deltas for transaction groups, with their associated Ids, in a single round.", + "content": { + "application/json": { + "schema": { + "required": [ + "Deltas" + ], + "type": "object", + "properties": { + "Deltas": { + "type": "array", + "items": { + "$ref": "#/components/schemas/LedgerStateDeltaForTransactionGroup" + } + } + } + } + } + } + }, + "LedgerStateDeltaResponse": { + "description": "Contains ledger deltas", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LedgerStateDelta" + } + } + } + }, + "LightBlockHeaderProofResponse": { + "description": "Proof of a light block header.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LightBlockHeaderProof" + } + } + } + }, + "StateProofResponse": { + "description": "StateProofResponse wraps the StateProof type in a response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StateProof" + } + } + } + }, + "AccountResponse": { + "description": "AccountResponse wraps the Account type in a response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Account" + } + } + } + }, + "AccountAssetResponse": { + "description": "AccountAssetResponse describes the account's asset holding and asset parameters (if either exist) for a specific asset ID. Asset parameters will only be returned if the provided address is the asset's creator.", + "content": { + "application/json": { + "schema": { + "required": [ + "round" + ], + "type": "object", + "properties": { + "round": { + "type": "integer", + "description": "The round for which this information is relevant.", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + }, + "asset-holding": { + "$ref": "#/components/schemas/AssetHolding" + }, + "created-asset": { + "$ref": "#/components/schemas/AssetParams" + } + } + } + } + } + }, + "AccountAssetsInformationResponse": { + "description": "AccountAssetsInformationResponse contains a list of assets held by an account.", + "content": { + "application/json": { + "schema": { + "required": [ + "round" + ], + "type": "object", + "properties": { + "round": { + "type": "integer", + "description": "The round for which this information is relevant.", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + }, + "next-token": { + "type": "string", + "description": "Used for pagination, when making another request provide this token with the next parameter." + }, + "asset-holdings": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AccountAssetHolding" + } + } + } + } + } + } + }, + "AccountApplicationResponse": { + "description": "AccountApplicationResponse describes the account's application local state and global state (AppLocalState and AppParams, if either exists) for a specific application ID. Global state will only be returned if the provided address is the application's creator.", + "content": { + "application/json": { + "schema": { + "required": [ + "round" + ], + "type": "object", + "properties": { + "round": { + "type": "integer", + "description": "The round for which this information is relevant.", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + }, + "app-local-state": { + "$ref": "#/components/schemas/ApplicationLocalState" + }, + "created-app": { + "$ref": "#/components/schemas/ApplicationParams" + } + } + } + } + } + }, + "BlockResponse": { + "description": "Encoded block object.", + "content": { + "application/json": { + "schema": { + "required": [ + "block" + ], + "type": "object", + "properties": { + "block": { + "type": "object", + "properties": {}, + "description": "Block header data.", + "x-algorand-format": "BlockHeader" + }, + "cert": { + "type": "object", + "properties": {}, + "description": "Optional certificate object. This is only included when the format is set to message pack.", + "x-algorand-format": "BlockCertificate" + } + } + } + } + } + }, + "BlockTxidsResponse": { + "description": "Top level transaction IDs in a block.", + "content": { + "application/json": { + "schema": { + "required": [ + "blockTxids" + ], + "type": "object", + "properties": { + "blockTxids": { + "type": "array", + "description": "Block transaction IDs.", + "items": { + "type": "string" + } + } + } + } + } + } + }, + "BlockHashResponse": { + "description": "Hash of a block header.", + "content": { + "application/json": { + "schema": { + "required": [ + "blockHash" + ], + "type": "object", + "properties": { + "blockHash": { + "type": "string", + "description": "Block header hash." + } + } + } + } + } + }, + "TransactionProofResponse": { + "description": "Proof of transaction in a block.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TransactionProof" + } + } + } + }, + "CatchpointStartResponse": { + "content": { + "application/json": { + "schema": { + "required": [ + "catchup-message" + ], + "type": "object", + "properties": { + "catchup-message": { + "type": "string", + "description": "Catchup start response string" + } + }, + "description": "An catchpoint start response." + } + } + }, + "description": "Catchpoint start operation response" + }, + "CatchpointAbortResponse": { + "content": { + "application/json": { + "schema": { + "required": [ + "catchup-message" + ], + "type": "object", + "properties": { + "catchup-message": { + "type": "string", + "description": "Catchup abort response string" + } + }, + "description": "An catchpoint abort response." + } + } + }, + "description": "Catchpoint abort operation response" + }, + "NodeStatusResponse": { + "content": { + "application/json": { + "schema": { + "required": [ + "catchup-time", + "last-round", + "last-version", + "next-version", + "next-version-round", + "next-version-supported", + "stopped-at-unsupported-round", + "time-since-last-round" + ], + "type": "object", + "properties": { + "catchup-time": { + "type": "integer", + "description": "CatchupTime in nanoseconds", + "x-go-type": "int64", + "x-algokit-bigint": true + }, + "last-round": { + "type": "integer", + "description": "LastRound indicates the last round seen", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + }, + "last-version": { + "type": "string", + "description": "LastVersion indicates the last consensus version supported" + }, + "next-version": { + "type": "string", + "description": "NextVersion of consensus protocol to use" + }, + "next-version-round": { + "type": "integer", + "description": "NextVersionRound is the round at which the next consensus version will apply", + "x-go-type": "basics.Round" + }, + "next-version-supported": { + "type": "boolean", + "description": "NextVersionSupported indicates whether the next consensus version is supported by this node" + }, + "stopped-at-unsupported-round": { + "type": "boolean", + "description": "StoppedAtUnsupportedRound indicates that the node does not support the new rounds and has stopped making progress" + }, + "time-since-last-round": { + "type": "integer", + "description": "TimeSinceLastRound in nanoseconds", + "x-go-type": "int64", + "x-algokit-bigint": true + }, + "last-catchpoint": { + "type": "string", + "description": "The last catchpoint seen by the node" + }, + "catchpoint": { + "type": "string", + "description": "The current catchpoint that is being caught up to" + }, + "catchpoint-total-accounts": { + "type": "integer", + "description": "The total number of accounts included in the current catchpoint", + "x-algokit-bigint": true + }, + "catchpoint-processed-accounts": { + "type": "integer", + "description": "The number of accounts from the current catchpoint that have been processed so far as part of the catchup", + "x-algokit-bigint": true + }, + "catchpoint-verified-accounts": { + "type": "integer", + "description": "The number of accounts from the current catchpoint that have been verified so far as part of the catchup", + "x-algokit-bigint": true + }, + "catchpoint-total-kvs": { + "type": "integer", + "description": "The total number of key-values (KVs) included in the current catchpoint", + "x-algokit-bigint": true + }, + "catchpoint-processed-kvs": { + "type": "integer", + "description": "The number of key-values (KVs) from the current catchpoint that have been processed so far as part of the catchup", + "x-algokit-bigint": true + }, + "catchpoint-verified-kvs": { + "type": "integer", + "description": "The number of key-values (KVs) from the current catchpoint that have been verified so far as part of the catchup", + "x-algokit-bigint": true + }, + "catchpoint-total-blocks": { + "type": "integer", + "description": "The total number of blocks that are required to complete the current catchpoint catchup", + "x-algokit-bigint": true + }, + "catchpoint-acquired-blocks": { + "type": "integer", + "description": "The number of blocks that have already been obtained by the node as part of the catchup", + "x-algokit-bigint": true + }, + "upgrade-delay": { + "type": "integer", + "description": "Upgrade delay", + "x-go-type": "basics.Round" + }, + "upgrade-node-vote": { + "type": "boolean", + "description": "This node's upgrade vote" + }, + "upgrade-votes-required": { + "type": "integer", + "description": "Yes votes required for consensus upgrade", + "x-go-type": "basics.Round" + }, + "upgrade-votes": { + "type": "integer", + "description": "Total votes cast for consensus upgrade", + "x-go-type": "basics.Round" + }, + "upgrade-yes-votes": { + "type": "integer", + "description": "Yes votes cast for consensus upgrade", + "x-go-type": "basics.Round" + }, + "upgrade-no-votes": { + "type": "integer", + "description": "No votes cast for consensus upgrade", + "x-go-type": "basics.Round" + }, + "upgrade-next-protocol-vote-before": { + "type": "integer", + "description": "Next protocol round", + "x-go-type": "basics.Round" + }, + "upgrade-vote-rounds": { + "type": "integer", + "description": "Total voting rounds for current upgrade", + "x-go-type": "basics.Round" + } + }, + "description": "NodeStatus contains the information about a node status" + } + } + }, + "description": "Returns the current status of the node" + }, + "PendingTransactionsResponse": { + "description": "A potentially truncated list of transactions currently in the node's transaction pool. You can compute whether or not the list is truncated if the number of elements in the **top-transactions** array is fewer than **total-transactions**.", + "content": { + "application/json": { + "schema": { + "required": [ + "top-transactions", + "total-transactions" + ], + "type": "object", + "properties": { + "top-transactions": { + "type": "array", + "description": "An array of signed transaction objects.", + "items": { + "type": "object", + "properties": {}, + "x-algokit-signed-txn": true + } + }, + "total-transactions": { + "type": "integer", + "description": "Total number of transactions in the pool." + } + }, + "description": "PendingTransactions is an array of signed transactions exactly as they were submitted." + } + } + } + }, + "ParticipationKeysResponse": { + "description": "A list of participation keys", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ParticipationKey" + } + } + } + } + }, + "ParticipationKeyResponse": { + "description": "A detailed description of a participation ID", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ParticipationKey" + } + } + } + }, + "PostParticipationResponse": { + "description": "Participation ID of the submission", + "content": { + "application/json": { + "schema": { + "required": [ + "partId" + ], + "type": "object", + "properties": { + "partId": { + "type": "string", + "description": "encoding of the participation ID." + } + } + } + } + } + }, + "PostTransactionsResponse": { + "description": "Transaction ID of the submission.", + "content": { + "application/json": { + "schema": { + "required": [ + "txId" + ], + "type": "object", + "properties": { + "txId": { + "type": "string", + "description": "encoding of the transaction hash." + } + } + } + } + } + }, + "SimulateResponse": { + "description": "Result of a transaction group simulation.", + "content": { + "application/json": { + "schema": { + "required": [ + "last-round", + "txn-groups", + "version" + ], + "type": "object", + "properties": { + "version": { + "type": "integer", + "description": "The version of this response object.", + "x-algokit-bigint": true + }, + "last-round": { + "type": "integer", + "description": "The round immediately preceding this simulation. State changes through this round were used to run this simulation.", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + }, + "txn-groups": { + "type": "array", + "description": "A result object for each transaction group that was simulated.", + "items": { + "$ref": "#/components/schemas/SimulateTransactionGroupResult" + } + }, + "eval-overrides": { + "$ref": "#/components/schemas/SimulationEvalOverrides" + }, + "exec-trace-config": { + "$ref": "#/components/schemas/SimulateTraceConfig" + }, + "initial-states": { + "$ref": "#/components/schemas/SimulateInitialStates" + } + } + } + } + } + }, + "BlockLogsResponse": { + "description": "All logs emitted in the given round. Each app call, whether top-level or inner, that contains logs results in a separate AppCallLogs object. Therefore there may be multiple AppCallLogs with the same application ID and outer transaction ID in the event of multiple inner app calls to the same app. App calls with no logs are not included in the response. AppCallLogs are returned in the same order that their corresponding app call appeared in the block (pre-order traversal of inner app calls)", + "content": { + "application/json": { + "schema": { + "required": [ + "logs" + ], + "type": "object", + "properties": { + "logs": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AppCallLogs" + } + } + } + } + } + } + }, + "SupplyResponse": { + "description": "Supply represents the current supply of MicroAlgos in the system.", + "content": { + "application/json": { + "schema": { + "required": [ + "current_round", + "online-money", + "total-money" + ], + "type": "object", + "properties": { + "current_round": { + "type": "integer", + "description": "Round", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + }, + "online-money": { + "type": "integer", + "description": "OnlineMoney", + "x-algokit-bigint": true + }, + "total-money": { + "type": "integer", + "description": "TotalMoney", + "x-algokit-bigint": true + } + }, + "description": "Supply represents the current supply of MicroAlgos in the system" + } + } + } + }, + "TransactionParametersResponse": { + "description": "TransactionParams contains the parameters that help a client construct a new transaction.", + "content": { + "application/json": { + "schema": { + "required": [ + "consensus-version", + "fee", + "genesis-hash", + "genesis-id", + "last-round", + "min-fee" + ], + "type": "object", + "properties": { + "consensus-version": { + "type": "string", + "description": "ConsensusVersion indicates the consensus protocol version\nas of LastRound." + }, + "fee": { + "type": "integer", + "description": "Fee is the suggested transaction fee\nFee is in units of micro-Algos per byte.\nFee may fall to zero but transactions must still have a fee of\nat least MinTxnFee for the current network protocol.", + "x-algokit-bigint": true + }, + "genesis-hash": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "GenesisHash is the hash of the genesis block.", + "format": "byte" + }, + "genesis-id": { + "type": "string", + "description": "GenesisID is an ID listed in the genesis block." + }, + "last-round": { + "type": "integer", + "description": "LastRound indicates the last round seen", + "x-go-type": "basics.Round", + "x-algokit-bigint": true + }, + "min-fee": { + "type": "integer", + "description": "The minimum transaction fee (not per byte) required for the\ntxn to validate for the current network protocol.", + "x-algokit-bigint": true + } + }, + "description": "TransactionParams contains the parameters that help a client construct\na new transaction." + } + } + } + }, + "ApplicationResponse": { + "description": "Application information", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Application" + } + } + } + }, + "BoxesResponse": { + "description": "Box names of an application", + "content": { + "application/json": { + "schema": { + "required": [ + "boxes" + ], + "type": "object", + "properties": { + "boxes": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BoxDescriptor" + } + } + } + } + } + } + }, + "BoxResponse": { + "description": "Box information", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Box" + } + } + } + }, + "AssetResponse": { + "description": "Asset information", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Asset" + } + } + } + }, + "CompileResponse": { + "description": "Teal compile Result", + "content": { + "application/json": { + "schema": { + "required": [ + "hash", + "result" + ], + "type": "object", + "properties": { + "hash": { + "type": "string", + "description": "base32 SHA512_256 of program bytes (Address style)" + }, + "result": { + "type": "string", + "description": "base64 encoded program bytes" + }, + "sourcemap": { + "type": "object", + "properties": {}, + "description": "JSON of the source map" + } + } + } + } + } + }, + "DisassembleResponse": { + "description": "Teal disassembly Result", + "content": { + "application/json": { + "schema": { + "required": [ + "result" + ], + "type": "object", + "properties": { + "result": { + "type": "string", + "description": "disassembled Teal code" + } + } + } + } + } + }, + "DryrunResponse": { + "description": "DryrunResponse contains per-txn debug information from a dryrun.", + "content": { + "application/json": { + "schema": { + "required": [ + "error", + "protocol-version", + "txns" + ], + "type": "object", + "properties": { + "txns": { + "type": "array", + "items": { + "$ref": "#/components/schemas/DryrunTxnResult" + } + }, + "error": { + "type": "string" + }, + "protocol-version": { + "type": "string", + "description": "Protocol version is the protocol version Dryrun was operated under." + } + } + } + } + } + }, + "VersionsResponse": { + "description": "VersionsResponse is the response to 'GET /versions'", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Version" + } + } + } + }, + "DebugSettingsProfResponse": { + "description": "DebugPprof is the response to the /debug/extra/pprof endpoint", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DebugSettingsProf" + } + } + } + } + }, + "parameters": { + "catchpoint": { + "name": "catchpoint", + "in": "path", + "description": "A catch point", + "required": true, + "schema": { + "pattern": "[0-9]{1,10}#[A-Z0-9]{1,53}", + "type": "string", + "format": "catchpoint", + "x-algorand-format": "Catchpoint String" + }, + "x-algorand-format": "Catchpoint String" + }, + "format": { + "name": "format", + "in": "query", + "description": "Configures whether the response object is JSON or MessagePack encoded. If not provided, defaults to JSON.", + "schema": { + "type": "string", + "enum": [ + "json", + "msgpack" + ] + } + }, + "limit": { + "name": "limit", + "in": "query", + "description": "Maximum number of results to return.", + "schema": { + "type": "integer", + "x-algokit-bigint": true + }, + "x-algokit-bigint": true + }, + "max": { + "name": "max", + "in": "query", + "description": "Truncated number of transactions to display. If max=0, returns all pending txns.", + "schema": { + "type": "integer", + "x-algokit-bigint": true + }, + "x-algokit-bigint": true + }, + "next": { + "name": "next", + "in": "query", + "description": "The next page of results. Use the next token provided by the previous results.", + "schema": { + "type": "string" + } + }, + "round": { + "name": "round", + "in": "path", + "description": "A round number.", + "required": true, + "schema": { + "minimum": 0, + "type": "integer", + "x-go-type": "basics.Round" + }, + "x-go-type": "basics.Round" + }, + "address": { + "name": "address", + "in": "path", + "description": "An account public key.", + "required": true, + "schema": { + "pattern": "[A-Z0-9]{58}", + "type": "string", + "x-go-type": "basics.Address" + }, + "x-go-type": "basics.Address" + }, + "asset-id": { + "name": "asset-id", + "in": "path", + "description": "An asset identifier.", + "required": true, + "schema": { + "minimum": 0, + "type": "integer", + "x-go-type": "basics.AssetIndex" + }, + "x-go-type": "basics.AssetIndex" + }, + "application-id": { + "name": "application-id", + "in": "path", + "description": "An application identifier.", + "required": true, + "schema": { + "minimum": 0, + "type": "integer", + "x-go-type": "basics.AppIndex" + }, + "x-go-type": "basics.AppIndex" + }, + "sig-type": { + "name": "sig-type", + "in": "query", + "description": "SigType filters just results using the specified type of signature:\n* sig - Standard\n* msig - MultiSig\n* lsig - LogicSig", + "schema": { + "type": "string", + "enum": [ + "sig", + "msig", + "lsig" + ] + } + }, + "tx-id": { + "name": "tx-id", + "in": "query", + "description": "Lookup the specific transaction by ID.", + "schema": { + "type": "string", + "x-algorand-format": "Address", + "x-go-name": "TxID" + }, + "x-algorand-format": "Address", + "x-go-name": "TxID" + }, + "tx-type": { + "name": "tx-type", + "in": "query", + "schema": { + "type": "string", + "enum": [ + "pay", + "keyreg", + "acfg", + "axfer", + "afrz", + "appl", + "stpf" + ] + } + } + }, + "securitySchemes": { + "api_key": { + "type": "apiKey", + "description": "Generated header parameter. This token can be generated using the Goal command line tool. Example value ='b7e384d0317b8050ce45900a94a1931e28540e1f69b2d242b424659c341b4697'", + "name": "X-Algo-API-Token", + "in": "header" + } + } + }, + "x-original-swagger-version": "2.0" +} \ No newline at end of file diff --git a/algokit-configs/openapi-converter/specs/compatibility.md b/algokit-configs/openapi-converter/specs/compatibility.md new file mode 100644 index 000000000..618ad6332 --- /dev/null +++ b/algokit-configs/openapi-converter/specs/compatibility.md @@ -0,0 +1,79 @@ +| Endpoint | Response-msgpack | Input-msgpack | Response-json | Input-json | +| -------------------------------------------------------- | ---------------- | ------------- | ------------- | ---------- | +| GET /health | ❌ | N/A | ✅ | N/A | +| GET /ready | ❌ | N/A | ✅ | N/A | +| GET /metrics | ❌ | N/A | ✅ | N/A | +| GET /genesis | ❌ | N/A | ✅ | N/A | +| GET /swagger.json | ❌ | N/A | ✅ | N/A | +| GET /versions | ❌ | N/A | ✅ | N/A | +| GET /debug/settings/pprof | ❌ | N/A | ✅ | N/A | +| PUT /debug/settings/pprof | ❌ | N/A | ✅ | N/A | +| GET /debug/settings/config | ❌ | N/A | ✅ | N/A | +| GET /v2/accounts/{address} | ✅ | N/A | ✅ | N/A | +| GET /v2/accounts/{address}/assets/{asset-id} | ✅ | N/A | ✅ | N/A | +| GET /v2/accounts/{address}/assets | ❌ | N/A | ✅ | N/A | +| GET /v2/accounts/{address}/applications/{application-id} | ✅ | N/A | ✅ | N/A | +| GET /v2/accounts/{address}/transactions/pending | ✅ | N/A | ✅ | N/A | +| GET /v2/blocks/{round} | ✅ | N/A | ✅ | N/A | +| GET /v2/blocks/{round}/txids | ❌ | N/A | ✅ | N/A | +| GET /v2/blocks/{round}/hash | ❌ | N/A | ✅ | N/A | +| GET /v2/blocks/{round}/transactions/{txid}/proof | ❌ | N/A | ✅ | N/A | +| GET /v2/blocks/{round}/logs | ❌ | N/A | ✅ | N/A | +| GET /v2/ledger/supply | ❌ | N/A | ✅ | N/A | +| GET /v2/participation | ❌ | N/A | ✅ | N/A | +| POST /v2/participation | ❌ | ✅ | ✅ | ❌ | +| POST /v2/participation/generate/{address} | ❌ | N/A | ✅ | N/A | +| GET /v2/participation/{participation-id} | ❌ | N/A | ✅ | N/A | +| POST /v2/participation/{participation-id} | ❌ | ✅ | ✅ | ❌ | +| DELETE /v2/participation/{participation-id} | ❌ | N/A | ✅ | N/A | +| POST /v2/shutdown | ❌ | N/A | ✅ | N/A | +| GET /v2/status | ❌ | N/A | ✅ | N/A | +| GET /v2/status/wait-for-block-after/{round} | ❌ | N/A | ✅ | N/A | +| POST /v2/transactions | ❌ | ❌ | ✅ | ❌ | +| POST /v2/transactions/async | ❌ | ❌ | ✅ | ❌ | +| POST /v2/transactions/simulate | ✅ | ✅ | ✅ | ✅ | +| GET /v2/transactions/params | ❌ | N/A | ✅ | N/A | +| GET /v2/transactions/pending | ✅ | N/A | ✅ | N/A | +| GET /v2/transactions/pending/{txid} | ✅ | N/A | ✅ | N/A | +| GET /v2/deltas/{round} | ✅ | N/A | ✅ | N/A | +| GET /v2/deltas/{round}/txn/group | ✅ | N/A | ✅ | N/A | +| GET /v2/deltas/txn/group/{id} | ✅ | N/A | ✅ | N/A | +| GET /v2/stateproofs/{round} | ❌ | N/A | ✅ | N/A | +| GET /v2/blocks/{round}/lightheader/proof | ❌ | N/A | ✅ | N/A | +| GET /v2/applications/{application-id} | ❌ | N/A | ✅ | N/A | +| GET /v2/applications/{application-id}/boxes | ❌ | N/A | ✅ | N/A | +| GET /v2/applications/{application-id}/box | ❌ | N/A | ✅ | N/A | +| GET /v2/assets/{asset-id} | ❌ | N/A | ✅ | N/A | +| GET /v2/ledger/sync | ❌ | N/A | ✅ | N/A | +| DELETE /v2/ledger/sync | ❌ | N/A | ✅ | N/A | +| POST /v2/ledger/sync/{round} | ❌ | N/A | ✅ | N/A | +| POST /v2/teal/compile | ❌ | N/A | ✅ | ❌ | +| POST /v2/teal/disassemble | ❌ | N/A | ✅ | ❌ | +| POST /v2/catchup/{catchpoint} | ❌ | N/A | ✅ | N/A | +| DELETE /v2/catchup/{catchpoint} | ❌ | N/A | ✅ | N/A | +| POST /v2/teal/dryrun | ❌ | ✅ | ✅ | ✅ | +| GET /v2/experimental | ❌ | N/A | ✅ | N/A | +| GET /v2/devmode/blocks/offset | ❌ | N/A | ✅ | N/A | +| POST /v2/devmode/blocks/offset/{offset} | ❌ | N/A | ✅ | N/A | + +Similar to above but focused on abstractions: + +| Abstraction | Related Endpoints | Supports msgpack Encoding | Supports msgpack Decoding | +| ----------------------------------- | ----------------------------------------------------------------------------- | ------------------------- | ------------------------- | +| Account | GET /v2/accounts/{address} | No | Yes | +| AccountAssetResponse | GET /v2/accounts/{address}/assets/{asset-id} | No | Yes | +| AccountApplicationResponse | GET /v2/accounts/{address}/applications/{application-id} | No | Yes | +| AssetHolding | GET /v2/accounts/{address}/assets/{asset-id} | No | Yes | +| ApplicationLocalState | GET /v2/accounts/{address}/applications/{application-id} | No | Yes | +| BlockResponse | GET /v2/blocks/{round} | No | Yes | +| PendingTransactions | GET /v2/transactions/pending, GET /v2/accounts/{address}/transactions/pending | No | Yes | +| PendingTransactionResponse | GET /v2/transactions/pending/{txid} | No | Yes | +| LedgerStateDelta | GET /v2/deltas/{round}, GET /v2/deltas/txn/group/{id} | No | Yes | +| LedgerStateDeltaForTransactionGroup | GET /v2/deltas/{round}/txn/group | No | Yes | +| SimulateRequest | POST /v2/transactions/simulate | Yes | No | +| SimulateResponse | POST /v2/transactions/simulate (response) | No | Yes | +| DryrunRequest | POST /v2/teal/dryrun | Yes | No | +| DryrunResponse | POST /v2/teal/dryrun (response) | No | Yes | +| ErrorResponse | Various error responses across all endpoints | No | Yes | + +This table shows that while many abstractions in the Algorand API support msgpack decoding (receiving msgpack from the API), only two abstractions - SimulateRequest and DryrunRequest - support msgpack encoding (sending msgpack to the API). diff --git a/algokit-configs/openapi-converter/specs/indexer.oas3.json b/algokit-configs/openapi-converter/specs/indexer.oas3.json new file mode 100644 index 000000000..0b37fe3c7 --- /dev/null +++ b/algokit-configs/openapi-converter/specs/indexer.oas3.json @@ -0,0 +1,5779 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "Indexer", + "description": "Algorand ledger analytics API.", + "contact": { + "name": "Algorand", + "url": "https://www.algorand.com/get-in-touch/contact" + }, + "version": "2.0" + }, + "servers": [ + { + "url": "https://example.com/" + } + ], + "tags": [ + { + "name": "common" + }, + { + "name": "lookup" + }, + { + "name": "search" + } + ], + "paths": { + "/health": { + "get": { + "tags": [ + "common" + ], + "summary": "Returns 200 if healthy.", + "operationId": "makeHealthCheck", + "responses": { + "200": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HealthCheck" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v2/accounts": { + "get": { + "tags": [ + "search" + ], + "description": "Search for accounts.", + "operationId": "searchForAccounts", + "parameters": [ + { + "name": "asset-id", + "in": "query", + "description": "Asset ID", + "schema": { + "type": "integer" + } + }, + { + "name": "limit", + "in": "query", + "description": "Maximum number of results to return. There could be additional pages even if the limit is not reached.", + "schema": { + "type": "integer" + } + }, + { + "name": "next", + "in": "query", + "description": "The next page of results. Use the next token provided by the previous results.", + "schema": { + "type": "string" + } + }, + { + "name": "currency-greater-than", + "in": "query", + "description": "Results should have an amount greater than this value. MicroAlgos are the default currency unless an asset-id is provided, in which case the asset will be used.", + "schema": { + "type": "integer" + } + }, + { + "name": "include-all", + "in": "query", + "description": "Include all items including closed accounts, deleted applications, destroyed assets, opted-out asset holdings, and closed-out application localstates.", + "schema": { + "type": "boolean" + } + }, + { + "name": "exclude", + "in": "query", + "description": "Exclude additional items such as asset holdings, application local data stored for this account, asset parameters created by this account, and application parameters created by this account.", + "style": "form", + "explode": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "all", + "assets", + "created-assets", + "apps-local-state", + "created-apps", + "none" + ] + } + } + }, + { + "name": "currency-less-than", + "in": "query", + "description": "Results should have an amount less than this value. MicroAlgos are the default currency unless an asset-id is provided, in which case the asset will be used.", + "schema": { + "type": "integer" + } + }, + { + "name": "auth-addr", + "in": "query", + "description": "Include accounts configured to use this spending key.", + "schema": { + "type": "string", + "x-algorand-format": "Address" + }, + "x-algorand-format": "Address" + }, + { + "name": "round", + "in": "query", + "description": "Include results for the specified round. For performance reasons, this parameter may be disabled on some configurations. Using application-id or asset-id filters will return both creator and opt-in accounts. Filtering by include-all will return creator and opt-in accounts for deleted assets and accounts. Non-opt-in managers are not included in the results when asset-id is used.", + "schema": { + "type": "integer" + } + }, + { + "name": "application-id", + "in": "query", + "description": "Application ID", + "schema": { + "type": "integer" + } + }, + { + "name": "online-only", + "in": "query", + "description": "When this is set to true, return only accounts whose participation status is currently online.", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "required": [ + "accounts", + "current-round" + ], + "type": "object", + "properties": { + "accounts": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Account" + } + }, + "current-round": { + "type": "integer", + "description": "Round at which the results were computed." + }, + "next-token": { + "type": "string", + "description": "Used for pagination, when making another request provide this token with the next parameter." + } + } + } + } + } + }, + "400": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/v2/accounts/{account-id}": { + "get": { + "tags": [ + "lookup" + ], + "description": "Lookup account information.", + "operationId": "lookupAccountByID", + "parameters": [ + { + "name": "account-id", + "in": "path", + "description": "account string", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "round", + "in": "query", + "description": "Include results for the specified round.", + "schema": { + "type": "integer" + } + }, + { + "name": "include-all", + "in": "query", + "description": "Include all items including closed accounts, deleted applications, destroyed assets, opted-out asset holdings, and closed-out application localstates.", + "schema": { + "type": "boolean" + } + }, + { + "name": "exclude", + "in": "query", + "description": "Exclude additional items such as asset holdings, application local data stored for this account, asset parameters created by this account, and application parameters created by this account.", + "style": "form", + "explode": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "all", + "assets", + "created-assets", + "apps-local-state", + "created-apps", + "none" + ] + } + } + } + ], + "responses": { + "200": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "required": [ + "account", + "current-round" + ], + "type": "object", + "properties": { + "account": { + "$ref": "#/components/schemas/Account" + }, + "current-round": { + "type": "integer", + "description": "Round at which the results were computed." + } + } + } + } + } + }, + "400": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/v2/accounts/{account-id}/assets": { + "get": { + "tags": [ + "lookup" + ], + "description": "Lookup an account's asset holdings, optionally for a specific ID.", + "operationId": "lookupAccountAssets", + "parameters": [ + { + "name": "account-id", + "in": "path", + "description": "account string", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "asset-id", + "in": "query", + "description": "Asset ID", + "schema": { + "type": "integer" + } + }, + { + "name": "include-all", + "in": "query", + "description": "Include all items including closed accounts, deleted applications, destroyed assets, opted-out asset holdings, and closed-out application localstates.", + "schema": { + "type": "boolean" + } + }, + { + "name": "limit", + "in": "query", + "description": "Maximum number of results to return. There could be additional pages even if the limit is not reached.", + "schema": { + "type": "integer" + } + }, + { + "name": "next", + "in": "query", + "description": "The next page of results. Use the next token provided by the previous results.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "required": [ + "assets", + "current-round" + ], + "type": "object", + "properties": { + "current-round": { + "type": "integer", + "description": "Round at which the results were computed." + }, + "next-token": { + "type": "string", + "description": "Used for pagination, when making another request provide this token with the next parameter." + }, + "assets": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AssetHolding" + } + } + } + } + } + } + }, + "400": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/v2/accounts/{account-id}/created-assets": { + "get": { + "tags": [ + "lookup" + ], + "description": "Lookup an account's created asset parameters, optionally for a specific ID.", + "operationId": "lookupAccountCreatedAssets", + "parameters": [ + { + "name": "account-id", + "in": "path", + "description": "account string", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "asset-id", + "in": "query", + "description": "Asset ID", + "schema": { + "type": "integer" + } + }, + { + "name": "include-all", + "in": "query", + "description": "Include all items including closed accounts, deleted applications, destroyed assets, opted-out asset holdings, and closed-out application localstates.", + "schema": { + "type": "boolean" + } + }, + { + "name": "limit", + "in": "query", + "description": "Maximum number of results to return. There could be additional pages even if the limit is not reached.", + "schema": { + "type": "integer" + } + }, + { + "name": "next", + "in": "query", + "description": "The next page of results. Use the next token provided by the previous results.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "required": [ + "assets", + "current-round" + ], + "type": "object", + "properties": { + "assets": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Asset" + } + }, + "current-round": { + "type": "integer", + "description": "Round at which the results were computed." + }, + "next-token": { + "type": "string", + "description": "Used for pagination, when making another request provide this token with the next parameter." + } + } + } + } + } + }, + "400": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/v2/accounts/{account-id}/apps-local-state": { + "get": { + "tags": [ + "lookup" + ], + "description": "Lookup an account's asset holdings, optionally for a specific ID.", + "operationId": "lookupAccountAppLocalStates", + "parameters": [ + { + "name": "account-id", + "in": "path", + "description": "account string", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "application-id", + "in": "query", + "description": "Application ID", + "schema": { + "type": "integer" + } + }, + { + "name": "include-all", + "in": "query", + "description": "Include all items including closed accounts, deleted applications, destroyed assets, opted-out asset holdings, and closed-out application localstates.", + "schema": { + "type": "boolean" + } + }, + { + "name": "limit", + "in": "query", + "description": "Maximum number of results to return. There could be additional pages even if the limit is not reached.", + "schema": { + "type": "integer" + } + }, + { + "name": "next", + "in": "query", + "description": "The next page of results. Use the next token provided by the previous results.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "required": [ + "apps-local-states", + "current-round" + ], + "type": "object", + "properties": { + "apps-local-states": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ApplicationLocalState" + } + }, + "current-round": { + "type": "integer", + "description": "Round at which the results were computed." + }, + "next-token": { + "type": "string", + "description": "Used for pagination, when making another request provide this token with the next parameter." + } + } + } + } + } + }, + "400": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/v2/accounts/{account-id}/created-applications": { + "get": { + "tags": [ + "lookup" + ], + "description": "Lookup an account's created application parameters, optionally for a specific ID.", + "operationId": "lookupAccountCreatedApplications", + "parameters": [ + { + "name": "account-id", + "in": "path", + "description": "account string", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "application-id", + "in": "query", + "description": "Application ID", + "schema": { + "type": "integer" + } + }, + { + "name": "include-all", + "in": "query", + "description": "Include all items including closed accounts, deleted applications, destroyed assets, opted-out asset holdings, and closed-out application localstates.", + "schema": { + "type": "boolean" + } + }, + { + "name": "limit", + "in": "query", + "description": "Maximum number of results to return. There could be additional pages even if the limit is not reached.", + "schema": { + "type": "integer" + } + }, + { + "name": "next", + "in": "query", + "description": "The next page of results. Use the next token provided by the previous results.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "required": [ + "applications", + "current-round" + ], + "type": "object", + "properties": { + "applications": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Application" + } + }, + "current-round": { + "type": "integer", + "description": "Round at which the results were computed." + }, + "next-token": { + "type": "string", + "description": "Used for pagination, when making another request provide this token with the next parameter." + } + } + } + } + } + }, + "400": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/v2/accounts/{account-id}/transactions": { + "get": { + "tags": [ + "lookup" + ], + "description": "Lookup account transactions. Transactions are returned newest to oldest.", + "operationId": "lookupAccountTransactions", + "parameters": [ + { + "name": "limit", + "in": "query", + "description": "Maximum number of results to return. There could be additional pages even if the limit is not reached.", + "schema": { + "type": "integer" + } + }, + { + "name": "next", + "in": "query", + "description": "The next page of results. Use the next token provided by the previous results.", + "schema": { + "type": "string" + } + }, + { + "name": "note-prefix", + "in": "query", + "description": "Specifies a prefix which must be contained in the note field.", + "schema": { + "type": "string", + "x-algorand-format": "base64" + }, + "x-algorand-format": "base64" + }, + { + "name": "tx-type", + "in": "query", + "schema": { + "type": "string", + "enum": [ + "pay", + "keyreg", + "acfg", + "axfer", + "afrz", + "appl", + "stpf", + "hb" + ] + } + }, + { + "name": "sig-type", + "in": "query", + "description": "SigType filters just results using the specified type of signature:\n* sig - Standard\n* msig - MultiSig\n* lsig - LogicSig", + "schema": { + "type": "string", + "enum": [ + "sig", + "msig", + "lsig" + ] + } + }, + { + "name": "txid", + "in": "query", + "description": "Lookup the specific transaction by ID.", + "schema": { + "type": "string" + } + }, + { + "name": "round", + "in": "query", + "description": "Include results for the specified round.", + "schema": { + "type": "integer" + } + }, + { + "name": "min-round", + "in": "query", + "description": "Include results at or after the specified min-round.", + "schema": { + "type": "integer" + } + }, + { + "name": "max-round", + "in": "query", + "description": "Include results at or before the specified max-round.", + "schema": { + "type": "integer" + } + }, + { + "name": "asset-id", + "in": "query", + "description": "Asset ID", + "schema": { + "type": "integer" + } + }, + { + "name": "before-time", + "in": "query", + "description": "Include results before the given time. Must be an RFC 3339 formatted string.", + "schema": { + "type": "string", + "format": "date-time", + "x-algorand-format": "RFC3339 String" + }, + "x-algorand-format": "RFC3339 String" + }, + { + "name": "after-time", + "in": "query", + "description": "Include results after the given time. Must be an RFC 3339 formatted string.", + "schema": { + "type": "string", + "format": "date-time", + "x-algorand-format": "RFC3339 String" + }, + "x-algorand-format": "RFC3339 String" + }, + { + "name": "currency-greater-than", + "in": "query", + "description": "Results should have an amount greater than this value. MicroAlgos are the default currency unless an asset-id is provided, in which case the asset will be used.", + "schema": { + "type": "integer" + } + }, + { + "name": "currency-less-than", + "in": "query", + "description": "Results should have an amount less than this value. MicroAlgos are the default currency unless an asset-id is provided, in which case the asset will be used.", + "schema": { + "type": "integer" + } + }, + { + "name": "account-id", + "in": "path", + "description": "account string", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "rekey-to", + "in": "query", + "description": "Include results which include the rekey-to field.", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "required": [ + "current-round", + "transactions" + ], + "type": "object", + "properties": { + "current-round": { + "type": "integer", + "description": "Round at which the results were computed." + }, + "next-token": { + "type": "string", + "description": "Used for pagination, when making another request provide this token with the next parameter." + }, + "transactions": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Transaction" + } + } + } + } + } + } + }, + "400": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/v2/applications": { + "get": { + "tags": [ + "search" + ], + "description": "Search for applications", + "operationId": "searchForApplications", + "parameters": [ + { + "name": "application-id", + "in": "query", + "description": "Application ID", + "schema": { + "type": "integer" + } + }, + { + "name": "creator", + "in": "query", + "description": "Filter just applications with the given creator address.", + "schema": { + "type": "string" + } + }, + { + "name": "include-all", + "in": "query", + "description": "Include all items including closed accounts, deleted applications, destroyed assets, opted-out asset holdings, and closed-out application localstates.", + "schema": { + "type": "boolean" + } + }, + { + "name": "limit", + "in": "query", + "description": "Maximum number of results to return. There could be additional pages even if the limit is not reached.", + "schema": { + "type": "integer" + } + }, + { + "name": "next", + "in": "query", + "description": "The next page of results. Use the next token provided by the previous results.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "required": [ + "applications", + "current-round" + ], + "type": "object", + "properties": { + "applications": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Application" + } + }, + "current-round": { + "type": "integer", + "description": "Round at which the results were computed." + }, + "next-token": { + "type": "string", + "description": "Used for pagination, when making another request provide this token with the next parameter." + } + } + } + } + } + }, + "500": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/v2/applications/{application-id}": { + "get": { + "tags": [ + "lookup" + ], + "description": "Lookup application.", + "operationId": "lookupApplicationByID", + "parameters": [ + { + "name": "application-id", + "in": "path", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "include-all", + "in": "query", + "description": "Include all items including closed accounts, deleted applications, destroyed assets, opted-out asset holdings, and closed-out application localstates.", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "required": [ + "current-round" + ], + "type": "object", + "properties": { + "application": { + "$ref": "#/components/schemas/Application" + }, + "current-round": { + "type": "integer", + "description": "Round at which the results were computed." + } + } + } + } + } + }, + "404": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/v2/applications/{application-id}/boxes": { + "get": { + "tags": [ + "search" + ], + "summary": "Get box names for a given application.", + "description": "Given an application ID, returns the box names of that application sorted lexicographically.", + "operationId": "searchForApplicationBoxes", + "parameters": [ + { + "name": "application-id", + "in": "path", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "limit", + "in": "query", + "description": "Maximum number of results to return. There could be additional pages even if the limit is not reached.", + "schema": { + "type": "integer" + } + }, + { + "name": "next", + "in": "query", + "description": "The next page of results. Use the next token provided by the previous results.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Box names of an application", + "content": { + "application/json": { + "schema": { + "required": [ + "application-id", + "boxes" + ], + "type": "object", + "properties": { + "application-id": { + "type": "integer", + "description": "\\[appidx\\] application index." + }, + "boxes": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BoxDescriptor" + } + }, + "next-token": { + "type": "string", + "description": "Used for pagination, when making another request provide this token with the next parameter." + } + } + } + } + } + }, + "400": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/v2/applications/{application-id}/box": { + "get": { + "tags": [ + "lookup" + ], + "summary": "Get box information for a given application.", + "description": "Given an application ID and box name, returns base64 encoded box name and value. Box names must be in the goal app call arg form 'encoding:value'. For ints, use the form 'int:1234'. For raw bytes, encode base 64 and use 'b64' prefix as in 'b64:A=='. For printable strings, use the form 'str:hello'. For addresses, use the form 'addr:XYZ...'.", + "operationId": "lookupApplicationBoxByIDAndName", + "parameters": [ + { + "name": "application-id", + "in": "path", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "name", + "in": "query", + "description": "A box name in goal-arg form 'encoding:value'. For ints, use the form 'int:1234'. For raw bytes, use the form 'b64:A=='. For printable strings, use the form 'str:hello'. For addresses, use the form 'addr:XYZ...'.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Box information", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Box" + } + } + } + }, + "400": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/v2/applications/{application-id}/logs": { + "get": { + "tags": [ + "lookup" + ], + "description": "Lookup application logs.", + "operationId": "lookupApplicationLogsByID", + "parameters": [ + { + "name": "application-id", + "in": "path", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "limit", + "in": "query", + "description": "Maximum number of results to return. There could be additional pages even if the limit is not reached.", + "schema": { + "type": "integer" + } + }, + { + "name": "next", + "in": "query", + "description": "The next page of results. Use the next token provided by the previous results.", + "schema": { + "type": "string" + } + }, + { + "name": "txid", + "in": "query", + "description": "Lookup the specific transaction by ID.", + "schema": { + "type": "string" + } + }, + { + "name": "min-round", + "in": "query", + "description": "Include results at or after the specified min-round.", + "schema": { + "type": "integer" + } + }, + { + "name": "max-round", + "in": "query", + "description": "Include results at or before the specified max-round.", + "schema": { + "type": "integer" + } + }, + { + "name": "sender-address", + "in": "query", + "description": "Only include transactions with this sender address.", + "schema": { + "type": "string", + "x-algorand-format": "Address" + }, + "x-algorand-format": "Address" + } + ], + "responses": { + "200": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "required": [ + "application-id", + "current-round" + ], + "type": "object", + "properties": { + "application-id": { + "type": "integer", + "description": "\\[appidx\\] application index." + }, + "current-round": { + "type": "integer", + "description": "Round at which the results were computed." + }, + "next-token": { + "type": "string", + "description": "Used for pagination, when making another request provide this token with the next parameter." + }, + "log-data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ApplicationLogData" + } + } + } + } + } + } + } + } + } + }, + "/v2/assets": { + "get": { + "tags": [ + "search" + ], + "description": "Search for assets.", + "operationId": "searchForAssets", + "parameters": [ + { + "name": "include-all", + "in": "query", + "description": "Include all items including closed accounts, deleted applications, destroyed assets, opted-out asset holdings, and closed-out application localstates.", + "schema": { + "type": "boolean" + } + }, + { + "name": "limit", + "in": "query", + "description": "Maximum number of results to return. There could be additional pages even if the limit is not reached.", + "schema": { + "type": "integer" + } + }, + { + "name": "next", + "in": "query", + "description": "The next page of results. Use the next token provided by the previous results.", + "schema": { + "type": "string" + } + }, + { + "name": "creator", + "in": "query", + "description": "Filter just assets with the given creator address.", + "schema": { + "type": "string" + } + }, + { + "name": "name", + "in": "query", + "description": "Filter just assets with the given name.", + "schema": { + "type": "string" + } + }, + { + "name": "unit", + "in": "query", + "description": "Filter just assets with the given unit.", + "schema": { + "type": "string" + } + }, + { + "name": "asset-id", + "in": "query", + "description": "Asset ID", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "required": [ + "assets", + "current-round" + ], + "type": "object", + "properties": { + "assets": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Asset" + } + }, + "current-round": { + "type": "integer", + "description": "Round at which the results were computed." + }, + "next-token": { + "type": "string", + "description": "Used for pagination, when making another request provide this token with the next parameter." + } + } + } + } + } + }, + "400": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/v2/assets/{asset-id}": { + "get": { + "tags": [ + "lookup" + ], + "description": "Lookup asset information.", + "operationId": "lookupAssetByID", + "parameters": [ + { + "name": "asset-id", + "in": "path", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "include-all", + "in": "query", + "description": "Include all items including closed accounts, deleted applications, destroyed assets, opted-out asset holdings, and closed-out application localstates.", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "required": [ + "asset", + "current-round" + ], + "type": "object", + "properties": { + "asset": { + "$ref": "#/components/schemas/Asset" + }, + "current-round": { + "type": "integer", + "description": "Round at which the results were computed." + } + } + } + } + } + }, + "400": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/v2/assets/{asset-id}/balances": { + "get": { + "tags": [ + "lookup" + ], + "description": "Lookup the list of accounts who hold this asset ", + "operationId": "lookupAssetBalances", + "parameters": [ + { + "name": "include-all", + "in": "query", + "description": "Include all items including closed accounts, deleted applications, destroyed assets, opted-out asset holdings, and closed-out application localstates.", + "schema": { + "type": "boolean" + } + }, + { + "name": "limit", + "in": "query", + "description": "Maximum number of results to return. There could be additional pages even if the limit is not reached.", + "schema": { + "type": "integer" + } + }, + { + "name": "next", + "in": "query", + "description": "The next page of results. Use the next token provided by the previous results.", + "schema": { + "type": "string" + } + }, + { + "name": "currency-greater-than", + "in": "query", + "description": "Results should have an amount greater than this value. MicroAlgos are the default currency unless an asset-id is provided, in which case the asset will be used.", + "schema": { + "type": "integer" + } + }, + { + "name": "currency-less-than", + "in": "query", + "description": "Results should have an amount less than this value. MicroAlgos are the default currency unless an asset-id is provided, in which case the asset will be used.", + "schema": { + "type": "integer" + } + }, + { + "name": "asset-id", + "in": "path", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "required": [ + "balances", + "current-round" + ], + "type": "object", + "properties": { + "balances": { + "type": "array", + "items": { + "$ref": "#/components/schemas/MiniAssetHolding" + } + }, + "current-round": { + "type": "integer", + "description": "Round at which the results were computed." + }, + "next-token": { + "type": "string", + "description": "Used for pagination, when making another request provide this token with the next parameter." + } + } + } + } + } + }, + "400": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/v2/assets/{asset-id}/transactions": { + "get": { + "tags": [ + "lookup" + ], + "description": "Lookup transactions for an asset. Transactions are returned oldest to newest.", + "operationId": "lookupAssetTransactions", + "parameters": [ + { + "name": "limit", + "in": "query", + "description": "Maximum number of results to return. There could be additional pages even if the limit is not reached.", + "schema": { + "type": "integer" + } + }, + { + "name": "next", + "in": "query", + "description": "The next page of results. Use the next token provided by the previous results.", + "schema": { + "type": "string" + } + }, + { + "name": "note-prefix", + "in": "query", + "description": "Specifies a prefix which must be contained in the note field.", + "schema": { + "type": "string", + "x-algorand-format": "base64" + }, + "x-algorand-format": "base64" + }, + { + "name": "tx-type", + "in": "query", + "schema": { + "type": "string", + "enum": [ + "pay", + "keyreg", + "acfg", + "axfer", + "afrz", + "appl", + "stpf", + "hb" + ] + } + }, + { + "name": "sig-type", + "in": "query", + "description": "SigType filters just results using the specified type of signature:\n* sig - Standard\n* msig - MultiSig\n* lsig - LogicSig", + "schema": { + "type": "string", + "enum": [ + "sig", + "msig", + "lsig" + ] + } + }, + { + "name": "txid", + "in": "query", + "description": "Lookup the specific transaction by ID.", + "schema": { + "type": "string" + } + }, + { + "name": "round", + "in": "query", + "description": "Include results for the specified round.", + "schema": { + "type": "integer" + } + }, + { + "name": "min-round", + "in": "query", + "description": "Include results at or after the specified min-round.", + "schema": { + "type": "integer" + } + }, + { + "name": "max-round", + "in": "query", + "description": "Include results at or before the specified max-round.", + "schema": { + "type": "integer" + } + }, + { + "name": "before-time", + "in": "query", + "description": "Include results before the given time. Must be an RFC 3339 formatted string.", + "schema": { + "type": "string", + "format": "date-time", + "x-algorand-format": "RFC3339 String" + }, + "x-algorand-format": "RFC3339 String" + }, + { + "name": "after-time", + "in": "query", + "description": "Include results after the given time. Must be an RFC 3339 formatted string.", + "schema": { + "type": "string", + "format": "date-time", + "x-algorand-format": "RFC3339 String" + }, + "x-algorand-format": "RFC3339 String" + }, + { + "name": "currency-greater-than", + "in": "query", + "description": "Results should have an amount greater than this value. MicroAlgos are the default currency unless an asset-id is provided, in which case the asset will be used.", + "schema": { + "type": "integer" + } + }, + { + "name": "currency-less-than", + "in": "query", + "description": "Results should have an amount less than this value. MicroAlgos are the default currency unless an asset-id is provided, in which case the asset will be used.", + "schema": { + "type": "integer" + } + }, + { + "name": "address", + "in": "query", + "description": "Only include transactions with this address in one of the transaction fields.", + "schema": { + "type": "string", + "x-algorand-format": "Address" + }, + "x-algorand-format": "Address" + }, + { + "name": "address-role", + "in": "query", + "description": "Combine with the address parameter to define what type of address to search for.", + "schema": { + "type": "string", + "enum": [ + "sender", + "receiver", + "freeze-target" + ] + } + }, + { + "name": "exclude-close-to", + "in": "query", + "description": "Combine with address and address-role parameters to define what type of address to search for. The close to fields are normally treated as a receiver, if you would like to exclude them set this parameter to true.", + "schema": { + "type": "boolean" + } + }, + { + "name": "asset-id", + "in": "path", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "rekey-to", + "in": "query", + "description": "Include results which include the rekey-to field.", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "required": [ + "current-round", + "transactions" + ], + "type": "object", + "properties": { + "current-round": { + "type": "integer", + "description": "Round at which the results were computed." + }, + "next-token": { + "type": "string", + "description": "Used for pagination, when making another request provide this token with the next parameter." + }, + "transactions": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Transaction" + } + } + } + } + } + } + }, + "400": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/v2/block-headers": { + "get": { + "tags": [ + "search" + ], + "description": "Search for block headers. Block headers are returned in ascending round order. Transactions are not included in the output.", + "operationId": "searchForBlockHeaders", + "parameters": [ + { + "name": "limit", + "in": "query", + "description": "Maximum number of results to return. There could be additional pages even if the limit is not reached.", + "schema": { + "type": "integer" + } + }, + { + "name": "next", + "in": "query", + "description": "The next page of results. Use the next token provided by the previous results.", + "schema": { + "type": "string" + } + }, + { + "name": "min-round", + "in": "query", + "description": "Include results at or after the specified min-round.", + "schema": { + "type": "integer" + } + }, + { + "name": "max-round", + "in": "query", + "description": "Include results at or before the specified max-round.", + "schema": { + "type": "integer" + } + }, + { + "name": "before-time", + "in": "query", + "description": "Include results before the given time. Must be an RFC 3339 formatted string.", + "schema": { + "type": "string", + "format": "date-time", + "x-algorand-format": "RFC3339 String" + }, + "x-algorand-format": "RFC3339 String" + }, + { + "name": "after-time", + "in": "query", + "description": "Include results after the given time. Must be an RFC 3339 formatted string.", + "schema": { + "type": "string", + "format": "date-time", + "x-algorand-format": "RFC3339 String" + }, + "x-algorand-format": "RFC3339 String" + }, + { + "name": "proposers", + "in": "query", + "description": "Accounts marked as proposer in the block header's participation updates. This parameter accepts a comma separated list of addresses.", + "style": "form", + "explode": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "x-algorand-format": "Address" + } + } + }, + { + "name": "expired", + "in": "query", + "description": "Accounts marked as expired in the block header's participation updates. This parameter accepts a comma separated list of addresses.", + "style": "form", + "explode": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "x-algorand-format": "Address" + } + } + }, + { + "name": "absent", + "in": "query", + "description": "Accounts marked as absent in the block header's participation updates. This parameter accepts a comma separated list of addresses.", + "style": "form", + "explode": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "x-algorand-format": "Address" + } + } + } + ], + "responses": { + "200": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "required": [ + "blocks", + "current-round" + ], + "type": "object", + "properties": { + "current-round": { + "type": "integer", + "description": "Round at which the results were computed." + }, + "next-token": { + "type": "string", + "description": "Used for pagination, when making another request provide this token with the next parameter." + }, + "blocks": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Block" + } + } + } + } + } + } + }, + "404": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/v2/blocks/{round-number}": { + "get": { + "tags": [ + "lookup" + ], + "description": "Lookup block.", + "operationId": "lookupBlock", + "parameters": [ + { + "name": "round-number", + "in": "path", + "description": "Round number", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "header-only", + "in": "query", + "description": "Header only flag. When this is set to true, returned block does not contain the transactions", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Block" + } + } + } + }, + "404": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/v2/transactions/{txid}": { + "get": { + "tags": [ + "lookup" + ], + "description": "Lookup a single transaction.", + "operationId": "lookupTransaction", + "parameters": [ + { + "name": "txid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "required": [ + "current-round", + "transaction" + ], + "type": "object", + "properties": { + "transaction": { + "$ref": "#/components/schemas/Transaction" + }, + "current-round": { + "type": "integer", + "description": "Round at which the results were computed." + } + } + } + } + } + }, + "400": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/v2/transactions": { + "get": { + "tags": [ + "search" + ], + "description": "Search for transactions. Transactions are returned oldest to newest unless the address parameter is used, in which case results are returned newest to oldest.", + "operationId": "searchForTransactions", + "parameters": [ + { + "name": "limit", + "in": "query", + "description": "Maximum number of results to return. There could be additional pages even if the limit is not reached.", + "schema": { + "type": "integer" + } + }, + { + "name": "next", + "in": "query", + "description": "The next page of results. Use the next token provided by the previous results.", + "schema": { + "type": "string" + } + }, + { + "name": "note-prefix", + "in": "query", + "description": "Specifies a prefix which must be contained in the note field.", + "schema": { + "type": "string", + "x-algorand-format": "base64" + }, + "x-algorand-format": "base64" + }, + { + "name": "tx-type", + "in": "query", + "schema": { + "type": "string", + "enum": [ + "pay", + "keyreg", + "acfg", + "axfer", + "afrz", + "appl", + "stpf", + "hb" + ] + } + }, + { + "name": "sig-type", + "in": "query", + "description": "SigType filters just results using the specified type of signature:\n* sig - Standard\n* msig - MultiSig\n* lsig - LogicSig", + "schema": { + "type": "string", + "enum": [ + "sig", + "msig", + "lsig" + ] + } + }, + { + "name": "group-id", + "in": "query", + "description": "Lookup transactions by group ID. This field must be base64-encoded, and afterwards, base64 characters that are URL-unsafe (i.e. =, /, +) must be URL-encoded", + "schema": { + "type": "string", + "x-algorand-format": "base64" + }, + "x-algorand-format": "base64" + }, + { + "name": "txid", + "in": "query", + "description": "Lookup the specific transaction by ID.", + "schema": { + "type": "string" + } + }, + { + "name": "round", + "in": "query", + "description": "Include results for the specified round.", + "schema": { + "type": "integer" + } + }, + { + "name": "min-round", + "in": "query", + "description": "Include results at or after the specified min-round.", + "schema": { + "type": "integer" + } + }, + { + "name": "max-round", + "in": "query", + "description": "Include results at or before the specified max-round.", + "schema": { + "type": "integer" + } + }, + { + "name": "asset-id", + "in": "query", + "description": "Asset ID", + "schema": { + "type": "integer" + } + }, + { + "name": "before-time", + "in": "query", + "description": "Include results before the given time. Must be an RFC 3339 formatted string.", + "schema": { + "type": "string", + "format": "date-time", + "x-algorand-format": "RFC3339 String" + }, + "x-algorand-format": "RFC3339 String" + }, + { + "name": "after-time", + "in": "query", + "description": "Include results after the given time. Must be an RFC 3339 formatted string.", + "schema": { + "type": "string", + "format": "date-time", + "x-algorand-format": "RFC3339 String" + }, + "x-algorand-format": "RFC3339 String" + }, + { + "name": "currency-greater-than", + "in": "query", + "description": "Results should have an amount greater than this value. MicroAlgos are the default currency unless an asset-id is provided, in which case the asset will be used.", + "schema": { + "type": "integer" + } + }, + { + "name": "currency-less-than", + "in": "query", + "description": "Results should have an amount less than this value. MicroAlgos are the default currency unless an asset-id is provided, in which case the asset will be used.", + "schema": { + "type": "integer" + } + }, + { + "name": "address", + "in": "query", + "description": "Only include transactions with this address in one of the transaction fields.", + "schema": { + "type": "string", + "x-algorand-format": "Address" + }, + "x-algorand-format": "Address" + }, + { + "name": "address-role", + "in": "query", + "description": "Combine with the address parameter to define what type of address to search for.", + "schema": { + "type": "string", + "enum": [ + "sender", + "receiver", + "freeze-target" + ] + } + }, + { + "name": "exclude-close-to", + "in": "query", + "description": "Combine with address and address-role parameters to define what type of address to search for. The close to fields are normally treated as a receiver, if you would like to exclude them set this parameter to true.", + "schema": { + "type": "boolean" + } + }, + { + "name": "rekey-to", + "in": "query", + "description": "Include results which include the rekey-to field.", + "schema": { + "type": "boolean" + } + }, + { + "name": "application-id", + "in": "query", + "description": "Application ID", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "required": [ + "current-round", + "transactions" + ], + "type": "object", + "properties": { + "current-round": { + "type": "integer", + "description": "Round at which the results were computed." + }, + "next-token": { + "type": "string", + "description": "Used for pagination, when making another request provide this token with the next parameter." + }, + "transactions": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Transaction" + } + } + } + } + } + } + }, + "400": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "Hashtype": { + "type": "string", + "description": "The type of hash function used to create the proof, must be one of: \n* sha512_256 \n* sha256", + "enum": [ + "sha512_256", + "sha256" + ] + }, + "Account": { + "required": [ + "address", + "amount", + "amount-without-pending-rewards", + "min-balance", + "pending-rewards", + "rewards", + "round", + "status", + "total-apps-opted-in", + "total-assets-opted-in", + "total-box-bytes", + "total-boxes", + "total-created-apps", + "total-created-assets" + ], + "type": "object", + "properties": { + "address": { + "type": "string", + "description": "the account public key" + }, + "amount": { + "type": "integer", + "description": "total number of MicroAlgos in the account", + "x-algokit-bigint": true + }, + "min-balance": { + "type": "integer", + "description": "MicroAlgo balance required by the account.\n\nThe requirement grows based on asset and application usage.", + "x-algokit-bigint": true + }, + "amount-without-pending-rewards": { + "type": "integer", + "description": "specifies the amount of MicroAlgos in the account, without the pending rewards.", + "x-algokit-bigint": true + }, + "apps-local-state": { + "type": "array", + "description": "application local data stored in this account.\n\nNote the raw object uses `map[int] -> AppLocalState` for this type.", + "items": { + "$ref": "#/components/schemas/ApplicationLocalState" + } + }, + "apps-total-schema": { + "$ref": "#/components/schemas/ApplicationStateSchema" + }, + "apps-total-extra-pages": { + "type": "integer", + "description": "the sum of all extra application program pages for this account." + }, + "assets": { + "type": "array", + "description": "assets held by this account.\n\nNote the raw object uses `map[int] -> AssetHolding` for this type.", + "items": { + "$ref": "#/components/schemas/AssetHolding" + } + }, + "created-apps": { + "type": "array", + "description": "parameters of applications created by this account including app global data.\n\nNote: the raw account uses `map[int] -> AppParams` for this type.", + "items": { + "$ref": "#/components/schemas/Application" + } + }, + "created-assets": { + "type": "array", + "description": "parameters of assets created by this account.\n\nNote: the raw account uses `map[int] -> Asset` for this type.", + "items": { + "$ref": "#/components/schemas/Asset" + } + }, + "participation": { + "$ref": "#/components/schemas/AccountParticipation" + }, + "incentive-eligible": { + "type": "boolean", + "description": "can the account receive block incentives if its balance is in range at proposal time." + }, + "pending-rewards": { + "type": "integer", + "description": "amount of MicroAlgos of pending rewards in this account.", + "x-algokit-bigint": true + }, + "reward-base": { + "type": "integer", + "description": "used as part of the rewards computation. Only applicable to accounts which are participating.", + "x-algokit-bigint": true + }, + "rewards": { + "type": "integer", + "description": "total rewards of MicroAlgos the account has received, including pending rewards.", + "x-algokit-bigint": true + }, + "round": { + "type": "integer", + "description": "The round for which this information is relevant.", + "x-algokit-bigint": true + }, + "status": { + "type": "string", + "description": "voting status of the account's MicroAlgos\n* Offline - indicates that the associated account is delegated.\n* Online - indicates that the associated account used as part of the delegation pool.\n* NotParticipating - indicates that the associated account is neither a delegator nor a delegate." + }, + "sig-type": { + "type": "string", + "description": "the type of signature used by this account, must be one of:\n* sig\n* msig\n* lsig\n* or null if unknown", + "enum": [ + "sig", + "msig", + "lsig" + ] + }, + "total-apps-opted-in": { + "type": "integer", + "description": "The count of all applications that have been opted in, equivalent to the count of application local data (AppLocalState objects) stored in this account." + }, + "total-assets-opted-in": { + "type": "integer", + "description": "The count of all assets that have been opted in, equivalent to the count of AssetHolding objects held by this account." + }, + "total-box-bytes": { + "type": "integer", + "description": "For app-accounts only. The total number of bytes allocated for the keys and values of boxes which belong to the associated application." + }, + "total-boxes": { + "type": "integer", + "description": "For app-accounts only. The total number of boxes which belong to the associated application." + }, + "total-created-apps": { + "type": "integer", + "description": "The count of all apps (AppParams objects) created by this account." + }, + "total-created-assets": { + "type": "integer", + "description": "The count of all assets (AssetParams objects) created by this account." + }, + "auth-addr": { + "type": "string", + "description": "The address against which signing should be checked. If empty, the address of the current account is used. This field can be updated in any transaction by setting the RekeyTo field.", + "x-algorand-format": "Address" + }, + "last-proposed": { + "type": "integer", + "description": "The round in which this account last proposed the block.", + "x-algokit-bigint": true + }, + "last-heartbeat": { + "type": "integer", + "description": "The round in which this account last went online, or explicitly renewed their online status.", + "x-algokit-bigint": true + }, + "deleted": { + "type": "boolean", + "description": "Whether or not this account is currently closed." + }, + "created-at-round": { + "type": "integer", + "description": "Round during which this account first appeared in a transaction.", + "x-algokit-bigint": true + }, + "closed-at-round": { + "type": "integer", + "description": "Round during which this account was most recently closed.", + "x-algokit-bigint": true + } + }, + "description": "Account information at a given round.\n\nDefinition:\ndata/basics/userBalance.go : AccountData\n" + }, + "AccountParticipation": { + "required": [ + "selection-participation-key", + "vote-first-valid", + "vote-key-dilution", + "vote-last-valid", + "vote-participation-key" + ], + "type": "object", + "properties": { + "selection-participation-key": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "Selection public key (if any) currently registered for this round.", + "format": "byte" + }, + "vote-first-valid": { + "type": "integer", + "description": "First round for which this participation is valid.", + "x-algokit-bigint": true + }, + "vote-key-dilution": { + "type": "integer", + "description": "Number of subkeys in each batch of participation keys.", + "x-algokit-bigint": true + }, + "vote-last-valid": { + "type": "integer", + "description": "Last round for which this participation is valid.", + "x-algokit-bigint": true + }, + "vote-participation-key": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "root participation public key (if any) currently registered for this round.", + "format": "byte" + }, + "state-proof-key": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "Root of the state proof key (if any)", + "format": "byte" + } + }, + "description": "AccountParticipation describes the parameters used by this account in consensus protocol." + }, + "ApplicationStateSchema": { + "required": [ + "num-byte-slice", + "num-uint" + ], + "type": "object", + "properties": { + "num-uint": { + "type": "integer", + "description": "number of uints.", + "minimum": 0, + "maximum": 64 + }, + "num-byte-slice": { + "type": "integer", + "description": "number of byte slices.", + "minimum": 0, + "maximum": 64 + } + }, + "description": "Specifies maximums on the number of each type that may be stored." + }, + "ApplicationLocalState": { + "required": [ + "id", + "schema" + ], + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The application which this local state is for.", + "x-algokit-bigint": true + }, + "deleted": { + "type": "boolean", + "description": "Whether or not the application local state is currently deleted from its account." + }, + "opted-in-at-round": { + "type": "integer", + "description": "Round when the account opted into the application.", + "x-algokit-bigint": true + }, + "closed-out-at-round": { + "type": "integer", + "description": "Round when account closed out of the application.", + "x-algokit-bigint": true + }, + "schema": { + "$ref": "#/components/schemas/ApplicationStateSchema" + }, + "key-value": { + "$ref": "#/components/schemas/TealKeyValueStore" + } + }, + "description": "Stores local state associated with an application." + }, + "TealKeyValueStore": { + "type": "array", + "description": "Represents a key-value store for use in an application.", + "items": { + "$ref": "#/components/schemas/TealKeyValue" + } + }, + "TealKeyValue": { + "required": [ + "key", + "value" + ], + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "value": { + "$ref": "#/components/schemas/TealValue" + } + }, + "description": "Represents a key-value pair in an application store." + }, + "TealValue": { + "required": [ + "bytes", + "type", + "uint" + ], + "type": "object", + "properties": { + "type": { + "type": "integer", + "description": "type of the value. Value `1` refers to **bytes**, value `2` refers to **uint**" + }, + "bytes": { + "type": "string", + "description": "bytes value.", + "x-algokit-bytes-base64": true + }, + "uint": { + "type": "integer", + "description": "uint value.", + "x-algokit-bigint": true + } + }, + "description": "Represents a TEAL value." + }, + "Application": { + "required": [ + "id", + "params" + ], + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "application index.", + "x-algokit-bigint": true + }, + "deleted": { + "type": "boolean", + "description": "Whether or not this application is currently deleted." + }, + "created-at-round": { + "type": "integer", + "description": "Round when this application was created.", + "x-algokit-bigint": true + }, + "deleted-at-round": { + "type": "integer", + "description": "Round when this application was deleted.", + "x-algokit-bigint": true + }, + "params": { + "$ref": "#/components/schemas/ApplicationParams" + } + }, + "description": "Application index and its parameters" + }, + "ApplicationParams": { + "type": "object", + "properties": { + "creator": { + "type": "string", + "description": "The address that created this application. This is the address where the parameters and global state for this application can be found.", + "x-algorand-format": "Address" + }, + "approval-program": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "approval program.", + "format": "byte", + "x-algorand-format": "TEALProgram" + }, + "clear-state-program": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "clear state program.", + "format": "byte", + "x-algorand-format": "TEALProgram" + }, + "extra-program-pages": { + "type": "integer", + "description": "the number of extra program pages available to this app.", + "minimum": 0, + "maximum": 3 + }, + "local-state-schema": { + "$ref": "#/components/schemas/ApplicationStateSchema" + }, + "global-state-schema": { + "$ref": "#/components/schemas/ApplicationStateSchema" + }, + "global-state": { + "$ref": "#/components/schemas/TealKeyValueStore" + }, + "version": { + "type": "integer", + "description": "the number of updates to the application programs" + } + }, + "description": "Stores the global information associated with an application." + }, + "ApplicationLogData": { + "required": [ + "logs", + "txid" + ], + "type": "object", + "properties": { + "txid": { + "type": "string", + "description": "Transaction ID" + }, + "logs": { + "type": "array", + "description": "Logs for the application being executed by the transaction.", + "items": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "format": "byte" + } + } + }, + "description": "Stores the global information associated with an application." + }, + "Asset": { + "required": [ + "index", + "params" + ], + "type": "object", + "properties": { + "index": { + "type": "integer", + "description": "unique asset identifier", + "x-algokit-bigint": true + }, + "deleted": { + "type": "boolean", + "description": "Whether or not this asset is currently deleted." + }, + "created-at-round": { + "type": "integer", + "description": "Round during which this asset was created.", + "x-algokit-bigint": true + }, + "destroyed-at-round": { + "type": "integer", + "description": "Round during which this asset was destroyed.", + "x-algokit-bigint": true + }, + "params": { + "$ref": "#/components/schemas/AssetParams" + } + }, + "description": "Specifies both the unique identifier and the parameters for an asset" + }, + "AssetHolding": { + "required": [ + "amount", + "asset-id", + "is-frozen" + ], + "type": "object", + "properties": { + "amount": { + "type": "integer", + "description": "number of units held.", + "x-algokit-bigint": true + }, + "asset-id": { + "type": "integer", + "description": "Asset ID of the holding.", + "x-algokit-bigint": true + }, + "is-frozen": { + "type": "boolean", + "description": "whether or not the holding is frozen." + }, + "deleted": { + "type": "boolean", + "description": "Whether or not the asset holding is currently deleted from its account." + }, + "opted-in-at-round": { + "type": "integer", + "description": "Round during which the account opted into this asset holding.", + "x-algokit-bigint": true + }, + "opted-out-at-round": { + "type": "integer", + "description": "Round during which the account opted out of this asset holding.", + "x-algokit-bigint": true + } + }, + "description": "Describes an asset held by an account.\n\nDefinition:\ndata/basics/userBalance.go : AssetHolding" + }, + "AssetParams": { + "required": [ + "creator", + "decimals", + "total" + ], + "type": "object", + "properties": { + "clawback": { + "type": "string", + "description": "Address of account used to clawback holdings of this asset. If empty, clawback is not permitted." + }, + "creator": { + "type": "string", + "description": "The address that created this 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 in the worst case." + }, + "decimals": { + "maximum": 19, + "minimum": 0, + "type": "integer", + "description": "The number of digits to use after the decimal point when displaying this asset. 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, and so on. This value must be between 0 and 19 (inclusive)." + }, + "default-frozen": { + "type": "boolean", + "description": "Whether holdings of this asset are frozen by default." + }, + "freeze": { + "type": "string", + "description": "Address of account used to freeze holdings of this asset. If empty, freezing is not permitted." + }, + "manager": { + "type": "string", + "description": "Address of account used to manage the keys of this asset and to destroy it." + }, + "metadata-hash": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "A commitment to some unspecified asset metadata. The format of this metadata is up to the application.", + "format": "byte" + }, + "name": { + "type": "string", + "description": "Name of this asset, as supplied by the creator. Included only when the asset name is composed of printable utf-8 characters." + }, + "name-b64": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "Base64 encoded name of this asset, as supplied by the creator.", + "format": "byte" + }, + "reserve": { + "type": "string", + "description": "Address of account holding reserve (non-minted) units of this asset." + }, + "total": { + "type": "integer", + "description": "The total number of units of this asset.", + "x-algokit-bigint": true + }, + "unit-name": { + "type": "string", + "description": "Name of a unit of this asset, as supplied by the creator. Included only when the name of a unit of this asset is composed of printable utf-8 characters." + }, + "unit-name-b64": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "Base64 encoded name of a unit of this asset, as supplied by the creator.", + "format": "byte" + }, + "url": { + "type": "string", + "description": "URL where more information about the asset can be retrieved. Included only when the URL is composed of printable utf-8 characters." + }, + "url-b64": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "Base64 encoded URL where more information about the asset can be retrieved.", + "format": "byte" + } + }, + "description": "AssetParams specifies the parameters for an asset.\n\n\\[apar\\] when part of an AssetConfig transaction.\n\nDefinition:\ndata/transactions/asset.go : AssetParams" + }, + "Block": { + "required": [ + "genesis-hash", + "genesis-id", + "previous-block-hash", + "round", + "seed", + "timestamp", + "transactions-root", + "transactions-root-sha256" + ], + "type": "object", + "properties": { + "proposer": { + "type": "string", + "description": "the proposer of this block.", + "x-algorand-format": "Address" + }, + "fees-collected": { + "type": "integer", + "description": "the sum of all fees paid by transactions in this block." + }, + "bonus": { + "type": "integer", + "description": "the potential bonus payout for this block." + }, + "proposer-payout": { + "type": "integer", + "description": "the actual amount transferred to the proposer from the fee sink." + }, + "genesis-hash": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[gh\\] hash to which this block belongs.", + "format": "byte" + }, + "genesis-id": { + "type": "string", + "description": "\\[gen\\] ID to which this block belongs." + }, + "previous-block-hash": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[prev\\] Previous block hash.", + "format": "byte" + }, + "previous-block-hash-512": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[prev512\\] Previous block hash, using SHA-512.", + "format": "byte" + }, + "rewards": { + "$ref": "#/components/schemas/BlockRewards" + }, + "round": { + "type": "integer", + "description": "\\[rnd\\] Current round on which this block was appended to the chain.", + "x-algokit-bigint": true + }, + "seed": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[seed\\] Sortition seed.", + "format": "byte" + }, + "state-proof-tracking": { + "type": "array", + "description": "Tracks the status of state proofs.", + "items": { + "$ref": "#/components/schemas/StateProofTracking" + } + }, + "timestamp": { + "type": "integer", + "description": "\\[ts\\] Block creation timestamp in seconds since epoch" + }, + "transactions": { + "type": "array", + "description": "\\[txns\\] list of transactions corresponding to a given round.", + "items": { + "$ref": "#/components/schemas/Transaction" + } + }, + "transactions-root": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[txn\\] TransactionsRoot authenticates the set of transactions appearing in the block. More specifically, it's the root of a merkle tree whose leaves are the block's Txids, in lexicographic order. For the empty block, it's 0. Note that the TxnRoot does not authenticate the signatures on the transactions, only the transactions themselves. Two blocks with the same transactions but in a different order and with different signatures will have the same TxnRoot.", + "format": "byte" + }, + "transactions-root-sha256": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[txn256\\] TransactionsRootSHA256 is an auxiliary TransactionRoot, built using a vector commitment instead of a merkle tree, and SHA256 hash function instead of the default SHA512_256. This commitment can be used on environments where only the SHA256 function exists.", + "format": "byte" + }, + "transactions-root-sha512": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[txn512\\] TransactionsRootSHA512 is an auxiliary TransactionRoot, built using a vector commitment instead of a merkle tree, and SHA512 hash function instead of the default SHA512_256.", + "format": "byte" + }, + "txn-counter": { + "type": "integer", + "description": "\\[tc\\] TxnCounter counts the number of transactions committed in the ledger, from the time at which support for this feature was introduced.\n\nSpecifically, TxnCounter is the number of the next transaction that will be committed after this block. It is 0 when no transactions have ever been committed (since TxnCounter started being supported)." + }, + "upgrade-state": { + "$ref": "#/components/schemas/BlockUpgradeState" + }, + "upgrade-vote": { + "$ref": "#/components/schemas/BlockUpgradeVote" + }, + "participation-updates": { + "$ref": "#/components/schemas/ParticipationUpdates" + } + }, + "description": "Block information.\n\nDefinition:\ndata/bookkeeping/block.go : Block" + }, + "BlockRewards": { + "required": [ + "fee-sink", + "rewards-calculation-round", + "rewards-level", + "rewards-pool", + "rewards-rate", + "rewards-residue" + ], + "type": "object", + "properties": { + "fee-sink": { + "type": "string", + "description": "\\[fees\\] accepts transaction fees, it can only spend to the incentive pool." + }, + "rewards-calculation-round": { + "type": "integer", + "description": "\\[rwcalr\\] number of leftover MicroAlgos after the distribution of rewards-rate MicroAlgos for every reward unit in the next round." + }, + "rewards-level": { + "type": "integer", + "description": "\\[earn\\] How many rewards, in MicroAlgos, have been distributed to each RewardUnit of MicroAlgos since genesis." + }, + "rewards-pool": { + "type": "string", + "description": "\\[rwd\\] accepts periodic injections from the fee-sink and continually redistributes them as rewards." + }, + "rewards-rate": { + "type": "integer", + "description": "\\[rate\\] Number of new MicroAlgos added to the participation stake from rewards at the next round." + }, + "rewards-residue": { + "type": "integer", + "description": "\\[frac\\] Number of leftover MicroAlgos after the distribution of RewardsRate/rewardUnits MicroAlgos for every reward unit in the next round." + } + }, + "description": "Fields relating to rewards," + }, + "BlockUpgradeState": { + "required": [ + "current-protocol" + ], + "type": "object", + "properties": { + "current-protocol": { + "type": "string", + "description": "\\[proto\\] The current protocol version." + }, + "next-protocol": { + "type": "string", + "description": "\\[nextproto\\] The next proposed protocol version." + }, + "next-protocol-approvals": { + "type": "integer", + "description": "\\[nextyes\\] Number of blocks which approved the protocol upgrade." + }, + "next-protocol-switch-on": { + "type": "integer", + "description": "\\[nextswitch\\] Round on which the protocol upgrade will take effect." + }, + "next-protocol-vote-before": { + "type": "integer", + "description": "\\[nextbefore\\] Deadline round for this protocol upgrade (No votes will be consider after this round)." + } + }, + "description": "Fields relating to a protocol upgrade." + }, + "BlockUpgradeVote": { + "type": "object", + "properties": { + "upgrade-approve": { + "type": "boolean", + "description": "\\[upgradeyes\\] Indicates a yes vote for the current proposal." + }, + "upgrade-delay": { + "type": "integer", + "description": "\\[upgradedelay\\] Indicates the time between acceptance and execution." + }, + "upgrade-propose": { + "type": "string", + "description": "\\[upgradeprop\\] Indicates a proposed upgrade." + } + }, + "description": "Fields relating to voting for a protocol upgrade." + }, + "Box": { + "required": [ + "name", + "round", + "value" + ], + "type": "object", + "properties": { + "round": { + "type": "integer", + "description": "The round for which this information is relevant", + "x-algokit-bigint": true + }, + "name": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[name\\] box name, base64 encoded", + "format": "byte" + }, + "value": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[value\\] box value, base64 encoded.", + "format": "byte" + } + }, + "description": "Box name and its content." + }, + "BoxDescriptor": { + "required": [ + "name" + ], + "type": "object", + "properties": { + "name": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "Base64 encoded box name", + "format": "byte" + } + }, + "description": "Box descriptor describes an app box without a value." + }, + "BoxReference": { + "required": [ + "app", + "name" + ], + "type": "object", + "properties": { + "app": { + "type": "integer", + "description": "Application ID to which the box belongs, or zero if referring to the called application." + }, + "name": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "Base64 encoded box name", + "format": "byte" + } + }, + "description": "BoxReference names a box by its name and the application ID it belongs to." + }, + "HealthCheck": { + "required": [ + "db-available", + "is-migrating", + "message", + "round", + "version" + ], + "type": "object", + "properties": { + "version": { + "type": "string", + "description": "Current version." + }, + "data": { + "type": "object", + "properties": {} + }, + "round": { + "type": "integer", + "x-algokit-bigint": true + }, + "is-migrating": { + "type": "boolean" + }, + "db-available": { + "type": "boolean" + }, + "message": { + "type": "string" + }, + "errors": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "description": "A health check response." + }, + "HoldingRef": { + "required": [ + "address", + "asset" + ], + "type": "object", + "properties": { + "address": { + "type": "string", + "description": "\\[d\\] Address in access list, or the sender of the transaction.", + "x-algorand-format": "Address" + }, + "asset": { + "type": "integer", + "description": "\\[s\\] Asset ID for asset in access list." + } + }, + "description": "HoldingRef names a holding by referring to an Address and Asset it belongs to." + }, + "LocalsRef": { + "required": [ + "address", + "app" + ], + "type": "object", + "properties": { + "address": { + "type": "string", + "description": "\\[d\\] Address in access list, or the sender of the transaction.", + "x-algorand-format": "Address" + }, + "app": { + "type": "integer", + "description": "\\[p\\] Application ID for app in access list, or zero if referring to the called application." + } + }, + "description": "LocalsRef names a local state by referring to an Address and App it belongs to." + }, + "MiniAssetHolding": { + "required": [ + "address", + "amount", + "is-frozen" + ], + "type": "object", + "properties": { + "address": { + "type": "string" + }, + "amount": { + "type": "integer", + "x-algokit-bigint": true + }, + "is-frozen": { + "type": "boolean" + }, + "deleted": { + "type": "boolean", + "description": "Whether or not this asset holding is currently deleted from its account." + }, + "opted-in-at-round": { + "type": "integer", + "description": "Round during which the account opted into the asset.", + "x-algokit-bigint": true + }, + "opted-out-at-round": { + "type": "integer", + "description": "Round during which the account opted out of the asset.", + "x-algokit-bigint": true + } + }, + "description": "A simplified version of AssetHolding " + }, + "OnCompletion": { + "type": "string", + "description": "\\[apan\\] defines the what additional actions occur with the transaction.\n\nValid types:\n* noop\n* optin\n* closeout\n* clear\n* update\n* delete", + "enum": [ + "noop", + "optin", + "closeout", + "clear", + "update", + "delete" + ] + }, + "ParticipationUpdates": { + "type": "object", + "properties": { + "expired-participation-accounts": { + "type": "array", + "description": "\\[partupdrmv\\] a list of online accounts that needs to be converted to offline since their participation key expired.", + "items": { + "type": "string" + } + }, + "absent-participation-accounts": { + "type": "array", + "description": "\\[partupabs\\] a list of online accounts that need to be suspended.", + "items": { + "type": "string" + } + } + }, + "description": "Participation account data that needs to be checked/acted on by the network." + }, + "ResourceRef": { + "type": "object", + "properties": { + "address": { + "type": "string", + "description": "\\[d\\] Account whose balance record is accessible by the executing ApprovalProgram or ClearStateProgram.", + "x-algorand-format": "Address" + }, + "application-id": { + "type": "integer", + "description": "\\[p\\] Application id whose GlobalState may be read by the executing\n ApprovalProgram or ClearStateProgram." + }, + "asset-id": { + "type": "integer", + "description": "\\[s\\] Asset whose AssetParams may be read by the executing\n ApprovalProgram or ClearStateProgram.", + "x-algokit-bigint": true + }, + "box": { + "$ref": "#/components/schemas/BoxReference" + }, + "holding": { + "$ref": "#/components/schemas/HoldingRef" + }, + "local": { + "$ref": "#/components/schemas/LocalsRef" + } + }, + "description": "ResourceRef names a single resource. Only one of the fields should be set." + }, + "StateDelta": { + "type": "array", + "description": "Application state delta.", + "items": { + "$ref": "#/components/schemas/EvalDeltaKeyValue" + } + }, + "AccountStateDelta": { + "required": [ + "address", + "delta" + ], + "type": "object", + "properties": { + "address": { + "type": "string" + }, + "delta": { + "$ref": "#/components/schemas/StateDelta" + } + }, + "description": "Application state delta." + }, + "EvalDeltaKeyValue": { + "required": [ + "key", + "value" + ], + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "value": { + "$ref": "#/components/schemas/EvalDelta" + } + }, + "description": "Key-value pairs for StateDelta." + }, + "EvalDelta": { + "required": [ + "action" + ], + "type": "object", + "properties": { + "action": { + "type": "integer", + "description": "\\[at\\] delta action." + }, + "bytes": { + "type": "string", + "description": "\\[bs\\] bytes value." + }, + "uint": { + "type": "integer", + "description": "\\[ui\\] uint value.", + "x-algokit-bigint": true + } + }, + "description": "Represents a TEAL value delta." + }, + "StateSchema": { + "required": [ + "num-byte-slice", + "num-uint" + ], + "type": "object", + "properties": { + "num-uint": { + "type": "integer", + "description": "Maximum number of TEAL uints that may be stored in the key/value store.", + "minimum": 0, + "maximum": 64 + }, + "num-byte-slice": { + "type": "integer", + "description": "Maximum number of TEAL byte slices that may be stored in the key/value store.", + "minimum": 0, + "maximum": 64 + } + }, + "description": "Represents a \\[apls\\] local-state or \\[apgs\\] global-state schema. These schemas determine how much storage may be used in a local-state or global-state for an application. The more space used, the larger minimum balance must be maintained in the account holding the data." + }, + "Transaction": { + "required": [ + "fee", + "first-valid", + "last-valid", + "sender", + "tx-type" + ], + "type": "object", + "properties": { + "application-transaction": { + "$ref": "#/components/schemas/TransactionApplication" + }, + "asset-config-transaction": { + "$ref": "#/components/schemas/TransactionAssetConfig" + }, + "asset-freeze-transaction": { + "$ref": "#/components/schemas/TransactionAssetFreeze" + }, + "asset-transfer-transaction": { + "$ref": "#/components/schemas/TransactionAssetTransfer" + }, + "state-proof-transaction": { + "$ref": "#/components/schemas/TransactionStateProof" + }, + "heartbeat-transaction": { + "$ref": "#/components/schemas/TransactionHeartbeat" + }, + "auth-addr": { + "type": "string", + "description": "\\[sgnr\\] this is included with signed transactions when the signing address does not equal the sender. The backend can use this to ensure that auth addr is equal to the accounts auth addr.", + "x-algorand-format": "Address" + }, + "close-rewards": { + "type": "integer", + "description": "\\[rc\\] rewards applied to close-remainder-to account." + }, + "closing-amount": { + "type": "integer", + "description": "\\[ca\\] closing amount for transaction.", + "x-algokit-bigint": true + }, + "confirmed-round": { + "type": "integer", + "description": "Round when the transaction was confirmed.", + "x-algokit-bigint": true + }, + "created-application-index": { + "type": "integer", + "description": "Specifies an application index (ID) if an application was created with this transaction.", + "x-algokit-bigint": true + }, + "created-asset-index": { + "type": "integer", + "description": "Specifies an asset index (ID) if an asset was created with this transaction.", + "x-algokit-bigint": true + }, + "fee": { + "type": "integer", + "description": "\\[fee\\] Transaction fee.", + "x-algokit-bigint": true + }, + "first-valid": { + "type": "integer", + "description": "\\[fv\\] First valid round for this transaction." + }, + "genesis-hash": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[gh\\] Hash of genesis block.", + "format": "byte" + }, + "genesis-id": { + "type": "string", + "description": "\\[gen\\] genesis block ID." + }, + "group": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[grp\\] Base64 encoded byte array of a sha512/256 digest. When present indicates that this transaction is part of a transaction group and the value is the sha512/256 hash of the transactions in that group.", + "format": "byte" + }, + "id": { + "type": "string", + "description": "Transaction ID" + }, + "intra-round-offset": { + "type": "integer", + "description": "Offset into the round where this transaction was confirmed." + }, + "keyreg-transaction": { + "$ref": "#/components/schemas/TransactionKeyreg" + }, + "last-valid": { + "type": "integer", + "description": "\\[lv\\] Last valid round for this transaction." + }, + "lease": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[lx\\] Base64 encoded 32-byte array. Lease enforces mutual exclusion of transactions. If this field is nonzero, then once the transaction is confirmed, it acquires the lease identified by the (Sender, Lease) pair of the transaction until the LastValid round passes. While this transaction possesses the lease, no other transaction specifying this lease can be confirmed.", + "format": "byte" + }, + "note": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[note\\] Free form data.", + "format": "byte" + }, + "payment-transaction": { + "$ref": "#/components/schemas/TransactionPayment" + }, + "receiver-rewards": { + "type": "integer", + "description": "\\[rr\\] rewards applied to receiver account." + }, + "rekey-to": { + "type": "string", + "description": "\\[rekey\\] when included in a valid transaction, the accounts auth addr will be updated with this value and future signatures must be signed with the key represented by this address.", + "x-algorand-format": "Address" + }, + "round-time": { + "type": "integer", + "description": "Time when the block this transaction is in was confirmed." + }, + "sender": { + "type": "string", + "description": "\\[snd\\] Sender's address." + }, + "sender-rewards": { + "type": "integer", + "description": "\\[rs\\] rewards applied to sender account." + }, + "signature": { + "$ref": "#/components/schemas/TransactionSignature" + }, + "tx-type": { + "type": "string", + "description": "\\[type\\] Indicates what type of transaction this is. Different types have different fields.\n\nValid types, and where their fields are stored:\n* \\[pay\\] payment-transaction\n* \\[keyreg\\] keyreg-transaction\n* \\[acfg\\] asset-config-transaction\n* \\[axfer\\] asset-transfer-transaction\n* \\[afrz\\] asset-freeze-transaction\n* \\[appl\\] application-transaction\n* \\[stpf\\] state-proof-transaction\n* \\[hb\\] heartbeat-transaction", + "enum": [ + "pay", + "keyreg", + "acfg", + "axfer", + "afrz", + "appl", + "stpf", + "hb" + ], + "x-algorand-format": "tx-type-enum" + }, + "local-state-delta": { + "type": "array", + "description": "\\[ld\\] Local state key/value changes for the application being executed by this transaction.", + "items": { + "$ref": "#/components/schemas/AccountStateDelta" + } + }, + "global-state-delta": { + "$ref": "#/components/schemas/StateDelta" + }, + "logs": { + "type": "array", + "description": "\\[lg\\] Logs for the application being executed by this transaction.", + "items": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "format": "byte" + } + }, + "inner-txns": { + "type": "array", + "description": "Inner transactions produced by application execution.", + "items": { + "$ref": "#/components/schemas/Transaction" + } + } + }, + "description": "Contains all fields common to all transactions and serves as an envelope to all transactions type. Represents both regular and inner transactions.\n\nDefinition:\ndata/transactions/signedtxn.go : SignedTxn\ndata/transactions/transaction.go : Transaction\n" + }, + "TransactionApplication": { + "required": [ + "application-id", + "on-completion" + ], + "type": "object", + "properties": { + "application-id": { + "type": "integer", + "description": "\\[apid\\] ID of the application being configured or empty if creating." + }, + "on-completion": { + "$ref": "#/components/schemas/OnCompletion" + }, + "application-args": { + "type": "array", + "description": "\\[apaa\\] transaction specific arguments accessed from the application's approval-program and clear-state-program.", + "items": { + "type": "string" + } + }, + "access": { + "type": "array", + "description": "\\[al\\] Access unifies `accounts`, `foreign-apps`, `foreign-assets`, and `box-references` under a single list. If access is non-empty, these lists must be empty. If access is empty, those lists may be non-empty.", + "items": { + "$ref": "#/components/schemas/ResourceRef" + } + }, + "accounts": { + "type": "array", + "description": "\\[apat\\] List of accounts in addition to the sender that may be accessed from the application's approval-program and clear-state-program.", + "items": { + "type": "string", + "x-algorand-format": "Address" + } + }, + "box-references": { + "type": "array", + "description": "\\[apbx\\] the boxes that can be accessed by this transaction (and others in the same group).", + "items": { + "$ref": "#/components/schemas/BoxReference" + } + }, + "foreign-apps": { + "type": "array", + "description": "\\[apfa\\] Lists the applications in addition to the application-id whose global states may be accessed by this application's approval-program and clear-state-program. The access is read-only.", + "items": { + "type": "integer" + } + }, + "foreign-assets": { + "type": "array", + "description": "\\[apas\\] lists the assets whose parameters may be accessed by this application's ApprovalProgram and ClearStateProgram. The access is read-only.", + "items": { + "type": "integer" + } + }, + "local-state-schema": { + "$ref": "#/components/schemas/StateSchema" + }, + "global-state-schema": { + "$ref": "#/components/schemas/StateSchema" + }, + "approval-program": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[apap\\] Logic executed for every application transaction, except when on-completion is set to \"clear\". It can read and write global state for the application, as well as account-specific local state. Approval programs may reject the transaction.", + "format": "byte", + "x-algorand-format": "TEALProgram" + }, + "clear-state-program": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[apsu\\] Logic executed for application transactions with on-completion set to \"clear\". It can read and write global state for the application, as well as account-specific local state. Clear state programs cannot reject the transaction.", + "format": "byte", + "x-algorand-format": "TEALProgram" + }, + "extra-program-pages": { + "type": "integer", + "description": "\\[epp\\] specifies the additional app program len requested in pages.", + "minimum": 0, + "maximum": 3 + }, + "reject-version": { + "type": "integer", + "description": "\\[aprv\\] the lowest application version for which this transaction should immediately fail. 0 indicates that no version check should be performed." + } + }, + "description": "Fields for application transactions.\n\nDefinition:\ndata/transactions/application.go : ApplicationCallTxnFields" + }, + "TransactionAssetConfig": { + "type": "object", + "properties": { + "asset-id": { + "type": "integer", + "description": "\\[xaid\\] ID of the asset being configured or empty if creating.", + "x-algokit-bigint": true + }, + "params": { + "$ref": "#/components/schemas/AssetParams" + } + }, + "description": "Fields for asset allocation, re-configuration, and destruction.\n\n\nA zero value for asset-id indicates asset creation.\nA zero value for the params indicates asset destruction.\n\nDefinition:\ndata/transactions/asset.go : AssetConfigTxnFields" + }, + "TransactionAssetFreeze": { + "required": [ + "address", + "asset-id", + "new-freeze-status" + ], + "type": "object", + "properties": { + "address": { + "type": "string", + "description": "\\[fadd\\] Address of the account whose asset is being frozen or thawed." + }, + "asset-id": { + "type": "integer", + "description": "\\[faid\\] ID of the asset being frozen or thawed.", + "x-algokit-bigint": true + }, + "new-freeze-status": { + "type": "boolean", + "description": "\\[afrz\\] The new freeze status." + } + }, + "description": "Fields for an asset freeze transaction.\n\nDefinition:\ndata/transactions/asset.go : AssetFreezeTxnFields" + }, + "TransactionStateProof": { + "type": "object", + "properties": { + "state-proof-type": { + "type": "integer", + "description": "\\[sptype\\] Type of the state proof. Integer representing an entry defined in protocol/stateproof.go", + "x-algokit-bigint": true + }, + "state-proof": { + "$ref": "#/components/schemas/StateProofFields" + }, + "message": { + "$ref": "#/components/schemas/IndexerStateProofMessage" + } + }, + "description": "Fields for a state proof transaction. \n\nDefinition:\ndata/transactions/stateproof.go : StateProofTxnFields" + }, + "TransactionHeartbeat": { + "required": [ + "hb-address", + "hb-key-dilution", + "hb-proof", + "hb-seed", + "hb-vote-id" + ], + "type": "object", + "properties": { + "hb-address": { + "type": "string", + "description": "\\[hbad\\] HbAddress is the account this txn is proving onlineness for." + }, + "hb-proof": { + "$ref": "#/components/schemas/HbProofFields" + }, + "hb-seed": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[hbsd\\] HbSeed must be the block seed for the this transaction's firstValid block.", + "format": "byte" + }, + "hb-vote-id": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[hbvid\\] HbVoteID must match the HbAddress account's current VoteID.", + "format": "byte" + }, + "hb-key-dilution": { + "type": "integer", + "description": "\\[hbkd\\] HbKeyDilution must match HbAddress account's current KeyDilution.", + "x-algokit-bigint": true + } + }, + "description": "Fields for a heartbeat transaction.\n\nDefinition:\ndata/transactions/heartbeat.go : HeartbeatTxnFields" + }, + "TransactionAssetTransfer": { + "required": [ + "amount", + "asset-id", + "receiver" + ], + "type": "object", + "properties": { + "amount": { + "type": "integer", + "description": "\\[aamt\\] Amount of asset to transfer. A zero amount transferred to self allocates that asset in the account's Assets map.", + "x-algokit-bigint": true + }, + "asset-id": { + "type": "integer", + "description": "\\[xaid\\] ID of the asset being transferred.", + "x-algokit-bigint": true + }, + "close-amount": { + "type": "integer", + "description": "Number of assets transferred to the close-to account as part of the transaction.", + "x-algokit-bigint": true + }, + "close-to": { + "type": "string", + "description": "\\[aclose\\] Indicates that the asset should be removed from the account's Assets map, and specifies where the remaining asset holdings should be transferred. It's always valid to transfer remaining asset holdings to the creator account." + }, + "receiver": { + "type": "string", + "description": "\\[arcv\\] Recipient address of the transfer." + }, + "sender": { + "type": "string", + "description": "\\[asnd\\] The effective sender during a clawback transactions. If this is not a zero value, the real transaction sender must be the Clawback address from the AssetParams." + } + }, + "description": "Fields for an asset transfer transaction.\n\nDefinition:\ndata/transactions/asset.go : AssetTransferTxnFields" + }, + "TransactionKeyreg": { + "type": "object", + "properties": { + "non-participation": { + "type": "boolean", + "description": "\\[nonpart\\] Mark the account as participating or non-participating." + }, + "selection-participation-key": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[selkey\\] Public key used with the Verified Random Function (VRF) result during committee selection.", + "format": "byte" + }, + "vote-first-valid": { + "type": "integer", + "description": "\\[votefst\\] First round this participation key is valid.", + "x-algokit-bigint": true + }, + "vote-key-dilution": { + "type": "integer", + "description": "\\[votekd\\] Number of subkeys in each batch of participation keys.", + "x-algokit-bigint": true + }, + "vote-last-valid": { + "type": "integer", + "description": "\\[votelst\\] Last round this participation key is valid.", + "x-algokit-bigint": true + }, + "vote-participation-key": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[votekey\\] Participation public key used in key registration transactions.", + "format": "byte" + }, + "state-proof-key": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[sprfkey\\] State proof key used in key registration transactions.", + "format": "byte" + } + }, + "description": "Fields for a keyreg transaction.\n\nDefinition:\ndata/transactions/keyreg.go : KeyregTxnFields" + }, + "TransactionPayment": { + "required": [ + "amount", + "receiver" + ], + "type": "object", + "properties": { + "amount": { + "type": "integer", + "description": "\\[amt\\] number of MicroAlgos intended to be transferred.", + "x-algokit-bigint": true + }, + "close-amount": { + "type": "integer", + "description": "Number of MicroAlgos that were sent to the close-remainder-to address when closing the sender account." + }, + "close-remainder-to": { + "type": "string", + "description": "\\[close\\] when set, indicates that the sending account should be closed and all remaining funds be transferred to this address." + }, + "receiver": { + "type": "string", + "description": "\\[rcv\\] receiver's address." + } + }, + "description": "Fields for a payment transaction.\n\nDefinition:\ndata/transactions/payment.go : PaymentTxnFields" + }, + "TransactionSignature": { + "type": "object", + "properties": { + "logicsig": { + "$ref": "#/components/schemas/TransactionSignatureLogicsig" + }, + "multisig": { + "$ref": "#/components/schemas/TransactionSignatureMultisig" + }, + "sig": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[sig\\] Standard ed25519 signature.", + "format": "byte" + } + }, + "description": "Validation signature associated with some data. Only one of the signatures should be provided." + }, + "TransactionSignatureLogicsig": { + "required": [ + "logic" + ], + "type": "object", + "properties": { + "args": { + "type": "array", + "description": "\\[arg\\] Logic arguments, base64 encoded.", + "items": { + "type": "string" + } + }, + "logic": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[l\\] Program signed by a signature or multi signature, or hashed to be the address of an account. Base64 encoded TEAL program.", + "format": "byte" + }, + "multisig-signature": { + "$ref": "#/components/schemas/TransactionSignatureMultisig" + }, + "logic-multisig-signature": { + "$ref": "#/components/schemas/TransactionSignatureMultisig" + }, + "signature": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[sig\\] ed25519 signature.", + "format": "byte" + } + }, + "description": "\\[lsig\\] Programatic transaction signature.\n\nDefinition:\ndata/transactions/logicsig.go" + }, + "TransactionSignatureMultisig": { + "type": "object", + "properties": { + "subsignature": { + "type": "array", + "description": "\\[subsig\\] holds pairs of public key and signatures.", + "items": { + "$ref": "#/components/schemas/TransactionSignatureMultisigSubsignature" + } + }, + "threshold": { + "type": "integer", + "description": "\\[thr\\]" + }, + "version": { + "type": "integer", + "description": "\\[v\\]" + } + }, + "description": "structure holding multiple subsignatures.\n\nDefinition:\ncrypto/multisig.go : MultisigSig" + }, + "TransactionSignatureMultisigSubsignature": { + "type": "object", + "properties": { + "public-key": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[pk\\]", + "format": "byte" + }, + "signature": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[s\\]", + "format": "byte" + } + } + }, + "StateProofFields": { + "type": "object", + "properties": { + "sig-commit": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[c\\]", + "format": "byte" + }, + "signed-weight": { + "type": "integer", + "description": "\\[w\\]", + "x-algokit-bigint": true + }, + "sig-proofs": { + "$ref": "#/components/schemas/MerkleArrayProof" + }, + "part-proofs": { + "$ref": "#/components/schemas/MerkleArrayProof" + }, + "salt-version": { + "type": "integer", + "description": "\\[v\\] Salt version of the merkle signature." + }, + "reveals": { + "type": "array", + "description": "\\[r\\] Note that this is actually stored as a map[uint64] - Reveal in the actual msgp", + "items": { + "$ref": "#/components/schemas/StateProofReveal" + } + }, + "positions-to-reveal": { + "type": "array", + "description": "\\[pr\\] Sequence of reveal positions.", + "items": { + "type": "integer", + "x-algokit-bigint": true + } + } + }, + "description": "\\[sp\\] represents a state proof.\n\nDefinition:\ncrypto/stateproof/structs.go : StateProof" + }, + "HbProofFields": { + "type": "object", + "properties": { + "hb-sig": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[s\\] Signature of the heartbeat message.", + "format": "byte" + }, + "hb-pk": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[p\\] Public key of the heartbeat message.", + "format": "byte" + }, + "hb-pk2": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[p2\\] Key for new-style two-level ephemeral signature.", + "format": "byte" + }, + "hb-pk1sig": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[p1s\\] Signature of OneTimeSignatureSubkeyOffsetID(PK, Batch, Offset) under the key PK2.", + "format": "byte" + }, + "hb-pk2sig": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[p2s\\] Signature of OneTimeSignatureSubkeyBatchID(PK2, Batch) under the master key (OneTimeSignatureVerifier).", + "format": "byte" + } + }, + "description": "\\[hbprf\\] HbProof is a signature using HeartbeatAddress's partkey, thereby showing it is online." + }, + "IndexerStateProofMessage": { + "type": "object", + "properties": { + "block-headers-commitment": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[b\\]", + "format": "byte" + }, + "voters-commitment": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[v\\]", + "format": "byte" + }, + "ln-proven-weight": { + "type": "integer", + "description": "\\[P\\]", + "x-algokit-bigint": true + }, + "first-attested-round": { + "type": "integer", + "description": "\\[f\\]", + "x-algokit-bigint": true + }, + "latest-attested-round": { + "type": "integer", + "description": "\\[l\\]", + "x-algokit-bigint": true + } + } + }, + "StateProofReveal": { + "type": "object", + "properties": { + "position": { + "type": "integer", + "description": "The position in the signature and participants arrays corresponding to this entry.", + "x-algokit-bigint": true + }, + "sig-slot": { + "$ref": "#/components/schemas/StateProofSigSlot" + }, + "participant": { + "$ref": "#/components/schemas/StateProofParticipant" + } + } + }, + "StateProofSigSlot": { + "type": "object", + "properties": { + "signature": { + "$ref": "#/components/schemas/StateProofSignature" + }, + "lower-sig-weight": { + "type": "integer", + "description": "\\[l\\] The total weight of signatures in the lower-numbered slots.", + "x-algokit-bigint": true + } + } + }, + "StateProofSignature": { + "type": "object", + "properties": { + "falcon-signature": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "format": "byte" + }, + "merkle-array-index": { + "type": "integer", + "x-algorand-foramt": "uint64" + }, + "proof": { + "$ref": "#/components/schemas/MerkleArrayProof" + }, + "verifying-key": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[vkey\\]", + "format": "byte" + } + } + }, + "StateProofParticipant": { + "type": "object", + "properties": { + "verifier": { + "$ref": "#/components/schemas/StateProofVerifier" + }, + "weight": { + "type": "integer", + "description": "\\[w\\]", + "x-algokit-bigint": true + } + } + }, + "StateProofVerifier": { + "type": "object", + "properties": { + "commitment": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[cmt\\] Represents the root of the vector commitment tree.", + "format": "byte" + }, + "key-lifetime": { + "type": "integer", + "description": "\\[lf\\] Key lifetime.", + "x-algokit-bigint": true + } + } + }, + "StateProofTracking": { + "type": "object", + "properties": { + "type": { + "type": "integer", + "description": "State Proof Type. Note the raw object uses map with this as key.", + "x-algokit-bigint": true + }, + "voters-commitment": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "\\[v\\] Root of a vector commitment containing online accounts that will help sign the proof.", + "format": "byte" + }, + "online-total-weight": { + "type": "integer", + "description": "\\[t\\] The total number of microalgos held by the online accounts during the StateProof round." + }, + "next-round": { + "type": "integer", + "description": "\\[n\\] Next round for which we will accept a state proof transaction." + } + } + }, + "MerkleArrayProof": { + "type": "object", + "properties": { + "path": { + "type": "array", + "description": "\\[pth\\]", + "items": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "format": "byte" + } + }, + "hash-factory": { + "$ref": "#/components/schemas/HashFactory" + }, + "tree-depth": { + "type": "integer", + "description": "\\[td\\]", + "x-algorand-format": "uint8" + } + } + }, + "HashFactory": { + "type": "object", + "properties": { + "hash-type": { + "type": "integer", + "description": "\\[t\\]", + "x-algorand-format": "uint16" + } + } + } + }, + "responses": { + "AccountResponse": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "required": [ + "account", + "current-round" + ], + "type": "object", + "properties": { + "account": { + "$ref": "#/components/schemas/Account" + }, + "current-round": { + "type": "integer", + "description": "Round at which the results were computed." + } + } + } + } + } + }, + "AssetHoldingsResponse": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "required": [ + "assets", + "current-round" + ], + "type": "object", + "properties": { + "current-round": { + "type": "integer", + "description": "Round at which the results were computed." + }, + "next-token": { + "type": "string", + "description": "Used for pagination, when making another request provide this token with the next parameter." + }, + "assets": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AssetHolding" + } + } + } + } + } + } + }, + "AccountsResponse": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "required": [ + "accounts", + "current-round" + ], + "type": "object", + "properties": { + "accounts": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Account" + } + }, + "current-round": { + "type": "integer", + "description": "Round at which the results were computed." + }, + "next-token": { + "type": "string", + "description": "Used for pagination, when making another request provide this token with the next parameter." + } + } + } + } + } + }, + "AssetBalancesResponse": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "required": [ + "balances", + "current-round" + ], + "type": "object", + "properties": { + "balances": { + "type": "array", + "items": { + "$ref": "#/components/schemas/MiniAssetHolding" + } + }, + "current-round": { + "type": "integer", + "description": "Round at which the results were computed." + }, + "next-token": { + "type": "string", + "description": "Used for pagination, when making another request provide this token with the next parameter." + } + } + } + } + } + }, + "ApplicationResponse": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "required": [ + "current-round" + ], + "type": "object", + "properties": { + "application": { + "$ref": "#/components/schemas/Application" + }, + "current-round": { + "type": "integer", + "description": "Round at which the results were computed." + } + } + } + } + } + }, + "ApplicationsResponse": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "required": [ + "applications", + "current-round" + ], + "type": "object", + "properties": { + "applications": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Application" + } + }, + "current-round": { + "type": "integer", + "description": "Round at which the results were computed." + }, + "next-token": { + "type": "string", + "description": "Used for pagination, when making another request provide this token with the next parameter." + } + } + } + } + } + }, + "ApplicationLogsResponse": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "required": [ + "application-id", + "current-round" + ], + "type": "object", + "properties": { + "application-id": { + "type": "integer", + "description": "\\[appidx\\] application index." + }, + "current-round": { + "type": "integer", + "description": "Round at which the results were computed." + }, + "next-token": { + "type": "string", + "description": "Used for pagination, when making another request provide this token with the next parameter." + }, + "log-data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ApplicationLogData" + } + } + } + } + } + } + }, + "ApplicationLocalStatesResponse": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "required": [ + "apps-local-states", + "current-round" + ], + "type": "object", + "properties": { + "apps-local-states": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ApplicationLocalState" + } + }, + "current-round": { + "type": "integer", + "description": "Round at which the results were computed." + }, + "next-token": { + "type": "string", + "description": "Used for pagination, when making another request provide this token with the next parameter." + } + } + } + } + } + }, + "AssetResponse": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "required": [ + "asset", + "current-round" + ], + "type": "object", + "properties": { + "asset": { + "$ref": "#/components/schemas/Asset" + }, + "current-round": { + "type": "integer", + "description": "Round at which the results were computed." + } + } + } + } + } + }, + "BoxesResponse": { + "description": "Box names of an application", + "content": { + "application/json": { + "schema": { + "required": [ + "application-id", + "boxes" + ], + "type": "object", + "properties": { + "application-id": { + "type": "integer", + "description": "\\[appidx\\] application index." + }, + "boxes": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BoxDescriptor" + } + }, + "next-token": { + "type": "string", + "description": "Used for pagination, when making another request provide this token with the next parameter." + } + } + } + } + } + }, + "BoxResponse": { + "description": "Box information", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Box" + } + } + } + }, + "ErrorResponse": { + "description": "Response for errors", + "content": { + "application/json": { + "schema": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": {} + }, + "message": { + "type": "string" + } + } + } + } + } + }, + "AssetsResponse": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "required": [ + "assets", + "current-round" + ], + "type": "object", + "properties": { + "assets": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Asset" + } + }, + "current-round": { + "type": "integer", + "description": "Round at which the results were computed." + }, + "next-token": { + "type": "string", + "description": "Used for pagination, when making another request provide this token with the next parameter." + } + } + } + } + } + }, + "BlockResponse": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Block" + } + } + } + }, + "BlockHeadersResponse": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "required": [ + "blocks", + "current-round" + ], + "type": "object", + "properties": { + "current-round": { + "type": "integer", + "description": "Round at which the results were computed." + }, + "next-token": { + "type": "string", + "description": "Used for pagination, when making another request provide this token with the next parameter." + }, + "blocks": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Block" + } + } + } + } + } + } + }, + "HealthCheckResponse": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HealthCheck" + } + } + } + }, + "TransactionResponse": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "required": [ + "current-round", + "transaction" + ], + "type": "object", + "properties": { + "transaction": { + "$ref": "#/components/schemas/Transaction" + }, + "current-round": { + "type": "integer", + "description": "Round at which the results were computed." + } + } + } + } + } + }, + "TransactionsResponse": { + "description": "(empty)", + "content": { + "application/json": { + "schema": { + "required": [ + "current-round", + "transactions" + ], + "type": "object", + "properties": { + "current-round": { + "type": "integer", + "description": "Round at which the results were computed." + }, + "next-token": { + "type": "string", + "description": "Used for pagination, when making another request provide this token with the next parameter." + }, + "transactions": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Transaction" + } + } + } + } + } + } + } + }, + "parameters": { + "proposers": { + "name": "proposers", + "in": "query", + "description": "Accounts marked as proposer in the block header's participation updates. This parameter accepts a comma separated list of addresses.", + "style": "form", + "explode": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "x-algorand-format": "Address" + } + } + }, + "absent": { + "name": "absent", + "in": "query", + "description": "Accounts marked as absent in the block header's participation updates. This parameter accepts a comma separated list of addresses.", + "style": "form", + "explode": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "x-algorand-format": "Address" + } + } + }, + "expired": { + "name": "expired", + "in": "query", + "description": "Accounts marked as expired in the block header's participation updates. This parameter accepts a comma separated list of addresses.", + "style": "form", + "explode": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "x-algorand-format": "Address" + } + } + }, + "account-id": { + "name": "account-id", + "in": "path", + "description": "account string", + "required": true, + "schema": { + "type": "string" + } + }, + "address": { + "name": "address", + "in": "query", + "description": "Only include transactions with this address in one of the transaction fields.", + "schema": { + "type": "string", + "x-algorand-format": "Address" + }, + "x-algorand-format": "Address" + }, + "address-role": { + "name": "address-role", + "in": "query", + "description": "Combine with the address parameter to define what type of address to search for.", + "schema": { + "type": "string", + "enum": [ + "sender", + "receiver", + "freeze-target" + ] + } + }, + "after-time": { + "name": "after-time", + "in": "query", + "description": "Include results after the given time. Must be an RFC 3339 formatted string.", + "schema": { + "type": "string", + "format": "date-time", + "x-algorand-format": "RFC3339 String" + }, + "x-algorand-format": "RFC3339 String" + }, + "application-id": { + "name": "application-id", + "in": "query", + "description": "Application ID", + "schema": { + "type": "integer" + } + }, + "asset-id": { + "name": "asset-id", + "in": "query", + "description": "Asset ID", + "schema": { + "type": "integer" + } + }, + "before-time": { + "name": "before-time", + "in": "query", + "description": "Include results before the given time. Must be an RFC 3339 formatted string.", + "schema": { + "type": "string", + "format": "date-time", + "x-algorand-format": "RFC3339 String" + }, + "x-algorand-format": "RFC3339 String" + }, + "box-name": { + "name": "name", + "in": "query", + "description": "A box name in goal-arg form 'encoding:value'. For ints, use the form 'int:1234'. For raw bytes, use the form 'b64:A=='. For printable strings, use the form 'str:hello'. For addresses, use the form 'addr:XYZ...'.", + "required": true, + "schema": { + "type": "string" + } + }, + "currency-greater-than": { + "name": "currency-greater-than", + "in": "query", + "description": "Results should have an amount greater than this value. MicroAlgos are the default currency unless an asset-id is provided, in which case the asset will be used.", + "schema": { + "type": "integer" + } + }, + "currency-less-than": { + "name": "currency-less-than", + "in": "query", + "description": "Results should have an amount less than this value. MicroAlgos are the default currency unless an asset-id is provided, in which case the asset will be used.", + "schema": { + "type": "integer" + } + }, + "exclude-close-to": { + "name": "exclude-close-to", + "in": "query", + "description": "Combine with address and address-role parameters to define what type of address to search for. The close to fields are normally treated as a receiver, if you would like to exclude them set this parameter to true.", + "schema": { + "type": "boolean" + } + }, + "header-only": { + "name": "header-only", + "in": "query", + "description": "Header only flag. When this is set to true, returned block does not contain the transactions", + "schema": { + "type": "boolean" + } + }, + "include-all": { + "name": "include-all", + "in": "query", + "description": "Include all items including closed accounts, deleted applications, destroyed assets, opted-out asset holdings, and closed-out application localstates.", + "schema": { + "type": "boolean" + } + }, + "exclude": { + "name": "exclude", + "in": "query", + "description": "Exclude additional items such as asset holdings, application local data stored for this account, asset parameters created by this account, and application parameters created by this account.", + "style": "form", + "explode": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "all", + "assets", + "created-assets", + "apps-local-state", + "created-apps", + "none" + ] + } + } + }, + "limit": { + "name": "limit", + "in": "query", + "description": "Maximum number of results to return. There could be additional pages even if the limit is not reached.", + "schema": { + "type": "integer" + } + }, + "max-round": { + "name": "max-round", + "in": "query", + "description": "Include results at or before the specified max-round.", + "schema": { + "type": "integer" + } + }, + "min-round": { + "name": "min-round", + "in": "query", + "description": "Include results at or after the specified min-round.", + "schema": { + "type": "integer" + } + }, + "next": { + "name": "next", + "in": "query", + "description": "The next page of results. Use the next token provided by the previous results.", + "schema": { + "type": "string" + } + }, + "note-prefix": { + "name": "note-prefix", + "in": "query", + "description": "Specifies a prefix which must be contained in the note field.", + "schema": { + "type": "string", + "x-algorand-format": "base64" + }, + "x-algorand-format": "base64" + }, + "online-only": { + "name": "online-only", + "in": "query", + "description": "When this is set to true, return only accounts whose participation status is currently online.", + "schema": { + "type": "boolean" + } + }, + "rekey-to": { + "name": "rekey-to", + "in": "query", + "description": "Include results which include the rekey-to field.", + "schema": { + "type": "boolean" + } + }, + "round": { + "name": "round", + "in": "query", + "description": "Include results for the specified round.", + "schema": { + "type": "integer" + } + }, + "round-number": { + "name": "round-number", + "in": "path", + "description": "Round number", + "required": true, + "schema": { + "type": "integer" + } + }, + "sender-address": { + "name": "sender-address", + "in": "query", + "description": "Only include transactions with this sender address.", + "schema": { + "type": "string", + "x-algorand-format": "Address" + }, + "x-algorand-format": "Address" + }, + "sig-type": { + "name": "sig-type", + "in": "query", + "description": "SigType filters just results using the specified type of signature:\n* sig - Standard\n* msig - MultiSig\n* lsig - LogicSig", + "schema": { + "type": "string", + "enum": [ + "sig", + "msig", + "lsig" + ] + } + }, + "auth-addr": { + "name": "auth-addr", + "in": "query", + "description": "Include accounts configured to use this spending key.", + "schema": { + "type": "string", + "x-algorand-format": "Address" + }, + "x-algorand-format": "Address" + }, + "group-id": { + "name": "group-id", + "in": "query", + "description": "Lookup transactions by group ID. This field must be base64-encoded, and afterwards, base64 characters that are URL-unsafe (i.e. =, /, +) must be URL-encoded", + "schema": { + "type": "string", + "x-algorand-format": "base64" + }, + "x-algorand-format": "base64" + }, + "txid": { + "name": "txid", + "in": "query", + "description": "Lookup the specific transaction by ID.", + "schema": { + "type": "string" + } + }, + "tx-type": { + "name": "tx-type", + "in": "query", + "schema": { + "type": "string", + "enum": [ + "pay", + "keyreg", + "acfg", + "axfer", + "afrz", + "appl", + "stpf", + "hb" + ] + } + } + } + }, + "x-original-swagger-version": "2.0" +} \ No newline at end of file diff --git a/algokit-configs/openapi-converter/specs/kmd.oas3.json b/algokit-configs/openapi-converter/specs/kmd.oas3.json new file mode 100644 index 000000000..029b87aa9 --- /dev/null +++ b/algokit-configs/openapi-converter/specs/kmd.oas3.json @@ -0,0 +1,1953 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "for KMD HTTP API", + "description": "API for KMD (Key Management Daemon)", + "contact": { + "email": "contact@algorand.com" + }, + "version": "0.0.1" + }, + "servers": [ + { + "url": "http://localhost/" + } + ], + "security": [ + { + "api_key": [] + } + ], + "paths": { + "/swagger.json": { + "get": { + "summary": "Gets the current swagger spec.", + "description": "Returns the entire swagger spec in json.", + "operationId": "SwaggerHandler", + "responses": { + "200": { + "description": "The current swagger spec", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + }, + "default": { + "description": "Unknown Error", + "content": {} + } + } + } + }, + "/v1/key": { + "post": { + "summary": "Generate a key", + "description": "Generates the next key in the deterministic key sequence (as determined by the master derivation key) and adds it to the wallet, returning the public key.\n", + "operationId": "GenerateKey", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GenerateKeyRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Response to `POST /v1/key`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTKeyResponse" + } + } + } + } + }, + "x-codegen-request-body-name": "Generate Key Request" + }, + "delete": { + "summary": "Delete a key", + "description": "Deletes the key with the passed public key from the wallet.", + "operationId": "DeleteKey", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteKeyRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Response to `DELETE /v1/key`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DELETEKeyResponse" + } + } + } + } + }, + "x-codegen-request-body-name": "Delete Key Request" + } + }, + "/v1/key/export": { + "post": { + "summary": "Export a key", + "description": "Export the secret key associated with the passed public key.", + "operationId": "ExportKey", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ExportKeyRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Response to `POST /v1/key/export`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTKeyExportResponse" + } + } + } + } + }, + "x-codegen-request-body-name": "Export Key Request" + } + }, + "/v1/key/import": { + "post": { + "summary": "Import a key", + "description": "Import an externally generated key into the wallet. Note that if you wish to back up the imported key, you must do so by backing up the entire wallet database, because imported keys were not derived from the wallet's master derivation key.\n", + "operationId": "ImportKey", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ImportKeyRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Response to `POST /v1/key/import`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTKeyImportResponse" + } + } + } + } + }, + "x-codegen-request-body-name": "Import Key Request" + } + }, + "/v1/key/list": { + "post": { + "summary": "List keys in wallet", + "description": "Lists all of the public keys in this wallet. All of them have a stored private key.", + "operationId": "ListKeysInWallet", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListKeysRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Response to `POST /v1/key/list`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTKeyListResponse" + } + } + } + } + }, + "x-codegen-request-body-name": "List Keys Request" + } + }, + "/v1/master-key/export": { + "post": { + "summary": "Export the master derivation key from a wallet", + "description": "Export the master derivation key from the wallet. This key is a master \"backup\" key for the underlying wallet. With it, you can regenerate all of the wallets that have been generated with this wallet's `POST /v1/key` endpoint. This key will not allow you to recover keys imported from other wallets, however.\n", + "operationId": "ExportMasterKey", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ExportMasterKeyRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Response to `POST /v1/master-key/export`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTMasterKeyExportResponse" + } + } + } + } + }, + "x-codegen-request-body-name": "Export Master Key Request" + } + }, + "/v1/multisig": { + "delete": { + "summary": "Delete a multisig", + "description": "Deletes multisig preimage information for the passed address from the wallet.\n", + "operationId": "DeleteMultisig", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteMultisigRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Response to POST /v1/multisig/delete", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DELETEMultisigResponse" + } + } + } + } + }, + "x-codegen-request-body-name": "Delete Multisig Request" + } + }, + "/v1/multisig/export": { + "post": { + "summary": "Export multisig address metadata", + "description": "Given a multisig address whose preimage this wallet stores, returns the information used to generate the address, including public keys, threshold, and multisig version.\n", + "operationId": "ExportMultisig", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ExportMultisigRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Response to `POST /v1/multisig/export`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTMultisigExportResponse" + } + } + } + } + }, + "x-codegen-request-body-name": "Export Multisig Request" + } + }, + "/v1/multisig/import": { + "post": { + "summary": "Import a multisig account", + "description": "Generates a multisig account from the passed public keys array and multisig metadata, and stores all of this in the wallet.\n", + "operationId": "ImportMultisig", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ImportMultisigRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Response to `POST /v1/multisig/import`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTMultisigImportResponse" + } + } + } + } + }, + "x-codegen-request-body-name": "Import Multisig Request" + } + }, + "/v1/multisig/list": { + "post": { + "summary": "List multisig accounts", + "description": "Lists all of the multisig accounts whose preimages this wallet stores", + "operationId": "ListMultisg", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListMultisigRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Response to `POST /v1/multisig/list`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTMultisigListResponse" + } + } + } + } + }, + "x-codegen-request-body-name": "List Multisig Request" + } + }, + "/v1/multisig/sign": { + "post": { + "summary": "Sign a multisig transaction", + "description": "Start a multisig signature, or add a signature to a partially completed multisig signature object.\n", + "operationId": "SignMultisigTransaction", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SignMultisigRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Response to `POST /v1/multisig/sign`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTMultisigTransactionSignResponse" + } + } + } + } + }, + "x-codegen-request-body-name": "Sign Multisig Transaction Request" + } + }, + "/v1/multisig/signprogram": { + "post": { + "summary": "Sign a program for a multisig account", + "description": "Start a multisig signature, or add a signature to a partially completed multisig signature object.\n", + "operationId": "SignMultisigProgram", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SignProgramMultisigRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Response to `POST /v1/multisig/signdata`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTMultisigProgramSignResponse" + } + } + } + } + }, + "x-codegen-request-body-name": "Sign Multisig Program Request" + } + }, + "/v1/program/sign": { + "post": { + "summary": "Sign program", + "description": "Signs the passed program with a key from the wallet, determined by the account named in the request.\n", + "operationId": "SignProgram", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SignProgramRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Response to `POST /v1/data/sign`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTProgramSignResponse" + } + } + } + } + }, + "x-codegen-request-body-name": "Sign Program Request" + } + }, + "/v1/transaction/sign": { + "post": { + "summary": "Sign a transaction", + "description": "Signs the passed transaction with a key from the wallet, determined by the sender encoded in the transaction.\n", + "operationId": "SignTransaction", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SignTransactionRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Response to `POST /v1/transaction/sign`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTTransactionSignResponse" + } + } + } + } + }, + "x-codegen-request-body-name": "Sign Transaction Request" + } + }, + "/v1/wallet": { + "post": { + "summary": "Create a wallet", + "description": "Create a new wallet (collection of keys) with the given parameters.", + "operationId": "CreateWallet", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateWalletRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Response to `POST /v1/wallet`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTWalletResponse" + } + } + } + } + }, + "x-codegen-request-body-name": "Create Wallet Request" + } + }, + "/v1/wallet/info": { + "post": { + "summary": "Get wallet info", + "description": "Returns information about the wallet associated with the passed wallet handle token. Additionally returns expiration information about the token itself.\n", + "operationId": "GetWalletInfo", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WalletInfoRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Response to `POST /v1/wallet/info`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTWalletInfoResponse" + } + } + } + } + }, + "x-codegen-request-body-name": "Get Wallet Info Request" + } + }, + "/v1/wallet/init": { + "post": { + "summary": "Initialize a wallet handle token", + "description": "Unlock the wallet and return a wallet handle token that can be used for subsequent operations. These tokens expire periodically and must be renewed. You can `POST` the token to `/v1/wallet/info` to see how much time remains until expiration, and renew it with `/v1/wallet/renew`. When you're done, you can invalidate the token with `/v1/wallet/release`.\n", + "operationId": "InitWalletHandleToken", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InitWalletHandleTokenRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Response to `POST /v1/wallet/init`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTWalletInitResponse" + } + } + } + } + }, + "x-codegen-request-body-name": "Initialize Wallet Handle Token Request" + } + }, + "/v1/wallet/release": { + "post": { + "summary": "Release a wallet handle token", + "description": "Invalidate the passed wallet handle token, making it invalid for use in subsequent requests.", + "operationId": "ReleaseWalletHandleToken", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReleaseWalletHandleTokenRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Response to `POST /v1/wallet/release`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTWalletReleaseResponse" + } + } + } + } + }, + "x-codegen-request-body-name": "Release Wallet Handle Token Request" + } + }, + "/v1/wallet/rename": { + "post": { + "summary": "Rename a wallet", + "description": "Rename the underlying wallet to something else", + "operationId": "RenameWallet", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RenameWalletRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Response to `POST /v1/wallet/rename`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTWalletRenameResponse" + } + } + } + } + }, + "x-codegen-request-body-name": "Rename Wallet Request" + } + }, + "/v1/wallet/renew": { + "post": { + "summary": "Renew a wallet handle token", + "description": "Renew a wallet handle token, increasing its expiration duration to its initial value", + "operationId": "RenewWalletHandleToken", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RenewWalletHandleTokenRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Response `POST /v1/wallet/renew`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTWalletRenewResponse" + } + } + } + } + }, + "x-codegen-request-body-name": "Renew Wallet Handle Token Request" + } + }, + "/v1/wallets": { + "get": { + "summary": "List wallets", + "description": "Lists all of the wallets that kmd is aware of.", + "operationId": "ListWallets", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListWalletsRequest" + } + } + }, + "required": false + }, + "responses": { + "200": { + "description": "Response to `GET /v1/wallets`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GETWalletsResponse" + } + } + } + } + }, + "x-codegen-request-body-name": "List Wallet Request" + } + }, + "/versions": { + "get": { + "summary": "Retrieves the current version", + "operationId": "GetVersion", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VersionsRequest" + } + } + }, + "required": false + }, + "responses": { + "200": { + "description": "Response to `GET /versions`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VersionsResponse" + } + } + } + } + }, + "x-codegen-request-body-name": "Versions Request" + } + } + }, + "components": { + "schemas": { + "DELETEKeyResponse": { + "type": "object", + "properties": { + "error": { + "type": "boolean", + "x-go-name": "Error" + }, + "message": { + "type": "string", + "x-go-name": "Message" + } + }, + "description": "APIV1DELETEKeyResponse is the response to `DELETE /v1/key`\nfriendly:DeleteKeyResponse", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi", + "x-algokit-original-name": "APIV1DELETEKeyResponse", + "x-algokit-kmd-api-version": 1 + }, + "DELETEMultisigResponse": { + "type": "object", + "properties": { + "error": { + "type": "boolean", + "x-go-name": "Error" + }, + "message": { + "type": "string", + "x-go-name": "Message" + } + }, + "description": "APIV1DELETEMultisigResponse is the response to POST /v1/multisig/delete`\nfriendly:DeleteMultisigResponse", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi", + "x-algokit-original-name": "APIV1DELETEMultisigResponse", + "x-algokit-kmd-api-version": 1 + }, + "GETWalletsResponse": { + "type": "object", + "properties": { + "error": { + "type": "boolean", + "x-go-name": "Error" + }, + "message": { + "type": "string", + "x-go-name": "Message" + }, + "wallets": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Wallet" + }, + "x-go-name": "Wallets" + } + }, + "description": "APIV1GETWalletsResponse is the response to `GET /v1/wallets`\nfriendly:ListWalletsResponse", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi", + "x-algokit-original-name": "APIV1GETWalletsResponse", + "x-algokit-kmd-api-version": 1 + }, + "POSTKeyExportResponse": { + "type": "object", + "properties": { + "error": { + "type": "boolean", + "x-go-name": "Error" + }, + "message": { + "type": "string", + "x-go-name": "Message" + }, + "private_key": { + "type": "string", + "x-algokit-bytes-base64": true + } + }, + "description": "APIV1POSTKeyExportResponse is the response to `POST /v1/key/export`\nfriendly:ExportKeyResponse", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi", + "x-algokit-original-name": "APIV1POSTKeyExportResponse", + "x-algokit-kmd-api-version": 1 + }, + "POSTKeyImportResponse": { + "type": "object", + "properties": { + "address": { + "type": "string", + "x-go-name": "Address" + }, + "error": { + "type": "boolean", + "x-go-name": "Error" + }, + "message": { + "type": "string", + "x-go-name": "Message" + } + }, + "description": "APIV1POSTKeyImportResponse is the response to `POST /v1/key/import`\nfriendly:ImportKeyResponse", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi", + "x-algokit-original-name": "APIV1POSTKeyImportResponse", + "x-algokit-kmd-api-version": 1 + }, + "POSTKeyListResponse": { + "type": "object", + "properties": { + "addresses": { + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Addresses" + }, + "error": { + "type": "boolean", + "x-go-name": "Error" + }, + "message": { + "type": "string", + "x-go-name": "Message" + } + }, + "description": "APIV1POSTKeyListResponse is the response to `POST /v1/key/list`\nfriendly:ListKeysResponse", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi", + "x-algokit-original-name": "APIV1POSTKeyListResponse", + "x-algokit-kmd-api-version": 1 + }, + "POSTKeyResponse": { + "type": "object", + "properties": { + "address": { + "type": "string", + "x-go-name": "Address" + }, + "error": { + "type": "boolean", + "x-go-name": "Error" + }, + "message": { + "type": "string", + "x-go-name": "Message" + } + }, + "description": "APIV1POSTKeyResponse is the response to `POST /v1/key`\nfriendly:GenerateKeyResponse", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi", + "x-algokit-original-name": "APIV1POSTKeyResponse", + "x-algokit-kmd-api-version": 1 + }, + "POSTMasterKeyExportResponse": { + "type": "object", + "properties": { + "error": { + "type": "boolean", + "x-go-name": "Error" + }, + "master_derivation_key": { + "$ref": "#/components/schemas/MasterDerivationKey" + }, + "message": { + "type": "string", + "x-go-name": "Message" + } + }, + "description": "APIV1POSTMasterKeyExportResponse is the response to `POST /v1/master-key/export`\nfriendly:ExportMasterKeyResponse", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi", + "x-algokit-original-name": "APIV1POSTMasterKeyExportResponse", + "x-algokit-kmd-api-version": 1 + }, + "POSTMultisigExportResponse": { + "type": "object", + "properties": { + "error": { + "type": "boolean", + "x-go-name": "Error" + }, + "message": { + "type": "string", + "x-go-name": "Message" + }, + "multisig_version": { + "type": "integer", + "format": "uint8", + "x-go-name": "Version" + }, + "pks": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PublicKey" + }, + "x-go-name": "PKs" + }, + "threshold": { + "type": "integer", + "format": "uint8", + "x-go-name": "Threshold" + } + }, + "description": "APIV1POSTMultisigExportResponse is the response to `POST /v1/multisig/export`\nfriendly:ExportMultisigResponse", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi", + "x-algokit-original-name": "APIV1POSTMultisigExportResponse", + "x-algokit-kmd-api-version": 1 + }, + "POSTMultisigImportResponse": { + "type": "object", + "properties": { + "address": { + "type": "string", + "x-go-name": "Address" + }, + "error": { + "type": "boolean", + "x-go-name": "Error" + }, + "message": { + "type": "string", + "x-go-name": "Message" + } + }, + "description": "APIV1POSTMultisigImportResponse is the response to `POST /v1/multisig/import`\nfriendly:ImportMultisigResponse", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi", + "x-algokit-original-name": "APIV1POSTMultisigImportResponse", + "x-algokit-kmd-api-version": 1 + }, + "POSTMultisigListResponse": { + "type": "object", + "properties": { + "addresses": { + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Addresses" + }, + "error": { + "type": "boolean", + "x-go-name": "Error" + }, + "message": { + "type": "string", + "x-go-name": "Message" + } + }, + "description": "APIV1POSTMultisigListResponse is the response to `POST /v1/multisig/list`\nfriendly:ListMultisigResponse", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi", + "x-algokit-original-name": "APIV1POSTMultisigListResponse", + "x-algokit-kmd-api-version": 1 + }, + "POSTMultisigProgramSignResponse": { + "type": "object", + "properties": { + "error": { + "type": "boolean", + "x-go-name": "Error" + }, + "message": { + "type": "string", + "x-go-name": "Message" + }, + "multisig": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "format": "byte", + "x-go-name": "Multisig" + } + }, + "description": "APIV1POSTMultisigProgramSignResponse is the response to `POST /v1/multisig/signdata`\nfriendly:SignProgramMultisigResponse", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi", + "x-algokit-original-name": "APIV1POSTMultisigProgramSignResponse", + "x-algokit-kmd-api-version": 1 + }, + "POSTMultisigTransactionSignResponse": { + "type": "object", + "properties": { + "error": { + "type": "boolean", + "x-go-name": "Error" + }, + "message": { + "type": "string", + "x-go-name": "Message" + }, + "multisig": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "format": "byte", + "x-go-name": "Multisig" + } + }, + "description": "APIV1POSTMultisigTransactionSignResponse is the response to `POST /v1/multisig/sign`\nfriendly:SignMultisigResponse", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi", + "x-algokit-original-name": "APIV1POSTMultisigTransactionSignResponse", + "x-algokit-kmd-api-version": 1 + }, + "POSTProgramSignResponse": { + "type": "object", + "properties": { + "error": { + "type": "boolean", + "x-go-name": "Error" + }, + "message": { + "type": "string", + "x-go-name": "Message" + }, + "sig": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "format": "byte", + "x-go-name": "Signature" + } + }, + "description": "APIV1POSTProgramSignResponse is the response to `POST /v1/data/sign`\nfriendly:SignProgramResponse", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi", + "x-algokit-original-name": "APIV1POSTProgramSignResponse", + "x-algokit-kmd-api-version": 1 + }, + "POSTTransactionSignResponse": { + "type": "object", + "properties": { + "error": { + "type": "boolean", + "x-go-name": "Error" + }, + "message": { + "type": "string", + "x-go-name": "Message" + }, + "signed_transaction": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "format": "byte", + "x-go-name": "SignedTransaction" + } + }, + "description": "APIV1POSTTransactionSignResponse is the response to `POST /v1/transaction/sign`\nfriendly:SignTransactionResponse", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi", + "x-algokit-original-name": "APIV1POSTTransactionSignResponse", + "x-algokit-kmd-api-version": 1 + }, + "POSTWalletInfoResponse": { + "type": "object", + "properties": { + "error": { + "type": "boolean", + "x-go-name": "Error" + }, + "message": { + "type": "string", + "x-go-name": "Message" + }, + "wallet_handle": { + "$ref": "#/components/schemas/WalletHandle" + } + }, + "description": "APIV1POSTWalletInfoResponse is the response to `POST /v1/wallet/info`\nfriendly:WalletInfoResponse", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi", + "x-algokit-original-name": "APIV1POSTWalletInfoResponse", + "x-algokit-kmd-api-version": 1 + }, + "POSTWalletInitResponse": { + "type": "object", + "properties": { + "error": { + "type": "boolean", + "x-go-name": "Error" + }, + "message": { + "type": "string", + "x-go-name": "Message" + }, + "wallet_handle_token": { + "type": "string", + "x-go-name": "WalletHandleToken" + } + }, + "description": "APIV1POSTWalletInitResponse is the response to `POST /v1/wallet/init`\nfriendly:InitWalletHandleTokenResponse", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi", + "x-algokit-original-name": "APIV1POSTWalletInitResponse", + "x-algokit-kmd-api-version": 1 + }, + "POSTWalletReleaseResponse": { + "type": "object", + "properties": { + "error": { + "type": "boolean", + "x-go-name": "Error" + }, + "message": { + "type": "string", + "x-go-name": "Message" + } + }, + "description": "APIV1POSTWalletReleaseResponse is the response to `POST /v1/wallet/release`\nfriendly:ReleaseWalletHandleTokenResponse", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi", + "x-algokit-original-name": "APIV1POSTWalletReleaseResponse", + "x-algokit-kmd-api-version": 1 + }, + "POSTWalletRenameResponse": { + "type": "object", + "properties": { + "error": { + "type": "boolean", + "x-go-name": "Error" + }, + "message": { + "type": "string", + "x-go-name": "Message" + }, + "wallet": { + "$ref": "#/components/schemas/Wallet" + } + }, + "description": "APIV1POSTWalletRenameResponse is the response to `POST /v1/wallet/rename`\nfriendly:RenameWalletResponse", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi", + "x-algokit-original-name": "APIV1POSTWalletRenameResponse", + "x-algokit-kmd-api-version": 1 + }, + "POSTWalletRenewResponse": { + "type": "object", + "properties": { + "error": { + "type": "boolean", + "x-go-name": "Error" + }, + "message": { + "type": "string", + "x-go-name": "Message" + }, + "wallet_handle": { + "$ref": "#/components/schemas/WalletHandle" + } + }, + "description": "APIV1POSTWalletRenewResponse is the response to `POST /v1/wallet/renew`\nfriendly:RenewWalletHandleTokenResponse", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi", + "x-algokit-original-name": "APIV1POSTWalletRenewResponse", + "x-algokit-kmd-api-version": 1 + }, + "POSTWalletResponse": { + "type": "object", + "properties": { + "error": { + "type": "boolean", + "x-go-name": "Error" + }, + "message": { + "type": "string", + "x-go-name": "Message" + }, + "wallet": { + "$ref": "#/components/schemas/Wallet" + } + }, + "description": "APIV1POSTWalletResponse is the response to `POST /v1/wallet`\nfriendly:CreateWalletResponse", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi", + "x-algokit-original-name": "APIV1POSTWalletResponse", + "x-algokit-kmd-api-version": 1 + }, + "Wallet": { + "type": "object", + "properties": { + "driver_name": { + "type": "string", + "x-go-name": "DriverName" + }, + "driver_version": { + "type": "integer", + "format": "uint32", + "x-go-name": "DriverVersion" + }, + "id": { + "type": "string", + "x-go-name": "ID" + }, + "mnemonic_ux": { + "type": "boolean", + "x-go-name": "SupportsMnemonicUX" + }, + "name": { + "type": "string", + "x-go-name": "Name" + }, + "supported_txs": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TxType" + }, + "x-go-name": "SupportedTransactions" + } + }, + "description": "APIV1Wallet is the API's representation of a wallet", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi", + "x-algokit-original-name": "APIV1Wallet", + "x-algokit-kmd-api-version": 1 + }, + "WalletHandle": { + "type": "object", + "properties": { + "expires_seconds": { + "type": "integer", + "format": "int64", + "x-go-name": "ExpiresSeconds" + }, + "wallet": { + "$ref": "#/components/schemas/Wallet" + } + }, + "description": "APIV1WalletHandle includes the wallet the handle corresponds to\nand the number of number of seconds to expiration", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi", + "x-algokit-original-name": "APIV1WalletHandle", + "x-algokit-kmd-api-version": 1 + }, + "CreateWalletRequest": { + "type": "object", + "properties": { + "master_derivation_key": { + "$ref": "#/components/schemas/MasterDerivationKey" + }, + "wallet_driver_name": { + "type": "string", + "x-go-name": "WalletDriverName" + }, + "wallet_name": { + "type": "string", + "x-go-name": "WalletName" + }, + "wallet_password": { + "type": "string", + "x-go-name": "WalletPassword" + } + }, + "description": "APIV1POSTWalletRequest is the request for `POST /v1/wallet`", + "x-go-name": "APIV1POSTWalletRequest", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi" + }, + "DeleteKeyRequest": { + "type": "object", + "properties": { + "address": { + "type": "string", + "x-go-name": "Address" + }, + "wallet_handle_token": { + "type": "string", + "x-go-name": "WalletHandleToken" + }, + "wallet_password": { + "type": "string", + "x-go-name": "WalletPassword" + } + }, + "description": "APIV1DELETEKeyRequest is the request for `DELETE /v1/key`", + "x-go-name": "APIV1DELETEKeyRequest", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi" + }, + "DeleteMultisigRequest": { + "type": "object", + "properties": { + "address": { + "type": "string", + "x-go-name": "Address" + }, + "wallet_handle_token": { + "type": "string", + "x-go-name": "WalletHandleToken" + }, + "wallet_password": { + "type": "string", + "x-go-name": "WalletPassword" + } + }, + "description": "APIV1DELETEMultisigRequest is the request for `DELETE /v1/multisig`", + "x-go-name": "APIV1DELETEMultisigRequest", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi" + }, + "Digest": { + "title": "Digest represents a 32-byte value holding the 256-bit Hash digest.", + "type": "array", + "items": { + "type": "integer", + "format": "uint8" + }, + "x-go-package": "github.com/algorand/go-algorand/crypto" + }, + "ExportKeyRequest": { + "type": "object", + "properties": { + "address": { + "type": "string", + "x-go-name": "Address" + }, + "wallet_handle_token": { + "type": "string", + "x-go-name": "WalletHandleToken" + }, + "wallet_password": { + "type": "string", + "x-go-name": "WalletPassword" + } + }, + "description": "APIV1POSTKeyExportRequest is the request for `POST /v1/key/export`", + "x-go-name": "APIV1POSTKeyExportRequest", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi" + }, + "ExportMasterKeyRequest": { + "type": "object", + "properties": { + "wallet_handle_token": { + "type": "string", + "x-go-name": "WalletHandleToken" + }, + "wallet_password": { + "type": "string", + "x-go-name": "WalletPassword" + } + }, + "description": "APIV1POSTMasterKeyExportRequest is the request for `POST /v1/master-key/export`", + "x-go-name": "APIV1POSTMasterKeyExportRequest", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi" + }, + "ExportMultisigRequest": { + "type": "object", + "properties": { + "address": { + "type": "string", + "x-go-name": "Address" + }, + "wallet_handle_token": { + "type": "string", + "x-go-name": "WalletHandleToken" + } + }, + "description": "APIV1POSTMultisigExportRequest is the request for `POST /v1/multisig/export`", + "x-go-name": "APIV1POSTMultisigExportRequest", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi" + }, + "GenerateKeyRequest": { + "type": "object", + "properties": { + "display_mnemonic": { + "type": "boolean", + "x-go-name": "DisplayMnemonic" + }, + "wallet_handle_token": { + "type": "string", + "x-go-name": "WalletHandleToken" + } + }, + "description": "APIV1POSTKeyRequest is the request for `POST /v1/key`", + "x-go-name": "APIV1POSTKeyRequest", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi" + }, + "ImportKeyRequest": { + "type": "object", + "properties": { + "private_key": { + "type": "string", + "x-algokit-bytes-base64": true + }, + "wallet_handle_token": { + "type": "string", + "x-go-name": "WalletHandleToken" + } + }, + "description": "APIV1POSTKeyImportRequest is the request for `POST /v1/key/import`", + "x-go-name": "APIV1POSTKeyImportRequest", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi" + }, + "ImportMultisigRequest": { + "type": "object", + "properties": { + "multisig_version": { + "type": "integer", + "format": "uint8", + "x-go-name": "Version" + }, + "pks": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PublicKey" + }, + "x-go-name": "PKs" + }, + "threshold": { + "type": "integer", + "format": "uint8", + "x-go-name": "Threshold" + }, + "wallet_handle_token": { + "type": "string", + "x-go-name": "WalletHandleToken" + } + }, + "description": "APIV1POSTMultisigImportRequest is the request for `POST /v1/multisig/import`", + "x-go-name": "APIV1POSTMultisigImportRequest", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi" + }, + "InitWalletHandleTokenRequest": { + "type": "object", + "properties": { + "wallet_id": { + "type": "string", + "x-go-name": "WalletID" + }, + "wallet_password": { + "type": "string", + "x-go-name": "WalletPassword" + } + }, + "description": "APIV1POSTWalletInitRequest is the request for `POST /v1/wallet/init`", + "x-go-name": "APIV1POSTWalletInitRequest", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi" + }, + "ListKeysRequest": { + "type": "object", + "properties": { + "wallet_handle_token": { + "type": "string", + "x-go-name": "WalletHandleToken" + } + }, + "description": "APIV1POSTKeyListRequest is the request for `POST /v1/key/list`", + "x-go-name": "APIV1POSTKeyListRequest", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi" + }, + "ListMultisigRequest": { + "type": "object", + "properties": { + "wallet_handle_token": { + "type": "string", + "x-go-name": "WalletHandleToken" + } + }, + "description": "APIV1POSTMultisigListRequest is the request for `POST /v1/multisig/list`", + "x-go-name": "APIV1POSTMultisigListRequest", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi" + }, + "ListWalletsRequest": { + "type": "object", + "description": "APIV1GETWalletsRequest is the request for `GET /v1/wallets`", + "x-go-name": "APIV1GETWalletsRequest", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi" + }, + "MasterDerivationKey": { + "type": "array", + "description": "MasterDerivationKey is used to derive ed25519 keys for use in wallets", + "items": { + "type": "integer", + "format": "uint8" + }, + "x-go-package": "github.com/algorand/go-algorand/crypto" + }, + "MultisigSig": { + "type": "object", + "properties": { + "Subsigs": { + "type": "array", + "items": { + "$ref": "#/components/schemas/MultisigSubsig" + } + }, + "Threshold": { + "type": "integer", + "format": "uint8" + }, + "Version": { + "type": "integer", + "format": "uint8" + } + }, + "description": "MultisigSig is the structure that holds multiple Subsigs", + "x-go-package": "github.com/algorand/go-algorand/crypto" + }, + "MultisigSubsig": { + "type": "object", + "properties": { + "Key": { + "$ref": "#/components/schemas/PublicKey" + }, + "Sig": { + "$ref": "#/components/schemas/Signature" + } + }, + "description": "MultisigSubsig is a struct that holds a pair of public key and signatures\nsignatures may be empty", + "x-go-package": "github.com/algorand/go-algorand/crypto" + }, + "PrivateKey": { + "$ref": "#/components/schemas/ed25519PrivateKey" + }, + "PublicKey": { + "$ref": "#/components/schemas/ed25519PublicKey" + }, + "ReleaseWalletHandleTokenRequest": { + "type": "object", + "properties": { + "wallet_handle_token": { + "type": "string", + "x-go-name": "WalletHandleToken" + } + }, + "description": "APIV1POSTWalletReleaseRequest is the request for `POST /v1/wallet/release`", + "x-go-name": "APIV1POSTWalletReleaseRequest", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi" + }, + "RenameWalletRequest": { + "type": "object", + "properties": { + "wallet_id": { + "type": "string", + "x-go-name": "WalletID" + }, + "wallet_name": { + "type": "string", + "x-go-name": "NewWalletName" + }, + "wallet_password": { + "type": "string", + "x-go-name": "WalletPassword" + } + }, + "description": "APIV1POSTWalletRenameRequest is the request for `POST /v1/wallet/rename`", + "x-go-name": "APIV1POSTWalletRenameRequest", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi" + }, + "RenewWalletHandleTokenRequest": { + "type": "object", + "properties": { + "wallet_handle_token": { + "type": "string", + "x-go-name": "WalletHandleToken" + } + }, + "description": "APIV1POSTWalletRenewRequest is the request for `POST /v1/wallet/renew`", + "x-go-name": "APIV1POSTWalletRenewRequest", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi" + }, + "SignMultisigRequest": { + "type": "object", + "properties": { + "partial_multisig": { + "$ref": "#/components/schemas/MultisigSig" + }, + "public_key": { + "$ref": "#/components/schemas/PublicKey" + }, + "signer": { + "$ref": "#/components/schemas/Digest" + }, + "transaction": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "format": "byte", + "x-go-name": "Transaction" + }, + "wallet_handle_token": { + "type": "string", + "x-go-name": "WalletHandleToken" + }, + "wallet_password": { + "type": "string", + "x-go-name": "WalletPassword" + } + }, + "description": "APIV1POSTMultisigTransactionSignRequest is the request for `POST /v1/multisig/sign`", + "x-go-name": "APIV1POSTMultisigTransactionSignRequest", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi" + }, + "SignProgramMultisigRequest": { + "type": "object", + "properties": { + "address": { + "type": "string", + "x-go-name": "Address" + }, + "data": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "format": "byte", + "x-go-name": "Program" + }, + "partial_multisig": { + "$ref": "#/components/schemas/MultisigSig" + }, + "public_key": { + "$ref": "#/components/schemas/PublicKey" + }, + "use_legacy_msig": { + "type": "boolean", + "x-go-name": "UseLegacyMsig" + }, + "wallet_handle_token": { + "type": "string", + "x-go-name": "WalletHandleToken" + }, + "wallet_password": { + "type": "string", + "x-go-name": "WalletPassword" + } + }, + "description": "APIV1POSTMultisigProgramSignRequest is the request for `POST /v1/multisig/signprogram`", + "x-go-name": "APIV1POSTMultisigProgramSignRequest", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi" + }, + "SignProgramRequest": { + "type": "object", + "properties": { + "address": { + "type": "string", + "x-go-name": "Address" + }, + "data": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "format": "byte", + "x-go-name": "Program" + }, + "wallet_handle_token": { + "type": "string", + "x-go-name": "WalletHandleToken" + }, + "wallet_password": { + "type": "string", + "x-go-name": "WalletPassword" + } + }, + "description": "APIV1POSTProgramSignRequest is the request for `POST /v1/program/sign`", + "x-go-name": "APIV1POSTProgramSignRequest", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi" + }, + "SignTransactionRequest": { + "type": "object", + "properties": { + "public_key": { + "$ref": "#/components/schemas/PublicKey" + }, + "transaction": { + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "type": "string", + "description": "Base64 encoding of msgpack encoding of a `Transaction` object\nNote: SDK and goal usually generate `SignedTxn` objects\nin that case, the field `txn` / `Transaction` of the\ngenerated `SignedTxn` object needs to be used", + "format": "byte", + "x-go-name": "Transaction" + }, + "wallet_handle_token": { + "type": "string", + "x-go-name": "WalletHandleToken" + }, + "wallet_password": { + "type": "string", + "x-go-name": "WalletPassword" + } + }, + "description": "APIV1POSTTransactionSignRequest is the request for `POST /v1/transaction/sign`", + "x-go-name": "APIV1POSTTransactionSignRequest", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi" + }, + "Signature": { + "$ref": "#/components/schemas/ed25519Signature" + }, + "TxType": { + "type": "string", + "description": "TxType is the type of the transaction written to the ledger", + "x-go-package": "github.com/algorand/go-algorand/protocol" + }, + "VersionsRequest": { + "type": "object", + "description": "VersionsRequest is the request for `GET /versions`", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi" + }, + "VersionsResponse": { + "type": "object", + "properties": { + "versions": { + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "Versions" + } + }, + "description": "VersionsResponse is the response to `GET /versions`\nfriendly:VersionsResponse", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi" + }, + "WalletInfoRequest": { + "type": "object", + "properties": { + "wallet_handle_token": { + "type": "string", + "x-go-name": "WalletHandleToken" + } + }, + "description": "APIV1POSTWalletInfoRequest is the request for `POST /v1/wallet/info`", + "x-go-name": "APIV1POSTWalletInfoRequest", + "x-go-package": "github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi" + }, + "ed25519PrivateKey": { + "type": "array", + "items": { + "type": "integer", + "format": "uint8" + }, + "x-go-package": "github.com/algorand/go-algorand/crypto" + }, + "ed25519PublicKey": { + "type": "array", + "items": { + "type": "integer", + "format": "uint8" + }, + "x-go-package": "github.com/algorand/go-algorand/crypto" + }, + "ed25519Signature": { + "title": "Classical signatures */", + "type": "array", + "items": { + "type": "integer", + "format": "uint8" + }, + "x-go-package": "github.com/algorand/go-algorand/crypto" + } + }, + "responses": { + "CreateWalletResponse": { + "description": "Response to `POST /v1/wallet`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTWalletResponse" + } + } + } + }, + "DeleteKeyResponse": { + "description": "Response to `DELETE /v1/key`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DELETEKeyResponse" + } + } + } + }, + "DeleteMultisigResponse": { + "description": "Response to POST /v1/multisig/delete", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DELETEMultisigResponse" + } + } + } + }, + "ExportKeyResponse": { + "description": "Response to `POST /v1/key/export`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTKeyExportResponse" + } + } + } + }, + "ExportMasterKeyResponse": { + "description": "Response to `POST /v1/master-key/export`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTMasterKeyExportResponse" + } + } + } + }, + "ExportMultisigResponse": { + "description": "Response to `POST /v1/multisig/export`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTMultisigExportResponse" + } + } + } + }, + "GenerateKeyResponse": { + "description": "Response to `POST /v1/key`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTKeyResponse" + } + } + } + }, + "ImportKeyResponse": { + "description": "Response to `POST /v1/key/import`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTKeyImportResponse" + } + } + } + }, + "ImportMultisigResponse": { + "description": "Response to `POST /v1/multisig/import`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTMultisigImportResponse" + } + } + } + }, + "InitWalletHandleTokenResponse": { + "description": "Response to `POST /v1/wallet/init`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTWalletInitResponse" + } + } + } + }, + "ListKeysResponse": { + "description": "Response to `POST /v1/key/list`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTKeyListResponse" + } + } + } + }, + "ListMultisigResponse": { + "description": "Response to `POST /v1/multisig/list`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTMultisigListResponse" + } + } + } + }, + "ListWalletsResponse": { + "description": "Response to `GET /v1/wallets`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GETWalletsResponse" + } + } + } + }, + "ReleaseWalletHandleTokenResponse": { + "description": "Response to `POST /v1/wallet/release`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTWalletReleaseResponse" + } + } + } + }, + "RenameWalletResponse": { + "description": "Response to `POST /v1/wallet/rename`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTWalletRenameResponse" + } + } + } + }, + "RenewWalletHandleTokenResponse": { + "description": "Response `POST /v1/wallet/renew`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTWalletRenewResponse" + } + } + } + }, + "SignMultisigResponse": { + "description": "Response to `POST /v1/multisig/sign`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTMultisigTransactionSignResponse" + } + } + } + }, + "SignProgramMultisigResponse": { + "description": "Response to `POST /v1/multisig/signdata`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTMultisigProgramSignResponse" + } + } + } + }, + "SignProgramResponse": { + "description": "Response to `POST /v1/data/sign`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTProgramSignResponse" + } + } + } + }, + "SignTransactionResponse": { + "description": "Response to `POST /v1/transaction/sign`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTTransactionSignResponse" + } + } + } + }, + "VersionsResponse": { + "description": "Response to `GET /versions`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VersionsResponse" + } + } + } + }, + "WalletInfoResponse": { + "description": "Response to `POST /v1/wallet/info`", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POSTWalletInfoResponse" + } + } + } + } + }, + "securitySchemes": { + "api_key": { + "type": "apiKey", + "description": "Generated header parameter. This value can be found in `/kmd/data/dir/kmd.token`. Example value: '330b2e4fc9b20f4f89812cf87f1dabeb716d23e3f11aec97a61ff5f750563b78'", + "name": "X-KMD-API-Token", + "in": "header" + } + } + }, + "x-original-swagger-version": "2.0" +} \ No newline at end of file diff --git a/oas-generator/README.md b/oas-generator/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/oas-generator/pyproject.toml b/oas-generator/pyproject.toml new file mode 100644 index 000000000..bcd7e45d1 --- /dev/null +++ b/oas-generator/pyproject.toml @@ -0,0 +1,22 @@ +[project] +name = "oas-generator" +version = "1.0.0" +description = "A Jinja2-based generator that produces Rust API clients from OpenAPI specifications" +readme = "README.md" +authors = [{ name = "AlgoKit Core Team" }] +classifiers = [ + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.12", +] +requires-python = ">=3.12" +dependencies = ["jinja2>=3.0.0"] + +[project.scripts] +oas-generator = "oas_generator.cli:main" + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" diff --git a/oas-generator/src/oas_generator/__init__.py b/oas-generator/src/oas_generator/__init__.py new file mode 100644 index 000000000..e198ef497 --- /dev/null +++ b/oas-generator/src/oas_generator/__init__.py @@ -0,0 +1,11 @@ +"""Top-level package metadata for ``oas_generator``.""" + +from oas_generator import cli, constants, generator, parser, utils + +__all__ = [ + "cli", + "constants", + "generator", + "parser", + "utils", +] diff --git a/oas-generator/src/oas_generator/cli.py b/oas-generator/src/oas_generator/cli.py new file mode 100644 index 000000000..16c2bca20 --- /dev/null +++ b/oas-generator/src/oas_generator/cli.py @@ -0,0 +1,173 @@ +#!/usr/bin/env python3 +"""Command-line interface for the TypeScript OAS Generator (Phase 2).""" + +from __future__ import annotations + +import argparse +import contextlib +import json +import shutil +import sys +import tempfile +import traceback +from collections.abc import Generator +from pathlib import Path + +from oas_generator import constants +from oas_generator.generator.template_engine import CodeGenerator +from oas_generator.utils.file_utils import write_files_to_disk + +# Exit codes for better error reporting +EXIT_SUCCESS = 0 +EXIT_FILE_NOT_FOUND = 1 +EXIT_INVALID_JSON = 2 +EXIT_GENERATION_ERROR = 3 + + +def parse_command_line_args(args: list[str] | None = None) -> argparse.Namespace: + """Create and configure the command line argument parser for TS generator.""" + parser = argparse.ArgumentParser( + description="Generate TypeScript client from OpenAPI specification", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +Examples: + %(prog)s ../specs/algod.oas3.json --output ./packages/algod_client --package-name algod_client + %(prog)s ../specs/indexer.oas3.json -o ./packages/indexer_client -p indexer_client + """, + ) + + parser.add_argument( + "spec_file", + type=Path, + help="Path to OpenAPI specification file (JSON or YAML)", + metavar="SPEC_FILE", + ) + parser.add_argument( + "--output", + "-o", + type=Path, + default=Path(constants.DEFAULT_OUTPUT_DIR), + help="Output directory for generated files (default: %(default)s)", + dest="output_dir", + ) + parser.add_argument( + "--package-name", + "-p", + default=constants.DEFAULT_PACKAGE_NAME, + help="Name for the generated TypeScript package (default: %(default)s)", + dest="package_name", + ) + parser.add_argument( + "--template-dir", + "-t", + type=Path, + help="Custom template directory (optional)", + dest="template_dir", + ) + parser.add_argument( + "--verbose", + "-v", + action="store_true", + help="Enable verbose output", + ) + parser.add_argument( + "--description", + "-d", + help="Custom description for the generated package (overrides spec description)", + dest="custom_description", + ) + + parsed_args = parser.parse_args(args) + + # Validate inputs + if not parsed_args.spec_file.exists(): + parser.error(f"Specification file not found: {parsed_args.spec_file!s}") + + return parsed_args + + +def print_generation_summary(*, file_count: int, files: dict[Path, str], output_dir: Path) -> None: + """Print summary of generated files.""" + print(f"Generated {file_count} files:") + for file_path in sorted(files.keys()): + print(f" {file_path!s}") + print(f"\nTypeScript client generated successfully in {output_dir!s}") + + +@contextlib.contextmanager +def backup_and_prepare_output_dir(output_dir: Path) -> Generator[None, None, None]: + """Backup and ensure the output directory exists before generation.""" + backup_dir: Path | None = None + + # Create a backup of the existing directory if it exists and is non-empty + if output_dir.exists() and any(output_dir.iterdir()): + backup_dir = Path(tempfile.mkdtemp(prefix=constants.BACKUP_DIR_PREFIX)) + shutil.copytree(output_dir, backup_dir, dirs_exist_ok=True) + + # Ensure directory exists + output_dir.mkdir(parents=True, exist_ok=True) + + try: + yield + except Exception: + if backup_dir: + print( + "Error: Generation failed. Restoring original content.", + file=sys.stderr, + ) + # Restore backup + if output_dir.exists(): + shutil.rmtree(output_dir) + shutil.copytree(backup_dir, output_dir, dirs_exist_ok=True) + raise + finally: + if backup_dir and backup_dir.exists(): + shutil.rmtree(backup_dir) + + +def main(args: list[str] | None = None) -> int: + parsed_args = parse_command_line_args(args) + + try: + with backup_and_prepare_output_dir(parsed_args.output_dir): + generator = CodeGenerator(template_dir=parsed_args.template_dir) + + generated_files = generator.generate( + parsed_args.spec_file, + parsed_args.output_dir, + parsed_args.package_name, + custom_description=parsed_args.custom_description, + ) + + # Write files to disk (overwrite safely) + write_files_to_disk(generated_files) + + if parsed_args.verbose: + print_generation_summary( + file_count=len(generated_files), + files=generated_files, + output_dir=parsed_args.output_dir, + ) + else: + print(f"TypeScript client generated successfully in {parsed_args.output_dir!s}") + + return EXIT_SUCCESS + + except FileNotFoundError: + print( + f"Error: Specification file not found: {parsed_args.spec_file!s}", + file=sys.stderr, + ) + return EXIT_FILE_NOT_FOUND + except json.JSONDecodeError as e: + print(f"Error: Invalid JSON in specification file: {e!s}", file=sys.stderr) + return EXIT_INVALID_JSON + except Exception as e: + print(f"Error: {e!s}", file=sys.stderr) + if parsed_args.verbose: + traceback.print_exc() + return EXIT_GENERATION_ERROR + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/oas-generator/src/oas_generator/constants.py b/oas-generator/src/oas_generator/constants.py new file mode 100644 index 000000000..513e6a4e4 --- /dev/null +++ b/oas-generator/src/oas_generator/constants.py @@ -0,0 +1,219 @@ +"""Constants for the TypeScript OAS generator using Enums for better organization.""" + +from __future__ import annotations + +from enum import StrEnum +from typing import Final + + +class MediaType(StrEnum): + """Content types for request/response handling.""" + + JSON = "application/json" + MSGPACK = "application/msgpack" + TEXT = "text/plain" + BINARY = "application/x-binary" + OCTET_STREAM = "application/octet-stream" + + +class ParamLocation(StrEnum): + """OpenAPI parameter locations.""" + + PATH = "path" + QUERY = "query" + HEADER = "header" + + +class TypeScriptType(StrEnum): + """TypeScript type literals.""" + + UINT8ARRAY = "Uint8Array" + VOID = "void" + STRING = "string" + NUMBER = "number" + BIGINT = "bigint" + BOOLEAN = "boolean" + ANY = "any" + NULL = "null" + OBJECT = "object" + NUMBER_OR_BIGINT = "number | bigint" + NEVER = "never" + + +class SchemaKey(StrEnum): + """OpenAPI schema object keys.""" + + TYPE = "type" + PROPERTIES = "properties" + REQUIRED = "required" + ADDITIONAL_PROPERTIES = "additionalProperties" + ALL_OF = "allOf" + ONE_OF = "oneOf" + ANY_OF = "anyOf" + ITEMS = "items" + ENUM = "enum" + NULLABLE = "nullable" + FORMAT = "format" + COMPONENTS = "components" + COMPONENTS_SCHEMAS = "schemas" + PATHS = "paths" + MAXIMUM = "maximum" + MINIMUM = "minimum" + + +class OperationKey(StrEnum): + """OpenAPI operation object keys.""" + + OPERATION_ID = "operationId" + PARAMETERS = "parameters" + REQUEST_BODY = "requestBody" + RESPONSES = "responses" + TAGS = "tags" + CONTENT = "content" + IN = "in" + NAME = "name" + DESCRIPTION = "description" + + +class DirectoryName(StrEnum): + """Generated code directory structure.""" + + SRC = "src" + MODELS = "models" + APIS = "apis" + CORE = "core" + + +class HttpMethod(StrEnum): + """HTTP methods supported by the generator.""" + + GET = "get" + POST = "post" + PUT = "put" + DELETE = "delete" + PATCH = "patch" + HEAD = "head" + OPTIONS = "options" + + +# TypeScript reserved words (kept as frozenset for performance in lookups) +TS_RESERVED_WORDS: Final[frozenset[str]] = frozenset( + [ + "abstract", + "any", + "as", + "boolean", + "break", + "case", + "catch", + "class", + "const", + "continue", + "debugger", + "default", + "delete", + "do", + "else", + "enum", + "export", + "extends", + "false", + "finally", + "for", + "from", + "function", + "if", + "implements", + "import", + "in", + "instanceof", + "interface", + "let", + "new", + "null", + "number", + "package", + "private", + "protected", + "public", + "return", + "static", + "string", + "super", + "switch", + "symbol", + "this", + "throw", + "true", + "try", + "type", + "typeof", + "undefined", + "var", + "void", + "while", + "with", + "yield", + "await", + "async", + "constructor", + ] +) + +# Builtin TypeScript types (derived from enum for consistency) +TS_BUILTIN_TYPES: Final[frozenset[str]] = frozenset( + [ + TypeScriptType.UINT8ARRAY, + TypeScriptType.VOID, + TypeScriptType.STRING, + TypeScriptType.NUMBER, + TypeScriptType.BIGINT, + TypeScriptType.BOOLEAN, + TypeScriptType.NEVER, + ] +) + +# HTTP methods as frozenset (for performance in lookups) +HTTP_METHODS: Final[frozenset[str]] = frozenset(m.value for m in HttpMethod) + +# Default values +DEFAULT_OUTPUT_DIR: Final[str] = "./generated_ts" +DEFAULT_PACKAGE_NAME: Final[str] = "api_ts_client" +DEFAULT_TEMPLATE_DIR: Final[str] = "templates" + +# File names +INDEX_FILE: Final[str] = "index.ts" +API_SERVICE_FILE: Final[str] = "api.service.ts" +MODEL_FILE_EXTENSION: Final[str] = ".ts" + +# Template file names +MODEL_TEMPLATE: Final[str] = "models/model.ts.j2" +MODELS_INDEX_TEMPLATE: Final[str] = "models/index.ts.j2" +API_SERVICE_TEMPLATE: Final[str] = "apis/service.ts.j2" +APIS_INDEX_TEMPLATE: Final[str] = "apis/index.ts.j2" + +# Status code prefixes +SUCCESS_STATUS_PREFIX: Final[str] = "2" + +# Special parameter values +FORMAT_PARAM_NAME: Final[str] = "format" + +# Default values for operations +DEFAULT_TAG: Final[str] = "default" +DEFAULT_API_TAG: Final[str] = "api" + + +# Vendor extensions +X_ALGOKIT_FIELD_RENAME: Final[str] = "x-algokit-field-rename" + +# Backup directory prefix +BACKUP_DIR_PREFIX: Final[str] = "tsgen_bak_" + +# Custom extension +X_ALGOKIT_BIGINT: Final[str] = "x-algokit-bigint" +X_ALGOKIT_SIGNED_TXN: Final[str] = "x-algokit-signed-txn" +X_ALGOKIT_BYTES_BASE64: Final[str] = "x-algokit-bytes-base64" + +# Template configuration +TEMPLATE_TRIM_BLOCKS: Final[bool] = True +TEMPLATE_LSTRIP_BLOCKS: Final[bool] = True diff --git a/oas-generator/src/oas_generator/generator/__init__.py b/oas-generator/src/oas_generator/generator/__init__.py new file mode 100644 index 000000000..5253f4e97 --- /dev/null +++ b/oas-generator/src/oas_generator/generator/__init__.py @@ -0,0 +1,5 @@ +"""Generation utilities for the TypeScript OAS generator.""" + +from oas_generator.generator.template_engine import CodeGenerator + +__all__ = ["CodeGenerator"] diff --git a/oas-generator/src/oas_generator/generator/filters.py b/oas-generator/src/oas_generator/generator/filters.py new file mode 100644 index 000000000..cdf92d913 --- /dev/null +++ b/oas-generator/src/oas_generator/generator/filters.py @@ -0,0 +1,459 @@ +"""TypeScript-specific Jinja2 filters and helpers. + +Phase 2 adds OpenAPI -> TS type mapping and naming utilities. +""" + +from __future__ import annotations + +import re +from collections.abc import Callable, Iterable, Mapping +from functools import cache +from typing import Any + +from oas_generator import constants +from oas_generator.constants import MediaType, OperationKey, SchemaKey, TypeScriptType + +type Schema = Mapping[str, Any] +type Schemas = Mapping[str, Schema] + +_IDENTIFIER_RE = re.compile(r"^[A-Za-z_][A-Za-z0-9_]*$") + + +def ts_doc_comment(text: str | None) -> str: + """Format text as a TypeScript doc comment.""" + if not text: + return "" + lines = [line.strip() for line in str(text).strip().splitlines()] + body = "\n".join(f" * {line}" if line else " *" for line in lines) + return f"/**\n{body}\n */" + + +def ts_string_literal(text: str) -> str: + """Escape to a valid TypeScript string literal using backticks.""" + escaped = str(text).replace("`", "\\`").replace("\\", "\\\\") + return f"`{escaped}`" + + +def ts_optional(type_str: str) -> str: + """Return a TS optional type representation.""" + return f"{type_str} | undefined" + + +def ts_array(type_str: str) -> str: + """Return a TS array type representation.""" + return f"Array<{type_str}>" + + +_WORD_BOUNDARY_RE = re.compile(r"([a-z0-9])([A-Z])") +_NON_ALNUM_RE = re.compile(r"[^A-Za-z0-9]+") +_SNAKE_CASE_DELIMITER_RE = re.compile(r"[\-\.\s]") +_ACRONYM_SPLIT_RE = re.compile(r"([A-Z])([A-Z][a-z])") +_LOWER_TO_UPPER_SPLIT_RE = re.compile(r"([a-z0-9])([A-Z])") + +_U32_MAX_VALUE = 4294967295 +_SMALL_INTEGER_MAX = 100 +_ENUM_KEYWORDS = ( + "value `1`", + "value `2`", + "value 1", + "value 2", + "refers to", + "type.", + "action.", + "enum", +) + + +@cache +def _split_words(name: str) -> tuple[str, ...]: + """Split name into words for case conversion.""" + normalized = _NON_ALNUM_RE.sub(" ", _WORD_BOUNDARY_RE.sub(r"\1 \2", name)).strip() + parts = tuple(part for part in normalized.split() if part) + return parts or (name,) + + +def _snake_case_like_rust(name: str) -> str: + """Convert a string to snake_case using the same rules as the Rust generator.""" + + # Replace common delimiters with underscore + s = _SNAKE_CASE_DELIMITER_RE.sub("_", name) + # Split acronym sequences before CamelCase words (e.g., "EMultisig" -> "E_Multisig") + s = _ACRONYM_SPLIT_RE.sub(r"\1_\2", s) + # Split lower/digit to upper transitions (e.g., "v1Delete" -> "v1_Delete") + s = _LOWER_TO_UPPER_SPLIT_RE.sub(r"\1_\2", s) + return s.lower() + + +def ts_pascal_case(name: str) -> str: + """Convert name to PascalCase (aligned with Rust pascalcase).""" + snake = _snake_case_like_rust(name) + return "".join(part.capitalize() for part in snake.split("_") if part) + + +def ts_camel_case(name: str) -> str: + """Convert name to camelCase.""" + pascal = ts_pascal_case(name) + return pascal[:1].lower() + pascal[1:] if pascal else pascal + + +def ts_kebab_case(name: str) -> str: + """Convert name to kebab-case (aligned with Rust snakecase rules).""" + return _snake_case_like_rust(name).replace("_", "-") + + +def ts_property_name(name: str) -> str: + """Return a safe TS property name, quoting if necessary.""" + return name if _IDENTIFIER_RE.match(name) else f"'{name}'" + + +# ---------- OpenAPI -> TS type mapping ---------- + + +def _extract_ref_name(ref_string: str) -> str: + return ref_string.split("/")[-1] + + +def _union(types: Iterable[str]) -> str: + """Create TypeScript union type from list of types.""" + uniqued = tuple(dict.fromkeys(t for t in types if t)) + return " | ".join(uniqued) if uniqued else TypeScriptType.NEVER + + +def _intersection(types: Iterable[str]) -> str: + """Create TypeScript intersection type from list of types.""" + parts = [t for t in types if t and t != TypeScriptType.ANY] + return " & ".join(parts) if parts else TypeScriptType.ANY + + +def _nullable(type_str: str, schema: Schema, schemas: Schemas | None) -> str: + # OpenAPI 3.0 nullable flag + if schema.get(SchemaKey.NULLABLE) is True: + return _union((type_str, TypeScriptType.NULL)) + + # OpenAPI 3.1 union type with null + t = schema.get(SchemaKey.TYPE) + if isinstance(t, list) and TypeScriptType.NULL in t: + non_nulls = [x for x in t if x != TypeScriptType.NULL] + # If there's exactly one non-null type, union with null + if len(non_nulls) == 1: + return _union((ts_type({SchemaKey.TYPE: non_nulls[0]}, schemas), TypeScriptType.NULL)) + # Else, build a union of all non-nulls + null + inner = _union(ts_type({SchemaKey.TYPE: n}, schemas) for n in non_nulls) + return _union((inner, TypeScriptType.NULL)) + + return type_str + + +def _inline_object(schema: Schema, schemas: Schemas | None) -> str: + properties: dict[str, Any] = schema.get(SchemaKey.PROPERTIES, {}) or {} + required = set(schema.get(SchemaKey.REQUIRED, []) or []) + parts: list[str] = [] + + for prop_name, prop_schema in properties.items(): + canonical_name = prop_schema.get(constants.X_ALGOKIT_FIELD_RENAME) or prop_name + # Add property description as doc comment + description = prop_schema.get("description") + if description: + doc_comment = ts_doc_comment(description) + indented_doc = "\n ".join(doc_comment.split("\n")) + parts.append(f"\n {indented_doc}") + + # Generate camelCase TS property names for better DX + ts_name = ts_camel_case(canonical_name) + ts_t = ts_type(prop_schema, schemas) + opt = "" if prop_name in required else "?" + parts.append(f"{ts_name}{opt}: {ts_t};") + + # additionalProperties -> index signature + if "additionalProperties" in schema: + addl = schema["additionalProperties"] + if addl is True: + parts.append("[key: string]: unknown;") + elif isinstance(addl, dict): + parts.append(f"[key: string]: {ts_type(addl, schemas)};") + + if parts: + # Format with proper indentation + formatted_parts = [] + for part in parts: + if part.startswith("\n"): + formatted_parts.append(part) + else: + formatted_parts.append(f" {part}") + return "{\n" + "\n".join(formatted_parts) + "\n}" + return "Record" + + +def _map_primitive(schema_type: str, schema_format: str | None, schema: Schema) -> str: + """Map OpenAPI primitive types to TypeScript types.""" + if schema_type == "integer": + schema_format = schema.get(SchemaKey.FORMAT) + is_declared_bigint = schema.get(constants.X_ALGOKIT_BIGINT) is True + is_signed_32_bit = schema_format == "int32" + coerced_to_number = False + + if not is_declared_bigint and not is_signed_32_bit: + maximum: int | None = schema.get(SchemaKey.MAXIMUM) + minimum: int | None = schema.get(SchemaKey.MINIMUM) + description = str(schema.get("description", "")).lower() + + if ( + (maximum is not None and maximum <= _U32_MAX_VALUE) + or (minimum is not None and minimum >= 0 and maximum is not None and maximum <= _SMALL_INTEGER_MAX) + or any(keyword in description for keyword in _ENUM_KEYWORDS) + ): + coerced_to_number = True + + result = ( + TypeScriptType.BIGINT + if is_declared_bigint + else TypeScriptType.NUMBER + if is_signed_32_bit or coerced_to_number + else TypeScriptType.BIGINT + ) + elif schema_type == "number": + result = TypeScriptType.NUMBER + elif schema_type == "string": + is_byte = schema_format == "byte" or schema.get(constants.X_ALGOKIT_BYTES_BASE64) is True + result = TypeScriptType.UINT8ARRAY if is_byte else TypeScriptType.STRING + elif schema_type == "boolean": + result = TypeScriptType.BOOLEAN + else: + result = TypeScriptType.ANY + + return result + + +def ts_enum_type(schema: Schema) -> str | None: + if SchemaKey.ENUM not in schema: + return None + + if schema.get(constants.X_ALGOKIT_BIGINT) is True: + # For bigint-marked enums, use bigint type directly + return TypeScriptType.BIGINT + + type_val = schema.get(SchemaKey.TYPE) + values = schema.get(SchemaKey.ENUM, []) + + if type_val == "string": + return " | ".join([f"'{v!s}'" for v in values]) + + if type_val == "integer": + # Integers used as enum discriminators are small; map to number + return " | ".join([str(v) for v in values]) + + # Fallback: treat as string literals + return " | ".join([f"'{v!s}'" for v in values]) + + +def ts_type(schema: Schema | None, schemas: Schemas | None = None) -> str: + """Map OpenAPI schema to a TypeScript type string.""" + if not schema: + return TypeScriptType.ANY + + if isinstance(schema, dict) and schema.get(constants.X_ALGOKIT_SIGNED_TXN) is True: + return "SignedTransaction" + + if "$ref" in schema: + ref_name = _extract_ref_name(schema["$ref"]) + return ts_pascal_case(ref_name) + + return _ts_type_inner(schema, schemas) + + +def _ts_type_inner(schema: Schema, schemas: Schemas | None) -> str: + processors: list[tuple[str, _TypeProcessor]] = [ + (SchemaKey.ALL_OF, _process_all_of), + (SchemaKey.ONE_OF, _process_one_of), + (SchemaKey.ANY_OF, _process_any_of), + ] + + for key, handler in processors: + if key in schema: + return handler(schema, schemas) + + enum_type = ts_enum_type(schema) + if enum_type: + return enum_type + + return _map_non_composite(schema, schemas) + + +def _map_non_composite(schema: Schema, schemas: Schemas | None) -> str: + schema_type = schema.get(SchemaKey.TYPE) + + if schema_type == "array": + items_schema = schema.get(SchemaKey.ITEMS, {}) + is_signed_txn = isinstance(items_schema, dict) and (items_schema.get(constants.X_ALGOKIT_SIGNED_TXN) is True) + items_type = "SignedTransaction" if is_signed_txn else ts_type(items_schema, schemas) + return f"{items_type}[]" + + if schema_type == TypeScriptType.OBJECT or ( + not schema_type and (SchemaKey.PROPERTIES in schema or SchemaKey.ADDITIONAL_PROPERTIES in schema) + ): + object_type = _inline_object(schema, schemas) + return _nullable(object_type, schema, schemas) + + primitive_type = _map_primitive(str(schema_type), schema.get(SchemaKey.FORMAT), schema) + return _nullable(primitive_type, schema, schemas) + + +_TypeProcessor = Callable[[Schema, Schemas | None], str] + + +def _process_all_of(schema: Schema, schemas: Schemas | None) -> str: + parts = schema.get(SchemaKey.ALL_OF, []) + return _intersection(ts_type(part, schemas) for part in parts) + + +def _process_one_of(schema: Schema, schemas: Schemas | None) -> str: + options = schema.get(SchemaKey.ONE_OF, []) + return _union(ts_type(option, schemas) for option in options) + + +def _process_any_of(schema: Schema, schemas: Schemas | None) -> str: + options = schema.get(SchemaKey.ANY_OF, []) + return _union(ts_type(option, schemas) for option in options) + + +# ---------- Response helpers ---------- + + +def has_msgpack_2xx(responses: Schema) -> bool: + for status, resp in (responses or {}).items(): + if not str(status).startswith(constants.SUCCESS_STATUS_PREFIX): + continue + content = (resp or {}).get(OperationKey.CONTENT, {}) + if any(ct in (content or {}) for ct in (MediaType.MSGPACK, MediaType.BINARY)): + return True + return False + + +def response_content_types(responses: Schema) -> list[str]: + content_types: set[str] = set() + for status, resp in (responses or {}).items(): + if not str(status).startswith(constants.SUCCESS_STATUS_PREFIX): + continue + content = (resp or {}).get(OperationKey.CONTENT, {}) + content_types.update(content) + return sorted(content_types) + + +def collect_schema_refs(schema: Schema, current_schema_name: str | None = None) -> list[str]: + """Collect referenced schema names, excluding self-references.""" + refs: set[str] = set() + target_name = ts_pascal_case(current_schema_name) if current_schema_name else None + stack: list[Any] = [schema] + + while stack: + node = stack.pop() + if not isinstance(node, dict): + continue + if "$ref" in node: + ref_name = ts_pascal_case(_extract_ref_name(node["$ref"])) + if target_name is None or ref_name != target_name: + refs.add(ref_name) + continue + + props = node.get(SchemaKey.PROPERTIES) + if isinstance(props, dict): + stack.extend(props.values()) + + items = node.get(SchemaKey.ITEMS) + if isinstance(items, dict): + stack.append(items) + + for key in (SchemaKey.ALL_OF, SchemaKey.ONE_OF, SchemaKey.ANY_OF): + collection = node.get(key) + if isinstance(collection, list): + stack.extend(child for child in collection if isinstance(child, dict)) + + additional = node.get(SchemaKey.ADDITIONAL_PROPERTIES) + if isinstance(additional, dict): + stack.append(additional) + + return sorted(refs) + + +def schema_uses_signed_txn(schema: Schema) -> bool: + """Detect if a schema (recursively) uses the x-algokit-signed-txn vendor extension.""" + stack: list[Any] = [schema] + + while stack: + node = stack.pop() + if not isinstance(node, dict): + continue + if node.get(constants.X_ALGOKIT_SIGNED_TXN) is True: + return True + if "$ref" in node: + continue + + props = node.get(constants.SchemaKey.PROPERTIES) + if isinstance(props, dict): + stack.extend(props.values()) + + items = node.get(constants.SchemaKey.ITEMS) + if isinstance(items, dict): + stack.append(items) + + for key in (constants.SchemaKey.ALL_OF, constants.SchemaKey.ONE_OF, constants.SchemaKey.ANY_OF): + collection = node.get(key) + if isinstance(collection, list): + stack.extend(child for child in collection if isinstance(child, dict)) + + addl = node.get(constants.SchemaKey.ADDITIONAL_PROPERTIES) + if isinstance(addl, dict): + stack.append(addl) + + return False + + +# ---------- Type string helpers for templates ---------- + + +def ts_is_array_type(type_str: str) -> bool: + t = (type_str or "").strip() + return t.endswith("[]") or (t.startswith("Array<") and t.endswith(">")) + + +def ts_array_item_type(type_str: str) -> str: + t = (type_str or "").strip() + if t.endswith("[]"): + return t[:-2] + if t.startswith("Array<") and t.endswith(">"): + return t[len("Array<") : -1] + return t + + +def ts_is_builtin_or_primitive(type_str: str) -> bool: + t = (type_str or "").strip() + return t in constants.TS_BUILTIN_TYPES or t in {TypeScriptType.ANY, TypeScriptType.NULL, TypeScriptType.OBJECT} + + +def ts_is_model_type(type_str: str) -> bool: + t = (type_str or "").strip() + if ts_is_array_type(t): + t = ts_array_item_type(t) + # Treat PascalCase identifiers as model types and exclude TS builtins + return bool(re.match(r"^[A-Z][A-Za-z0-9_]*$", t)) and not ts_is_builtin_or_primitive(t) + + +FILTERS: dict[str, Any] = { + "ts_doc_comment": ts_doc_comment, + "ts_string_literal": ts_string_literal, + "ts_optional": ts_optional, + "ts_array": ts_array, + "ts_type": ts_type, + "ts_pascal_case": ts_pascal_case, + "ts_camel_case": ts_camel_case, + "ts_kebab_case": ts_kebab_case, + "ts_property_name": ts_property_name, + "has_msgpack_2xx": has_msgpack_2xx, + "response_content_types": response_content_types, + "collect_schema_refs": collect_schema_refs, + "schema_uses_signed_txn": schema_uses_signed_txn, + "ts_is_array_type": ts_is_array_type, + "ts_array_item_type": ts_array_item_type, + "ts_is_builtin_or_primitive": ts_is_builtin_or_primitive, + "ts_is_model_type": ts_is_model_type, +} diff --git a/oas-generator/src/oas_generator/generator/models.py b/oas-generator/src/oas_generator/generator/models.py new file mode 100644 index 000000000..7f73cc5c9 --- /dev/null +++ b/oas-generator/src/oas_generator/generator/models.py @@ -0,0 +1,150 @@ +from __future__ import annotations + +from dataclasses import dataclass +from pathlib import Path +from typing import Any + +Schema = dict[str, Any] +Operation = dict[str, Any] +TemplateContext = dict[str, Any] +FileMap = dict[Path, str] + + +@dataclass +class Parameter: + """Represents an API parameter.""" + + name: str + var_name: str + location: str + required: bool + ts_type: str + description: str | None = None + stringify_bigint: bool = False + + +@dataclass +class RequestBody: + """Represents a request body specification.""" + + media_type: str + ts_type: str + required: bool + supports_msgpack: bool = False + supports_json: bool = False + + +@dataclass +class OperationContext: + """Complete context for an API operation.""" + + operation_id: str + method: str + path: str + description: str | None + parameters: list[Parameter] + request_body: RequestBody | None + response_type: str + import_types: set[str] + tags: list[str] | None = None + returns_msgpack: bool = False + has_format_param: bool = False + format_var_name: str | None = None + # When the original spec had a query param `format` with enum ['msgpack'] only, + # we don't expose it to callers but still need to set it implicitly on requests + force_msgpack_query: bool = False + error_types: list[ErrorDescriptor] | None = None + + def to_dict(self) -> dict[str, Any]: + """Convert to dictionary for template rendering.""" + return { + "operationId": self.operation_id, + "method": self.method, + "path": self.path, + "description": self.description, + "parameters": [self._param_to_dict(p) for p in self.parameters], + "pathParameters": [self._param_to_dict(p) for p in self.parameters if p.location == "path"], + "otherParameters": [self._param_to_dict(p) for p in self.parameters if p.location in {"query", "header"}], + "requestBody": self._request_body_to_dict(self.request_body) if self.request_body else None, + "responseTsType": self.response_type, + "returnsMsgpack": self.returns_msgpack, + "hasFormatParam": self.has_format_param, + "formatVarName": self.format_var_name, + "forceMsgpackQuery": self.force_msgpack_query, + "errorTypes": [self._error_to_dict(e) for e in (self.error_types or [])], + } + + @staticmethod + def _error_to_dict(error: ErrorDescriptor) -> dict[str, Any]: + return { + "errorName": error.error_name, + "statusCodes": error.status_codes, + "errorType": error.error_type, + "description": error.description, + "isArray": error.is_array, + "arrayItemType": error.array_item_type, + } + + @staticmethod + def _param_to_dict(param: Parameter) -> dict[str, Any]: + return { + "name": param.name, + "varName": param.var_name, + "in": param.location, + "required": param.required, + "tsType": param.ts_type, + "description": param.description, + "stringifyBigInt": param.stringify_bigint, + } + + @staticmethod + def _request_body_to_dict(body: RequestBody) -> dict[str, Any]: + return { + "mediaType": body.media_type, + "tsType": body.ts_type, + "required": body.required, + "supportsMsgpack": body.supports_msgpack, + "supportsJson": body.supports_json, + } + + +@dataclass +class FieldDescriptor: + """Descriptor for a single model field used by templates.""" + + name: str + wire_name: str + ts_type: str + is_array: bool + ref_model: str | None + is_bytes: bool + is_bigint: bool + is_signed_txn: bool + is_optional: bool + is_nullable: bool + + +@dataclass +class ErrorDescriptor: + """Descriptor for error response handling with structured error types.""" + + error_name: str + status_codes: list[str] + error_type: str + description: str | None = None + is_array: bool = False + array_item_type: str | None = None + + +@dataclass +class ModelDescriptor: + """Descriptor for a schema model including field metadata.""" + + model_name: str + fields: list[FieldDescriptor] + is_object: bool + is_array: bool = False + array_item_ref: str | None = None + array_item_is_bytes: bool = False + array_item_is_bigint: bool = False + array_item_is_signed_txn: bool = False diff --git a/oas-generator/src/oas_generator/generator/template_engine.py b/oas-generator/src/oas_generator/generator/template_engine.py new file mode 100644 index 000000000..f34e118bd --- /dev/null +++ b/oas-generator/src/oas_generator/generator/template_engine.py @@ -0,0 +1,845 @@ +from __future__ import annotations + +import re +from collections.abc import Mapping +from dataclasses import dataclass +from pathlib import Path +from typing import Any + +from jinja2 import Environment, FileSystemLoader, select_autoescape + +from oas_generator import constants +from oas_generator.generator.filters import ( + FILTERS, + ts_camel_case, + ts_kebab_case, + ts_pascal_case, + ts_type, +) +from oas_generator.generator.models import ( + FieldDescriptor, + ModelDescriptor, + OperationContext, + Parameter, + RequestBody, +) +from oas_generator.parser.oas_parser import OASParser + +# Type aliases for clarity +type Schema = dict[str, Any] +type Schemas = Mapping[str, Schema] +type TemplateContext = dict[str, Any] +type FileMap = dict[Path, str] + +_TYPE_TOKEN_RE = re.compile(r"\b[A-Z][A-Za-z0-9_]*\b") + + +@dataclass +class OperationInput: + """Inputs required to build an `OperationContext`.""" + + operation_id: str + method: str + path: str + operation: Schema + path_params: list[Schema] + spec: Schema + + +class TemplateRenderer: + """Handles template rendering operations.""" + + def __init__(self, template_dir: Path | None = None) -> None: + if template_dir is None: + template_dir = Path(__file__).parent.parent / constants.DEFAULT_TEMPLATE_DIR + + self.template_dir = Path(template_dir) + self.env = self._create_environment() + + def _create_environment(self) -> Environment: + env = Environment( + loader=FileSystemLoader(str(self.template_dir)), + autoescape=select_autoescape(["html", "xml"]), + trim_blocks=constants.TEMPLATE_TRIM_BLOCKS, + lstrip_blocks=constants.TEMPLATE_LSTRIP_BLOCKS, + ) + env.filters.update(FILTERS) + return env + + def render(self, template_name: str, context: TemplateContext) -> str: + template = self.env.get_template(template_name) + return template.render(**context) + + def render_batch(self, template_map: dict[Path, tuple[str, TemplateContext]]) -> FileMap: + return {path: self.render(template, context) for path, (template, context) in template_map.items()} + + +class SchemaProcessor: + """Processes OpenAPI schemas and generates TypeScript models.""" + + def __init__(self, renderer: TemplateRenderer) -> None: + self.renderer = renderer + self._wire_to_canonical: dict[str, str] = {} + self._camel_to_wire: dict[str, str] = {} + + def generate_models(self, output_dir: Path, schemas: Schemas) -> FileMap: + models_dir = output_dir / constants.DirectoryName.SRC / constants.DirectoryName.MODELS + files: FileMap = {} + + # Generate individual model files + for name, schema in schemas.items(): + descriptor = self._build_model_descriptor(name, schema, schemas) + context = self._create_model_context(name, schema, schemas, descriptor) + content = self.renderer.render(constants.MODEL_TEMPLATE, context) + file_name = f"{ts_kebab_case(name)}{constants.MODEL_FILE_EXTENSION}" + files[models_dir / file_name] = content + + files[models_dir / constants.INDEX_FILE] = self.renderer.render( + constants.MODELS_INDEX_TEMPLATE, + {"schemas": schemas}, + ) + + return files + + def _create_model_context( + self, name: str, schema: Schema, all_schemas: Schemas, descriptor: ModelDescriptor + ) -> TemplateContext: + is_object = self._is_object_schema(schema) + properties = self._extract_properties(schema) if is_object else [] + + return { + "schema_name": name, + "schema": schema, + "schemas": all_schemas, + "is_object": is_object, + "properties": properties, + "has_additional_properties": schema.get(constants.SchemaKey.ADDITIONAL_PROPERTIES) is not None, + "additional_properties_type": schema.get(constants.SchemaKey.ADDITIONAL_PROPERTIES), + "descriptor": descriptor, + } + + @staticmethod + def _is_object_schema(schema: Schema) -> bool: + is_type_object = schema.get(constants.SchemaKey.TYPE) == constants.TypeScriptType.OBJECT + has_properties = constants.SchemaKey.PROPERTIES in schema + has_composition = any( + k in schema for k in [constants.SchemaKey.ALL_OF, constants.SchemaKey.ONE_OF, constants.SchemaKey.ANY_OF] + ) + return (is_type_object or has_properties) and not has_composition + + def _extract_properties(self, schema: Schema) -> list[dict[str, Any]]: + properties = [] + required_fields = set(schema.get(constants.SchemaKey.REQUIRED, [])) + + for prop_name, prop_schema in (schema.get(constants.SchemaKey.PROPERTIES) or {}).items(): + self._register_rename(prop_name, prop_schema) + properties.append( + { + "name": prop_name, + "schema": prop_schema, + "is_required": prop_name in required_fields, + } + ) + + return properties + + def _register_rename(self, wire_name: str, schema: Schema) -> None: + rename_value = schema.get(constants.X_ALGOKIT_FIELD_RENAME) + if not isinstance(rename_value, str) or not rename_value: + return + + # Preserve first occurrence to avoid accidental overrides from conflicting specs + self._wire_to_canonical.setdefault(wire_name, rename_value) + self._camel_to_wire.setdefault(ts_camel_case(rename_value), wire_name) + + @property + def rename_mappings(self) -> tuple[dict[str, str], dict[str, str]]: + return self._wire_to_canonical, self._camel_to_wire + + def _build_model_descriptor(self, name: str, schema: Schema, all_schemas: Schemas) -> ModelDescriptor: + """Build a per-model descriptor from OAS schema and vendor extensions.""" + model_name = ts_pascal_case(name) + + # Top-level array schema support + if isinstance(schema, dict) and schema.get(constants.SchemaKey.TYPE) == "array": + items = schema.get(constants.SchemaKey.ITEMS, {}) or {} + ref_model = None + if isinstance(items, dict) and "$ref" in items: + ref = items["$ref"].split("/")[-1] + ref_model = ts_pascal_case(ref) + fmt = items.get(constants.SchemaKey.FORMAT) + is_bytes = fmt == "byte" or items.get(constants.X_ALGOKIT_BYTES_BASE64) is True + is_bigint = bool(items.get(constants.X_ALGOKIT_BIGINT) is True) + is_signed_txn = bool(items.get(constants.X_ALGOKIT_SIGNED_TXN) is True) + return ModelDescriptor( + model_name=model_name, + fields=[], + is_object=False, + is_array=True, + array_item_ref=ref_model, + array_item_is_bytes=is_bytes, + array_item_is_bigint=is_bigint, + array_item_is_signed_txn=is_signed_txn, + ) + + # Object schema descriptor + fields: list[FieldDescriptor] = [] + is_object = self._is_object_schema(schema) + required_fields = set(schema.get(constants.SchemaKey.REQUIRED, []) or []) + props = schema.get(constants.SchemaKey.PROPERTIES) or {} + for prop_name, prop_schema in props.items(): + wire_name = prop_name + canonical = prop_schema.get(constants.X_ALGOKIT_FIELD_RENAME) or prop_name + name_camel = ts_camel_case(canonical) + + ts_t = ts_type(prop_schema, all_schemas) + is_array = prop_schema.get(constants.SchemaKey.TYPE) == "array" + items = prop_schema.get(constants.SchemaKey.ITEMS, {}) if is_array else None + ref_model = None + signed_txn = False + bytes_flag = False + bigint_flag = False + if is_array and isinstance(items, dict): + if "$ref" in items: + ref_model = ts_pascal_case(items["$ref"].split("/")[-1]) + fmt = items.get(constants.SchemaKey.FORMAT) + bytes_flag = fmt == "byte" or items.get(constants.X_ALGOKIT_BYTES_BASE64) is True + bigint_flag = bool(items.get(constants.X_ALGOKIT_BIGINT) is True) + signed_txn = bool(items.get(constants.X_ALGOKIT_SIGNED_TXN) is True) + else: + if "$ref" in (prop_schema or {}): + ref_model = ts_pascal_case(prop_schema["$ref"].split("/")[-1]) + fmt = prop_schema.get(constants.SchemaKey.FORMAT) + bytes_flag = fmt == "byte" or prop_schema.get(constants.X_ALGOKIT_BYTES_BASE64) is True + bigint_flag = bool(prop_schema.get(constants.X_ALGOKIT_BIGINT) is True) + signed_txn = bool(prop_schema.get(constants.X_ALGOKIT_SIGNED_TXN) is True) + + is_optional = prop_name not in required_fields + # Nullable per OpenAPI + is_nullable = bool(prop_schema.get(constants.SchemaKey.NULLABLE) is True) + + fields.append( + FieldDescriptor( + name=name_camel, + wire_name=wire_name, + ts_type=ts_t, + is_array=is_array, + ref_model=ref_model, + is_bytes=bytes_flag, + is_bigint=bigint_flag, + is_signed_txn=signed_txn, + is_optional=is_optional, + is_nullable=is_nullable, + ) + ) + + return ModelDescriptor(model_name=model_name, fields=fields, is_object=is_object) + + +class OperationProcessor: + """Processes OpenAPI operations and generates API services.""" + + def __init__(self, renderer: TemplateRenderer) -> None: + self.renderer = renderer + self._model_names: set[str] = set() + self._synthetic_models: dict[str, Schema] = {} + + def process_spec(self, spec: Schema) -> tuple[dict[str, list[OperationContext]], set[str], dict[str, Schema]]: + """Process entire OpenAPI spec and return operations by tag.""" + self._initialize_model_names(spec) + + operations_by_tag: dict[str, list[OperationContext]] = {} + tags: set[str] = set() + + paths = spec.get(constants.SchemaKey.PATHS, {}) + for path, path_item in paths.items(): + if not isinstance(path_item, dict): + continue + + operations = self._process_path_operations(path, path_item, spec) + for op in operations: + for tag in op.tags: + tags.add(tag) + operations_by_tag.setdefault(tag, []).append(op) + + # Sort operations by ID for stability + for ops in operations_by_tag.values(): + ops.sort(key=lambda o: o.operation_id) + + return operations_by_tag, tags, self._synthetic_models + + def generate_service( + self, + output_dir: Path, + operations_by_tag: dict[str, list[OperationContext]], + tags: set[str], + service_class_name: str, + ) -> FileMap: + """Generate API service files.""" + apis_dir = output_dir / constants.DirectoryName.SRC / constants.DirectoryName.APIS + files: FileMap = {} + + # Collect unique operations + all_operations = self._collect_unique_operations(operations_by_tag, tags) + + # Convert to template context + operations_context = [op.to_dict() for op in all_operations] + import_types = set().union(*(op.import_types for op in all_operations)) + + # Generate service file + files[apis_dir / constants.API_SERVICE_FILE] = self.renderer.render( + constants.API_SERVICE_TEMPLATE, + { + "tag_name": constants.DEFAULT_API_TAG, + "operations": operations_context, + "import_types": sorted(import_types), + "service_class_name": service_class_name, + }, + ) + + # Generate barrel export + files[apis_dir / constants.INDEX_FILE] = self.renderer.render( + constants.APIS_INDEX_TEMPLATE, {"service_class_name": service_class_name} + ) + + return files + + def _initialize_model_names(self, spec: Schema) -> None: + """Initialize set of model names from spec.""" + + components = spec.get(constants.SchemaKey.COMPONENTS, {}) + schemas = components.get(constants.SchemaKey.COMPONENTS_SCHEMAS, {}) + self._model_names = {ts_pascal_case(name) for name in schemas} + + def _process_path_operations(self, path: str, path_item: Schema, spec: Schema) -> list[OperationContext]: + """Process all operations for a given path.""" + + operations = [] + path_params = path_item.get(constants.OperationKey.PARAMETERS, []) + + for method, operation in path_item.items(): + if method.lower() not in constants.HTTP_METHODS or not isinstance(operation, dict): + continue + + # Generate operation ID if missing + operation_id = operation.get(constants.OperationKey.OPERATION_ID) or ts_camel_case( + f"{method.lower()}_{path}" + ) + + op_input = OperationInput( + operation_id=operation_id, + method=method.upper(), + path=path, + operation=operation, + path_params=path_params, + spec=spec, + ) + + # Process operation + context = self._create_operation_context(op_input) + + context.tags = operation.get(constants.OperationKey.TAGS, [constants.DEFAULT_TAG]) + operations.append(context) + + return operations + + def _create_operation_context(self, op_input: OperationInput) -> OperationContext: + """Create complete operation context.""" + # Merge path and operation parameters + all_params = [*op_input.path_params, *op_input.operation.get(constants.OperationKey.PARAMETERS, [])] + + # Process components + parameters = self._process_parameters(all_params, op_input.spec) + request_body = self._process_request_body( + op_input.operation.get(constants.OperationKey.REQUEST_BODY), op_input.spec + ) + response_type, returns_msgpack = self._process_responses( + op_input.operation.get(constants.OperationKey.RESPONSES, {}), op_input.operation_id, op_input.spec + ) + + # Build context + context = OperationContext( + operation_id=op_input.operation_id, + method=op_input.method, + path=op_input.path, + description=op_input.operation.get(constants.OperationKey.DESCRIPTION), + parameters=parameters, + request_body=request_body, + response_type=response_type, + import_types=set(), + tags=[], + returns_msgpack=returns_msgpack, + ) + + # Compute additional properties + self._compute_format_param(context) + self._compute_force_msgpack_query(context, op_input.operation, op_input.spec) + self._compute_import_types(context) + + return context + + def _process_parameters(self, params: list[Schema], spec: Schema) -> list[Parameter]: + """Process operation parameters.""" + + parameters = [] + used_names: set[str] = set() + schemas = self._get_schemas(spec) + + for param_def in params: + # Resolve $ref if present + param = self._resolve_ref(param_def, spec) if "$ref" in param_def else param_def + + # Extract parameter details + raw_name = str(param.get("name")) + # Skip `format` query param when it's constrained to a single format (json or msgpack) + location_candidate = param.get(constants.OperationKey.IN, constants.ParamLocation.QUERY) + if location_candidate == constants.ParamLocation.QUERY and raw_name == constants.FORMAT_PARAM_NAME: + schema_obj = param.get("schema", {}) or {} + enum_vals = schema_obj.get(constants.SchemaKey.ENUM) + if isinstance(enum_vals, list) and len(enum_vals) == 1 and enum_vals[0] in ("msgpack", "json"): + # Endpoint only supports a single format; do not expose/append `format` + continue + var_name = self._sanitize_variable_name(ts_camel_case(raw_name), used_names) + used_names.add(var_name) + + schema = param.get("schema", {}) + ts_type_str = ts_type(schema, schemas) + + # Handle bigint ergonomics + if ts_type_str == constants.TypeScriptType.BIGINT: + ts_type_str = constants.TypeScriptType.NUMBER_OR_BIGINT + stringify_bigint = True + else: + stringify_bigint = constants.TypeScriptType.BIGINT in ts_type_str + + location = location_candidate + required = param.get(constants.SchemaKey.REQUIRED, False) or location == constants.ParamLocation.PATH + + parameters.append( + Parameter( + name=raw_name, + var_name=var_name, + location=location, + required=required, + ts_type=ts_type_str, + description=param.get(constants.OperationKey.DESCRIPTION), + stringify_bigint=stringify_bigint, + ) + ) + + return parameters + + def _process_request_body(self, request_body: Schema | None, spec: Schema) -> RequestBody | None: + """Process request body specification.""" + + if not isinstance(request_body, dict): + return None + + content = request_body.get("content", {}) + schemas = self._get_schemas(spec) + + # Check content type support + supports_msgpack = constants.MediaType.MSGPACK in content + supports_json = constants.MediaType.JSON in content + required = request_body.get(constants.SchemaKey.REQUIRED, False) + + # Determine media type and TypeScript type + if supports_json or supports_msgpack: + media_type = ( + constants.MediaType.MSGPACK if supports_msgpack and not supports_json else constants.MediaType.JSON + ) + schema = content.get(media_type, {}).get("schema", {}) + ts_type_str = ts_type(schema, schemas) + elif constants.MediaType.TEXT in content: + media_type = constants.MediaType.TEXT + schema = content[constants.MediaType.TEXT].get("schema", {}) + ts_type_str = ts_type(schema, schemas) + supports_msgpack = supports_json = False + elif constants.MediaType.BINARY in content or constants.MediaType.OCTET_STREAM in content: + media_type = ( + constants.MediaType.BINARY + if constants.MediaType.BINARY in content + else constants.MediaType.OCTET_STREAM + ) + ts_type_str = constants.TypeScriptType.UINT8ARRAY + supports_msgpack = supports_json = False + else: + return None + + return RequestBody( + media_type=media_type, + ts_type=ts_type_str, + required=required, + supports_msgpack=supports_msgpack, + supports_json=supports_json, + ) + + def _process_responses(self, responses: Schema, operation_id: str, spec: Schema) -> tuple[str, bool]: + """Process response specifications.""" + + return_types: list[str] = [] + returns_msgpack = False + schemas = self._get_schemas(spec) + + for status, response in responses.items(): + if not str(status).startswith(constants.SUCCESS_STATUS_PREFIX): + continue + + content = (response or {}).get("content", {}) + if constants.MediaType.MSGPACK in content: + returns_msgpack = True + + for _, media_details in content.items(): + schema = (media_details or {}).get("schema") + if not schema: + continue + + type_name = self._resolve_response_type(schema, operation_id, schemas) + if type_name: + return_types.append(type_name) + + # Determine final response type + if return_types: + response_type = " | ".join(dict.fromkeys(return_types)) + elif returns_msgpack: + response_type = constants.TypeScriptType.UINT8ARRAY + else: + response_type = constants.TypeScriptType.VOID + + return response_type, returns_msgpack + + def _compute_format_param(self, context: OperationContext) -> None: + """Detect and set format parameter for content negotiation.""" + for param in context.parameters: + if param.location == constants.ParamLocation.QUERY and param.name == constants.FORMAT_PARAM_NAME: + context.has_format_param = True + context.format_var_name = param.var_name + break + + def _compute_force_msgpack_query(self, context: OperationContext, raw_operation: Schema, spec: Schema) -> None: + """Detect if the raw spec constrains query format to only 'msgpack' and mark for implicit query injection.""" + params = raw_operation.get(constants.OperationKey.PARAMETERS, []) or [] + for param_def in params: + param = ( + self._resolve_ref(param_def, spec) if isinstance(param_def, dict) and "$ref" in param_def else param_def + ) + if not isinstance(param, dict): + continue + name = param.get("name") + location = param.get(constants.OperationKey.IN, constants.ParamLocation.QUERY) + if location == constants.ParamLocation.QUERY and name == constants.FORMAT_PARAM_NAME: + schema_obj = param.get("schema", {}) or {} + enum_vals = schema_obj.get(constants.SchemaKey.ENUM) + if isinstance(enum_vals, list) and len(enum_vals) == 1 and enum_vals[0] == "msgpack": + context.force_msgpack_query = True + return + + def _compute_import_types(self, context: OperationContext) -> None: + """Collect model types that need importing.""" + builtin_types = constants.TS_BUILTIN_TYPES + + def extract_types(type_str: str) -> set[str]: + if not type_str: + return set() + tokens = set(_TYPE_TOKEN_RE.findall(type_str)) + types: set[str] = {tok for tok in tokens if tok in self._model_names and tok not in builtin_types} + # Include synthetic models that aren't part of _model_names + if "AlgokitSignedTransaction" in tokens: + types.add("AlgokitSignedTransaction") + return types + + # Collect from all type references + context.import_types = extract_types(context.response_type) + + # Only include request body types if the method actually uses a body + if context.request_body and context.method.upper() not in ["GET", "HEAD", "DELETE"]: + context.import_types |= extract_types(context.request_body.ts_type) + + for param in context.parameters: + context.import_types |= extract_types(param.ts_type) + + def _collect_unique_operations( + self, operations_by_tag: dict[str, list[OperationContext]], tags: set[str] + ) -> list[OperationContext]: + """Collect unique operations across all tags.""" + seen_keys: set[tuple[str, str]] = set() + unique_operations = [] + + for tag in sorted(tags): + for op in operations_by_tag.get(tag, []): + key = (op.method, op.path) + if key not in seen_keys: + seen_keys.add(key) + unique_operations.append(op) + + return sorted(unique_operations, key=lambda o: o.operation_id) + + @staticmethod + def _should_synthesize_model(schema: Schema) -> bool: + """Check if schema should become a synthetic model.""" + return ( + isinstance(schema, dict) + and "$ref" not in schema + and (schema.get("type") == "object" or "properties" in schema or "additionalProperties" in schema) + ) + + def _resolve_response_type(self, schema: Schema, operation_id: str, schemas: Schema) -> str: + """Ensure response schemas are represented by concrete TypeScript types.""" + if "$ref" in schema: + return ts_type(schema, schemas) + + if self._should_synthesize_model(schema): + base_name = ts_pascal_case(operation_id) + if base_name in self._model_names and base_name not in self._synthetic_models: + return base_name + if base_name in self._synthetic_models: + return base_name + model_name = self._allocate_synthetic_model_name(operation_id) + if model_name not in self._synthetic_models: + self._synthetic_models[model_name] = schema + self._model_names.add(model_name) + return model_name + + return ts_type(schema, schemas) + + def _allocate_synthetic_model_name(self, operation_id: str) -> str: + """Generate a unique model name for an inline response schema.""" + + base_name = ts_pascal_case(operation_id) + candidate = base_name + + if candidate in self._model_names or candidate in self._synthetic_models: + candidate = f"{candidate}Response" + + counter = 2 + while candidate in self._model_names or candidate in self._synthetic_models: + candidate = f"{base_name}Response{counter}" + counter += 1 + + return candidate + + @staticmethod + def _sanitize_variable_name(base_name: str, used_names: set[str]) -> str: + """Ensure variable name is valid and unique.""" + # Handle reserved words + if base_name in constants.TS_RESERVED_WORDS: + base_name = f"{base_name}_" + + # Ensure uniqueness + if base_name not in used_names: + return base_name + + counter = 2 + while f"{base_name}{counter}" in used_names: + counter += 1 + return f"{base_name}{counter}" + + @staticmethod + def _resolve_ref(ref_obj: Schema, spec: Schema) -> Schema: + """Resolve a $ref pointer in the spec.""" + ref = ref_obj.get("$ref", "") + parts = ref.split("/")[1:] # Skip leading # + + node = spec + for part in parts: + node = node.get(part, {}) + return node + + @staticmethod + def _get_schemas(spec: Schema) -> Schema: + """Extract schemas from spec components.""" + components = spec.get(constants.SchemaKey.COMPONENTS, {}) + return components.get(constants.SchemaKey.COMPONENTS_SCHEMAS, {}) + + +class CodeGenerator: + """Main code generator orchestrating the generation process.""" + + def __init__(self, template_dir: Path | None = None) -> None: + self.renderer = TemplateRenderer(template_dir) + self.schema_processor = SchemaProcessor(self.renderer) + self.operation_processor = OperationProcessor(self.renderer) + + def generate( + self, + spec_path: Path, + output_dir: Path, + package_name: str, + *, + custom_description: str | None = None, + ) -> FileMap: + """Generate complete TypeScript client from OpenAPI spec.""" + # Parse specification + parser = OASParser() + parser.parse_file(spec_path) + spec = parser.spec_data or {} + + # Extract class names + client_class, service_class = self._extract_class_names(package_name) + + # Generate base runtime + files = self._generate_runtime(output_dir, package_name, client_class, service_class, custom_description) + + # Process operations and schemas + ops_by_tag, tags, synthetic_models = self.operation_processor.process_spec(spec) + + # Merge schemas + components = spec.get(constants.SchemaKey.COMPONENTS, {}) + base_schemas = components.get(constants.SchemaKey.COMPONENTS_SCHEMAS, {}) + all_schemas = {**base_schemas, **synthetic_models} + + # Generate components + files.update(self.schema_processor.generate_models(output_dir, all_schemas)) + + # Inject custom Algod models if this spec targets Algod + client_type = self._detect_client_type(spec) + if client_type == "Algod": + models_dir = output_dir / constants.DirectoryName.SRC / constants.DirectoryName.MODELS + # Custom typed block models + # Block-specific models (prefixed to avoid shape collisions) + files[models_dir / "block-eval-delta.ts"] = self.renderer.render( + "models/block/block-eval-delta.ts.j2", + {"spec": spec}, + ) + files[models_dir / "block-state-delta.ts"] = self.renderer.render( + "models/block/block-state-delta.ts.j2", + {"spec": spec}, + ) + files[models_dir / "block-account-state-delta.ts"] = self.renderer.render( + "models/block/block-account-state-delta.ts.j2", + {"spec": spec}, + ) + # BlockAppEvalDelta is implemented by repurposing application-eval-delta.ts.j2 to new name + files[models_dir / "block-app-eval-delta.ts"] = self.renderer.render( + "models/block/application-eval-delta.ts.j2", + {"spec": spec}, + ) + files[models_dir / "block_state_proof_tracking_data.ts"] = self.renderer.render( + "models/block/block-state-proof-tracking-data.ts.j2", + {"spec": spec}, + ) + files[models_dir / "block_state_proof_tracking.ts"] = self.renderer.render( + "models/block/block-state-proof-tracking.ts.j2", + {"spec": spec}, + ) + files[models_dir / "signed-txn-in-block.ts"] = self.renderer.render( + "models/block/signed-txn-in-block.ts.j2", + {"spec": spec}, + ) + files[models_dir / "block.ts"] = self.renderer.render( + "models/block/block.ts.j2", + {"spec": spec}, + ) + files[models_dir / "get-block.ts"] = self.renderer.render( + "models/block/get-block.ts.j2", + {"spec": spec}, + ) + + # Ensure index exports include the custom models + index_path = models_dir / constants.INDEX_FILE + base_index = self.renderer.render(constants.MODELS_INDEX_TEMPLATE, {"schemas": all_schemas}) + extras = ( + "\n" + "export type { BlockEvalDelta } from './block-eval-delta';\n" + "export { BlockEvalDeltaMeta } from './block-eval-delta';\n" + "export type { BlockStateDelta } from './block-state-delta';\n" + "export { BlockStateDeltaMeta } from './block-state-delta';\n" + "export type { BlockAccountStateDelta } from './block-account-state-delta';\n" + "export { BlockAccountStateDeltaMeta } from './block-account-state-delta';\n" + "export type { BlockAppEvalDelta } from './block-app-eval-delta';\n" + "export { BlockAppEvalDeltaMeta } from './block-app-eval-delta';\n" + "export type { BlockStateProofTrackingData } from './block_state_proof_tracking_data';\n" + "export { BlockStateProofTrackingDataMeta } from './block_state_proof_tracking_data';\n" + "export type { BlockStateProofTracking } from './block_state_proof_tracking';\n" + "export { BlockStateProofTrackingMeta } from './block_state_proof_tracking';\n" + "export type { Block } from './block';\n" + "export { BlockMeta } from './block';\n" + "export type { SignedTxnInBlock } from './signed-txn-in-block';\n" + "export { SignedTxnInBlockMeta } from './signed-txn-in-block';\n" + "export type { GetBlock } from './get-block';\n" + "export { GetBlockMeta } from './get-block';\n" + ) + files[index_path] = base_index + extras + files.update(self.operation_processor.generate_service(output_dir, ops_by_tag, tags, service_class)) + files.update(self._generate_client_files(output_dir, client_class, service_class)) + + return files + + @staticmethod + def _detect_client_type(spec: Schema) -> str: + """Detect client type from the OpenAPI spec title.""" + try: + title = (spec.get("info", {}) or {}).get("title", "") + if not isinstance(title, str): + return "Api" + tl = title.lower() + if "algod" in tl: + return "Algod" + if "indexer" in tl: + return "Indexer" + if "kmd" in tl: + return "Kmd" + return (title.split()[0] or "Api").title() + except Exception: + return "Api" + + def _generate_runtime( + self, + output_dir: Path, + package_name: str, + client_class: str, + service_class: str, + custom_description: str | None, + ) -> FileMap: + """Generate runtime support files.""" + src_dir = output_dir / constants.DirectoryName.SRC + core_dir = src_dir / constants.DirectoryName.CORE + + context = { + "package_name": package_name, + "custom_description": custom_description, + "client_class_name": client_class, + "service_class_name": service_class, + } + + template_map = { + # Core runtime + core_dir / "client-config.ts": ("base/src/core/client-config.ts.j2", context), + core_dir / "base-http-request.ts": ("base/src/core/base-http-request.ts.j2", context), + core_dir / "fetch-http-request.ts": ("base/src/core/fetch-http-request.ts.j2", context), + core_dir / "api-error.ts": ("base/src/core/api-error.ts.j2", context), + core_dir / "request.ts": ("base/src/core/request.ts.j2", context), + core_dir / "serialization.ts": ("base/src/core/serialization.ts.j2", context), + core_dir / "codecs.ts": ("base/src/core/codecs.ts.j2", context), + core_dir / "model-runtime.ts": ("base/src/core/model-runtime.ts.j2", context), + # Project files + src_dir / "index.ts": ("base/src/index.ts.j2", context), + } + + return self.renderer.render_batch(template_map) + + def _generate_client_files(self, output_dir: Path, client_class: str, service_class: str) -> FileMap: + """Generate client wrapper files.""" + src_dir = output_dir / constants.DirectoryName.SRC + + template_map = { + src_dir / "client.ts": ( + "client.ts.j2", + { + "service_class_name": service_class, + "client_class_name": client_class, + }, + ), + } + + return self.renderer.render_batch(template_map) + + # Centralized transformers/maps removed; per-model codecs handle all transforms. + + @staticmethod + def _extract_class_names(package_name: str) -> tuple[str, str]: + """Extract client and service class names from package name.""" + + base_name = ts_pascal_case(package_name) + base_core = base_name[:-6] if base_name.lower().endswith("client") else base_name + return f"{base_core}Client", f"{base_core}Api" diff --git a/oas-generator/src/oas_generator/parser/__init__.py b/oas-generator/src/oas_generator/parser/__init__.py new file mode 100644 index 000000000..68c02d286 --- /dev/null +++ b/oas-generator/src/oas_generator/parser/__init__.py @@ -0,0 +1,5 @@ +"""Parser utilities exposed by ``oas_generator.parser``.""" + +from oas_generator.parser.oas_parser import OASParser + +__all__ = ["OASParser"] diff --git a/oas-generator/src/oas_generator/parser/oas_parser.py b/oas-generator/src/oas_generator/parser/oas_parser.py new file mode 100644 index 000000000..109dca6cd --- /dev/null +++ b/oas-generator/src/oas_generator/parser/oas_parser.py @@ -0,0 +1,46 @@ +"""Lightweight OpenAPI Specification Parser for TypeScript Client Generation. + +This module provides a minimal parser that loads OpenAPI 3.x specifications +for use by the TypeScript generator. It focuses only on loading the spec +data, leaving all processing to the template engine. +""" + +from __future__ import annotations + +import json +from pathlib import Path +from typing import Any + + +class OASParser: + """Simple parser for OpenAPI 3.x specifications.""" + + def __init__(self) -> None: + """Initialize the parser with no loaded data.""" + self.spec_data: dict[str, Any] | None = None + + def parse_file(self, file_path: str | Path) -> None: + """Parse OpenAPI specification from a JSON file. + + Args: + file_path: Path to the OpenAPI specification file (JSON format) + + Raises: + FileNotFoundError: If the file doesn't exist + json.JSONDecodeError: If the file is not valid JSON + """ + path = Path(file_path) + if not path.exists(): + msg = f"OpenAPI spec file not found: {file_path}" + raise FileNotFoundError(msg) + + with path.open(encoding="utf-8") as f: + self.spec_data = json.load(f) + + def parse_dict(self, spec_dict: dict[str, Any]) -> None: + """Parse OpenAPI specification from a dictionary. + + Args: + spec_dict: The OpenAPI specification as a dictionary + """ + self.spec_data = spec_dict diff --git a/oas-generator/src/oas_generator/templates/apis/index.ts.j2 b/oas-generator/src/oas_generator/templates/apis/index.ts.j2 new file mode 100644 index 000000000..59555ee46 --- /dev/null +++ b/oas-generator/src/oas_generator/templates/apis/index.ts.j2 @@ -0,0 +1,2 @@ +// Barrel file for services +export { {{ service_class_name }} } from './api.service'; diff --git a/oas-generator/src/oas_generator/templates/apis/service.ts.j2 b/oas-generator/src/oas_generator/templates/apis/service.ts.j2 new file mode 100644 index 000000000..027aa9b5e --- /dev/null +++ b/oas-generator/src/oas_generator/templates/apis/service.ts.j2 @@ -0,0 +1,166 @@ +import type { BaseHttpRequest, ApiRequestOptions } from '../core/base-http-request'; +import { AlgorandSerializer } from '../core/model-runtime'; +import type { BodyFormat } from '../core/model-runtime'; +{% if import_types and import_types|length > 0 %} +{% set sorted = import_types | sort %} +import type { {{ sorted | join(', ') }} } from '../models/index'; +import { {% for t in sorted %}{{ t }}Meta{% if not loop.last %}, {% endif %}{% endfor %} } from '../models/index'; +{% endif %} + +{% macro field_type_meta(type_name) -%} +{%- if type_name in import_types -%} +({ kind: 'model', meta: () => {{ type_name }}Meta } as const) +{%- elif type_name == 'SignedTransaction' -%} +({ kind: 'codec', codecKey: 'SignedTransaction' } as const) +{%- elif type_name == 'Uint8Array' -%} +({ kind: 'scalar', isBytes: true } as const) +{%- elif type_name == 'bigint' -%} +({ kind: 'scalar', isBigint: true } as const) +{%- else -%} +null +{%- endif -%} +{%- endmacro %} + +{% macro array_meta(type_name) -%} +{%- set inner = type_name.strip() -%} +{%- if inner.endswith('[]') -%} + {%- set base = inner[:-2] -%} +{%- elif inner.startswith('Array<') and inner.endswith('>') -%} + {%- set base = inner[6:-1] -%} +{%- else -%} + {%- set base = None -%} +{%- endif -%} +{%- if base is none -%} +null +{%- else -%} + {%- set item = field_type_meta(base) -%} +{%- if item == 'null' -%} +null + {%- else -%} +({ name: '{{ base }}[]', kind: 'array', arrayItems: {{ item }} } as const) + {%- endif -%} +{%- endif -%} +{%- endmacro %} + +{% macro base_meta(type_name) -%} +{%- set t = type_name.strip() -%} +{%- if t.endswith('[]') or (t.startswith('Array<') and t.endswith('>')) -%} +{{ array_meta(type_name) }} +{%- else -%} + {%- if t in import_types -%} +{{ t }}Meta + {%- elif t == 'SignedTransaction' -%} +({ name: 'SignedTransaction', kind: 'passthrough', codecKey: 'SignedTransaction' } as const) + {%- elif t == 'Uint8Array' -%} +({ name: 'Uint8Array', kind: 'passthrough', passThrough: { kind: 'scalar', isBytes: true } as const } as const) + {%- elif t == 'bigint' -%} +({ name: 'bigint', kind: 'passthrough', passThrough: { kind: 'scalar', isBigint: true } as const } as const) + {%- else -%} +null + {%- endif -%} +{%- endif -%} +{%- endmacro %} + +{% macro meta_expr(type_name) -%} +{%- set meta = base_meta(type_name) -%} +{%- if meta == 'null' -%} +undefined +{%- else -%} +{{ meta }} +{%- endif -%} +{%- endmacro %} + +export class {{ service_class_name }} { + constructor(public readonly httpRequest: BaseHttpRequest) {} + + private static acceptFor(format: BodyFormat): string { + return format === 'json' ? 'application/json' : 'application/msgpack'; + } + + private static mediaFor(format: BodyFormat): string { + return format === 'json' ? 'application/json' : 'application/msgpack'; + } + +{% for op in operations %} + {% set is_raw_bytes_body = op.requestBody and op.requestBody.tsType == 'Uint8Array' %} + {{ op.description | ts_doc_comment }} + async {{ op.operationId | ts_camel_case }}( +{%- for p in op.pathParameters %} + {{ p.varName }}: {{ p.tsType }}, +{%- endfor %} +{%- if op.otherParameters|length > 0 or (op.requestBody and op.method.upper() not in ['GET', 'HEAD', 'DELETE']) %} + params?: { +{%- for p in op.otherParameters %} + {{ p.varName }}{% if not p.required %}?{% endif %}: {{ p.tsType }}; +{%- endfor %} +{%- if op.requestBody and op.method.upper() not in ['GET', 'HEAD', 'DELETE'] %} + body{% if not op.requestBody.required %}?{% endif %}: {{ op.requestBody.tsType }}; +{%- endif %} + }, +{%- endif %} + requestOptions?: ApiRequestOptions + ): Promise<{{ op.responseTsType }}> { + const headers: Record = {}; + {% set supports_msgpack = op.returnsMsgpack or (op.requestBody and op.requestBody.supportsMsgpack) %} + const responseFormat: BodyFormat = {% if supports_msgpack %}{% if op.hasFormatParam and op.formatVarName %}(params?.{{ op.formatVarName }} as BodyFormat | undefined) ?? 'msgpack'{% else %}'msgpack'{% endif %}{% else %}'json'{% endif %}; + headers['Accept'] = {{ service_class_name }}.acceptFor(responseFormat); + + {% if op.requestBody and op.method.upper() not in ['GET', 'HEAD', 'DELETE'] %} + {% if is_raw_bytes_body %} + const serializedBody = params?.body ?? undefined; + const mediaType = 'application/msgpack'; + headers['Content-Type'] = mediaType; + {% else %} + const bodyMeta = {{ meta_expr(op.requestBody.tsType) }}; + const mediaType = bodyMeta ? {{ service_class_name }}.mediaFor(responseFormat) : undefined; + if (mediaType) headers['Content-Type'] = mediaType; + const serializedBody = bodyMeta && params?.body !== undefined + ? AlgorandSerializer.encode(params.body, bodyMeta, responseFormat) + : params?.body; + {% endif %} + {% endif %} + + {% set query_params = op.otherParameters | selectattr('in', 'equalto', 'query') | list %} + {% set header_params = op.otherParameters | selectattr('in', 'equalto', 'header') | list %} + {% if header_params|length > 0 %} + for (const param of [{% for p in header_params %}{ name: '{{ p.name }}', value: params?.{{ p.varName }} }{% if not loop.last %}, {% endif %}{% endfor %}]) { + if (param.value !== undefined) headers[param.name] = String(param.value); + } + {% endif %} + + const payload = await this.httpRequest.request({ + method: '{{ op.method }}', + url: '{{ op.path }}', + path: { +{%- for p in op.pathParameters %} + '{{ p.name }}': {% if p.stringifyBigInt %}(typeof {{ p.varName }} === 'bigint' ? {{ p.varName }}.toString() : {{ p.varName }}){% else %}{{ p.varName }}{% endif %}, +{%- endfor %} + }, + query: { +{%- for p in query_params %} + '{{ p.name }}': {% if p.stringifyBigInt %}(typeof params?.{{ p.varName }} === 'bigint' ? (params!.{{ p.varName }} as bigint).toString() : params?.{{ p.varName }}){% else %}params?.{{ p.varName }}{% endif %}, +{%- endfor %} +{%- if op.forceMsgpackQuery %} + 'format': 'msgpack', +{%- endif %} + }, + headers, + {% if op.requestBody and op.method.upper() not in ['GET', 'HEAD', 'DELETE'] %} + body: serializedBody, + mediaType: mediaType, + {% else %} + body: undefined, + mediaType: undefined, + {% endif %} + ...(requestOptions ?? {}), + }); + + const responseMeta = {{ meta_expr(op.responseTsType) }}; + if (responseMeta) { + return AlgorandSerializer.decode(payload, responseMeta, responseFormat); + } + return payload as {{ op.responseTsType }}; + } + +{% endfor %} +} diff --git a/oas-generator/src/oas_generator/templates/base/src/core/api-error.ts.j2 b/oas-generator/src/oas_generator/templates/base/src/core/api-error.ts.j2 new file mode 100644 index 000000000..0adbbb200 --- /dev/null +++ b/oas-generator/src/oas_generator/templates/base/src/core/api-error.ts.j2 @@ -0,0 +1,12 @@ +export class ApiError extends Error { + public readonly url: string; + public readonly status: number; + public readonly body: T | undefined; + + constructor(url: string, status: number, body?: T) { + super(`Request to ${url} failed with status ${status}`); + this.url = url; + this.status = status; + this.body = body; + } +} diff --git a/oas-generator/src/oas_generator/templates/base/src/core/base-http-request.ts.j2 b/oas-generator/src/oas_generator/templates/base/src/core/base-http-request.ts.j2 new file mode 100644 index 000000000..9226ab8d8 --- /dev/null +++ b/oas-generator/src/oas_generator/templates/base/src/core/base-http-request.ts.j2 @@ -0,0 +1,22 @@ +import type { ClientConfig } from './client-config'; + +export type QueryValue = string | number | bigint | boolean; +export type QueryParams = Record; + +export type BodyValue = Uint8Array | Record | unknown[] | string | number | boolean | null; + +export interface ApiRequestOptions { + method: string; + url: string; + path?: Record; + query?: QueryParams; + headers?: Record; + body?: BodyValue; + mediaType?: string; + responseHeader?: string; +} + +export abstract class BaseHttpRequest { + constructor(public readonly config: ClientConfig) {} + abstract request(options: ApiRequestOptions): Promise; +} diff --git a/oas-generator/src/oas_generator/templates/base/src/core/cancelable-promise.ts.j2 b/oas-generator/src/oas_generator/templates/base/src/core/cancelable-promise.ts.j2 new file mode 100644 index 000000000..84a895c50 --- /dev/null +++ b/oas-generator/src/oas_generator/templates/base/src/core/cancelable-promise.ts.j2 @@ -0,0 +1,58 @@ +export type OnCancel = (cancelHandler: () => void) => void; + +export class CancelError extends Error { + constructor() { + super('Request aborted'); + this.name = 'CancelError'; + } +} + +export class CancelablePromise implements Promise { + [Symbol.toStringTag] = 'CancelablePromise'; + + private readonly inner: Promise; + private isCancelled = false; + private cancelHandlers: Array<() => void> = []; + + constructor( + executor: ( + resolve: (value: T | PromiseLike) => void, + reject: (reason?: unknown) => void, + onCancel: OnCancel, + ) => void, + ) { + const onCancel: OnCancel = (handler) => { + if (this.isCancelled) { + handler(); + } else { + this.cancelHandlers.push(handler); + } + }; + + this.inner = new Promise((resolve, reject) => executor(resolve, reject, onCancel)); + } + + public cancel(): void { + if (this.isCancelled) return; + this.isCancelled = true; + for (const handler of this.cancelHandlers) handler(); + this.cancelHandlers = []; + } + + then( + onFulfilled?: ((value: T) => TResult1 | PromiseLike) | null, + onRejected?: ((reason: unknown) => TResult2 | PromiseLike) | null, + ): Promise { + return this.inner.then(onFulfilled ?? undefined, onRejected ?? undefined); + } + + catch( + onRejected?: ((reason: unknown) => TResult | PromiseLike) | null, + ): Promise { + return this.inner.catch(onRejected ?? undefined); + } + + finally(onFinally?: (() => void) | null): Promise { + return this.inner.finally(onFinally ?? undefined); + } +} diff --git a/oas-generator/src/oas_generator/templates/base/src/core/client-config.ts.j2 b/oas-generator/src/oas_generator/templates/base/src/core/client-config.ts.j2 new file mode 100644 index 000000000..b02340b73 --- /dev/null +++ b/oas-generator/src/oas_generator/templates/base/src/core/client-config.ts.j2 @@ -0,0 +1,22 @@ +/* Minimal client runtime config holder */ +export type BaseURL = string; + +export interface ClientConfig { + // Prefer idiomatic camelCase going forward + baseUrl: BaseURL; + credentials?: 'include' | 'omit' | 'same-origin'; + token?: string | (() => string | Promise); + apiToken?: string; + username?: string; + password?: string; + headers?: Record | (() => Record | Promise>); + encodePath?: (path: string) => string; + /** Optional override for retry attempts; values <= 1 disable retries. This is the canonical field. */ + maxRetries?: number; + /** Optional cap on exponential backoff delay in milliseconds. */ + maxBackoffMs?: number; + /** Optional list of HTTP status codes that should trigger a retry. */ + retryStatusCodes?: number[]; + /** Optional list of Node.js/System error codes that should trigger a retry. */ + retryErrorCodes?: string[]; +} diff --git a/oas-generator/src/oas_generator/templates/base/src/core/codecs.ts.j2 b/oas-generator/src/oas_generator/templates/base/src/core/codecs.ts.j2 new file mode 100644 index 000000000..0476523ef --- /dev/null +++ b/oas-generator/src/oas_generator/templates/base/src/core/codecs.ts.j2 @@ -0,0 +1,42 @@ +import { decode as msgpackDecode, encode as msgpackEncode } from 'algorand-msgpack' + +export function encodeMsgPack(data: T): Uint8Array { + return new Uint8Array(msgpackEncode(data, { sortKeys: true, ignoreUndefined: true })); +} + +export function decodeMsgPack(buffer: Uint8Array): T { + const map = msgpackDecode(buffer, { useMap: true }) as unknown; + return mapToObject(map) as T; +} + +/** + * Converts a Map structure from msgpack decoding to a plain object structure. + * Maps are converted to objects recursively, except for the special case + * where the field name is "r" which remains as a Map. + */ +export function mapToObject(value: unknown, fieldName?: string): unknown { + // Preserve Uint8Array as-is + if (value instanceof Uint8Array) { + return value; + } else if (value instanceof Map) { + // Special case: keep "r" field as Map + if (fieldName === 'r') { + const newMap = new Map(); + for (const [k, v] of value.entries()) { + newMap.set(k, mapToObject(v)); + } + return newMap; + } + + // Convert Map to object + const obj: Record = {}; + for (const [k, v] of value.entries()) { + obj[k] = mapToObject(v, k); + } + return obj; + } else if (Array.isArray(value)) { + return value.map((item) => mapToObject(item)); + } + + return value; +} diff --git a/oas-generator/src/oas_generator/templates/base/src/core/fetch-http-request.ts.j2 b/oas-generator/src/oas_generator/templates/base/src/core/fetch-http-request.ts.j2 new file mode 100644 index 000000000..c7651b8b2 --- /dev/null +++ b/oas-generator/src/oas_generator/templates/base/src/core/fetch-http-request.ts.j2 @@ -0,0 +1,120 @@ +import { BaseHttpRequest, type ApiRequestOptions } from './base-http-request'; +import { request } from './request'; + +const RETRY_STATUS_CODES = [408, 413, 429, 500, 502, 503, 504]; +const RETRY_ERROR_CODES = [ + 'ETIMEDOUT', + 'ECONNRESET', + 'EADDRINUSE', + 'ECONNREFUSED', + 'EPIPE', + 'ENOTFOUND', + 'ENETUNREACH', + 'EAI_AGAIN', + 'EPROTO', +]; + +const DEFAULT_MAX_TRIES = 5; +const DEFAULT_MAX_BACKOFF_MS = 10_000; + +const toNumber = (value: unknown): number | undefined => { + if (typeof value === 'number') { + return Number.isNaN(value) ? undefined : value; + } + if (typeof value === 'string') { + const parsed = Number(value); + return Number.isNaN(parsed) ? undefined : parsed; + } + return undefined; +}; + +const extractStatus = (error: unknown): number | undefined => { + if (!error || typeof error !== 'object') { + return undefined; + } + const candidate = error as { status?: unknown; response?: { status?: unknown } }; + return toNumber(candidate.status ?? candidate.response?.status); +}; + +const extractCode = (error: unknown): string | undefined => { + if (!error || typeof error !== 'object') { + return undefined; + } + const candidate = error as { code?: unknown; cause?: { code?: unknown } }; + const raw = candidate.code ?? candidate.cause?.code; + return typeof raw === 'string' ? raw : undefined; +}; + +const delay = async (ms: number): Promise => + new Promise((resolve) => { + setTimeout(resolve, ms); + }); + +const normalizeTries = (maxRetries?: number): number => { + const candidate = maxRetries; + if (typeof candidate !== 'number' || !Number.isFinite(candidate)) { + return DEFAULT_MAX_TRIES; + } + const rounded = Math.floor(candidate); + return rounded <= 1 ? 1 : rounded; +}; + +const normalizeBackoff = (maxBackoffMs?: number): number => { + if (typeof maxBackoffMs !== 'number' || !Number.isFinite(maxBackoffMs)) { + return DEFAULT_MAX_BACKOFF_MS; + } + const normalized = Math.floor(maxBackoffMs); + return normalized <= 0 ? 0 : normalized; +}; + +export class FetchHttpRequest extends BaseHttpRequest { + async request(options: ApiRequestOptions): Promise { + const maxTries = normalizeTries(this.config.maxRetries); + const maxBackoffMs = normalizeBackoff(this.config.maxBackoffMs); + + let attempt = 1; + let lastError: unknown; + while (attempt <= maxTries) { + try { + return await request(this.config, options); + } catch (error) { + lastError = error; + if (!this.shouldRetry(error, attempt, maxTries)) { + throw error; + } + + const backoff = attempt === 1 ? 0 : Math.min(1000 * 2 ** (attempt - 1), maxBackoffMs); + if (backoff > 0) { + await delay(backoff); + } + attempt += 1; + } + } + + throw lastError ?? new Error(`Request failed after ${maxTries} attempt(s)`) + } + + private shouldRetry(error: unknown, attempt: number, maxTries: number): boolean { + if (attempt >= maxTries) { + return false; + } + + const status = extractStatus(error); + if (status !== undefined) { + const retryStatuses = this.config.retryStatusCodes ?? RETRY_STATUS_CODES; + if (retryStatuses.includes(status)) { + return true; + } + } + + const code = extractCode(error); + if (code) { + const retryCodes = this.config.retryErrorCodes ?? RETRY_ERROR_CODES; + if (retryCodes.includes(code)) { + return true; + } + } + + return false; + } +} diff --git a/oas-generator/src/oas_generator/templates/base/src/core/model-runtime.ts.j2 b/oas-generator/src/oas_generator/templates/base/src/core/model-runtime.ts.j2 new file mode 100644 index 000000000..72d16545d --- /dev/null +++ b/oas-generator/src/oas_generator/templates/base/src/core/model-runtime.ts.j2 @@ -0,0 +1,308 @@ +import { + encodeSignedTransaction as transactEncodeSignedTransaction, + decodeSignedTransaction as transactDecodeSignedTransaction, + type SignedTransaction, +} from '@algorandfoundation/algokit-transact'; +import { encodeMsgPack, decodeMsgPack } from './codecs'; +import { toBase64, fromBase64 } from './serialization'; + +export type BodyFormat = 'json' | 'msgpack'; + +export interface ScalarFieldType { + readonly kind: 'scalar'; + readonly isBytes?: boolean; + readonly isBigint?: boolean; +} + +export interface CodecFieldType { + readonly kind: 'codec'; + readonly codecKey: string; +} + +export interface ModelFieldType { + readonly kind: 'model'; + readonly meta: ModelMetadata | (() => ModelMetadata); +} + +export interface ArrayFieldType { + readonly kind: 'array'; + readonly item: FieldType; +} + +export interface RecordFieldType { + readonly kind: 'record'; + readonly value: FieldType; +} + +export type FieldType = ScalarFieldType | CodecFieldType | ModelFieldType | ArrayFieldType | RecordFieldType; + +export interface FieldMetadata { + readonly name: string; + readonly wireKey?: string; + readonly optional: boolean; + readonly nullable: boolean; + readonly type: FieldType; + /** + * If true and the field is a SignedTransaction codec, its encoded map entries + * are merged into the parent object (no own wire key). + */ + readonly flattened?: boolean; +} + +export type ModelKind = 'object' | 'array' | 'passthrough'; + +export interface ModelMetadata { + readonly name: string; + readonly kind: ModelKind; + readonly fields?: readonly FieldMetadata[]; + readonly arrayItems?: FieldType; + readonly codecKey?: string; + readonly additionalProperties?: FieldType; + readonly passThrough?: FieldType; +} + +// Registry for model metadata to avoid direct circular imports between model files +const modelMetaRegistry = new Map(); + +export function registerModelMeta(name: string, meta: ModelMetadata): void { + modelMetaRegistry.set(name, meta); +} + +export function getModelMeta(name: string): ModelMetadata { + const meta = modelMetaRegistry.get(name); + if (!meta) throw new Error(`Model metadata not registered: ${name}`); + return meta; +} + +export interface TypeCodec { + encode(value: TValue, format: BodyFormat): unknown; + decode(value: unknown, format: BodyFormat): TValue; +} + +const codecRegistry = new Map>(); + +export function registerCodec(key: string, codec: TypeCodec): void { + codecRegistry.set(key, codec as TypeCodec); +} + +export function getCodec(key: string): TypeCodec | undefined { + return codecRegistry.get(key) as TypeCodec | undefined; +} + +export class AlgorandSerializer { + static encode(value: unknown, meta: ModelMetadata, format: BodyFormat = 'msgpack'): Uint8Array | string { + const wire = this.transform(value, meta, { direction: 'encode', format }); + if (format === 'msgpack') { + return wire instanceof Uint8Array ? wire : encodeMsgPack(wire); + } + return typeof wire === 'string' ? wire : JSON.stringify(wire); + } + + static decode(payload: unknown, meta: ModelMetadata, format: BodyFormat = 'msgpack'): T { + let wire: unknown = payload; + if (format === 'msgpack') { + if (payload instanceof Uint8Array) { + wire = decodeMsgPack(payload); + } + } else if (typeof payload === 'string') { + wire = JSON.parse(payload); + } + return this.transform(wire, meta, { direction: 'decode', format }) as T; + } + + private static transform(value: unknown, meta: ModelMetadata, ctx: TransformContext): unknown { + if (value === undefined || value === null) { + return value; + } + + if (meta.codecKey) { + return this.applyCodec(value, meta.codecKey, ctx); + } + + switch (meta.kind) { + case 'object': + return this.transformObject(value, meta, ctx); + case 'array': + return this.transformType(value, { kind: 'array', item: meta.arrayItems ?? { kind: 'scalar' } }, ctx); + case 'passthrough': + default: + return this.transformType(value, meta.passThrough ?? { kind: 'scalar' }, ctx); + } + } + + private static transformObject(value: unknown, meta: ModelMetadata, ctx: TransformContext): unknown { + const fields = meta.fields ?? []; + const hasFlattenedSignedTxn = fields.some( + (f) => f.flattened && f.type.kind === 'codec' && f.type.codecKey === 'SignedTransaction', + ); + if (ctx.direction === 'encode') { + const src = value as Record; + const out: Record = {}; + for (const field of fields) { + const fieldValue = src[field.name]; + if (fieldValue === undefined) continue; + const encoded = this.transformType(fieldValue, field.type, ctx); + if (encoded === undefined && fieldValue === undefined) continue; + if (field.flattened && field.type.kind === 'codec' && field.type.codecKey === 'SignedTransaction') { + // Merge signed transaction map into parent + const mapValue = encoded as Record; + for (const [k, v] of Object.entries(mapValue ?? {})) out[k] = v; + continue; + } + if (field.wireKey) out[field.wireKey] = encoded; + } + if (meta.additionalProperties) { + for (const [key, val] of Object.entries(src)) { + if (fields.some((f) => f.name === key)) continue; + out[key] = this.transformType(val, meta.additionalProperties, ctx); + } + } + return out; + } + + const src = value as Record; + const out: Record = {}; + const fieldByWire = new Map(fields.filter((f) => !!f.wireKey).map((field) => [field.wireKey as string, field])); + + for (const [wireKey, wireValue] of Object.entries(src)) { + const field = fieldByWire.get(wireKey); + if (field) { + const decoded = this.transformType(wireValue, field.type, ctx); + out[field.name] = decoded; + continue; + } + if (meta.additionalProperties) { + out[wireKey] = this.transformType(wireValue, meta.additionalProperties, ctx); + continue; + } + // If we have a flattened SignedTransaction, skip unknown keys (e.g., 'sig', 'txn') + if (!hasFlattenedSignedTxn) { + out[wireKey] = wireValue; + } + } + + // If there are flattened fields, attempt to reconstruct them from remaining keys by decoding + for (const field of fields) { + if (out[field.name] !== undefined) continue; + if (field.flattened && field.type.kind === 'codec' && field.type.codecKey === 'SignedTransaction') { + // Reconstruct from entire object map + out[field.name] = this.applyCodec(src, 'SignedTransaction', ctx); + } + } + + return out; + } + + private static transformType(value: unknown, type: FieldType, ctx: TransformContext): unknown { + if (value === undefined || value === null) return value; + + switch (type.kind) { + case 'scalar': + return this.transformScalar(value, type, ctx); + case 'codec': + return this.applyCodec(value, type.codecKey, ctx); + case 'model': + return this.transform(value, typeof type.meta === 'function' ? type.meta() : type.meta, ctx); + case 'array': + if (!Array.isArray(value)) return value; + return value.map((item) => this.transformType(item, type.item, ctx)); + case 'record': + if (typeof value !== 'object' || value === null) return value; + return Object.fromEntries( + Object.entries(value as Record).map(([k, v]) => [k, this.transformType(v, type.value, ctx)]), + ); + default: + return value; + } + } + + private static transformScalar(value: unknown, meta: ScalarFieldType, ctx: TransformContext): unknown { + if (ctx.direction === 'encode') { + if (meta.isBytes && ctx.format === 'json') { + if (value instanceof Uint8Array) return toBase64(value); + } + if (meta.isBigint && ctx.format === 'json') { + if (typeof value === 'bigint') return value.toString(); + if (typeof value === 'number') return Math.trunc(value).toString(); + if (typeof value === 'string') return value; + } + return value; + } + + if (meta.isBytes && ctx.format === 'json' && typeof value === 'string') { + return fromBase64(value); + } + + if (meta.isBigint) { + if (typeof value === 'string') { + try { + return BigInt(value); + } catch { + return value; + } + } + if (typeof value === 'number' && Number.isInteger(value)) { + return BigInt(value); + } + } + + return value; + } + + private static applyCodec(value: unknown, codecKey: string, ctx: TransformContext): unknown { + const codec = codecRegistry.get(codecKey); + if (!codec) { + throw new Error(`Codec for "${codecKey}" is not registered`); + } + return ctx.direction === 'encode' + ? codec.encode(value, ctx.format) + : codec.decode(value, ctx.format); + } +} + +type TransformDirection = 'encode' | 'decode'; + +interface TransformContext { + readonly direction: TransformDirection; + readonly format: BodyFormat; +} + +const encodeSignedTransactionImpl = (value: unknown): Uint8Array => + transactEncodeSignedTransaction(value as SignedTransaction); +const decodeSignedTransactionImpl = (value: Uint8Array): SignedTransaction => + transactDecodeSignedTransaction(value); + +class SignedTransactionCodec implements TypeCodec { + encode(value: unknown, format: BodyFormat): unknown { + if (value == null) return value; + if (format === 'json') { + if (value instanceof Uint8Array) return toBase64(value); + return toBase64(encodeSignedTransactionImpl(value)); + } + if (value instanceof Uint8Array) { + // Already canonical bytes; decode to structured map so parent encoding keeps map semantics + return decodeMsgPack(value); + } + // Convert signed transaction object into canonical map representation + return decodeMsgPack(encodeSignedTransactionImpl(value)); + } + + decode(value: unknown, format: BodyFormat): unknown { + if (value == null) return value; + if (format === 'json') { + if (typeof value === 'string') return decodeSignedTransactionImpl(fromBase64(value)); + if (value instanceof Uint8Array) return decodeSignedTransactionImpl(value); + return value; + } + if (value instanceof Uint8Array) return decodeSignedTransactionImpl(value); + // Value is a decoded map; re-encode to bytes before handing to transact decoder + try { + return decodeSignedTransactionImpl(encodeMsgPack(value)); + } catch { + return value; + } + } +} + +registerCodec('SignedTransaction', new SignedTransactionCodec()); + diff --git a/oas-generator/src/oas_generator/templates/base/src/core/request.ts.j2 b/oas-generator/src/oas_generator/templates/base/src/core/request.ts.j2 new file mode 100644 index 000000000..63e8c74b4 --- /dev/null +++ b/oas-generator/src/oas_generator/templates/base/src/core/request.ts.j2 @@ -0,0 +1,127 @@ +import type { ClientConfig } from './client-config'; +import { ApiError } from './api-error'; +import { decodeMsgPack, encodeMsgPack } from './codecs'; +import type { QueryParams, BodyValue } from './base-http-request'; + +const encodeURIPath = (path: string): string => encodeURI(path).replace(/%5B/g, '[').replace(/%5D/g, ']'); + +export async function request(config: ClientConfig, options: { + method: string; + url: string; + path?: Record; + query?: QueryParams; + headers?: Record; + body?: BodyValue; + mediaType?: string; + responseHeader?: string; +}): Promise { + let rawPath = options.url; + if (options.path) { + for (const [key, value] of Object.entries(options.path)) { + const raw = typeof value === 'bigint' ? value.toString() : String(value); + const replace = config.encodePath ? config.encodePath(raw) : encodeURIPath(raw); + rawPath = rawPath.replace(`{${key}}`, replace); + } + } + + const url = new URL(rawPath, config.baseUrl); + + if (options.query) { + for (const [key, value] of Object.entries(options.query)) { + if (value === undefined || value === null) continue; + if (Array.isArray(value)) { + for (const item of value) { + url.searchParams.append(key, item.toString()); + } + } else { + url.searchParams.append(key, value.toString()); + } + } + } + + const headers: Record = { + ...(typeof config.headers === 'function' ? await config.headers() : config.headers ?? {}), + ...(options.headers ?? {}), + }; + + const apiToken = config.apiToken; + if (apiToken) { + {% if client_class_name == 'IndexerClient' %} + headers['X-Indexer-API-Token'] = apiToken; + {% elif client_class_name == 'KmdClient' %} + headers['X-KMD-API-Token'] = apiToken; + {% else %} + headers['X-Algo-API-Token'] = apiToken; + {% endif %} + } + + const token = typeof config.token === 'function' ? await config.token() : config.token; + if (token) headers['Authorization'] = `Bearer ${token}`; + if (!token && config.username && config.password) { + headers['Authorization'] = `Basic ${btoa(`${config.username}:${config.password}`)}`; + } + + let bodyPayload: BodyInit | undefined = undefined; + if (options.body != null) { + if (options.body instanceof Uint8Array) { + bodyPayload = options.body; + } else if (typeof options.body === 'string') { + bodyPayload = options.body; + } else if (options.mediaType?.includes('msgpack')) { + bodyPayload = encodeMsgPack(options.body); + } else if (options.mediaType?.includes('json')) { + bodyPayload = JSON.stringify(options.body); + } else { + bodyPayload = JSON.stringify(options.body); + } + } + + const response = await fetch(url.toString(), { + method: options.method, + headers, + body: bodyPayload, + credentials: config.credentials, + }); + + if (!response.ok) { + let errorBody: unknown; + try { + const ct = response.headers.get('content-type') ?? ''; + if (ct.includes('application/msgpack')) { + errorBody = decodeMsgPack(new Uint8Array(await response.arrayBuffer())); + } else if (ct.includes('application/json')) { + errorBody = JSON.parse(await response.text()); + } else { + errorBody = await response.text(); + } + } catch { + errorBody = undefined; + } + throw new ApiError(url.toString(), response.status, errorBody); + } + + if (options.responseHeader) { + const value = response.headers.get(options.responseHeader); + return value as unknown as T; + } + + const contentType = response.headers.get('content-type') ?? ''; + + if (contentType.includes('application/msgpack')) { + return new Uint8Array(await response.arrayBuffer()) as unknown as T; + } + + if (contentType.includes('application/octet-stream') || contentType.includes('application/x-binary')) { + return new Uint8Array(await response.arrayBuffer()) as unknown as T; + } + + if (contentType.includes('application/json')) { + return (await response.text()) as unknown as T; + } + + if (!contentType) { + return new Uint8Array(await response.arrayBuffer()) as unknown as T; + } + + return (await response.text()) as unknown as T; +} diff --git a/oas-generator/src/oas_generator/templates/base/src/core/serialization.ts.j2 b/oas-generator/src/oas_generator/templates/base/src/core/serialization.ts.j2 new file mode 100644 index 000000000..411a8bb6e --- /dev/null +++ b/oas-generator/src/oas_generator/templates/base/src/core/serialization.ts.j2 @@ -0,0 +1,26 @@ +export function toBase64(bytes: Uint8Array): string { + if (typeof Buffer !== 'undefined') { + return Buffer.from(bytes).toString('base64'); + } + const globalRef: Record = globalThis as unknown as Record; + const btoaFn = globalRef.btoa as ((value: string) => string) | undefined; + if (typeof btoaFn === 'function') { + return btoaFn(String.fromCharCode(...bytes)); + } + throw new Error('Base64 encoding not supported in this environment'); +} + +export function fromBase64(s: string): Uint8Array { + if (typeof Buffer !== 'undefined') { + return new Uint8Array(Buffer.from(s, 'base64')); + } + const globalRef: Record = globalThis as unknown as Record; + const atobFn = globalRef.atob as ((value: string) => string) | undefined; + if (typeof atobFn === 'function') { + const bin = atobFn(s); + const out = new Uint8Array(bin.length); + for (let i = 0; i < bin.length; i += 1) out[i] = bin.charCodeAt(i); + return out; + } + throw new Error('Base64 decoding not supported in this environment'); +} diff --git a/oas-generator/src/oas_generator/templates/base/src/index.ts.j2 b/oas-generator/src/oas_generator/templates/base/src/index.ts.j2 new file mode 100644 index 000000000..6eb10e708 --- /dev/null +++ b/oas-generator/src/oas_generator/templates/base/src/index.ts.j2 @@ -0,0 +1,12 @@ +export * from './core/client-config'; +export * from './core/base-http-request'; +export * from './core/fetch-http-request'; +export * from './core/api-error'; +export * from './core/serialization'; +export * from './core/codecs'; +export * from './core/model-runtime'; + +// Generated +export * from './models'; +export * from './apis'; +export * from './client'; diff --git a/oas-generator/src/oas_generator/templates/client.ts.j2 b/oas-generator/src/oas_generator/templates/client.ts.j2 new file mode 100644 index 000000000..85b877c7f --- /dev/null +++ b/oas-generator/src/oas_generator/templates/client.ts.j2 @@ -0,0 +1,10 @@ +import type { ClientConfig } from './core/client-config'; +import type { BaseHttpRequest } from './core/base-http-request'; +import { FetchHttpRequest } from './core/fetch-http-request'; +import { {{ service_class_name }} } from './apis/api.service'; + +export class {{ client_class_name }} extends {{ service_class_name }} { + constructor(config: ClientConfig, request?: BaseHttpRequest) { + super(request ?? new FetchHttpRequest(config)); + } +} diff --git a/oas-generator/src/oas_generator/templates/models/block/application-eval-delta.ts.j2 b/oas-generator/src/oas_generator/templates/models/block/application-eval-delta.ts.j2 new file mode 100644 index 000000000..849ec0f21 --- /dev/null +++ b/oas-generator/src/oas_generator/templates/models/block/application-eval-delta.ts.j2 @@ -0,0 +1,37 @@ +import type { ModelMetadata } from '../core/model-runtime'; +import { getModelMeta, registerModelMeta } from '../core/model-runtime'; +import type { SignedTxnInBlock } from './signed-txn-in-block'; +import type { BlockStateDelta } from './block-state-delta'; +import { BlockStateDeltaMeta } from './block-state-delta'; + +/** + * State changes from application execution, including inner transactions and logs. + */ +export interface BlockAppEvalDelta { + /** [gd] Global state delta for the application. */ + globalDelta?: BlockStateDelta; + /** [ld] Local state deltas keyed by address index. */ + localDeltas?: Record; + /** [itx] Inner transactions produced by this application execution. */ + innerTxns?: SignedTxnInBlock[]; + /** [sa] Shared accounts referenced by local deltas. */ + sharedAccounts?: Uint8Array[]; + /** [lg] Application log outputs. */ + logs?: Uint8Array[]; +} + +export const BlockAppEvalDeltaMeta: ModelMetadata = { + name: 'BlockAppEvalDelta', + kind: 'object', + fields: [ + { name: 'globalDelta', wireKey: 'gd', optional: true, nullable: false, type: { kind: 'model', meta: () => BlockStateDeltaMeta } }, + { name: 'localDeltas', wireKey: 'ld', optional: true, nullable: false, type: { kind: 'record', value: { kind: 'model', meta: () => BlockStateDeltaMeta } } }, + { name: 'innerTxns', wireKey: 'itx', optional: true, nullable: false, type: { kind: 'array', item: { kind: 'model', meta: () => getModelMeta('SignedTxnInBlock') } } }, + { name: 'sharedAccounts', wireKey: 'sa', optional: true, nullable: false, type: { kind: 'array', item: { kind: 'scalar', isBytes: true } } }, + { name: 'logs', wireKey: 'lg', optional: true, nullable: false, type: { kind: 'array', item: { kind: 'scalar', isBytes: true } } }, + ], +}; + +registerModelMeta('BlockAppEvalDelta', BlockAppEvalDeltaMeta); + + diff --git a/oas-generator/src/oas_generator/templates/models/block/block-account-state-delta.ts.j2 b/oas-generator/src/oas_generator/templates/models/block/block-account-state-delta.ts.j2 new file mode 100644 index 000000000..d49bb97a1 --- /dev/null +++ b/oas-generator/src/oas_generator/templates/models/block/block-account-state-delta.ts.j2 @@ -0,0 +1,22 @@ +import type { ModelMetadata } from '../core/model-runtime'; +import { registerModelMeta } from '../core/model-runtime'; +import { BlockStateDeltaMeta } from './block-state-delta'; + +/** BlockAccountStateDelta pairs an address with a BlockStateDelta map. */ +export interface BlockAccountStateDelta { + address: string; + delta: import('./block-state-delta').BlockStateDelta; +} + +export const BlockAccountStateDeltaMeta: ModelMetadata = { + name: 'BlockAccountStateDelta', + kind: 'object', + fields: [ + { name: 'address', wireKey: 'address', optional: false, nullable: false, type: { kind: 'scalar' } }, + { name: 'delta', wireKey: 'delta', optional: false, nullable: false, type: { kind: 'model', meta: () => BlockStateDeltaMeta } }, + ], +}; + +registerModelMeta('BlockAccountStateDelta', BlockAccountStateDeltaMeta); + + diff --git a/oas-generator/src/oas_generator/templates/models/block/block-eval-delta.ts.j2 b/oas-generator/src/oas_generator/templates/models/block/block-eval-delta.ts.j2 new file mode 100644 index 000000000..93d9eb020 --- /dev/null +++ b/oas-generator/src/oas_generator/templates/models/block/block-eval-delta.ts.j2 @@ -0,0 +1,26 @@ +import type { ModelMetadata } from '../core/model-runtime'; +import { registerModelMeta } from '../core/model-runtime'; + +/** BlockEvalDelta represents a TEAL value delta (block/msgpack wire keys). */ +export interface BlockEvalDelta { + /** [at] delta action. */ + action: number; + /** [bs] bytes value. */ + bytes?: string; + /** [ui] uint value. */ + uint?: bigint; +} + +export const BlockEvalDeltaMeta: ModelMetadata = { + name: 'BlockEvalDelta', + kind: 'object', + fields: [ + { name: 'action', wireKey: 'at', optional: false, nullable: false, type: { kind: 'scalar' } }, + { name: 'bytes', wireKey: 'bs', optional: true, nullable: false, type: { kind: 'scalar' } }, + { name: 'uint', wireKey: 'ui', optional: true, nullable: false, type: { kind: 'scalar', isBigint: true } }, + ], +}; + +registerModelMeta('BlockEvalDelta', BlockEvalDeltaMeta); + + diff --git a/oas-generator/src/oas_generator/templates/models/block/block-state-delta.ts.j2 b/oas-generator/src/oas_generator/templates/models/block/block-state-delta.ts.j2 new file mode 100644 index 000000000..945a2f890 --- /dev/null +++ b/oas-generator/src/oas_generator/templates/models/block/block-state-delta.ts.j2 @@ -0,0 +1,16 @@ +import type { ModelMetadata } from '../core/model-runtime'; +import { registerModelMeta } from '../core/model-runtime'; +import { BlockEvalDeltaMeta } from './block-eval-delta'; + +/** BlockStateDelta is a map keyed by state key to BlockEvalDelta. */ +export type BlockStateDelta = Record; + +export const BlockStateDeltaMeta: ModelMetadata = { + name: 'BlockStateDelta', + kind: 'object', + additionalProperties: { kind: 'model', meta: () => BlockEvalDeltaMeta }, +}; + +registerModelMeta('BlockStateDelta', BlockStateDeltaMeta); + + diff --git a/oas-generator/src/oas_generator/templates/models/block/block-state-proof-tracking-data.ts.j2 b/oas-generator/src/oas_generator/templates/models/block/block-state-proof-tracking-data.ts.j2 new file mode 100644 index 000000000..6306e924f --- /dev/null +++ b/oas-generator/src/oas_generator/templates/models/block/block-state-proof-tracking-data.ts.j2 @@ -0,0 +1,26 @@ +import type { ModelMetadata } from '../core/model-runtime'; +import { registerModelMeta } from '../core/model-runtime'; + +/** Tracking metadata for a specific StateProofType. */ +export interface BlockStateProofTrackingData { + /** [v] Vector commitment root of state proof voters. */ + stateProofVotersCommitment?: Uint8Array; + /** [t] Online total weight during state proof round. */ + stateProofOnlineTotalWeight?: bigint; + /** [n] Next round for which state proofs are accepted. */ + stateProofNextRound?: bigint; +} + +export const BlockStateProofTrackingDataMeta: ModelMetadata = { + name: 'BlockStateProofTrackingData', + kind: 'object', + fields: [ + { name: 'stateProofVotersCommitment', wireKey: 'v', optional: true, nullable: false, type: { kind: 'scalar', isBytes: true } }, + { name: 'stateProofOnlineTotalWeight', wireKey: 't', optional: true, nullable: false, type: { kind: 'scalar', isBigint: true } }, + { name: 'stateProofNextRound', wireKey: 'n', optional: true, nullable: false, type: { kind: 'scalar', isBigint: true } }, + ], +}; + +registerModelMeta('BlockStateProofTrackingData', BlockStateProofTrackingDataMeta); + + diff --git a/oas-generator/src/oas_generator/templates/models/block/block-state-proof-tracking.ts.j2 b/oas-generator/src/oas_generator/templates/models/block/block-state-proof-tracking.ts.j2 new file mode 100644 index 000000000..c2ccaef96 --- /dev/null +++ b/oas-generator/src/oas_generator/templates/models/block/block-state-proof-tracking.ts.j2 @@ -0,0 +1,17 @@ +import type { ModelMetadata } from '../core/model-runtime'; +import { registerModelMeta } from '../core/model-runtime'; +import type { BlockStateProofTrackingData } from './block_state_proof_tracking_data'; +import { BlockStateProofTrackingDataMeta } from './block_state_proof_tracking_data'; + +/** Tracks state proof metadata by state proof type. */ +export type BlockStateProofTracking = Record; + +export const BlockStateProofTrackingMeta: ModelMetadata = { + name: 'BlockStateProofTracking', + kind: 'object', + additionalProperties: { kind: 'model', meta: () => BlockStateProofTrackingDataMeta }, +}; + +registerModelMeta('BlockStateProofTracking', BlockStateProofTrackingMeta); + + diff --git a/oas-generator/src/oas_generator/templates/models/block/block.ts.j2 b/oas-generator/src/oas_generator/templates/models/block/block.ts.j2 new file mode 100644 index 000000000..465ebd0df --- /dev/null +++ b/oas-generator/src/oas_generator/templates/models/block/block.ts.j2 @@ -0,0 +1,120 @@ +import type { ModelMetadata } from '../core/model-runtime'; +import type { SignedTxnInBlock } from './signed-txn-in-block'; +import { SignedTxnInBlockMeta } from './signed-txn-in-block'; +import type { BlockStateProofTracking } from './block_state_proof_tracking'; +import { BlockStateProofTrackingMeta } from './block_state_proof_tracking'; + +/** + * Block contains the BlockHeader and the list of transactions (Payset). + */ +export interface Block { + /** [rnd] Round number. */ + round?: bigint; + /** [prev] Previous block hash. */ + previousBlockHash?: Uint8Array; + /** [prev512] Previous block hash using SHA-512. */ + previousBlockHash512?: Uint8Array; + /** [seed] Sortition seed. */ + seed?: Uint8Array; + /** [txn] Root of transaction merkle tree using SHA512_256. */ + transactionsRoot?: Uint8Array; + /** [txn256] Root of transaction vector commitment using SHA256. */ + transactionsRootSha256?: Uint8Array; + /** [txn512] Root of transaction vector commitment using SHA512. */ + transactionsRootSha512?: Uint8Array; + /** [ts] Block timestamp in seconds since epoch. */ + timestamp?: bigint; + /** [gen] Genesis ID. */ + genesisId?: string; + /** [gh] Genesis hash. */ + genesisHash?: Uint8Array; + /** [prp] Proposer address. */ + proposer?: Uint8Array; + /** [fc] Fees collected in this block. */ + feesCollected?: bigint; + /** [bi] Bonus incentive for block proposal. */ + bonus?: bigint; + /** [pp] Proposer payout. */ + proposerPayout?: bigint; + /** [fees] FeeSink address. */ + feeSink?: Uint8Array; + /** [rwd] RewardsPool address. */ + rewardsPool?: Uint8Array; + /** [earn] Rewards level. */ + rewardsLevel?: bigint; + /** [rate] Rewards rate. */ + rewardsRate?: bigint; + /** [frac] Rewards residue. */ + rewardsResidue?: bigint; + /** [rwcalr] Rewards recalculation round. */ + rewardsRecalculationRound?: bigint; + /** [proto] Current consensus protocol. */ + currentProtocol?: string; + /** [nextproto] Next proposed protocol. */ + nextProtocol?: string; + /** [nextyes] Next protocol approvals. */ + nextProtocolApprovals?: bigint; + /** [nextbefore] Next protocol vote deadline. */ + nextProtocolVoteBefore?: bigint; + /** [nextswitch] Next protocol switch round. */ + nextProtocolSwitchOn?: bigint; + /** [upgradeprop] Upgrade proposal. */ + upgradePropose?: string; + /** [upgradedelay] Upgrade delay in rounds. */ + upgradeDelay?: bigint; + /** [upgradeyes] Upgrade approval flag. */ + upgradeApprove?: boolean; + /** [tc] Transaction counter. */ + txnCounter?: bigint; + /** [spt] State proof tracking data keyed by state proof type. */ + stateProofTracking?: BlockStateProofTracking; + /** [partupdrmv] Expired participation accounts. */ + expiredParticipationAccounts?: Uint8Array[]; + /** [partupdabs] Absent participation accounts. */ + absentParticipationAccounts?: Uint8Array[]; + /** [txns] Block transactions (Payset). */ + transactions?: SignedTxnInBlock[]; +} + +export const BlockMeta: ModelMetadata = { + name: 'Block', + kind: 'object', + fields: [ + { name: 'round', wireKey: 'rnd', optional: true, nullable: false, type: { kind: 'scalar', isBigint: true } }, + { name: 'previousBlockHash', wireKey: 'prev', optional: true, nullable: false, type: { kind: 'scalar', isBytes: true } }, + { name: 'previousBlockHash512', wireKey: 'prev512', optional: true, nullable: false, type: { kind: 'scalar', isBytes: true } }, + { name: 'seed', wireKey: 'seed', optional: true, nullable: false, type: { kind: 'scalar', isBytes: true } }, + { name: 'transactionsRoot', wireKey: 'txn', optional: true, nullable: false, type: { kind: 'scalar', isBytes: true } }, + { name: 'transactionsRootSha256', wireKey: 'txn256', optional: true, nullable: false, type: { kind: 'scalar', isBytes: true } }, + { name: 'transactionsRootSha512', wireKey: 'txn512', optional: true, nullable: false, type: { kind: 'scalar', isBytes: true } }, + { name: 'timestamp', wireKey: 'ts', optional: true, nullable: false, type: { kind: 'scalar', isBigint: true } }, + { name: 'genesisId', wireKey: 'gen', optional: true, nullable: false, type: { kind: 'scalar' } }, + { name: 'genesisHash', wireKey: 'gh', optional: true, nullable: false, type: { kind: 'scalar', isBytes: true } }, + { name: 'proposer', wireKey: 'prp', optional: true, nullable: false, type: { kind: 'scalar', isBytes: true } }, + { name: 'feesCollected', wireKey: 'fc', optional: true, nullable: false, type: { kind: 'scalar', isBigint: true } }, + { name: 'bonus', wireKey: 'bi', optional: true, nullable: false, type: { kind: 'scalar', isBigint: true } }, + { name: 'proposerPayout', wireKey: 'pp', optional: true, nullable: false, type: { kind: 'scalar', isBigint: true } }, + { name: 'feeSink', wireKey: 'fees', optional: true, nullable: false, type: { kind: 'scalar', isBytes: true } }, + { name: 'rewardsPool', wireKey: 'rwd', optional: true, nullable: false, type: { kind: 'scalar', isBytes: true } }, + { name: 'rewardsLevel', wireKey: 'earn', optional: true, nullable: false, type: { kind: 'scalar', isBigint: true } }, + { name: 'rewardsRate', wireKey: 'rate', optional: true, nullable: false, type: { kind: 'scalar', isBigint: true } }, + { name: 'rewardsResidue', wireKey: 'frac', optional: true, nullable: false, type: { kind: 'scalar', isBigint: true } }, + { name: 'rewardsRecalculationRound', wireKey: 'rwcalr', optional: true, nullable: false, type: { kind: 'scalar', isBigint: true } }, + { name: 'currentProtocol', wireKey: 'proto', optional: true, nullable: false, type: { kind: 'scalar' } }, + { name: 'nextProtocol', wireKey: 'nextproto', optional: true, nullable: false, type: { kind: 'scalar' } }, + { name: 'nextProtocolApprovals', wireKey: 'nextyes', optional: true, nullable: false, type: { kind: 'scalar', isBigint: true } }, + { name: 'nextProtocolVoteBefore', wireKey: 'nextbefore', optional: true, nullable: false, type: { kind: 'scalar', isBigint: true } }, + { name: 'nextProtocolSwitchOn', wireKey: 'nextswitch', optional: true, nullable: false, type: { kind: 'scalar', isBigint: true } }, + { name: 'upgradePropose', wireKey: 'upgradeprop', optional: true, nullable: false, type: { kind: 'scalar' } }, + { name: 'upgradeDelay', wireKey: 'upgradedelay', optional: true, nullable: false, type: { kind: 'scalar', isBigint: true } }, + { name: 'upgradeApprove', wireKey: 'upgradeyes', optional: true, nullable: false, type: { kind: 'scalar' } }, + { name: 'txnCounter', wireKey: 'tc', optional: true, nullable: false, type: { kind: 'scalar', isBigint: true } }, + { name: 'stateProofTracking', wireKey: 'spt', optional: true, nullable: false, type: { kind: 'model', meta: () => BlockStateProofTrackingMeta } }, + { name: 'expiredParticipationAccounts', wireKey: 'partupdrmv', optional: true, nullable: false, type: { kind: 'array', item: { kind: 'scalar', isBytes: true } } }, + { name: 'absentParticipationAccounts', wireKey: 'partupdabs', optional: true, nullable: false, type: { kind: 'array', item: { kind: 'scalar', isBytes: true } } }, + { name: 'transactions', wireKey: 'txns', optional: true, nullable: false, type: { kind: 'array', item: { kind: 'model', meta: () => SignedTxnInBlockMeta } } }, + ], +}; + + + diff --git a/oas-generator/src/oas_generator/templates/models/block/get-block.ts.j2 b/oas-generator/src/oas_generator/templates/models/block/get-block.ts.j2 new file mode 100644 index 000000000..04816e656 --- /dev/null +++ b/oas-generator/src/oas_generator/templates/models/block/get-block.ts.j2 @@ -0,0 +1,22 @@ +import type { ModelMetadata } from '../core/model-runtime'; +import type { Block } from './block'; +import { BlockMeta } from './block'; + +export type GetBlock = { + /** Block data including header and transactions. */ + block: Block; + /** Block certificate (msgpack only). */ + cert?: Record; +}; + +export const GetBlockMeta: ModelMetadata = { + name: 'GetBlock', + kind: 'object', + fields: [ + { name: 'block', wireKey: 'block', optional: false, nullable: false, type: { kind: 'model', meta: () => BlockMeta } }, + { name: 'cert', wireKey: 'cert', optional: true, nullable: false, type: { kind: 'scalar' } }, + ], +}; + + + diff --git a/oas-generator/src/oas_generator/templates/models/block/signed-txn-in-block.ts.j2 b/oas-generator/src/oas_generator/templates/models/block/signed-txn-in-block.ts.j2 new file mode 100644 index 000000000..cabf849da --- /dev/null +++ b/oas-generator/src/oas_generator/templates/models/block/signed-txn-in-block.ts.j2 @@ -0,0 +1,63 @@ +/* + * {{ spec.info.title }} + * + * {{ spec.info.description or "API client generated from OpenAPI specification" }} + * + * The version of the OpenAPI document: {{ spec.info.version }} + {% if spec.info.contact and spec.info.contact.email %} * Contact: {{ spec.info.contact.email }} + {% endif %} * Generated by: Rust OpenAPI Generator + */ + +import type { ModelMetadata } from '../core/model-runtime'; +import type { SignedTransaction } from '@algorandfoundation/algokit-transact'; +import type { BlockAppEvalDelta } from './block-app-eval-delta'; +import { getModelMeta, registerModelMeta } from '../core/model-runtime'; + +/** + * SignedTxnInBlock is a SignedTransaction with additional ApplyData and block-specific metadata. + */ +export interface SignedTxnInBlock { + signedTransaction: SignedTransaction; + logicSignature?: Record; + closingAmount?: bigint; + assetClosingAmount?: bigint; + senderRewards?: bigint; + receiverRewards?: bigint; + closeRewards?: bigint; + evalDelta?: BlockAppEvalDelta; + configAsset?: bigint; + applicationId?: bigint; + hasGenesisId?: boolean; + hasGenesisHash?: boolean; +} + +export const SignedTxnInBlockMeta: ModelMetadata = { + name: 'SignedTxnInBlock', + kind: 'object', + fields: [ + { + name: 'signedTransaction', + // flatten signed transaction fields into parent + flattened: true, + optional: false, + nullable: false, + type: { kind: 'codec', codecKey: 'SignedTransaction' }, + }, + { name: 'logicSignature', wireKey: 'lsig', optional: true, nullable: false, type: { kind: 'scalar' } }, + { name: 'closingAmount', wireKey: 'ca', optional: true, nullable: false, type: { kind: 'scalar', isBigint: true } }, + { name: 'assetClosingAmount', wireKey: 'aca', optional: true, nullable: false, type: { kind: 'scalar', isBigint: true } }, + { name: 'senderRewards', wireKey: 'rs', optional: true, nullable: false, type: { kind: 'scalar', isBigint: true } }, + { name: 'receiverRewards', wireKey: 'rr', optional: true, nullable: false, type: { kind: 'scalar', isBigint: true } }, + { name: 'closeRewards', wireKey: 'rc', optional: true, nullable: false, type: { kind: 'scalar', isBigint: true } }, + { name: 'evalDelta', wireKey: 'dt', optional: true, nullable: false, type: { kind: 'model', meta: () => getModelMeta('BlockAppEvalDelta') } }, + { name: 'configAsset', wireKey: 'caid', optional: true, nullable: false, type: { kind: 'scalar', isBigint: true } }, + { name: 'applicationId', wireKey: 'apid', optional: true, nullable: false, type: { kind: 'scalar', isBigint: true } }, + { name: 'hasGenesisId', wireKey: 'hgi', optional: true, nullable: false, type: { kind: 'scalar' } }, + { name: 'hasGenesisHash', wireKey: 'hgh', optional: true, nullable: false, type: { kind: 'scalar' } }, + ], +}; + +registerModelMeta('SignedTxnInBlock', SignedTxnInBlockMeta); + + + diff --git a/oas-generator/src/oas_generator/templates/models/index.ts.j2 b/oas-generator/src/oas_generator/templates/models/index.ts.j2 new file mode 100644 index 000000000..582202076 --- /dev/null +++ b/oas-generator/src/oas_generator/templates/models/index.ts.j2 @@ -0,0 +1,4 @@ +{% for name, _ in schemas.items() %} +export type { {{ name | ts_pascal_case }} } from './{{ name | ts_kebab_case }}'; +export { {{ name | ts_pascal_case }}Meta } from './{{ name | ts_kebab_case }}'; +{% endfor %} diff --git a/oas-generator/src/oas_generator/templates/models/model.ts.j2 b/oas-generator/src/oas_generator/templates/models/model.ts.j2 new file mode 100644 index 000000000..f6680f2ad --- /dev/null +++ b/oas-generator/src/oas_generator/templates/models/model.ts.j2 @@ -0,0 +1,99 @@ +{% set modelName = schema_name | ts_pascal_case %} +{% set descriptor = descriptor %} +{% set isObject = descriptor.is_object %} +{% set isArray = descriptor.is_array %} +{% set refTypes = schema | collect_schema_refs(schema_name) %} +{% set uses_signed_txn = schema | schema_uses_signed_txn %} +{% set schemaSignedTxn = schema.get('x-algokit-signed-txn') is true %} +{% set schemaBytes = schema.get('format') == 'byte' or schema.get('x-algokit-bytes-base64') is true %} +{% set schemaBigint = schema.get('x-algokit-bigint') is true %} + +{% macro scalar_meta(is_bytes, is_bigint) -%} +{ kind: 'scalar'{% if is_bytes %}, isBytes: true{% endif %}{% if is_bigint %}, isBigint: true{% endif %} } +{%- endmacro %} + +{% macro base_type(ref_model, is_signed_txn, is_bytes, is_bigint) -%} +{%- if is_signed_txn -%} +{ kind: 'codec', codecKey: 'SignedTransaction' } +{%- elif ref_model -%} +{ kind: 'model', meta: () => {{ ref_model }}Meta } +{%- else -%} +{{ scalar_meta(is_bytes, is_bigint) }} +{%- endif -%} +{%- endmacro %} + +{% macro field_type(field) -%} +{%- if field.is_array -%} +{ kind: 'array', item: {{ base_type(field.ref_model, field.is_signed_txn, field.is_bytes, field.is_bigint) }} } +{%- else -%} +{{ base_type(field.ref_model, field.is_signed_txn, field.is_bytes, field.is_bigint) }} +{%- endif -%} +{%- endmacro %} + +{% macro array_item_meta(descriptor) -%} +{{ base_type(descriptor.array_item_ref, descriptor.array_item_is_signed_txn, descriptor.array_item_is_bytes, descriptor.array_item_is_bigint) }} +{%- endmacro %} + +import type { ModelMetadata } from '../core/model-runtime'; +{% if uses_signed_txn %} +import type { SignedTransaction } from '@algorandfoundation/algokit-transact'; +{% endif %} +{% set ns = namespace(refs_with_meta=[]) %} +{% if descriptor.is_object %} +{% for f in descriptor.fields %} +{% if f.ref_model and f.ref_model not in ns.refs_with_meta %} +{% set ns.refs_with_meta = ns.refs_with_meta + [f.ref_model] %} +{% endif %} +{% endfor %} +{% endif %} +{% if descriptor.is_array and descriptor.array_item_ref %} +{% if descriptor.array_item_ref not in ns.refs_with_meta %} +{% set ns.refs_with_meta = ns.refs_with_meta + [descriptor.array_item_ref] %} +{% endif %} +{% endif %} +{% for r in refTypes %} +import type { {{ r }} } from './{{ r | ts_kebab_case }}'; +{% if r in ns.refs_with_meta %} +import { {{ r }}Meta } from './{{ r | ts_kebab_case }}'; +{% endif %} +{% endfor %} + +{{ schema.description | ts_doc_comment }} +{% if isObject and schema.get('allOf') is not defined and schema.get('oneOf') is not defined and schema.get('anyOf') is not defined %} +export interface {{ modelName }} { +{% for f in descriptor.fields %} + {{ f.name }}{{ '' if not f.is_optional else '?' }}: {{ f.ts_type }}; +{% endfor %} +} +{% else %} +export type {{ modelName }} = {{ schema | ts_type(schemas) }}; +{% endif %} + +export const {{ modelName }}Meta: ModelMetadata = { + name: '{{ modelName }}', + kind: {% if isObject %}'object'{% elif isArray %}'array'{% else %}'passthrough'{% endif %}, +{% if isObject %} + fields: [ +{% for f in descriptor.fields %} + { + name: '{{ f.name }}', + wireKey: '{{ f.wire_name }}', + optional: {{ 'true' if f.is_optional else 'false' }}, + nullable: {{ 'true' if f.is_nullable else 'false' }}, + type: {{ field_type(f) }}, + }, +{% endfor %} + ], +{% if has_additional_properties %} + additionalProperties: {{ scalar_meta(false, false) }}, +{% endif %} +{% elif isArray %} + arrayItems: {{ array_item_meta(descriptor) }}, +{% else %} +{% if schemaSignedTxn %} + codecKey: 'SignedTransaction', +{% else %} + passThrough: {{ scalar_meta(schemaBytes, schemaBigint) }}, +{% endif %} +{% endif %} +}; diff --git a/oas-generator/src/oas_generator/utils/__init__.py b/oas-generator/src/oas_generator/utils/__init__.py new file mode 100644 index 000000000..bf85e06a2 --- /dev/null +++ b/oas-generator/src/oas_generator/utils/__init__.py @@ -0,0 +1,5 @@ +"""Utility helpers exposed by ``oas_generator.utils``.""" + +from oas_generator.utils.file_utils import write_files_to_disk + +__all__ = ["write_files_to_disk"] diff --git a/oas-generator/src/oas_generator/utils/file_utils.py b/oas-generator/src/oas_generator/utils/file_utils.py new file mode 100644 index 000000000..005edf917 --- /dev/null +++ b/oas-generator/src/oas_generator/utils/file_utils.py @@ -0,0 +1,18 @@ +"""File utilities for the TS OAS generator. + +Provides safe write operations similar to rust_oas_generator.utils.file_utils. +""" + +from __future__ import annotations + +from pathlib import Path + + +def write_files_to_disk(files: dict[Path, str]) -> None: + """Write generated files to disk, creating parent directories. + + Existing files are overwritten. Parent directories are created as needed. + """ + for path, content in files.items(): + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(content, encoding="utf-8") diff --git a/oas-generator/uv.lock b/oas-generator/uv.lock new file mode 100644 index 000000000..4e7222c50 --- /dev/null +++ b/oas-generator/uv.lock @@ -0,0 +1,89 @@ +version = 1 +revision = 2 +requires-python = ">=3.12" + +[[package]] +name = "jinja2" +version = "3.1.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, +] + +[[package]] +name = "markupsafe" +version = "3.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e", size = 11615, upload-time = "2025-09-27T18:36:30.854Z" }, + { url = "https://files.pythonhosted.org/packages/9a/81/7e4e08678a1f98521201c3079f77db69fb552acd56067661f8c2f534a718/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce", size = 12020, upload-time = "2025-09-27T18:36:31.971Z" }, + { url = "https://files.pythonhosted.org/packages/1e/2c/799f4742efc39633a1b54a92eec4082e4f815314869865d876824c257c1e/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d", size = 24332, upload-time = "2025-09-27T18:36:32.813Z" }, + { url = "https://files.pythonhosted.org/packages/3c/2e/8d0c2ab90a8c1d9a24f0399058ab8519a3279d1bd4289511d74e909f060e/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d", size = 22947, upload-time = "2025-09-27T18:36:33.86Z" }, + { url = "https://files.pythonhosted.org/packages/2c/54/887f3092a85238093a0b2154bd629c89444f395618842e8b0c41783898ea/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a", size = 21962, upload-time = "2025-09-27T18:36:35.099Z" }, + { url = "https://files.pythonhosted.org/packages/c9/2f/336b8c7b6f4a4d95e91119dc8521402461b74a485558d8f238a68312f11c/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b", size = 23760, upload-time = "2025-09-27T18:36:36.001Z" }, + { url = "https://files.pythonhosted.org/packages/32/43/67935f2b7e4982ffb50a4d169b724d74b62a3964bc1a9a527f5ac4f1ee2b/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f", size = 21529, upload-time = "2025-09-27T18:36:36.906Z" }, + { url = "https://files.pythonhosted.org/packages/89/e0/4486f11e51bbba8b0c041098859e869e304d1c261e59244baa3d295d47b7/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b", size = 23015, upload-time = "2025-09-27T18:36:37.868Z" }, + { url = "https://files.pythonhosted.org/packages/2f/e1/78ee7a023dac597a5825441ebd17170785a9dab23de95d2c7508ade94e0e/markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d", size = 14540, upload-time = "2025-09-27T18:36:38.761Z" }, + { url = "https://files.pythonhosted.org/packages/aa/5b/bec5aa9bbbb2c946ca2733ef9c4ca91c91b6a24580193e891b5f7dbe8e1e/markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c", size = 15105, upload-time = "2025-09-27T18:36:39.701Z" }, + { url = "https://files.pythonhosted.org/packages/e5/f1/216fc1bbfd74011693a4fd837e7026152e89c4bcf3e77b6692fba9923123/markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f", size = 13906, upload-time = "2025-09-27T18:36:40.689Z" }, + { url = "https://files.pythonhosted.org/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622, upload-time = "2025-09-27T18:36:41.777Z" }, + { url = "https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029, upload-time = "2025-09-27T18:36:43.257Z" }, + { url = "https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374, upload-time = "2025-09-27T18:36:44.508Z" }, + { url = "https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980, upload-time = "2025-09-27T18:36:45.385Z" }, + { url = "https://files.pythonhosted.org/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990, upload-time = "2025-09-27T18:36:46.916Z" }, + { url = "https://files.pythonhosted.org/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784, upload-time = "2025-09-27T18:36:47.884Z" }, + { url = "https://files.pythonhosted.org/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588, upload-time = "2025-09-27T18:36:48.82Z" }, + { url = "https://files.pythonhosted.org/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041, upload-time = "2025-09-27T18:36:49.797Z" }, + { url = "https://files.pythonhosted.org/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543, upload-time = "2025-09-27T18:36:51.584Z" }, + { url = "https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113, upload-time = "2025-09-27T18:36:52.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911, upload-time = "2025-09-27T18:36:53.513Z" }, + { url = "https://files.pythonhosted.org/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658, upload-time = "2025-09-27T18:36:54.819Z" }, + { url = "https://files.pythonhosted.org/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066, upload-time = "2025-09-27T18:36:55.714Z" }, + { url = "https://files.pythonhosted.org/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639, upload-time = "2025-09-27T18:36:56.908Z" }, + { url = "https://files.pythonhosted.org/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569, upload-time = "2025-09-27T18:36:57.913Z" }, + { url = "https://files.pythonhosted.org/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284, upload-time = "2025-09-27T18:36:58.833Z" }, + { url = "https://files.pythonhosted.org/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801, upload-time = "2025-09-27T18:36:59.739Z" }, + { url = "https://files.pythonhosted.org/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769, upload-time = "2025-09-27T18:37:00.719Z" }, + { url = "https://files.pythonhosted.org/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642, upload-time = "2025-09-27T18:37:01.673Z" }, + { url = "https://files.pythonhosted.org/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612, upload-time = "2025-09-27T18:37:02.639Z" }, + { url = "https://files.pythonhosted.org/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200, upload-time = "2025-09-27T18:37:03.582Z" }, + { url = "https://files.pythonhosted.org/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973, upload-time = "2025-09-27T18:37:04.929Z" }, + { url = "https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", size = 11619, upload-time = "2025-09-27T18:37:06.342Z" }, + { url = "https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", size = 12029, upload-time = "2025-09-27T18:37:07.213Z" }, + { url = "https://files.pythonhosted.org/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", size = 24408, upload-time = "2025-09-27T18:37:09.572Z" }, + { url = "https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97", size = 23005, upload-time = "2025-09-27T18:37:10.58Z" }, + { url = "https://files.pythonhosted.org/packages/bc/20/b7fdf89a8456b099837cd1dc21974632a02a999ec9bf7ca3e490aacd98e7/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d", size = 22048, upload-time = "2025-09-27T18:37:11.547Z" }, + { url = "https://files.pythonhosted.org/packages/9a/a7/591f592afdc734f47db08a75793a55d7fbcc6902a723ae4cfbab61010cc5/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda", size = 23821, upload-time = "2025-09-27T18:37:12.48Z" }, + { url = "https://files.pythonhosted.org/packages/7d/33/45b24e4f44195b26521bc6f1a82197118f74df348556594bd2262bda1038/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf", size = 21606, upload-time = "2025-09-27T18:37:13.485Z" }, + { url = "https://files.pythonhosted.org/packages/ff/0e/53dfaca23a69fbfbbf17a4b64072090e70717344c52eaaaa9c5ddff1e5f0/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe", size = 23043, upload-time = "2025-09-27T18:37:14.408Z" }, + { url = "https://files.pythonhosted.org/packages/46/11/f333a06fc16236d5238bfe74daccbca41459dcd8d1fa952e8fbd5dccfb70/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9", size = 14747, upload-time = "2025-09-27T18:37:15.36Z" }, + { url = "https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581", size = 15341, upload-time = "2025-09-27T18:37:16.496Z" }, + { url = "https://files.pythonhosted.org/packages/6f/18/acf23e91bd94fd7b3031558b1f013adfa21a8e407a3fdb32745538730382/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4", size = 14073, upload-time = "2025-09-27T18:37:17.476Z" }, + { url = "https://files.pythonhosted.org/packages/3c/f0/57689aa4076e1b43b15fdfa646b04653969d50cf30c32a102762be2485da/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab", size = 11661, upload-time = "2025-09-27T18:37:18.453Z" }, + { url = "https://files.pythonhosted.org/packages/89/c3/2e67a7ca217c6912985ec766c6393b636fb0c2344443ff9d91404dc4c79f/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175", size = 12069, upload-time = "2025-09-27T18:37:19.332Z" }, + { url = "https://files.pythonhosted.org/packages/f0/00/be561dce4e6ca66b15276e184ce4b8aec61fe83662cce2f7d72bd3249d28/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634", size = 25670, upload-time = "2025-09-27T18:37:20.245Z" }, + { url = "https://files.pythonhosted.org/packages/50/09/c419f6f5a92e5fadde27efd190eca90f05e1261b10dbd8cbcb39cd8ea1dc/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50", size = 23598, upload-time = "2025-09-27T18:37:21.177Z" }, + { url = "https://files.pythonhosted.org/packages/22/44/a0681611106e0b2921b3033fc19bc53323e0b50bc70cffdd19f7d679bb66/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e", size = 23261, upload-time = "2025-09-27T18:37:22.167Z" }, + { url = "https://files.pythonhosted.org/packages/5f/57/1b0b3f100259dc9fffe780cfb60d4be71375510e435efec3d116b6436d43/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5", size = 24835, upload-time = "2025-09-27T18:37:23.296Z" }, + { url = "https://files.pythonhosted.org/packages/26/6a/4bf6d0c97c4920f1597cc14dd720705eca0bf7c787aebc6bb4d1bead5388/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523", size = 22733, upload-time = "2025-09-27T18:37:24.237Z" }, + { url = "https://files.pythonhosted.org/packages/14/c7/ca723101509b518797fedc2fdf79ba57f886b4aca8a7d31857ba3ee8281f/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc", size = 23672, upload-time = "2025-09-27T18:37:25.271Z" }, + { url = "https://files.pythonhosted.org/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", size = 14819, upload-time = "2025-09-27T18:37:26.285Z" }, + { url = "https://files.pythonhosted.org/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", size = 15426, upload-time = "2025-09-27T18:37:27.316Z" }, + { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" }, +] + +[[package]] +name = "oas-generator" +version = "1.0.0" +source = { editable = "." } +dependencies = [ + { name = "jinja2" }, +] + +[package.metadata] +requires-dist = [{ name = "jinja2", specifier = ">=3.0.0" }] diff --git a/package.json b/package.json index 2e836d964..dffd3f432 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,8 @@ "commit-lint": "commitlint --edit -o", "semantic-release": "semantic-release", "generate:code-docs": "typedoc", - "pre-commit": "run-s check-types lint:fix audit format test generate:code-docs && npm run pre-commit --workspaces --if-present" + "pre-commit": "run-s check-types lint:fix audit format test generate:code-docs && npm run pre-commit --workspaces --if-present", + "generate:algod": "cd oas-generator && uv run oas-generator ../algokit-configs/openapi-converter/specs/algod.oas3.json --output ../packages/algod_client/ --package-name algod_client --description \"TypeScript client for algod interaction.\" --verbose && cd .." }, "overrides": { "esbuild": "0.25.0" From 6858df0bd128bf46587ee3e7af90b555adbbb800 Mon Sep 17 00:00:00 2001 From: Neil Campbell Date: Sat, 1 Nov 2025 00:43:25 +0800 Subject: [PATCH 02/10] fix: correct some algod client issues --- .../openapi-converter/specs/algod.oas3.json | 269 +++++++++--------- .../generator/template_engine.py | 2 - .../templates/base/src/core/request.ts.j2 | 6 +- package-lock.json | 6 +- package.json | 4 +- packages/algod_client/package.json | 2 +- packages/algod_client/src/apis/api.service.ts | 10 +- .../algod_client/src/core/model-runtime.ts | 6 +- packages/algod_client/src/core/request.ts | 12 +- .../algod_client/src/models/box-reference.ts | 2 +- .../algod_client/src/models/dryrun-request.ts | 2 +- .../get-pending-transactions-by-address.ts | 2 +- .../src/models/get-pending-transactions.ts | 2 +- .../algod_client/src/models/get-status.ts | 16 +- .../src/models/participation-key.ts | 6 +- .../models/pending-transaction-response.ts | 2 +- .../src/models/signed-txn-in-block.ts | 4 +- .../simulate-request-transaction-group.ts | 2 +- .../algod_client/src/models/wait-for-block.ts | 16 +- tsconfig.base.json | 2 +- tsconfig.json | 1 + 21 files changed, 182 insertions(+), 192 deletions(-) diff --git a/algokit-configs/openapi-converter/specs/algod.oas3.json b/algokit-configs/openapi-converter/specs/algod.oas3.json index 804c5fb03..e9e7ae640 100644 --- a/algokit-configs/openapi-converter/specs/algod.oas3.json +++ b/algokit-configs/openapi-converter/specs/algod.oas3.json @@ -364,9 +364,11 @@ "schema": { "minimum": 0, "type": "integer", - "x-go-type": "basics.AssetIndex" + "x-go-type": "basics.AssetIndex", + "x-algokit-bigint": true }, - "x-go-type": "basics.AssetIndex" + "x-go-type": "basics.AssetIndex", + "x-algokit-bigint": true }, { "name": "format", @@ -586,9 +588,11 @@ "schema": { "minimum": 0, "type": "integer", - "x-go-type": "basics.AppIndex" + "x-go-type": "basics.AppIndex", + "x-algokit-bigint": true }, - "x-go-type": "basics.AppIndex" + "x-go-type": "basics.AppIndex", + "x-algokit-bigint": true }, { "name": "format", @@ -845,9 +849,11 @@ "schema": { "minimum": 0, "type": "integer", - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true }, - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true }, { "name": "header-only", @@ -962,9 +968,11 @@ "schema": { "minimum": 0, "type": "integer", - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true }, - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true } ], "responses": { @@ -1054,9 +1062,11 @@ "schema": { "minimum": 0, "type": "integer", - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true }, - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true } ], "responses": { @@ -1143,9 +1153,11 @@ "schema": { "minimum": 0, "type": "integer", - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true }, - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true }, { "name": "txid", @@ -1258,9 +1270,11 @@ "schema": { "minimum": 0, "type": "integer", - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true }, - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true } ], "responses": { @@ -1596,7 +1610,8 @@ "x-go-type": "basics.Round", "x-algokit-bigint": true }, - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true }, { "name": "last", @@ -1609,7 +1624,8 @@ "x-go-type": "basics.Round", "x-algokit-bigint": true }, - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true } ], "responses": { @@ -1984,7 +2000,8 @@ "next-version-round": { "type": "integer", "description": "NextVersionRound is the round at which the next consensus version will apply", - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true }, "next-version-supported": { "type": "boolean", @@ -2051,7 +2068,8 @@ "upgrade-delay": { "type": "integer", "description": "Upgrade delay", - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true }, "upgrade-node-vote": { "type": "boolean", @@ -2060,32 +2078,33 @@ "upgrade-votes-required": { "type": "integer", "description": "Yes votes required for consensus upgrade", - "x-go-type": "basics.Round" + "format": "int32" }, "upgrade-votes": { "type": "integer", "description": "Total votes cast for consensus upgrade", - "x-go-type": "basics.Round" + "format": "int32" }, "upgrade-yes-votes": { "type": "integer", "description": "Yes votes cast for consensus upgrade", - "x-go-type": "basics.Round" + "format": "int32" }, "upgrade-no-votes": { "type": "integer", "description": "No votes cast for consensus upgrade", - "x-go-type": "basics.Round" + "format": "int32" }, "upgrade-next-protocol-vote-before": { "type": "integer", "description": "Next protocol round", - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true }, "upgrade-vote-rounds": { "type": "integer", "description": "Total voting rounds for current upgrade", - "x-go-type": "basics.Round" + "format": "int32" } }, "description": "NodeStatus contains the information about a node status" @@ -2139,9 +2158,11 @@ "schema": { "minimum": 0, "type": "integer", - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true }, - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true } ], "responses": { @@ -2184,7 +2205,8 @@ "next-version-round": { "type": "integer", "description": "NextVersionRound is the round at which the next consensus version will apply", - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true }, "next-version-supported": { "type": "boolean", @@ -2251,7 +2273,8 @@ "upgrade-delay": { "type": "integer", "description": "Upgrade delay", - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true }, "upgrade-node-vote": { "type": "boolean", @@ -2260,32 +2283,33 @@ "upgrade-votes-required": { "type": "integer", "description": "Yes votes required for consensus upgrade", - "x-go-type": "basics.Round" + "format": "int32" }, "upgrade-votes": { "type": "integer", "description": "Total votes cast for consensus upgrade", - "x-go-type": "basics.Round" + "format": "int32" }, "upgrade-yes-votes": { "type": "integer", "description": "Yes votes cast for consensus upgrade", - "x-go-type": "basics.Round" + "format": "int32" }, "upgrade-no-votes": { "type": "integer", "description": "No votes cast for consensus upgrade", - "x-go-type": "basics.Round" + "format": "int32" }, "upgrade-next-protocol-vote-before": { "type": "integer", "description": "Next protocol round", - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true }, "upgrade-vote-rounds": { "type": "integer", "description": "Total voting rounds for current upgrade", - "x-go-type": "basics.Round" + "format": "int32" } }, "description": "NodeStatus contains the information about a node status" @@ -2522,20 +2546,15 @@ "schema": { "type": "string", "enum": [ - "json", "msgpack" - ] + ], + "default": "msgpack" } } ], "requestBody": { "description": "The transactions to simulate, along with any other inputs.", "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SimulateRequest" - } - }, "application/msgpack": { "schema": { "$ref": "#/components/schemas/SimulateRequest" @@ -2548,45 +2567,6 @@ "200": { "description": "Result of a transaction group simulation.", "content": { - "application/json": { - "schema": { - "required": [ - "last-round", - "txn-groups", - "version" - ], - "type": "object", - "properties": { - "version": { - "type": "integer", - "description": "The version of this response object.", - "x-algokit-bigint": true - }, - "last-round": { - "type": "integer", - "description": "The round immediately preceding this simulation. State changes through this round were used to run this simulation.", - "x-go-type": "basics.Round", - "x-algokit-bigint": true - }, - "txn-groups": { - "type": "array", - "description": "A result object for each transaction group that was simulated.", - "items": { - "$ref": "#/components/schemas/SimulateTransactionGroupResult" - } - }, - "eval-overrides": { - "$ref": "#/components/schemas/SimulationEvalOverrides" - }, - "exec-trace-config": { - "$ref": "#/components/schemas/SimulateTraceConfig" - }, - "initial-states": { - "$ref": "#/components/schemas/SimulateInitialStates" - } - } - } - }, "application/msgpack": { "schema": { "required": [ @@ -2631,11 +2611,6 @@ "400": { "description": "Bad Request", "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - }, "application/msgpack": { "schema": { "$ref": "#/components/schemas/ErrorResponse" @@ -2646,11 +2621,6 @@ "401": { "description": "Invalid API Token", "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - }, "application/msgpack": { "schema": { "$ref": "#/components/schemas/ErrorResponse" @@ -2661,11 +2631,6 @@ "500": { "description": "Internal Error", "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - }, "application/msgpack": { "schema": { "$ref": "#/components/schemas/ErrorResponse" @@ -2676,11 +2641,6 @@ "503": { "description": "Service Temporarily Unavailable", "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - }, "application/msgpack": { "schema": { "$ref": "#/components/schemas/ErrorResponse" @@ -2993,9 +2953,11 @@ "schema": { "minimum": 0, "type": "integer", - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true }, - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true }, { "name": "format", @@ -3096,9 +3058,11 @@ "schema": { "minimum": 0, "type": "integer", - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true }, - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true }, { "name": "format", @@ -3310,9 +3274,11 @@ "schema": { "minimum": 0, "type": "integer", - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true }, - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true } ], "responses": { @@ -3400,9 +3366,11 @@ "schema": { "minimum": 0, "type": "integer", - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true }, - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true } ], "responses": { @@ -3491,9 +3459,11 @@ "schema": { "minimum": 0, "type": "integer", - "x-go-type": "basics.AppIndex" + "x-go-type": "basics.AppIndex", + "x-algokit-bigint": true }, - "x-go-type": "basics.AppIndex" + "x-go-type": "basics.AppIndex", + "x-algokit-bigint": true } ], "responses": { @@ -3572,9 +3542,11 @@ "schema": { "minimum": 0, "type": "integer", - "x-go-type": "basics.AppIndex" + "x-go-type": "basics.AppIndex", + "x-algokit-bigint": true }, - "x-go-type": "basics.AppIndex" + "x-go-type": "basics.AppIndex", + "x-algokit-bigint": true }, { "name": "max", @@ -3664,9 +3636,11 @@ "schema": { "minimum": 0, "type": "integer", - "x-go-type": "basics.AppIndex" + "x-go-type": "basics.AppIndex", + "x-algokit-bigint": true }, - "x-go-type": "basics.AppIndex" + "x-go-type": "basics.AppIndex", + "x-algokit-bigint": true }, { "name": "name", @@ -3754,9 +3728,11 @@ "schema": { "minimum": 0, "type": "integer", - "x-go-type": "basics.AssetIndex" + "x-go-type": "basics.AssetIndex", + "x-algokit-bigint": true }, - "x-go-type": "basics.AssetIndex" + "x-go-type": "basics.AssetIndex", + "x-algokit-bigint": true } ], "responses": { @@ -3972,9 +3948,11 @@ "schema": { "minimum": 0, "type": "integer", - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true }, - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true } ], "responses": { @@ -4244,9 +4222,11 @@ "description": "Specify the minimum number of blocks which the ledger must be advanced by in order to start the catchup. This is useful for simplifying tools which support fast catchup, they can run the catchup unconditionally and the node will skip the catchup if it is not needed.", "schema": { "type": "integer", - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true }, - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true } ], "responses": { @@ -5271,17 +5251,20 @@ "last-vote": { "type": "integer", "description": "Round when this key was last used to vote.", - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true }, "last-block-proposal": { "type": "integer", "description": "Round when this key was last used to propose a block.", - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true }, "last-state-proof": { "type": "integer", "description": "Round when this key was last used to generate a state proof.", - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true }, "key": { "$ref": "#/components/schemas/AccountParticipation" @@ -5862,7 +5845,8 @@ "app": { "type": "integer", "description": "Application ID which this box belongs to", - "x-go-type": "basics.AppIndex" + "x-go-type": "basics.AppIndex", + "x-algokit-bigint": true }, "name": { "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", @@ -6937,7 +6921,8 @@ "next-version-round": { "type": "integer", "description": "NextVersionRound is the round at which the next consensus version will apply", - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true }, "next-version-supported": { "type": "boolean", @@ -7004,7 +6989,8 @@ "upgrade-delay": { "type": "integer", "description": "Upgrade delay", - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true }, "upgrade-node-vote": { "type": "boolean", @@ -7013,32 +6999,33 @@ "upgrade-votes-required": { "type": "integer", "description": "Yes votes required for consensus upgrade", - "x-go-type": "basics.Round" + "format": "int32" }, "upgrade-votes": { "type": "integer", "description": "Total votes cast for consensus upgrade", - "x-go-type": "basics.Round" + "format": "int32" }, "upgrade-yes-votes": { "type": "integer", "description": "Yes votes cast for consensus upgrade", - "x-go-type": "basics.Round" + "format": "int32" }, "upgrade-no-votes": { "type": "integer", "description": "No votes cast for consensus upgrade", - "x-go-type": "basics.Round" + "format": "int32" }, "upgrade-next-protocol-vote-before": { "type": "integer", "description": "Next protocol round", - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true }, "upgrade-vote-rounds": { "type": "integer", "description": "Total voting rounds for current upgrade", - "x-go-type": "basics.Round" + "format": "int32" } }, "description": "NodeStatus contains the information about a node status" @@ -7500,9 +7487,11 @@ "schema": { "minimum": 0, "type": "integer", - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true }, - "x-go-type": "basics.Round" + "x-go-type": "basics.Round", + "x-algokit-bigint": true }, "address": { "name": "address", @@ -7524,9 +7513,11 @@ "schema": { "minimum": 0, "type": "integer", - "x-go-type": "basics.AssetIndex" + "x-go-type": "basics.AssetIndex", + "x-algokit-bigint": true }, - "x-go-type": "basics.AssetIndex" + "x-go-type": "basics.AssetIndex", + "x-algokit-bigint": true }, "application-id": { "name": "application-id", @@ -7536,9 +7527,11 @@ "schema": { "minimum": 0, "type": "integer", - "x-go-type": "basics.AppIndex" + "x-go-type": "basics.AppIndex", + "x-algokit-bigint": true }, - "x-go-type": "basics.AppIndex" + "x-go-type": "basics.AppIndex", + "x-algokit-bigint": true }, "sig-type": { "name": "sig-type", diff --git a/oas-generator/src/oas_generator/generator/template_engine.py b/oas-generator/src/oas_generator/generator/template_engine.py index f34e118bd..efef27810 100644 --- a/oas-generator/src/oas_generator/generator/template_engine.py +++ b/oas-generator/src/oas_generator/generator/template_engine.py @@ -756,8 +756,6 @@ def generate( "export { BlockMeta } from './block';\n" "export type { SignedTxnInBlock } from './signed-txn-in-block';\n" "export { SignedTxnInBlockMeta } from './signed-txn-in-block';\n" - "export type { GetBlock } from './get-block';\n" - "export { GetBlockMeta } from './get-block';\n" ) files[index_path] = base_index + extras files.update(self.operation_processor.generate_service(output_dir, ops_by_tag, tags, service_class)) diff --git a/oas-generator/src/oas_generator/templates/base/src/core/request.ts.j2 b/oas-generator/src/oas_generator/templates/base/src/core/request.ts.j2 index 63e8c74b4..88aef7102 100644 --- a/oas-generator/src/oas_generator/templates/base/src/core/request.ts.j2 +++ b/oas-generator/src/oas_generator/templates/base/src/core/request.ts.j2 @@ -64,11 +64,11 @@ export async function request(config: ClientConfig, options: { let bodyPayload: BodyInit | undefined = undefined; if (options.body != null) { if (options.body instanceof Uint8Array) { - bodyPayload = options.body; + bodyPayload = options.body.slice().buffer; } else if (typeof options.body === 'string') { bodyPayload = options.body; } else if (options.mediaType?.includes('msgpack')) { - bodyPayload = encodeMsgPack(options.body); + bodyPayload = encodeMsgPack(options.body).slice().buffer; } else if (options.mediaType?.includes('json')) { bodyPayload = JSON.stringify(options.body); } else { @@ -116,7 +116,7 @@ export async function request(config: ClientConfig, options: { } if (contentType.includes('application/json')) { - return (await response.text()) as unknown as T; + return JSON.parse(await response.text()) as unknown as T; } if (!contentType) { diff --git a/package-lock.json b/package-lock.json index c0c3b843a..d2ec49dfb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -41,7 +41,7 @@ "fast-glob": "^3.3.2", "magic-string": "^0.30.11", "npm-run-all2": "^8.0.4", - "prettier": "^3.3.3", + "prettier": "^3.6.2", "replace-in-files-cli": "^3.0.0", "rimraf": "^6.0.1", "rolldown": "^1.0.0-beta.45", @@ -9305,7 +9305,9 @@ } }, "node_modules/prettier": { - "version": "3.3.3", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "dev": true, "license": "MIT", "bin": { diff --git a/package.json b/package.json index dffd3f432..104ae5688 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "semantic-release": "semantic-release", "generate:code-docs": "typedoc", "pre-commit": "run-s check-types lint:fix audit format test generate:code-docs && npm run pre-commit --workspaces --if-present", - "generate:algod": "cd oas-generator && uv run oas-generator ../algokit-configs/openapi-converter/specs/algod.oas3.json --output ../packages/algod_client/ --package-name algod_client --description \"TypeScript client for algod interaction.\" --verbose && cd .." + "generate:algod": "cd oas-generator && uv run oas-generator ../algokit-configs/openapi-converter/specs/algod.oas3.json --output ../packages/algod_client/ --package-name algod_client --description \"TypeScript client for algod interaction.\" --verbose && prettier --write ../packages/algod_client/src/ && cd .." }, "overrides": { "esbuild": "0.25.0" @@ -90,7 +90,7 @@ "fast-glob": "^3.3.2", "magic-string": "^0.30.11", "npm-run-all2": "^8.0.4", - "prettier": "^3.3.3", + "prettier": "^3.6.2", "replace-in-files-cli": "^3.0.0", "rimraf": "^6.0.1", "rolldown": "^1.0.0-beta.45", diff --git a/packages/algod_client/package.json b/packages/algod_client/package.json index 5d3ce75ff..de108cfda 100644 --- a/packages/algod_client/package.json +++ b/packages/algod_client/package.json @@ -26,4 +26,4 @@ "dependencies": {}, "peerDependencies": {}, "devDependencies": {} -} \ No newline at end of file +} diff --git a/packages/algod_client/src/apis/api.service.ts b/packages/algod_client/src/apis/api.service.ts index 1c52a7f24..9f651086b 100644 --- a/packages/algod_client/src/apis/api.service.ts +++ b/packages/algod_client/src/apis/api.service.ts @@ -1,6 +1,6 @@ -import type { ApiRequestOptions, BaseHttpRequest } from '../core/base-http-request' -import type { BodyFormat } from '../core/model-runtime' +import type { BaseHttpRequest, ApiRequestOptions } from '../core/base-http-request' import { AlgorandSerializer } from '../core/model-runtime' +import type { BodyFormat } from '../core/model-runtime' import type { AbortCatchup, Account, @@ -46,10 +46,10 @@ import type { } from '../models/index' import { AbortCatchupMeta, + AccountMeta, AccountApplicationInformationMeta, AccountAssetInformationMeta, AccountAssetsInformationMeta, - AccountMeta, AddParticipationKeyMeta, ApplicationMeta, AssetMeta, @@ -58,13 +58,13 @@ import { DryrunRequestMeta, GenesisMeta, GetApplicationBoxesMeta, + GetBlockMeta, GetBlockHashMeta, GetBlockLogsMeta, - GetBlockMeta, GetBlockTimeStampOffsetMeta, GetBlockTxidsMeta, - GetPendingTransactionsByAddressMeta, GetPendingTransactionsMeta, + GetPendingTransactionsByAddressMeta, GetStatusMeta, GetSupplyMeta, GetSyncRoundMeta, diff --git a/packages/algod_client/src/core/model-runtime.ts b/packages/algod_client/src/core/model-runtime.ts index 64440074b..eecaf8bb8 100644 --- a/packages/algod_client/src/core/model-runtime.ts +++ b/packages/algod_client/src/core/model-runtime.ts @@ -1,10 +1,10 @@ import { - decodeSignedTransaction as transactDecodeSignedTransaction, encodeSignedTransaction as transactEncodeSignedTransaction, + decodeSignedTransaction as transactDecodeSignedTransaction, type SignedTransaction, } from '@algorandfoundation/algokit-transact' -import { decodeMsgPack, encodeMsgPack } from './codecs' -import { fromBase64, toBase64 } from './serialization' +import { encodeMsgPack, decodeMsgPack } from './codecs' +import { toBase64, fromBase64 } from './serialization' export type BodyFormat = 'json' | 'msgpack' diff --git a/packages/algod_client/src/core/request.ts b/packages/algod_client/src/core/request.ts index 368651f07..112098a7e 100644 --- a/packages/algod_client/src/core/request.ts +++ b/packages/algod_client/src/core/request.ts @@ -1,10 +1,7 @@ -import { ApiError } from './api-error' -import type { BodyValue, QueryParams } from './base-http-request' import type { ClientConfig } from './client-config' +import { ApiError } from './api-error' import { decodeMsgPack, encodeMsgPack } from './codecs' - -// TODO: PD - look into this type, if needed, we need to fix the OAS templates -type BodyInit = string | Uint8Array +import type { QueryParams, BodyValue } from './base-http-request' const encodeURIPath = (path: string): string => encodeURI(path).replace(/%5B/g, '[').replace(/%5D/g, ']') @@ -64,11 +61,11 @@ export async function request( let bodyPayload: BodyInit | undefined = undefined if (options.body != null) { if (options.body instanceof Uint8Array) { - bodyPayload = options.body + bodyPayload = options.body.slice().buffer } else if (typeof options.body === 'string') { bodyPayload = options.body } else if (options.mediaType?.includes('msgpack')) { - bodyPayload = encodeMsgPack(options.body) + bodyPayload = encodeMsgPack(options.body).slice().buffer } else if (options.mediaType?.includes('json')) { bodyPayload = JSON.stringify(options.body) } else { @@ -90,7 +87,6 @@ export async function request( if (ct.includes('application/msgpack')) { errorBody = decodeMsgPack(new Uint8Array(await response.arrayBuffer())) } else if (ct.includes('application/json')) { - // TODO: PD - update the template errorBody = JSON.parse(await response.text()) } else { errorBody = await response.text() diff --git a/packages/algod_client/src/models/box-reference.ts b/packages/algod_client/src/models/box-reference.ts index 1202e209a..9fa2a8baa 100644 --- a/packages/algod_client/src/models/box-reference.ts +++ b/packages/algod_client/src/models/box-reference.ts @@ -24,7 +24,7 @@ export const BoxReferenceMeta: ModelMetadata = { wireKey: 'app', optional: false, nullable: false, - type: { kind: 'scalar', isBigint: true }, // TODO: PD - make change to OAS + type: { kind: 'scalar', isBigint: true }, }, { name: 'name', diff --git a/packages/algod_client/src/models/dryrun-request.ts b/packages/algod_client/src/models/dryrun-request.ts index 0faf31484..fe165addb 100644 --- a/packages/algod_client/src/models/dryrun-request.ts +++ b/packages/algod_client/src/models/dryrun-request.ts @@ -1,5 +1,5 @@ -import type { SignedTransaction } from '@algorandfoundation/algokit-transact' import type { ModelMetadata } from '../core/model-runtime' +import type { SignedTransaction } from '@algorandfoundation/algokit-transact' import type { Account } from './account' import { AccountMeta } from './account' import type { Application } from './application' diff --git a/packages/algod_client/src/models/get-pending-transactions-by-address.ts b/packages/algod_client/src/models/get-pending-transactions-by-address.ts index 354bcf0d7..f96c63251 100644 --- a/packages/algod_client/src/models/get-pending-transactions-by-address.ts +++ b/packages/algod_client/src/models/get-pending-transactions-by-address.ts @@ -1,5 +1,5 @@ -import type { SignedTransaction } from '@algorandfoundation/algokit-transact' import type { ModelMetadata } from '../core/model-runtime' +import type { SignedTransaction } from '@algorandfoundation/algokit-transact' /** * PendingTransactions is an array of signed transactions exactly as they were submitted. diff --git a/packages/algod_client/src/models/get-pending-transactions.ts b/packages/algod_client/src/models/get-pending-transactions.ts index 5f1ffa9ad..f1cbb8688 100644 --- a/packages/algod_client/src/models/get-pending-transactions.ts +++ b/packages/algod_client/src/models/get-pending-transactions.ts @@ -1,5 +1,5 @@ -import type { SignedTransaction } from '@algorandfoundation/algokit-transact' import type { ModelMetadata } from '../core/model-runtime' +import type { SignedTransaction } from '@algorandfoundation/algokit-transact' /** * PendingTransactions is an array of signed transactions exactly as they were submitted. diff --git a/packages/algod_client/src/models/get-status.ts b/packages/algod_client/src/models/get-status.ts index 1ae84ff40..a9c5f1bd9 100644 --- a/packages/algod_client/src/models/get-status.ts +++ b/packages/algod_client/src/models/get-status.ts @@ -107,22 +107,22 @@ export type GetStatus = { /** * Yes votes required for consensus upgrade */ - upgradeVotesRequired?: bigint + upgradeVotesRequired?: number /** * Total votes cast for consensus upgrade */ - upgradeVotes?: bigint + upgradeVotes?: number /** * Yes votes cast for consensus upgrade */ - upgradeYesVotes?: bigint + upgradeYesVotes?: number /** * No votes cast for consensus upgrade */ - upgradeNoVotes?: bigint + upgradeNoVotes?: number /** * Next protocol round @@ -132,7 +132,7 @@ export type GetStatus = { /** * Total voting rounds for current upgrade */ - upgradeVoteRounds?: bigint + upgradeVoteRounds?: number } export const GetStatusMeta: ModelMetadata = { @@ -172,7 +172,7 @@ export const GetStatusMeta: ModelMetadata = { wireKey: 'next-version-round', optional: false, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'nextVersionSupported', @@ -270,7 +270,7 @@ export const GetStatusMeta: ModelMetadata = { wireKey: 'upgrade-delay', optional: true, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'upgradeNodeVote', @@ -312,7 +312,7 @@ export const GetStatusMeta: ModelMetadata = { wireKey: 'upgrade-next-protocol-vote-before', optional: true, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'upgradeVoteRounds', diff --git a/packages/algod_client/src/models/participation-key.ts b/packages/algod_client/src/models/participation-key.ts index b718584bc..4cf92f731 100644 --- a/packages/algod_client/src/models/participation-key.ts +++ b/packages/algod_client/src/models/participation-key.ts @@ -80,21 +80,21 @@ export const ParticipationKeyMeta: ModelMetadata = { wireKey: 'last-vote', optional: true, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'lastBlockProposal', wireKey: 'last-block-proposal', optional: true, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'lastStateProof', wireKey: 'last-state-proof', optional: true, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'key', diff --git a/packages/algod_client/src/models/pending-transaction-response.ts b/packages/algod_client/src/models/pending-transaction-response.ts index 3aaa6d816..72f37c04c 100644 --- a/packages/algod_client/src/models/pending-transaction-response.ts +++ b/packages/algod_client/src/models/pending-transaction-response.ts @@ -1,5 +1,5 @@ -import type { SignedTransaction } from '@algorandfoundation/algokit-transact' import type { ModelMetadata } from '../core/model-runtime' +import type { SignedTransaction } from '@algorandfoundation/algokit-transact' import type { AccountStateDelta } from './account-state-delta' import { AccountStateDeltaMeta } from './account-state-delta' import type { StateDelta } from './state-delta' diff --git a/packages/algod_client/src/models/signed-txn-in-block.ts b/packages/algod_client/src/models/signed-txn-in-block.ts index 7bf5f9b90..2ac4b30e6 100644 --- a/packages/algod_client/src/models/signed-txn-in-block.ts +++ b/packages/algod_client/src/models/signed-txn-in-block.ts @@ -8,10 +8,10 @@ * Generated by: Rust OpenAPI Generator */ -import type { SignedTransaction } from '@algorandfoundation/algokit-transact' import type { ModelMetadata } from '../core/model-runtime' -import { getModelMeta, registerModelMeta } from '../core/model-runtime' +import type { SignedTransaction } from '@algorandfoundation/algokit-transact' import type { BlockAppEvalDelta } from './block-app-eval-delta' +import { getModelMeta, registerModelMeta } from '../core/model-runtime' /** * SignedTxnInBlock is a SignedTransaction with additional ApplyData and block-specific metadata. diff --git a/packages/algod_client/src/models/simulate-request-transaction-group.ts b/packages/algod_client/src/models/simulate-request-transaction-group.ts index bab4288d5..e66bad79f 100644 --- a/packages/algod_client/src/models/simulate-request-transaction-group.ts +++ b/packages/algod_client/src/models/simulate-request-transaction-group.ts @@ -1,5 +1,5 @@ -import type { SignedTransaction } from '@algorandfoundation/algokit-transact' import type { ModelMetadata } from '../core/model-runtime' +import type { SignedTransaction } from '@algorandfoundation/algokit-transact' /** * A transaction group to simulate. diff --git a/packages/algod_client/src/models/wait-for-block.ts b/packages/algod_client/src/models/wait-for-block.ts index 7b8458eff..51984e5a4 100644 --- a/packages/algod_client/src/models/wait-for-block.ts +++ b/packages/algod_client/src/models/wait-for-block.ts @@ -107,22 +107,22 @@ export type WaitForBlock = { /** * Yes votes required for consensus upgrade */ - upgradeVotesRequired?: bigint + upgradeVotesRequired?: number /** * Total votes cast for consensus upgrade */ - upgradeVotes?: bigint + upgradeVotes?: number /** * Yes votes cast for consensus upgrade */ - upgradeYesVotes?: bigint + upgradeYesVotes?: number /** * No votes cast for consensus upgrade */ - upgradeNoVotes?: bigint + upgradeNoVotes?: number /** * Next protocol round @@ -132,7 +132,7 @@ export type WaitForBlock = { /** * Total voting rounds for current upgrade */ - upgradeVoteRounds?: bigint + upgradeVoteRounds?: number } export const WaitForBlockMeta: ModelMetadata = { @@ -172,7 +172,7 @@ export const WaitForBlockMeta: ModelMetadata = { wireKey: 'next-version-round', optional: false, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'nextVersionSupported', @@ -270,7 +270,7 @@ export const WaitForBlockMeta: ModelMetadata = { wireKey: 'upgrade-delay', optional: true, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'upgradeNodeVote', @@ -312,7 +312,7 @@ export const WaitForBlockMeta: ModelMetadata = { wireKey: 'upgrade-next-protocol-vote-before', optional: true, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'upgradeVoteRounds', diff --git a/tsconfig.base.json b/tsconfig.base.json index 08685cb1d..ad96180ce 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -4,7 +4,7 @@ "target": "ES2022", "moduleResolution": "Bundler", "esModuleInterop": true, - "lib": ["es2023"], + "lib": ["es2020", "dom"], "types": ["node"], "declaration": true, "importHelpers": true, diff --git a/tsconfig.json b/tsconfig.json index 17de74364..f6b25f169 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,6 +5,7 @@ "target": "ES2020", "moduleResolution": "Bundler", "esModuleInterop": true, + "lib": ["es2020", "dom"], "types": ["node"], "outDir": "dist", "declaration": true, From 0d779b710a311be7cea1d1d43ce269a0e22f9e26 Mon Sep 17 00:00:00 2001 From: Neil Campbell Date: Sat, 1 Nov 2025 00:57:53 +0800 Subject: [PATCH 03/10] feat: add indexer and kmd client generation support --- package.json | 5 +- .../indexer_client/src/apis/api.service.ts | 4 +- packages/indexer_client/src/client.ts | 4 +- .../indexer_client/src/core/client-config.ts | 8 + packages/indexer_client/src/core/codecs.ts | 42 +++- .../src/core/fetch-http-request.ts | 114 ++++++++- .../indexer_client/src/core/model-runtime.ts | 6 +- packages/indexer_client/src/core/request.ts | 10 +- packages/indexer_client/src/index.ts | 10 +- packages/indexer_client/src/models/index.ts | 232 +++++++++--------- packages/kmd_client/src/apis/api.service.ts | 4 +- packages/kmd_client/src/client.ts | 4 +- packages/kmd_client/src/core/client-config.ts | 8 + packages/kmd_client/src/core/codecs.ts | 42 +++- .../kmd_client/src/core/fetch-http-request.ts | 114 ++++++++- packages/kmd_client/src/core/model-runtime.ts | 6 +- packages/kmd_client/src/core/request.ts | 10 +- packages/kmd_client/src/index.ts | 10 +- packages/kmd_client/src/models/index.ts | 158 ++++++------ 19 files changed, 545 insertions(+), 246 deletions(-) diff --git a/package.json b/package.json index 104ae5688..ed5631d4b 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,10 @@ "semantic-release": "semantic-release", "generate:code-docs": "typedoc", "pre-commit": "run-s check-types lint:fix audit format test generate:code-docs && npm run pre-commit --workspaces --if-present", - "generate:algod": "cd oas-generator && uv run oas-generator ../algokit-configs/openapi-converter/specs/algod.oas3.json --output ../packages/algod_client/ --package-name algod_client --description \"TypeScript client for algod interaction.\" --verbose && prettier --write ../packages/algod_client/src/ && cd .." + "generate:clients": "run-s generate:client-*", + "generate:client-algod": "cd oas-generator && uv run oas-generator ../algokit-configs/openapi-converter/specs/algod.oas3.json --output ../packages/algod_client/ --package-name algod_client --description \"TypeScript client for algod interaction.\" --verbose && prettier --write ../packages/algod_client/src/ && cd ..", + "generate:client-indexer": "cd oas-generator && uv run oas-generator ../algokit-configs/openapi-converter/specs/indexer.oas3.json --output ../packages/indexer_client/ --package-name indexer_client --description \"TypeScript client for indexer interaction.\" --verbose && prettier --write ../packages/indexer_client/src/ && cd ..", + "generate:client-kmd": "cd oas-generator && uv run oas-generator ../algokit-configs/openapi-converter/specs/kmd.oas3.json --output ../packages/kmd_client/ --package-name kmd_client --description \"TypeScript client for kmd interaction.\" --verbose && prettier --write ../packages/kmd_client/src/ && cd .." }, "overrides": { "esbuild": "0.25.0" diff --git a/packages/indexer_client/src/apis/api.service.ts b/packages/indexer_client/src/apis/api.service.ts index d7714fb58..14b1493fc 100644 --- a/packages/indexer_client/src/apis/api.service.ts +++ b/packages/indexer_client/src/apis/api.service.ts @@ -1,6 +1,6 @@ -import type { ApiRequestOptions, BaseHttpRequest } from '../core/base-http-request' -import type { BodyFormat } from '../core/model-runtime' +import type { BaseHttpRequest, ApiRequestOptions } from '../core/base-http-request' import { AlgorandSerializer } from '../core/model-runtime' +import type { BodyFormat } from '../core/model-runtime' import type { Block, Box, diff --git a/packages/indexer_client/src/client.ts b/packages/indexer_client/src/client.ts index a33ab2634..feda9e609 100644 --- a/packages/indexer_client/src/client.ts +++ b/packages/indexer_client/src/client.ts @@ -1,7 +1,7 @@ -import { IndexerApi } from './apis/api.service' -import type { BaseHttpRequest } from './core/base-http-request' import type { ClientConfig } from './core/client-config' +import type { BaseHttpRequest } from './core/base-http-request' import { FetchHttpRequest } from './core/fetch-http-request' +import { IndexerApi } from './apis/api.service' export class IndexerClient extends IndexerApi { constructor(config: ClientConfig, request?: BaseHttpRequest) { diff --git a/packages/indexer_client/src/core/client-config.ts b/packages/indexer_client/src/core/client-config.ts index 9f3a1a5de..fb2466a3a 100644 --- a/packages/indexer_client/src/core/client-config.ts +++ b/packages/indexer_client/src/core/client-config.ts @@ -11,4 +11,12 @@ export interface ClientConfig { password?: string headers?: Record | (() => Record | Promise>) encodePath?: (path: string) => string + /** Optional override for retry attempts; values <= 1 disable retries. This is the canonical field. */ + maxRetries?: number + /** Optional cap on exponential backoff delay in milliseconds. */ + maxBackoffMs?: number + /** Optional list of HTTP status codes that should trigger a retry. */ + retryStatusCodes?: number[] + /** Optional list of Node.js/System error codes that should trigger a retry. */ + retryErrorCodes?: string[] } diff --git a/packages/indexer_client/src/core/codecs.ts b/packages/indexer_client/src/core/codecs.ts index 1f2f35aeb..9215f7e64 100644 --- a/packages/indexer_client/src/core/codecs.ts +++ b/packages/indexer_client/src/core/codecs.ts @@ -1,12 +1,42 @@ import { decode as msgpackDecode, encode as msgpackEncode } from 'algorand-msgpack' -export function encodeMsgPack(value: unknown): Uint8Array { - return msgpackEncode(value, { - sortKeys: true, - ignoreUndefined: true, - }) +export function encodeMsgPack(data: T): Uint8Array { + return new Uint8Array(msgpackEncode(data, { sortKeys: true, ignoreUndefined: true })) } export function decodeMsgPack(buffer: Uint8Array): T { - return msgpackDecode(buffer, { useBigInt64: true }) as T + const map = msgpackDecode(buffer, { useMap: true }) as unknown + return mapToObject(map) as T +} + +/** + * Converts a Map structure from msgpack decoding to a plain object structure. + * Maps are converted to objects recursively, except for the special case + * where the field name is "r" which remains as a Map. + */ +export function mapToObject(value: unknown, fieldName?: string): unknown { + // Preserve Uint8Array as-is + if (value instanceof Uint8Array) { + return value + } else if (value instanceof Map) { + // Special case: keep "r" field as Map + if (fieldName === 'r') { + const newMap = new Map() + for (const [k, v] of value.entries()) { + newMap.set(k, mapToObject(v)) + } + return newMap + } + + // Convert Map to object + const obj: Record = {} + for (const [k, v] of value.entries()) { + obj[k] = mapToObject(v, k) + } + return obj + } else if (Array.isArray(value)) { + return value.map((item) => mapToObject(item)) + } + + return value } diff --git a/packages/indexer_client/src/core/fetch-http-request.ts b/packages/indexer_client/src/core/fetch-http-request.ts index d57c1e667..9286bd076 100644 --- a/packages/indexer_client/src/core/fetch-http-request.ts +++ b/packages/indexer_client/src/core/fetch-http-request.ts @@ -1,8 +1,120 @@ import { BaseHttpRequest, type ApiRequestOptions } from './base-http-request' import { request } from './request' +const RETRY_STATUS_CODES = [408, 413, 429, 500, 502, 503, 504] +const RETRY_ERROR_CODES = [ + 'ETIMEDOUT', + 'ECONNRESET', + 'EADDRINUSE', + 'ECONNREFUSED', + 'EPIPE', + 'ENOTFOUND', + 'ENETUNREACH', + 'EAI_AGAIN', + 'EPROTO', +] + +const DEFAULT_MAX_TRIES = 5 +const DEFAULT_MAX_BACKOFF_MS = 10_000 + +const toNumber = (value: unknown): number | undefined => { + if (typeof value === 'number') { + return Number.isNaN(value) ? undefined : value + } + if (typeof value === 'string') { + const parsed = Number(value) + return Number.isNaN(parsed) ? undefined : parsed + } + return undefined +} + +const extractStatus = (error: unknown): number | undefined => { + if (!error || typeof error !== 'object') { + return undefined + } + const candidate = error as { status?: unknown; response?: { status?: unknown } } + return toNumber(candidate.status ?? candidate.response?.status) +} + +const extractCode = (error: unknown): string | undefined => { + if (!error || typeof error !== 'object') { + return undefined + } + const candidate = error as { code?: unknown; cause?: { code?: unknown } } + const raw = candidate.code ?? candidate.cause?.code + return typeof raw === 'string' ? raw : undefined +} + +const delay = async (ms: number): Promise => + new Promise((resolve) => { + setTimeout(resolve, ms) + }) + +const normalizeTries = (maxRetries?: number): number => { + const candidate = maxRetries + if (typeof candidate !== 'number' || !Number.isFinite(candidate)) { + return DEFAULT_MAX_TRIES + } + const rounded = Math.floor(candidate) + return rounded <= 1 ? 1 : rounded +} + +const normalizeBackoff = (maxBackoffMs?: number): number => { + if (typeof maxBackoffMs !== 'number' || !Number.isFinite(maxBackoffMs)) { + return DEFAULT_MAX_BACKOFF_MS + } + const normalized = Math.floor(maxBackoffMs) + return normalized <= 0 ? 0 : normalized +} + export class FetchHttpRequest extends BaseHttpRequest { async request(options: ApiRequestOptions): Promise { - return request(this.config, options) + const maxTries = normalizeTries(this.config.maxRetries) + const maxBackoffMs = normalizeBackoff(this.config.maxBackoffMs) + + let attempt = 1 + let lastError: unknown + while (attempt <= maxTries) { + try { + return await request(this.config, options) + } catch (error) { + lastError = error + if (!this.shouldRetry(error, attempt, maxTries)) { + throw error + } + + const backoff = attempt === 1 ? 0 : Math.min(1000 * 2 ** (attempt - 1), maxBackoffMs) + if (backoff > 0) { + await delay(backoff) + } + attempt += 1 + } + } + + throw lastError ?? new Error(`Request failed after ${maxTries} attempt(s)`) + } + + private shouldRetry(error: unknown, attempt: number, maxTries: number): boolean { + if (attempt >= maxTries) { + return false + } + + const status = extractStatus(error) + if (status !== undefined) { + const retryStatuses = this.config.retryStatusCodes ?? RETRY_STATUS_CODES + if (retryStatuses.includes(status)) { + return true + } + } + + const code = extractCode(error) + if (code) { + const retryCodes = this.config.retryErrorCodes ?? RETRY_ERROR_CODES + if (retryCodes.includes(code)) { + return true + } + } + + return false } } diff --git a/packages/indexer_client/src/core/model-runtime.ts b/packages/indexer_client/src/core/model-runtime.ts index 64440074b..eecaf8bb8 100644 --- a/packages/indexer_client/src/core/model-runtime.ts +++ b/packages/indexer_client/src/core/model-runtime.ts @@ -1,10 +1,10 @@ import { - decodeSignedTransaction as transactDecodeSignedTransaction, encodeSignedTransaction as transactEncodeSignedTransaction, + decodeSignedTransaction as transactDecodeSignedTransaction, type SignedTransaction, } from '@algorandfoundation/algokit-transact' -import { decodeMsgPack, encodeMsgPack } from './codecs' -import { fromBase64, toBase64 } from './serialization' +import { encodeMsgPack, decodeMsgPack } from './codecs' +import { toBase64, fromBase64 } from './serialization' export type BodyFormat = 'json' | 'msgpack' diff --git a/packages/indexer_client/src/core/request.ts b/packages/indexer_client/src/core/request.ts index b9d5fdc9d..a8a88eff4 100644 --- a/packages/indexer_client/src/core/request.ts +++ b/packages/indexer_client/src/core/request.ts @@ -1,9 +1,7 @@ -import { ApiError } from './api-error' -import type { BodyValue, QueryParams } from './base-http-request' import type { ClientConfig } from './client-config' +import { ApiError } from './api-error' import { decodeMsgPack, encodeMsgPack } from './codecs' - -type BodyInit = string | Uint8Array +import type { QueryParams, BodyValue } from './base-http-request' const encodeURIPath = (path: string): string => encodeURI(path).replace(/%5B/g, '[').replace(/%5D/g, ']') @@ -63,11 +61,11 @@ export async function request( let bodyPayload: BodyInit | undefined = undefined if (options.body != null) { if (options.body instanceof Uint8Array) { - bodyPayload = options.body + bodyPayload = options.body.slice().buffer } else if (typeof options.body === 'string') { bodyPayload = options.body } else if (options.mediaType?.includes('msgpack')) { - bodyPayload = encodeMsgPack(options.body) + bodyPayload = encodeMsgPack(options.body).slice().buffer } else if (options.mediaType?.includes('json')) { bodyPayload = JSON.stringify(options.body) } else { diff --git a/packages/indexer_client/src/index.ts b/packages/indexer_client/src/index.ts index eeced017a..915506d52 100644 --- a/packages/indexer_client/src/index.ts +++ b/packages/indexer_client/src/index.ts @@ -1,12 +1,12 @@ -export * from './core/api-error' -export * from './core/base-http-request' export * from './core/client-config' -export * from './core/codecs' +export * from './core/base-http-request' export * from './core/fetch-http-request' -export * from './core/model-runtime' +export * from './core/api-error' export * from './core/serialization' +export * from './core/codecs' +export * from './core/model-runtime' // Generated +export * from './models' export * from './apis' export * from './client' -export * from './models' diff --git a/packages/indexer_client/src/models/index.ts b/packages/indexer_client/src/models/index.ts index 2fc2e26b3..6bd24affe 100644 --- a/packages/indexer_client/src/models/index.ts +++ b/packages/indexer_client/src/models/index.ts @@ -1,150 +1,150 @@ -export { AccountMeta } from './account' +export type { Hashtype } from './hashtype' +export { HashtypeMeta } from './hashtype' export type { Account } from './account' -export { AccountParticipationMeta } from './account-participation' +export { AccountMeta } from './account' export type { AccountParticipation } from './account-participation' -export { AccountStateDeltaMeta } from './account-state-delta' -export type { AccountStateDelta } from './account-state-delta' -export { ApplicationMeta } from './application' -export type { Application } from './application' -export { ApplicationLocalStateMeta } from './application-local-state' +export { AccountParticipationMeta } from './account-participation' +export type { ApplicationStateSchema } from './application-state-schema' +export { ApplicationStateSchemaMeta } from './application-state-schema' export type { ApplicationLocalState } from './application-local-state' -export { ApplicationLogDataMeta } from './application-log-data' -export type { ApplicationLogData } from './application-log-data' -export { ApplicationParamsMeta } from './application-params' +export { ApplicationLocalStateMeta } from './application-local-state' +export type { TealKeyValueStore } from './teal-key-value-store' +export { TealKeyValueStoreMeta } from './teal-key-value-store' +export type { TealKeyValue } from './teal-key-value' +export { TealKeyValueMeta } from './teal-key-value' +export type { TealValue } from './teal-value' +export { TealValueMeta } from './teal-value' +export type { Application } from './application' +export { ApplicationMeta } from './application' export type { ApplicationParams } from './application-params' -export { ApplicationStateSchemaMeta } from './application-state-schema' -export type { ApplicationStateSchema } from './application-state-schema' -export { AssetMeta } from './asset' +export { ApplicationParamsMeta } from './application-params' +export type { ApplicationLogData } from './application-log-data' +export { ApplicationLogDataMeta } from './application-log-data' export type { Asset } from './asset' -export { AssetHoldingMeta } from './asset-holding' +export { AssetMeta } from './asset' export type { AssetHolding } from './asset-holding' -export { AssetParamsMeta } from './asset-params' +export { AssetHoldingMeta } from './asset-holding' export type { AssetParams } from './asset-params' -export { BlockMeta } from './block' +export { AssetParamsMeta } from './asset-params' export type { Block } from './block' -export { BlockRewardsMeta } from './block-rewards' +export { BlockMeta } from './block' export type { BlockRewards } from './block-rewards' -export { BlockUpgradeStateMeta } from './block-upgrade-state' +export { BlockRewardsMeta } from './block-rewards' export type { BlockUpgradeState } from './block-upgrade-state' -export { BlockUpgradeVoteMeta } from './block-upgrade-vote' +export { BlockUpgradeStateMeta } from './block-upgrade-state' export type { BlockUpgradeVote } from './block-upgrade-vote' -export { BoxMeta } from './box' +export { BlockUpgradeVoteMeta } from './block-upgrade-vote' export type { Box } from './box' -export { BoxDescriptorMeta } from './box-descriptor' +export { BoxMeta } from './box' export type { BoxDescriptor } from './box-descriptor' -export { BoxReferenceMeta } from './box-reference' +export { BoxDescriptorMeta } from './box-descriptor' export type { BoxReference } from './box-reference' -export { EvalDeltaMeta } from './eval-delta' -export type { EvalDelta } from './eval-delta' -export { EvalDeltaKeyValueMeta } from './eval-delta-key-value' -export type { EvalDeltaKeyValue } from './eval-delta-key-value' -export { HashFactoryMeta } from './hash-factory' -export type { HashFactory } from './hash-factory' -export { HashtypeMeta } from './hashtype' -export type { Hashtype } from './hashtype' -export { HbProofFieldsMeta } from './hb-proof-fields' -export type { HbProofFields } from './hb-proof-fields' -export { HealthCheckMeta } from './health-check' +export { BoxReferenceMeta } from './box-reference' export type { HealthCheck } from './health-check' -export { HoldingRefMeta } from './holding-ref' +export { HealthCheckMeta } from './health-check' export type { HoldingRef } from './holding-ref' -export { IndexerStateProofMessageMeta } from './indexer-state-proof-message' -export type { IndexerStateProofMessage } from './indexer-state-proof-message' -export { LocalsRefMeta } from './locals-ref' +export { HoldingRefMeta } from './holding-ref' export type { LocalsRef } from './locals-ref' -export { LookupAccountAppLocalStatesMeta } from './lookup-account-app-local-states' -export type { LookupAccountAppLocalStates } from './lookup-account-app-local-states' -export { LookupAccountAssetsMeta } from './lookup-account-assets' -export type { LookupAccountAssets } from './lookup-account-assets' -export { LookupAccountByIdMeta } from './lookup-account-by-id' -export type { LookupAccountById } from './lookup-account-by-id' -export { LookupAccountCreatedApplicationsMeta } from './lookup-account-created-applications' -export type { LookupAccountCreatedApplications } from './lookup-account-created-applications' -export { LookupAccountCreatedAssetsMeta } from './lookup-account-created-assets' -export type { LookupAccountCreatedAssets } from './lookup-account-created-assets' -export { LookupAccountTransactionsMeta } from './lookup-account-transactions' -export type { LookupAccountTransactions } from './lookup-account-transactions' -export { LookupApplicationByIdMeta } from './lookup-application-by-id' -export type { LookupApplicationById } from './lookup-application-by-id' -export { LookupApplicationLogsByIdMeta } from './lookup-application-logs-by-id' -export type { LookupApplicationLogsById } from './lookup-application-logs-by-id' -export { LookupAssetBalancesMeta } from './lookup-asset-balances' -export type { LookupAssetBalances } from './lookup-asset-balances' -export { LookupAssetByIdMeta } from './lookup-asset-by-id' -export type { LookupAssetById } from './lookup-asset-by-id' -export { LookupAssetTransactionsMeta } from './lookup-asset-transactions' -export type { LookupAssetTransactions } from './lookup-asset-transactions' -export { LookupTransactionMeta } from './lookup-transaction' -export type { LookupTransaction } from './lookup-transaction' -export { MerkleArrayProofMeta } from './merkle-array-proof' -export type { MerkleArrayProof } from './merkle-array-proof' -export { MiniAssetHoldingMeta } from './mini-asset-holding' +export { LocalsRefMeta } from './locals-ref' export type { MiniAssetHolding } from './mini-asset-holding' -export { OnCompletionMeta } from './on-completion' +export { MiniAssetHoldingMeta } from './mini-asset-holding' export type { OnCompletion } from './on-completion' -export { ParticipationUpdatesMeta } from './participation-updates' +export { OnCompletionMeta } from './on-completion' export type { ParticipationUpdates } from './participation-updates' -export { ResourceRefMeta } from './resource-ref' +export { ParticipationUpdatesMeta } from './participation-updates' export type { ResourceRef } from './resource-ref' -export { SearchForAccountsMeta } from './search-for-accounts' -export type { SearchForAccounts } from './search-for-accounts' -export { SearchForApplicationBoxesMeta } from './search-for-application-boxes' -export type { SearchForApplicationBoxes } from './search-for-application-boxes' -export { SearchForApplicationsMeta } from './search-for-applications' -export type { SearchForApplications } from './search-for-applications' -export { SearchForAssetsMeta } from './search-for-assets' -export type { SearchForAssets } from './search-for-assets' -export { SearchForBlockHeadersMeta } from './search-for-block-headers' -export type { SearchForBlockHeaders } from './search-for-block-headers' -export { SearchForTransactionsMeta } from './search-for-transactions' -export type { SearchForTransactions } from './search-for-transactions' -export { StateDeltaMeta } from './state-delta' +export { ResourceRefMeta } from './resource-ref' export type { StateDelta } from './state-delta' -export { StateProofFieldsMeta } from './state-proof-fields' -export type { StateProofFields } from './state-proof-fields' -export { StateProofParticipantMeta } from './state-proof-participant' -export type { StateProofParticipant } from './state-proof-participant' -export { StateProofRevealMeta } from './state-proof-reveal' -export type { StateProofReveal } from './state-proof-reveal' -export { StateProofSigSlotMeta } from './state-proof-sig-slot' -export type { StateProofSigSlot } from './state-proof-sig-slot' -export { StateProofSignatureMeta } from './state-proof-signature' -export type { StateProofSignature } from './state-proof-signature' -export { StateProofTrackingMeta } from './state-proof-tracking' -export type { StateProofTracking } from './state-proof-tracking' -export { StateProofVerifierMeta } from './state-proof-verifier' -export type { StateProofVerifier } from './state-proof-verifier' -export { StateSchemaMeta } from './state-schema' +export { StateDeltaMeta } from './state-delta' +export type { AccountStateDelta } from './account-state-delta' +export { AccountStateDeltaMeta } from './account-state-delta' +export type { EvalDeltaKeyValue } from './eval-delta-key-value' +export { EvalDeltaKeyValueMeta } from './eval-delta-key-value' +export type { EvalDelta } from './eval-delta' +export { EvalDeltaMeta } from './eval-delta' export type { StateSchema } from './state-schema' -export { TealKeyValueMeta } from './teal-key-value' -export type { TealKeyValue } from './teal-key-value' -export { TealKeyValueStoreMeta } from './teal-key-value-store' -export type { TealKeyValueStore } from './teal-key-value-store' -export { TealValueMeta } from './teal-value' -export type { TealValue } from './teal-value' -export { TransactionMeta } from './transaction' +export { StateSchemaMeta } from './state-schema' export type { Transaction } from './transaction' -export { TransactionApplicationMeta } from './transaction-application' +export { TransactionMeta } from './transaction' export type { TransactionApplication } from './transaction-application' -export { TransactionAssetConfigMeta } from './transaction-asset-config' +export { TransactionApplicationMeta } from './transaction-application' export type { TransactionAssetConfig } from './transaction-asset-config' -export { TransactionAssetFreezeMeta } from './transaction-asset-freeze' +export { TransactionAssetConfigMeta } from './transaction-asset-config' export type { TransactionAssetFreeze } from './transaction-asset-freeze' -export { TransactionAssetTransferMeta } from './transaction-asset-transfer' -export type { TransactionAssetTransfer } from './transaction-asset-transfer' -export { TransactionHeartbeatMeta } from './transaction-heartbeat' +export { TransactionAssetFreezeMeta } from './transaction-asset-freeze' +export type { TransactionStateProof } from './transaction-state-proof' +export { TransactionStateProofMeta } from './transaction-state-proof' export type { TransactionHeartbeat } from './transaction-heartbeat' -export { TransactionKeyregMeta } from './transaction-keyreg' +export { TransactionHeartbeatMeta } from './transaction-heartbeat' +export type { TransactionAssetTransfer } from './transaction-asset-transfer' +export { TransactionAssetTransferMeta } from './transaction-asset-transfer' export type { TransactionKeyreg } from './transaction-keyreg' -export { TransactionPaymentMeta } from './transaction-payment' +export { TransactionKeyregMeta } from './transaction-keyreg' export type { TransactionPayment } from './transaction-payment' -export { TransactionSignatureMeta } from './transaction-signature' +export { TransactionPaymentMeta } from './transaction-payment' export type { TransactionSignature } from './transaction-signature' -export { TransactionSignatureLogicsigMeta } from './transaction-signature-logicsig' +export { TransactionSignatureMeta } from './transaction-signature' export type { TransactionSignatureLogicsig } from './transaction-signature-logicsig' -export { TransactionSignatureMultisigMeta } from './transaction-signature-multisig' +export { TransactionSignatureLogicsigMeta } from './transaction-signature-logicsig' export type { TransactionSignatureMultisig } from './transaction-signature-multisig' -export { TransactionSignatureMultisigSubsignatureMeta } from './transaction-signature-multisig-subsignature' +export { TransactionSignatureMultisigMeta } from './transaction-signature-multisig' export type { TransactionSignatureMultisigSubsignature } from './transaction-signature-multisig-subsignature' -export { TransactionStateProofMeta } from './transaction-state-proof' -export type { TransactionStateProof } from './transaction-state-proof' +export { TransactionSignatureMultisigSubsignatureMeta } from './transaction-signature-multisig-subsignature' +export type { StateProofFields } from './state-proof-fields' +export { StateProofFieldsMeta } from './state-proof-fields' +export type { HbProofFields } from './hb-proof-fields' +export { HbProofFieldsMeta } from './hb-proof-fields' +export type { IndexerStateProofMessage } from './indexer-state-proof-message' +export { IndexerStateProofMessageMeta } from './indexer-state-proof-message' +export type { StateProofReveal } from './state-proof-reveal' +export { StateProofRevealMeta } from './state-proof-reveal' +export type { StateProofSigSlot } from './state-proof-sig-slot' +export { StateProofSigSlotMeta } from './state-proof-sig-slot' +export type { StateProofSignature } from './state-proof-signature' +export { StateProofSignatureMeta } from './state-proof-signature' +export type { StateProofParticipant } from './state-proof-participant' +export { StateProofParticipantMeta } from './state-proof-participant' +export type { StateProofVerifier } from './state-proof-verifier' +export { StateProofVerifierMeta } from './state-proof-verifier' +export type { StateProofTracking } from './state-proof-tracking' +export { StateProofTrackingMeta } from './state-proof-tracking' +export type { MerkleArrayProof } from './merkle-array-proof' +export { MerkleArrayProofMeta } from './merkle-array-proof' +export type { HashFactory } from './hash-factory' +export { HashFactoryMeta } from './hash-factory' +export type { SearchForAccounts } from './search-for-accounts' +export { SearchForAccountsMeta } from './search-for-accounts' +export type { LookupAccountById } from './lookup-account-by-id' +export { LookupAccountByIdMeta } from './lookup-account-by-id' +export type { LookupAccountAssets } from './lookup-account-assets' +export { LookupAccountAssetsMeta } from './lookup-account-assets' +export type { LookupAccountCreatedAssets } from './lookup-account-created-assets' +export { LookupAccountCreatedAssetsMeta } from './lookup-account-created-assets' +export type { LookupAccountAppLocalStates } from './lookup-account-app-local-states' +export { LookupAccountAppLocalStatesMeta } from './lookup-account-app-local-states' +export type { LookupAccountCreatedApplications } from './lookup-account-created-applications' +export { LookupAccountCreatedApplicationsMeta } from './lookup-account-created-applications' +export type { LookupAccountTransactions } from './lookup-account-transactions' +export { LookupAccountTransactionsMeta } from './lookup-account-transactions' +export type { SearchForApplications } from './search-for-applications' +export { SearchForApplicationsMeta } from './search-for-applications' +export type { LookupApplicationById } from './lookup-application-by-id' +export { LookupApplicationByIdMeta } from './lookup-application-by-id' +export type { SearchForApplicationBoxes } from './search-for-application-boxes' +export { SearchForApplicationBoxesMeta } from './search-for-application-boxes' +export type { LookupApplicationLogsById } from './lookup-application-logs-by-id' +export { LookupApplicationLogsByIdMeta } from './lookup-application-logs-by-id' +export type { SearchForAssets } from './search-for-assets' +export { SearchForAssetsMeta } from './search-for-assets' +export type { LookupAssetById } from './lookup-asset-by-id' +export { LookupAssetByIdMeta } from './lookup-asset-by-id' +export type { LookupAssetBalances } from './lookup-asset-balances' +export { LookupAssetBalancesMeta } from './lookup-asset-balances' +export type { LookupAssetTransactions } from './lookup-asset-transactions' +export { LookupAssetTransactionsMeta } from './lookup-asset-transactions' +export type { SearchForBlockHeaders } from './search-for-block-headers' +export { SearchForBlockHeadersMeta } from './search-for-block-headers' +export type { LookupTransaction } from './lookup-transaction' +export { LookupTransactionMeta } from './lookup-transaction' +export type { SearchForTransactions } from './search-for-transactions' +export { SearchForTransactionsMeta } from './search-for-transactions' diff --git a/packages/kmd_client/src/apis/api.service.ts b/packages/kmd_client/src/apis/api.service.ts index 682e82083..56e104c63 100644 --- a/packages/kmd_client/src/apis/api.service.ts +++ b/packages/kmd_client/src/apis/api.service.ts @@ -1,6 +1,6 @@ -import type { ApiRequestOptions, BaseHttpRequest } from '../core/base-http-request' -import type { BodyFormat } from '../core/model-runtime' +import type { BaseHttpRequest, ApiRequestOptions } from '../core/base-http-request' import { AlgorandSerializer } from '../core/model-runtime' +import type { BodyFormat } from '../core/model-runtime' import type { CreateWalletRequest, DeleteKeyResponse, diff --git a/packages/kmd_client/src/client.ts b/packages/kmd_client/src/client.ts index aaaaba649..1f00fe25d 100644 --- a/packages/kmd_client/src/client.ts +++ b/packages/kmd_client/src/client.ts @@ -1,7 +1,7 @@ -import { KmdApi } from './apis/api.service' -import type { BaseHttpRequest } from './core/base-http-request' import type { ClientConfig } from './core/client-config' +import type { BaseHttpRequest } from './core/base-http-request' import { FetchHttpRequest } from './core/fetch-http-request' +import { KmdApi } from './apis/api.service' export class KmdClient extends KmdApi { constructor(config: ClientConfig, request?: BaseHttpRequest) { diff --git a/packages/kmd_client/src/core/client-config.ts b/packages/kmd_client/src/core/client-config.ts index 9f3a1a5de..fb2466a3a 100644 --- a/packages/kmd_client/src/core/client-config.ts +++ b/packages/kmd_client/src/core/client-config.ts @@ -11,4 +11,12 @@ export interface ClientConfig { password?: string headers?: Record | (() => Record | Promise>) encodePath?: (path: string) => string + /** Optional override for retry attempts; values <= 1 disable retries. This is the canonical field. */ + maxRetries?: number + /** Optional cap on exponential backoff delay in milliseconds. */ + maxBackoffMs?: number + /** Optional list of HTTP status codes that should trigger a retry. */ + retryStatusCodes?: number[] + /** Optional list of Node.js/System error codes that should trigger a retry. */ + retryErrorCodes?: string[] } diff --git a/packages/kmd_client/src/core/codecs.ts b/packages/kmd_client/src/core/codecs.ts index 1f2f35aeb..9215f7e64 100644 --- a/packages/kmd_client/src/core/codecs.ts +++ b/packages/kmd_client/src/core/codecs.ts @@ -1,12 +1,42 @@ import { decode as msgpackDecode, encode as msgpackEncode } from 'algorand-msgpack' -export function encodeMsgPack(value: unknown): Uint8Array { - return msgpackEncode(value, { - sortKeys: true, - ignoreUndefined: true, - }) +export function encodeMsgPack(data: T): Uint8Array { + return new Uint8Array(msgpackEncode(data, { sortKeys: true, ignoreUndefined: true })) } export function decodeMsgPack(buffer: Uint8Array): T { - return msgpackDecode(buffer, { useBigInt64: true }) as T + const map = msgpackDecode(buffer, { useMap: true }) as unknown + return mapToObject(map) as T +} + +/** + * Converts a Map structure from msgpack decoding to a plain object structure. + * Maps are converted to objects recursively, except for the special case + * where the field name is "r" which remains as a Map. + */ +export function mapToObject(value: unknown, fieldName?: string): unknown { + // Preserve Uint8Array as-is + if (value instanceof Uint8Array) { + return value + } else if (value instanceof Map) { + // Special case: keep "r" field as Map + if (fieldName === 'r') { + const newMap = new Map() + for (const [k, v] of value.entries()) { + newMap.set(k, mapToObject(v)) + } + return newMap + } + + // Convert Map to object + const obj: Record = {} + for (const [k, v] of value.entries()) { + obj[k] = mapToObject(v, k) + } + return obj + } else if (Array.isArray(value)) { + return value.map((item) => mapToObject(item)) + } + + return value } diff --git a/packages/kmd_client/src/core/fetch-http-request.ts b/packages/kmd_client/src/core/fetch-http-request.ts index d57c1e667..9286bd076 100644 --- a/packages/kmd_client/src/core/fetch-http-request.ts +++ b/packages/kmd_client/src/core/fetch-http-request.ts @@ -1,8 +1,120 @@ import { BaseHttpRequest, type ApiRequestOptions } from './base-http-request' import { request } from './request' +const RETRY_STATUS_CODES = [408, 413, 429, 500, 502, 503, 504] +const RETRY_ERROR_CODES = [ + 'ETIMEDOUT', + 'ECONNRESET', + 'EADDRINUSE', + 'ECONNREFUSED', + 'EPIPE', + 'ENOTFOUND', + 'ENETUNREACH', + 'EAI_AGAIN', + 'EPROTO', +] + +const DEFAULT_MAX_TRIES = 5 +const DEFAULT_MAX_BACKOFF_MS = 10_000 + +const toNumber = (value: unknown): number | undefined => { + if (typeof value === 'number') { + return Number.isNaN(value) ? undefined : value + } + if (typeof value === 'string') { + const parsed = Number(value) + return Number.isNaN(parsed) ? undefined : parsed + } + return undefined +} + +const extractStatus = (error: unknown): number | undefined => { + if (!error || typeof error !== 'object') { + return undefined + } + const candidate = error as { status?: unknown; response?: { status?: unknown } } + return toNumber(candidate.status ?? candidate.response?.status) +} + +const extractCode = (error: unknown): string | undefined => { + if (!error || typeof error !== 'object') { + return undefined + } + const candidate = error as { code?: unknown; cause?: { code?: unknown } } + const raw = candidate.code ?? candidate.cause?.code + return typeof raw === 'string' ? raw : undefined +} + +const delay = async (ms: number): Promise => + new Promise((resolve) => { + setTimeout(resolve, ms) + }) + +const normalizeTries = (maxRetries?: number): number => { + const candidate = maxRetries + if (typeof candidate !== 'number' || !Number.isFinite(candidate)) { + return DEFAULT_MAX_TRIES + } + const rounded = Math.floor(candidate) + return rounded <= 1 ? 1 : rounded +} + +const normalizeBackoff = (maxBackoffMs?: number): number => { + if (typeof maxBackoffMs !== 'number' || !Number.isFinite(maxBackoffMs)) { + return DEFAULT_MAX_BACKOFF_MS + } + const normalized = Math.floor(maxBackoffMs) + return normalized <= 0 ? 0 : normalized +} + export class FetchHttpRequest extends BaseHttpRequest { async request(options: ApiRequestOptions): Promise { - return request(this.config, options) + const maxTries = normalizeTries(this.config.maxRetries) + const maxBackoffMs = normalizeBackoff(this.config.maxBackoffMs) + + let attempt = 1 + let lastError: unknown + while (attempt <= maxTries) { + try { + return await request(this.config, options) + } catch (error) { + lastError = error + if (!this.shouldRetry(error, attempt, maxTries)) { + throw error + } + + const backoff = attempt === 1 ? 0 : Math.min(1000 * 2 ** (attempt - 1), maxBackoffMs) + if (backoff > 0) { + await delay(backoff) + } + attempt += 1 + } + } + + throw lastError ?? new Error(`Request failed after ${maxTries} attempt(s)`) + } + + private shouldRetry(error: unknown, attempt: number, maxTries: number): boolean { + if (attempt >= maxTries) { + return false + } + + const status = extractStatus(error) + if (status !== undefined) { + const retryStatuses = this.config.retryStatusCodes ?? RETRY_STATUS_CODES + if (retryStatuses.includes(status)) { + return true + } + } + + const code = extractCode(error) + if (code) { + const retryCodes = this.config.retryErrorCodes ?? RETRY_ERROR_CODES + if (retryCodes.includes(code)) { + return true + } + } + + return false } } diff --git a/packages/kmd_client/src/core/model-runtime.ts b/packages/kmd_client/src/core/model-runtime.ts index 64440074b..eecaf8bb8 100644 --- a/packages/kmd_client/src/core/model-runtime.ts +++ b/packages/kmd_client/src/core/model-runtime.ts @@ -1,10 +1,10 @@ import { - decodeSignedTransaction as transactDecodeSignedTransaction, encodeSignedTransaction as transactEncodeSignedTransaction, + decodeSignedTransaction as transactDecodeSignedTransaction, type SignedTransaction, } from '@algorandfoundation/algokit-transact' -import { decodeMsgPack, encodeMsgPack } from './codecs' -import { fromBase64, toBase64 } from './serialization' +import { encodeMsgPack, decodeMsgPack } from './codecs' +import { toBase64, fromBase64 } from './serialization' export type BodyFormat = 'json' | 'msgpack' diff --git a/packages/kmd_client/src/core/request.ts b/packages/kmd_client/src/core/request.ts index ae89897f1..706e60f7d 100644 --- a/packages/kmd_client/src/core/request.ts +++ b/packages/kmd_client/src/core/request.ts @@ -1,9 +1,7 @@ -import { ApiError } from './api-error' -import type { BodyValue, QueryParams } from './base-http-request' import type { ClientConfig } from './client-config' +import { ApiError } from './api-error' import { decodeMsgPack, encodeMsgPack } from './codecs' - -type BodyInit = string | Uint8Array +import type { QueryParams, BodyValue } from './base-http-request' const encodeURIPath = (path: string): string => encodeURI(path).replace(/%5B/g, '[').replace(/%5D/g, ']') @@ -63,11 +61,11 @@ export async function request( let bodyPayload: BodyInit | undefined = undefined if (options.body != null) { if (options.body instanceof Uint8Array) { - bodyPayload = options.body + bodyPayload = options.body.slice().buffer } else if (typeof options.body === 'string') { bodyPayload = options.body } else if (options.mediaType?.includes('msgpack')) { - bodyPayload = encodeMsgPack(options.body) + bodyPayload = encodeMsgPack(options.body).slice().buffer } else if (options.mediaType?.includes('json')) { bodyPayload = JSON.stringify(options.body) } else { diff --git a/packages/kmd_client/src/index.ts b/packages/kmd_client/src/index.ts index eeced017a..915506d52 100644 --- a/packages/kmd_client/src/index.ts +++ b/packages/kmd_client/src/index.ts @@ -1,12 +1,12 @@ -export * from './core/api-error' -export * from './core/base-http-request' export * from './core/client-config' -export * from './core/codecs' +export * from './core/base-http-request' export * from './core/fetch-http-request' -export * from './core/model-runtime' +export * from './core/api-error' export * from './core/serialization' +export * from './core/codecs' +export * from './core/model-runtime' // Generated +export * from './models' export * from './apis' export * from './client' -export * from './models' diff --git a/packages/kmd_client/src/models/index.ts b/packages/kmd_client/src/models/index.ts index 7105f6b12..2fb35b4c0 100644 --- a/packages/kmd_client/src/models/index.ts +++ b/packages/kmd_client/src/models/index.ts @@ -1,114 +1,114 @@ -export { CreateWalletRequestMeta } from './create-wallet-request' -export type { CreateWalletRequest } from './create-wallet-request' -export { DeleteKeyRequestMeta } from './delete-key-request' -export type { DeleteKeyRequest } from './delete-key-request' -export { DeleteKeyResponseMeta } from './delete-key-response' export type { DeleteKeyResponse } from './delete-key-response' -export { DeleteMultisigRequestMeta } from './delete-multisig-request' -export type { DeleteMultisigRequest } from './delete-multisig-request' -export { DeleteMultisigResponseMeta } from './delete-multisig-response' +export { DeleteKeyResponseMeta } from './delete-key-response' export type { DeleteMultisigResponse } from './delete-multisig-response' -export { DigestMeta } from './digest' -export type { Digest } from './digest' -export { Ed25519PrivateKeyMeta } from './ed25519-private-key' -export type { Ed25519PrivateKey } from './ed25519-private-key' -export { Ed25519PublicKeyMeta } from './ed25519-public-key' -export type { Ed25519PublicKey } from './ed25519-public-key' -export { Ed25519SignatureMeta } from './ed25519-signature' -export type { Ed25519Signature } from './ed25519-signature' -export { ExportKeyRequestMeta } from './export-key-request' -export type { ExportKeyRequest } from './export-key-request' -export { ExportMasterKeyRequestMeta } from './export-master-key-request' -export type { ExportMasterKeyRequest } from './export-master-key-request' -export { ExportMultisigRequestMeta } from './export-multisig-request' -export type { ExportMultisigRequest } from './export-multisig-request' -export { GenerateKeyRequestMeta } from './generate-key-request' -export type { GenerateKeyRequest } from './generate-key-request' -export { GetWalletsResponseMeta } from './get-wallets-response' +export { DeleteMultisigResponseMeta } from './delete-multisig-response' export type { GetWalletsResponse } from './get-wallets-response' -export { ImportKeyRequestMeta } from './import-key-request' -export type { ImportKeyRequest } from './import-key-request' -export { ImportMultisigRequestMeta } from './import-multisig-request' -export type { ImportMultisigRequest } from './import-multisig-request' -export { InitWalletHandleTokenRequestMeta } from './init-wallet-handle-token-request' -export type { InitWalletHandleTokenRequest } from './init-wallet-handle-token-request' -export { ListKeysRequestMeta } from './list-keys-request' -export type { ListKeysRequest } from './list-keys-request' -export { ListMultisigRequestMeta } from './list-multisig-request' -export type { ListMultisigRequest } from './list-multisig-request' -export { ListWalletsRequestMeta } from './list-wallets-request' -export type { ListWalletsRequest } from './list-wallets-request' -export { MasterDerivationKeyMeta } from './master-derivation-key' -export type { MasterDerivationKey } from './master-derivation-key' -export { MultisigSigMeta } from './multisig-sig' -export type { MultisigSig } from './multisig-sig' -export { MultisigSubsigMeta } from './multisig-subsig' -export type { MultisigSubsig } from './multisig-subsig' -export { PostKeyExportResponseMeta } from './post-key-export-response' +export { GetWalletsResponseMeta } from './get-wallets-response' export type { PostKeyExportResponse } from './post-key-export-response' -export { PostKeyImportResponseMeta } from './post-key-import-response' +export { PostKeyExportResponseMeta } from './post-key-export-response' export type { PostKeyImportResponse } from './post-key-import-response' -export { PostKeyListResponseMeta } from './post-key-list-response' +export { PostKeyImportResponseMeta } from './post-key-import-response' export type { PostKeyListResponse } from './post-key-list-response' -export { PostKeyResponseMeta } from './post-key-response' +export { PostKeyListResponseMeta } from './post-key-list-response' export type { PostKeyResponse } from './post-key-response' -export { PostMasterKeyExportResponseMeta } from './post-master-key-export-response' +export { PostKeyResponseMeta } from './post-key-response' export type { PostMasterKeyExportResponse } from './post-master-key-export-response' -export { PostMultisigExportResponseMeta } from './post-multisig-export-response' +export { PostMasterKeyExportResponseMeta } from './post-master-key-export-response' export type { PostMultisigExportResponse } from './post-multisig-export-response' -export { PostMultisigImportResponseMeta } from './post-multisig-import-response' +export { PostMultisigExportResponseMeta } from './post-multisig-export-response' export type { PostMultisigImportResponse } from './post-multisig-import-response' -export { PostMultisigListResponseMeta } from './post-multisig-list-response' +export { PostMultisigImportResponseMeta } from './post-multisig-import-response' export type { PostMultisigListResponse } from './post-multisig-list-response' -export { PostMultisigProgramSignResponseMeta } from './post-multisig-program-sign-response' +export { PostMultisigListResponseMeta } from './post-multisig-list-response' export type { PostMultisigProgramSignResponse } from './post-multisig-program-sign-response' -export { PostMultisigTransactionSignResponseMeta } from './post-multisig-transaction-sign-response' +export { PostMultisigProgramSignResponseMeta } from './post-multisig-program-sign-response' export type { PostMultisigTransactionSignResponse } from './post-multisig-transaction-sign-response' -export { PostProgramSignResponseMeta } from './post-program-sign-response' +export { PostMultisigTransactionSignResponseMeta } from './post-multisig-transaction-sign-response' export type { PostProgramSignResponse } from './post-program-sign-response' -export { PostTransactionSignResponseMeta } from './post-transaction-sign-response' +export { PostProgramSignResponseMeta } from './post-program-sign-response' export type { PostTransactionSignResponse } from './post-transaction-sign-response' -export { PostWalletInfoResponseMeta } from './post-wallet-info-response' +export { PostTransactionSignResponseMeta } from './post-transaction-sign-response' export type { PostWalletInfoResponse } from './post-wallet-info-response' -export { PostWalletInitResponseMeta } from './post-wallet-init-response' +export { PostWalletInfoResponseMeta } from './post-wallet-info-response' export type { PostWalletInitResponse } from './post-wallet-init-response' -export { PostWalletReleaseResponseMeta } from './post-wallet-release-response' +export { PostWalletInitResponseMeta } from './post-wallet-init-response' export type { PostWalletReleaseResponse } from './post-wallet-release-response' -export { PostWalletRenameResponseMeta } from './post-wallet-rename-response' +export { PostWalletReleaseResponseMeta } from './post-wallet-release-response' export type { PostWalletRenameResponse } from './post-wallet-rename-response' -export { PostWalletRenewResponseMeta } from './post-wallet-renew-response' +export { PostWalletRenameResponseMeta } from './post-wallet-rename-response' export type { PostWalletRenewResponse } from './post-wallet-renew-response' -export { PostWalletResponseMeta } from './post-wallet-response' +export { PostWalletRenewResponseMeta } from './post-wallet-renew-response' export type { PostWalletResponse } from './post-wallet-response' -export { PrivateKeyMeta } from './private-key' +export { PostWalletResponseMeta } from './post-wallet-response' +export type { Wallet } from './wallet' +export { WalletMeta } from './wallet' +export type { WalletHandle } from './wallet-handle' +export { WalletHandleMeta } from './wallet-handle' +export type { CreateWalletRequest } from './create-wallet-request' +export { CreateWalletRequestMeta } from './create-wallet-request' +export type { DeleteKeyRequest } from './delete-key-request' +export { DeleteKeyRequestMeta } from './delete-key-request' +export type { DeleteMultisigRequest } from './delete-multisig-request' +export { DeleteMultisigRequestMeta } from './delete-multisig-request' +export type { Digest } from './digest' +export { DigestMeta } from './digest' +export type { ExportKeyRequest } from './export-key-request' +export { ExportKeyRequestMeta } from './export-key-request' +export type { ExportMasterKeyRequest } from './export-master-key-request' +export { ExportMasterKeyRequestMeta } from './export-master-key-request' +export type { ExportMultisigRequest } from './export-multisig-request' +export { ExportMultisigRequestMeta } from './export-multisig-request' +export type { GenerateKeyRequest } from './generate-key-request' +export { GenerateKeyRequestMeta } from './generate-key-request' +export type { ImportKeyRequest } from './import-key-request' +export { ImportKeyRequestMeta } from './import-key-request' +export type { ImportMultisigRequest } from './import-multisig-request' +export { ImportMultisigRequestMeta } from './import-multisig-request' +export type { InitWalletHandleTokenRequest } from './init-wallet-handle-token-request' +export { InitWalletHandleTokenRequestMeta } from './init-wallet-handle-token-request' +export type { ListKeysRequest } from './list-keys-request' +export { ListKeysRequestMeta } from './list-keys-request' +export type { ListMultisigRequest } from './list-multisig-request' +export { ListMultisigRequestMeta } from './list-multisig-request' +export type { ListWalletsRequest } from './list-wallets-request' +export { ListWalletsRequestMeta } from './list-wallets-request' +export type { MasterDerivationKey } from './master-derivation-key' +export { MasterDerivationKeyMeta } from './master-derivation-key' +export type { MultisigSig } from './multisig-sig' +export { MultisigSigMeta } from './multisig-sig' +export type { MultisigSubsig } from './multisig-subsig' +export { MultisigSubsigMeta } from './multisig-subsig' export type { PrivateKey } from './private-key' -export { PublicKeyMeta } from './public-key' +export { PrivateKeyMeta } from './private-key' export type { PublicKey } from './public-key' -export { ReleaseWalletHandleTokenRequestMeta } from './release-wallet-handle-token-request' +export { PublicKeyMeta } from './public-key' export type { ReleaseWalletHandleTokenRequest } from './release-wallet-handle-token-request' -export { RenameWalletRequestMeta } from './rename-wallet-request' +export { ReleaseWalletHandleTokenRequestMeta } from './release-wallet-handle-token-request' export type { RenameWalletRequest } from './rename-wallet-request' -export { RenewWalletHandleTokenRequestMeta } from './renew-wallet-handle-token-request' +export { RenameWalletRequestMeta } from './rename-wallet-request' export type { RenewWalletHandleTokenRequest } from './renew-wallet-handle-token-request' -export { SignMultisigRequestMeta } from './sign-multisig-request' +export { RenewWalletHandleTokenRequestMeta } from './renew-wallet-handle-token-request' export type { SignMultisigRequest } from './sign-multisig-request' -export { SignProgramMultisigRequestMeta } from './sign-program-multisig-request' +export { SignMultisigRequestMeta } from './sign-multisig-request' export type { SignProgramMultisigRequest } from './sign-program-multisig-request' -export { SignProgramRequestMeta } from './sign-program-request' +export { SignProgramMultisigRequestMeta } from './sign-program-multisig-request' export type { SignProgramRequest } from './sign-program-request' -export { SignTransactionRequestMeta } from './sign-transaction-request' +export { SignProgramRequestMeta } from './sign-program-request' export type { SignTransactionRequest } from './sign-transaction-request' -export { SignatureMeta } from './signature' +export { SignTransactionRequestMeta } from './sign-transaction-request' export type { Signature } from './signature' -export { TxTypeMeta } from './tx-type' +export { SignatureMeta } from './signature' export type { TxType } from './tx-type' -export { VersionsRequestMeta } from './versions-request' +export { TxTypeMeta } from './tx-type' export type { VersionsRequest } from './versions-request' -export { VersionsResponseMeta } from './versions-response' +export { VersionsRequestMeta } from './versions-request' export type { VersionsResponse } from './versions-response' -export { WalletMeta } from './wallet' -export type { Wallet } from './wallet' -export { WalletHandleMeta } from './wallet-handle' -export type { WalletHandle } from './wallet-handle' -export { WalletInfoRequestMeta } from './wallet-info-request' +export { VersionsResponseMeta } from './versions-response' export type { WalletInfoRequest } from './wallet-info-request' +export { WalletInfoRequestMeta } from './wallet-info-request' +export type { Ed25519PrivateKey } from './ed25519-private-key' +export { Ed25519PrivateKeyMeta } from './ed25519-private-key' +export type { Ed25519PublicKey } from './ed25519-public-key' +export { Ed25519PublicKeyMeta } from './ed25519-public-key' +export type { Ed25519Signature } from './ed25519-signature' +export { Ed25519SignatureMeta } from './ed25519-signature' From 60f5e9f567efdde1abf62c499677ba259b41b427 Mon Sep 17 00:00:00 2001 From: Neil Campbell Date: Sat, 1 Nov 2025 23:57:12 +0800 Subject: [PATCH 04/10] feat: add algod support for sendRawTransaction --- .../src/oas_generator/generator/models.py | 4 + .../generator/template_engine.py | 74 +++++++++++++++++++ .../templates/apis/service.ts.j2 | 13 +++- packages/algod_client/src/apis/api.service.ts | 46 +++++------- packages/sdk/src/composer.ts | 10 +-- src/testing/transaction-logger.ts | 20 +---- src/transaction/transaction.ts | 2 +- 7 files changed, 113 insertions(+), 56 deletions(-) diff --git a/oas-generator/src/oas_generator/generator/models.py b/oas-generator/src/oas_generator/generator/models.py index 7f73cc5c9..6992bf5a2 100644 --- a/oas-generator/src/oas_generator/generator/models.py +++ b/oas-generator/src/oas_generator/generator/models.py @@ -54,6 +54,8 @@ class OperationContext: # we don't expose it to callers but still need to set it implicitly on requests force_msgpack_query: bool = False error_types: list[ErrorDescriptor] | None = None + is_private: bool = False + skip_generation: bool = False def to_dict(self) -> dict[str, Any]: """Convert to dictionary for template rendering.""" @@ -72,6 +74,8 @@ def to_dict(self) -> dict[str, Any]: "formatVarName": self.format_var_name, "forceMsgpackQuery": self.force_msgpack_query, "errorTypes": [self._error_to_dict(e) for e in (self.error_types or [])], + "isPrivate": self.is_private, + "skipGeneration": self.skip_generation, } @staticmethod diff --git a/oas-generator/src/oas_generator/generator/template_engine.py b/oas-generator/src/oas_generator/generator/template_engine.py index efef27810..74d492e44 100644 --- a/oas-generator/src/oas_generator/generator/template_engine.py +++ b/oas-generator/src/oas_generator/generator/template_engine.py @@ -282,10 +282,27 @@ def generate_service( # Collect unique operations all_operations = self._collect_unique_operations(operations_by_tag, tags) + # Get private and skipped methods configurations for this service + private_methods = self._get_private_methods(service_class_name) + skipped_methods = self._get_skipped_methods(service_class_name) + + # Mark operations as private or skipped, where required + for operation in all_operations: + if operation.operation_id in private_methods: + operation.is_private = True + if operation.operation_id in skipped_methods: + operation.skip_generation = True + + # Filter out operations marked for skipping + all_operations = [op for op in all_operations if not op.skip_generation] + # Convert to template context operations_context = [op.to_dict() for op in all_operations] import_types = set().union(*(op.import_types for op in all_operations)) + # Get custom imports and methods for this service + custom_imports, custom_methods = self._get_custom_service_extensions(service_class_name) + # Generate service file files[apis_dir / constants.API_SERVICE_FILE] = self.renderer.render( constants.API_SERVICE_TEMPLATE, @@ -294,6 +311,8 @@ def generate_service( "operations": operations_context, "import_types": sorted(import_types), "service_class_name": service_class_name, + "custom_imports": custom_imports, + "custom_methods": custom_methods, }, ) @@ -304,6 +323,61 @@ def generate_service( return files + def _get_custom_service_extensions(self, service_class_name: str) -> tuple[list[str], list[str]]: + """Get custom imports and methods for specific service classes.""" + custom_imports: list[str] = [] + custom_methods: list[str] = [] + + if service_class_name == "AlgodApi": + custom_imports = [ + "import { concatArrays } from '@algorandfoundation/algokit-common';", + ] + send_raw_transaction_method = '''/** + * Send a signed transaction or array of signed transactions to the network. + */ + async sendRawTransaction(stxOrStxs: Uint8Array | Uint8Array[]): Promise { + let rawTransactions = stxOrStxs; + if (Array.isArray(stxOrStxs)) { + if (!stxOrStxs.every((a) => a instanceof Uint8Array)) { + throw new Error('Array elements must be byte arrays'); + } + rawTransactions = concatArrays(...stxOrStxs); + } else if (!(rawTransactions instanceof Uint8Array)) { + throw new Error('Argument must be byte array'); + } + return this.rawTransaction({ body: rawTransactions }); + }''' + + custom_methods = [send_raw_transaction_method] + + return custom_imports, custom_methods + + def _get_private_methods(self, service_class_name: str) -> set[str]: + """Get set of operation IDs that should be marked as private for specific service classes.""" + # Default configuration for private methods by service class + private_method_config = { + "AlgodApi": { + "RawTransaction" # This is the raw transaction endpoint we're wrapping with sendRawTransaction + }, + "IndexerApi": set(), # No private methods by default + "KmdApi": set(), # No private methods by default + } + + return private_method_config.get(service_class_name, set()) + + def _get_skipped_methods(self, service_class_name: str) -> set[str]: + """Get set of operation IDs that should be skipped during generation for specific service classes.""" + # Default configuration for methods to skip generation by service class + skip_generation_config = { + "AlgodApi": { + "RawTransactionAsync", # Not exposed via algosdk + }, + "IndexerApi": set(), + "KmdApi": set(), + } + + return skip_generation_config.get(service_class_name, set()) + def _initialize_model_names(self, spec: Schema) -> None: """Initialize set of model names from spec.""" diff --git a/oas-generator/src/oas_generator/templates/apis/service.ts.j2 b/oas-generator/src/oas_generator/templates/apis/service.ts.j2 index 027aa9b5e..d776f3c02 100644 --- a/oas-generator/src/oas_generator/templates/apis/service.ts.j2 +++ b/oas-generator/src/oas_generator/templates/apis/service.ts.j2 @@ -1,6 +1,11 @@ import type { BaseHttpRequest, ApiRequestOptions } from '../core/base-http-request'; import { AlgorandSerializer } from '../core/model-runtime'; import type { BodyFormat } from '../core/model-runtime'; +{% if custom_imports %} +{% for import_statement in custom_imports %} +{{ import_statement }} +{% endfor %} +{% endif %} {% if import_types and import_types|length > 0 %} {% set sorted = import_types | sort %} import type { {{ sorted | join(', ') }} } from '../models/index'; @@ -84,7 +89,7 @@ export class {{ service_class_name }} { {% for op in operations %} {% set is_raw_bytes_body = op.requestBody and op.requestBody.tsType == 'Uint8Array' %} {{ op.description | ts_doc_comment }} - async {{ op.operationId | ts_camel_case }}( + {% if op.isPrivate %}private {% endif %}async {{ op.operationId | ts_camel_case }}( {%- for p in op.pathParameters %} {{ p.varName }}: {{ p.tsType }}, {%- endfor %} @@ -163,4 +168,10 @@ export class {{ service_class_name }} { } {% endfor %} +{% if custom_methods %} +{% for method in custom_methods %} + + {{ method }} +{% endfor %} +{% endif %} } diff --git a/packages/algod_client/src/apis/api.service.ts b/packages/algod_client/src/apis/api.service.ts index 9f651086b..0eab56f57 100644 --- a/packages/algod_client/src/apis/api.service.ts +++ b/packages/algod_client/src/apis/api.service.ts @@ -1,6 +1,7 @@ import type { BaseHttpRequest, ApiRequestOptions } from '../core/base-http-request' import { AlgorandSerializer } from '../core/model-runtime' import type { BodyFormat } from '../core/model-runtime' +import { concatArrays } from '@algorandfoundation/algokit-common' import type { AbortCatchup, Account, @@ -1184,7 +1185,7 @@ export class AlgodApi { return payload as DebugSettingsProf } - async rawTransaction(params?: { body: Uint8Array }, requestOptions?: ApiRequestOptions): Promise { + private async rawTransaction(params?: { body: Uint8Array }, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -1211,33 +1212,6 @@ export class AlgodApi { return payload as RawTransaction } - async rawTransactionAsync(params?: { body: Uint8Array }, requestOptions?: ApiRequestOptions): Promise { - const headers: Record = {} - const responseFormat: BodyFormat = 'json' - headers['Accept'] = AlgodApi.acceptFor(responseFormat) - - const serializedBody = params?.body ?? undefined - const mediaType = 'application/msgpack' - headers['Content-Type'] = mediaType - - const payload = await this.httpRequest.request({ - method: 'POST', - url: '/v2/transactions/async', - path: {}, - query: {}, - headers, - body: serializedBody, - mediaType: mediaType, - ...(requestOptions ?? {}), - }) - - const responseMeta = undefined - if (responseMeta) { - return AlgorandSerializer.decode(payload, responseMeta, responseFormat) - } - return payload as void - } - /** * Sets the timestamp offset (seconds) for blocks in dev mode. Providing an offset of 0 will unset this value and try to use the real clock for the timestamp. */ @@ -1565,4 +1539,20 @@ export class AlgodApi { } return payload as WaitForBlock } + + /** + * Send a signed transaction or array of signed transactions to the network. + */ + async sendRawTransaction(stxOrStxs: Uint8Array | Uint8Array[]): Promise { + let rawTransactions = stxOrStxs + if (Array.isArray(stxOrStxs)) { + if (!stxOrStxs.every((a) => a instanceof Uint8Array)) { + throw new Error('Array elements must be byte arrays') + } + rawTransactions = concatArrays(...stxOrStxs) + } else if (!(rawTransactions instanceof Uint8Array)) { + throw new Error('Argument must be byte array') + } + return this.rawTransaction({ body: rawTransactions }) + } } diff --git a/packages/sdk/src/composer.ts b/packages/sdk/src/composer.ts index 7fcc5a90a..52d29f128 100644 --- a/packages/sdk/src/composer.ts +++ b/packages/sdk/src/composer.ts @@ -567,15 +567,7 @@ export class AtomicTransactionComposer { const stxns = await this.gatherSignatures() - const totalLength = stxns.reduce((sum, stxn) => sum + stxn.length, 0) - const merged = new Uint8Array(totalLength) - let offset = 0 - for (const stxn of stxns) { - merged.set(stxn, offset) - offset += stxn.length - } - - await client.rawTransaction({ body: merged }) + await client.sendRawTransaction(stxns) this.status = AtomicTransactionComposerStatus.SUBMITTED diff --git a/src/testing/transaction-logger.ts b/src/testing/transaction-logger.ts index ea2df291c..d70dc0b4f 100644 --- a/src/testing/transaction-logger.ts +++ b/src/testing/transaction-logger.ts @@ -1,6 +1,5 @@ import { AlgodClient } from '@algorandfoundation/algokit-algod-client' import { decodeSignedTransaction, getTransactionId } from '@algorandfoundation/algokit-transact' -import * as algosdk from '@algorandfoundation/sdk' import { Indexer } from '@algorandfoundation/sdk' import { Config } from '../config' import { runWhenIndexerCaughtUp } from './indexer' @@ -85,25 +84,12 @@ class TransactionLoggingAlgodClientProxyHandler implements ProxyHandler { + if (property === 'sendRawTransaction') { + return (stxOrStxs: Uint8Array | Uint8Array[]) => { this.transactionLogger.logRawTransaction(stxOrStxs) - - let forPosting = stxOrStxs - if (Array.isArray(stxOrStxs)) { - if (!stxOrStxs.every((a) => a instanceof Uint8Array)) { - throw new TypeError('Array elements must be byte arrays') - } - // Flatten into a single Uint8Array - forPosting = algosdk.concatArrays(...stxOrStxs) - } else if (!(forPosting instanceof Uint8Array)) { - throw new TypeError('Argument must be byte array') - } - - return target[property].call(receiver, { body: forPosting }) + return target[property].call(receiver, stxOrStxs) } } // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/src/transaction/transaction.ts b/src/transaction/transaction.ts index a4b9a6254..fd198ce54 100644 --- a/src/transaction/transaction.ts +++ b/src/transaction/transaction.ts @@ -254,7 +254,7 @@ export const sendTransaction = async function ( const signedTransaction = await signTransaction(txnToSend, from) - await algod.rawTransaction({ body: signedTransaction }) + await algod.sendRawTransaction(signedTransaction) Config.getLogger(suppressLog).verbose( `Sent transaction ID ${getTransactionId(txnToSend)} ${txnToSend.type} from ${getSenderAddress(from)}`, From 2757111f9e8aaab08e779f11b6ccdf5684a78bcc Mon Sep 17 00:00:00 2001 From: Neil Campbell Date: Sun, 2 Nov 2025 00:16:40 +0800 Subject: [PATCH 05/10] chore: remmove requestOptions generation --- .../templates/apis/service.ts.j2 | 6 +- packages/algod_client/src/apis/api.service.ts | 184 +++++------------ .../indexer_client/src/apis/api.service.ts | 190 +++++++----------- packages/kmd_client/src/apis/api.service.ts | 92 +++------ 4 files changed, 147 insertions(+), 325 deletions(-) diff --git a/oas-generator/src/oas_generator/templates/apis/service.ts.j2 b/oas-generator/src/oas_generator/templates/apis/service.ts.j2 index d776f3c02..f1a6b2b4e 100644 --- a/oas-generator/src/oas_generator/templates/apis/service.ts.j2 +++ b/oas-generator/src/oas_generator/templates/apis/service.ts.j2 @@ -1,4 +1,4 @@ -import type { BaseHttpRequest, ApiRequestOptions } from '../core/base-http-request'; +import type { BaseHttpRequest } from '../core/base-http-request'; import { AlgorandSerializer } from '../core/model-runtime'; import type { BodyFormat } from '../core/model-runtime'; {% if custom_imports %} @@ -101,9 +101,8 @@ export class {{ service_class_name }} { {%- if op.requestBody and op.method.upper() not in ['GET', 'HEAD', 'DELETE'] %} body{% if not op.requestBody.required %}?{% endif %}: {{ op.requestBody.tsType }}; {%- endif %} - }, + } {%- endif %} - requestOptions?: ApiRequestOptions ): Promise<{{ op.responseTsType }}> { const headers: Record = {}; {% set supports_msgpack = op.returnsMsgpack or (op.requestBody and op.requestBody.supportsMsgpack) %} @@ -157,7 +156,6 @@ export class {{ service_class_name }} { body: undefined, mediaType: undefined, {% endif %} - ...(requestOptions ?? {}), }); const responseMeta = {{ meta_expr(op.responseTsType) }}; diff --git a/packages/algod_client/src/apis/api.service.ts b/packages/algod_client/src/apis/api.service.ts index 0eab56f57..208df3300 100644 --- a/packages/algod_client/src/apis/api.service.ts +++ b/packages/algod_client/src/apis/api.service.ts @@ -1,4 +1,4 @@ -import type { BaseHttpRequest, ApiRequestOptions } from '../core/base-http-request' +import type { BaseHttpRequest } from '../core/base-http-request' import { AlgorandSerializer } from '../core/model-runtime' import type { BodyFormat } from '../core/model-runtime' import { concatArrays } from '@algorandfoundation/algokit-common' @@ -103,7 +103,7 @@ export class AlgodApi { /** * Given a catchpoint, it aborts catching up to this catchpoint */ - async abortCatchup(catchpoint: string, requestOptions?: ApiRequestOptions): Promise { + async abortCatchup(catchpoint: string): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -116,7 +116,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = AbortCatchupMeta @@ -133,7 +132,6 @@ export class AlgodApi { address: string, applicationId: number | bigint, params?: { format?: 'json' | 'msgpack' }, - requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {} const responseFormat: BodyFormat = (params?.format as BodyFormat | undefined) ?? 'msgpack' @@ -147,7 +145,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = AccountApplicationInformationMeta @@ -160,11 +157,7 @@ export class AlgodApi { /** * Given a specific account public key and asset ID, this call returns the account's asset holding and asset parameters (if either exist). Asset parameters will only be returned if the provided address is the asset's creator. */ - async accountAssetInformation( - address: string, - assetId: number | bigint, - requestOptions?: ApiRequestOptions, - ): Promise { + async accountAssetInformation(address: string, assetId: number | bigint): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -177,7 +170,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = AccountAssetInformationMeta @@ -190,11 +182,7 @@ export class AlgodApi { /** * Lookup an account's asset holdings. */ - async accountAssetsInformation( - address: string, - params?: { limit?: number | bigint; next?: string }, - requestOptions?: ApiRequestOptions, - ): Promise { + async accountAssetsInformation(address: string, params?: { limit?: number | bigint; next?: string }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -207,7 +195,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = AccountAssetsInformationMeta @@ -220,7 +207,7 @@ export class AlgodApi { /** * Given a specific account public key, this call returns the account's status, balance and spendable amounts */ - async accountInformation(address: string, params?: { exclude?: 'all' | 'none' }, requestOptions?: ApiRequestOptions): Promise { + async accountInformation(address: string, params?: { exclude?: 'all' | 'none' }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -233,7 +220,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = AccountMeta @@ -243,7 +229,7 @@ export class AlgodApi { return payload as Account } - async addParticipationKey(params?: { body: string }, requestOptions?: ApiRequestOptions): Promise { + async addParticipationKey(params?: { body: string }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'msgpack' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -262,7 +248,6 @@ export class AlgodApi { headers, body: serializedBody, mediaType: mediaType, - ...(requestOptions ?? {}), }) const responseMeta = AddParticipationKeyMeta @@ -275,7 +260,7 @@ export class AlgodApi { /** * Given a participation ID, append state proof keys to a particular set of participation keys */ - async appendKeys(participationId: string, params?: { body: string }, requestOptions?: ApiRequestOptions): Promise { + async appendKeys(participationId: string, params?: { body: string }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'msgpack' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -294,7 +279,6 @@ export class AlgodApi { headers, body: serializedBody, mediaType: mediaType, - ...(requestOptions ?? {}), }) const responseMeta = ParticipationKeyMeta @@ -307,7 +291,7 @@ export class AlgodApi { /** * Delete a given participation key by ID */ - async deleteParticipationKeyById(participationId: string, requestOptions?: ApiRequestOptions): Promise { + async deleteParticipationKeyById(participationId: string): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -320,7 +304,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = undefined @@ -330,7 +313,7 @@ export class AlgodApi { return payload as void } - async experimentalCheck(requestOptions?: ApiRequestOptions): Promise { + async experimentalCheck(): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -343,7 +326,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = undefined @@ -356,7 +338,6 @@ export class AlgodApi { async generateParticipationKeys( address: string, params?: { dilution?: number | bigint; first: number | bigint; last: number | bigint }, - requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' @@ -374,7 +355,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = undefined @@ -387,11 +367,7 @@ export class AlgodApi { /** * Given an application ID and box name, it returns the round, box name, and value (each base64 encoded). Box names must be in the goal app call arg encoding form 'encoding:value'. For ints, use the form 'int:1234'. For raw bytes, use the form 'b64:A=='. For printable strings, use the form 'str:hello'. For addresses, use the form 'addr:XYZ...'. */ - async getApplicationBoxByName( - applicationId: number | bigint, - params?: { name: string }, - requestOptions?: ApiRequestOptions, - ): Promise { + async getApplicationBoxByName(applicationId: number | bigint, params?: { name: string }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -404,7 +380,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = BoxMeta @@ -417,11 +392,7 @@ export class AlgodApi { /** * Given an application ID, return all Box names. No particular ordering is guaranteed. Request fails when client or server-side configured limits prevent returning all Box names. */ - async getApplicationBoxes( - applicationId: number | bigint, - params?: { max?: number | bigint }, - requestOptions?: ApiRequestOptions, - ): Promise { + async getApplicationBoxes(applicationId: number | bigint, params?: { max?: number | bigint }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -434,7 +405,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = GetApplicationBoxesMeta @@ -447,7 +417,7 @@ export class AlgodApi { /** * Given a application ID, it returns application information including creator, approval and clear programs, global and local schemas, and global state. */ - async getApplicationById(applicationId: number | bigint, requestOptions?: ApiRequestOptions): Promise { + async getApplicationById(applicationId: number | bigint): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -460,7 +430,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = ApplicationMeta @@ -473,7 +442,7 @@ export class AlgodApi { /** * Given a asset ID, it returns asset information including creator, name, total supply and special addresses. */ - async getAssetById(assetId: number | bigint, requestOptions?: ApiRequestOptions): Promise { + async getAssetById(assetId: number | bigint): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -486,7 +455,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = AssetMeta @@ -496,7 +464,7 @@ export class AlgodApi { return payload as Asset } - async getBlock(round: number | bigint, params?: { headerOnly?: boolean }, requestOptions?: ApiRequestOptions): Promise { + async getBlock(round: number | bigint, params?: { headerOnly?: boolean }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'msgpack' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -509,7 +477,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = GetBlockMeta @@ -519,7 +486,7 @@ export class AlgodApi { return payload as GetBlock } - async getBlockHash(round: number | bigint, requestOptions?: ApiRequestOptions): Promise { + async getBlockHash(round: number | bigint): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -532,7 +499,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = GetBlockHashMeta @@ -545,7 +511,7 @@ export class AlgodApi { /** * Get all of the logs from outer and inner app calls in the given round */ - async getBlockLogs(round: number | bigint, requestOptions?: ApiRequestOptions): Promise { + async getBlockLogs(round: number | bigint): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -558,7 +524,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = GetBlockLogsMeta @@ -571,7 +536,7 @@ export class AlgodApi { /** * Gets the current timestamp offset. */ - async getBlockTimeStampOffset(requestOptions?: ApiRequestOptions): Promise { + async getBlockTimeStampOffset(): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -584,7 +549,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = GetBlockTimeStampOffsetMeta @@ -594,7 +558,7 @@ export class AlgodApi { return payload as GetBlockTimeStampOffset } - async getBlockTxids(round: number | bigint, requestOptions?: ApiRequestOptions): Promise { + async getBlockTxids(round: number | bigint): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -607,7 +571,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = GetBlockTxidsMeta @@ -620,7 +583,7 @@ export class AlgodApi { /** * Returns the merged (defaults + overrides) config file in json. */ - async getConfig(requestOptions?: ApiRequestOptions): Promise { + async getConfig(): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -633,7 +596,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = undefined @@ -646,7 +608,7 @@ export class AlgodApi { /** * Retrieves the current settings for blocking and mutex profiles */ - async getDebugSettingsProf(requestOptions?: ApiRequestOptions): Promise { + async getDebugSettingsProf(): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -659,7 +621,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = DebugSettingsProfMeta @@ -672,7 +633,7 @@ export class AlgodApi { /** * Returns the entire genesis file in json. */ - async getGenesis(requestOptions?: ApiRequestOptions): Promise { + async getGenesis(): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -685,7 +646,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = GenesisMeta @@ -698,7 +658,7 @@ export class AlgodApi { /** * Get ledger deltas for a round. */ - async getLedgerStateDelta(round: number | bigint, requestOptions?: ApiRequestOptions): Promise { + async getLedgerStateDelta(round: number | bigint): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'msgpack' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -711,7 +671,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = LedgerStateDeltaMeta @@ -724,7 +683,7 @@ export class AlgodApi { /** * Get a ledger delta for a given transaction group. */ - async getLedgerStateDeltaForTransactionGroup(id: string, requestOptions?: ApiRequestOptions): Promise { + async getLedgerStateDeltaForTransactionGroup(id: string): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'msgpack' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -737,7 +696,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = LedgerStateDeltaMeta @@ -747,7 +705,7 @@ export class AlgodApi { return payload as LedgerStateDelta } - async getLightBlockHeaderProof(round: number | bigint, requestOptions?: ApiRequestOptions): Promise { + async getLightBlockHeaderProof(round: number | bigint): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -760,7 +718,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = LightBlockHeaderProofMeta @@ -773,7 +730,7 @@ export class AlgodApi { /** * Given a participation ID, return information about that participation key */ - async getParticipationKeyById(participationId: string, requestOptions?: ApiRequestOptions): Promise { + async getParticipationKeyById(participationId: string): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -786,7 +743,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = ParticipationKeyMeta @@ -799,7 +755,7 @@ export class AlgodApi { /** * Return a list of participation keys */ - async getParticipationKeys(requestOptions?: ApiRequestOptions): Promise { + async getParticipationKeys(): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -812,7 +768,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = { @@ -829,7 +784,7 @@ export class AlgodApi { /** * Get the list of pending transactions, sorted by priority, in decreasing order, truncated at the end at MAX. If MAX = 0, returns all pending transactions. */ - async getPendingTransactions(params?: { max?: number | bigint }, requestOptions?: ApiRequestOptions): Promise { + async getPendingTransactions(params?: { max?: number | bigint }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'msgpack' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -842,7 +797,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = GetPendingTransactionsMeta @@ -855,11 +809,7 @@ export class AlgodApi { /** * Get the list of pending transactions by address, sorted by priority, in decreasing order, truncated at the end at MAX. If MAX = 0, returns all pending transactions. */ - async getPendingTransactionsByAddress( - address: string, - params?: { max?: number | bigint }, - requestOptions?: ApiRequestOptions, - ): Promise { + async getPendingTransactionsByAddress(address: string, params?: { max?: number | bigint }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'msgpack' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -872,7 +822,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = GetPendingTransactionsByAddressMeta @@ -882,7 +831,7 @@ export class AlgodApi { return payload as GetPendingTransactionsByAddress } - async getReady(requestOptions?: ApiRequestOptions): Promise { + async getReady(): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -895,7 +844,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = undefined @@ -905,7 +853,7 @@ export class AlgodApi { return payload as void } - async getStateProof(round: number | bigint, requestOptions?: ApiRequestOptions): Promise { + async getStateProof(round: number | bigint): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -918,7 +866,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = StateProofMeta @@ -928,7 +875,7 @@ export class AlgodApi { return payload as StateProof } - async getStatus(requestOptions?: ApiRequestOptions): Promise { + async getStatus(): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -941,7 +888,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = GetStatusMeta @@ -951,7 +897,7 @@ export class AlgodApi { return payload as GetStatus } - async getSupply(requestOptions?: ApiRequestOptions): Promise { + async getSupply(): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -964,7 +910,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = GetSupplyMeta @@ -977,7 +922,7 @@ export class AlgodApi { /** * Gets the minimum sync round for the ledger. */ - async getSyncRound(requestOptions?: ApiRequestOptions): Promise { + async getSyncRound(): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -990,7 +935,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = GetSyncRoundMeta @@ -1003,10 +947,7 @@ export class AlgodApi { /** * Get ledger deltas for transaction groups in a given round. */ - async getTransactionGroupLedgerStateDeltasForRound( - round: number | bigint, - requestOptions?: ApiRequestOptions, - ): Promise { + async getTransactionGroupLedgerStateDeltasForRound(round: number | bigint): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'msgpack' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -1019,7 +960,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = GetTransactionGroupLedgerStateDeltasForRoundMeta @@ -1033,7 +973,6 @@ export class AlgodApi { round: number | bigint, txid: string, params?: { hashtype?: 'sha512_256' | 'sha256'; format?: 'json' | 'msgpack' }, - requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' @@ -1047,7 +986,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = TransactionProofMeta @@ -1060,7 +998,7 @@ export class AlgodApi { /** * Retrieves the supported API versions, binary build versions, and genesis information. */ - async getVersion(requestOptions?: ApiRequestOptions): Promise { + async getVersion(): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -1073,7 +1011,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = VersionMeta @@ -1083,7 +1020,7 @@ export class AlgodApi { return payload as Version } - async healthCheck(requestOptions?: ApiRequestOptions): Promise { + async healthCheck(): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -1096,7 +1033,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = undefined @@ -1106,7 +1042,7 @@ export class AlgodApi { return payload as void } - async metrics(requestOptions?: ApiRequestOptions): Promise { + async metrics(): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -1119,7 +1055,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = undefined @@ -1136,7 +1071,7 @@ export class AlgodApi { * - transaction removed from pool due to error (committed round = 0, pool error != "") * Or the transaction may have happened sufficiently long ago that the node no longer remembers it, and this will return an error. */ - async pendingTransactionInformation(txid: string, requestOptions?: ApiRequestOptions): Promise { + async pendingTransactionInformation(txid: string): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'msgpack' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -1149,7 +1084,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = PendingTransactionResponseMeta @@ -1162,7 +1096,7 @@ export class AlgodApi { /** * Enables blocking and mutex profiles, and returns the old settings */ - async putDebugSettingsProf(requestOptions?: ApiRequestOptions): Promise { + async putDebugSettingsProf(): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -1175,7 +1109,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = DebugSettingsProfMeta @@ -1185,7 +1118,7 @@ export class AlgodApi { return payload as DebugSettingsProf } - private async rawTransaction(params?: { body: Uint8Array }, requestOptions?: ApiRequestOptions): Promise { + private async rawTransaction(params?: { body: Uint8Array }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -1202,7 +1135,6 @@ export class AlgodApi { headers, body: serializedBody, mediaType: mediaType, - ...(requestOptions ?? {}), }) const responseMeta = RawTransactionMeta @@ -1215,7 +1147,7 @@ export class AlgodApi { /** * Sets the timestamp offset (seconds) for blocks in dev mode. Providing an offset of 0 will unset this value and try to use the real clock for the timestamp. */ - async setBlockTimeStampOffset(offset: number | bigint, requestOptions?: ApiRequestOptions): Promise { + async setBlockTimeStampOffset(offset: number | bigint): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -1228,7 +1160,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = undefined @@ -1241,7 +1172,7 @@ export class AlgodApi { /** * Sets the minimum sync round on the ledger. */ - async setSyncRound(round: number | bigint, requestOptions?: ApiRequestOptions): Promise { + async setSyncRound(round: number | bigint): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -1254,7 +1185,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = undefined @@ -1267,7 +1197,7 @@ export class AlgodApi { /** * Special management endpoint to shutdown the node. Optionally provide a timeout parameter to indicate that the node should begin shutting down after a number of seconds. */ - async shutdownNode(params?: { timeout?: number | bigint }, requestOptions?: ApiRequestOptions): Promise { + async shutdownNode(params?: { timeout?: number | bigint }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -1280,7 +1210,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = ShutdownNodeMeta @@ -1290,7 +1219,7 @@ export class AlgodApi { return payload as ShutdownNode } - async simulateTransaction(params?: { body: SimulateRequest }, requestOptions?: ApiRequestOptions): Promise { + async simulateTransaction(params?: { body: SimulateRequest }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'msgpack' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -1309,7 +1238,6 @@ export class AlgodApi { headers, body: serializedBody, mediaType: mediaType, - ...(requestOptions ?? {}), }) const responseMeta = SimulateTransactionMeta @@ -1322,7 +1250,7 @@ export class AlgodApi { /** * Given a catchpoint, it starts catching up to this catchpoint */ - async startCatchup(catchpoint: string, params?: { min?: number | bigint }, requestOptions?: ApiRequestOptions): Promise { + async startCatchup(catchpoint: string, params?: { min?: number | bigint }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -1335,7 +1263,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = StartCatchupMeta @@ -1348,7 +1275,7 @@ export class AlgodApi { /** * Returns the entire swagger spec in json. */ - async swaggerJson(requestOptions?: ApiRequestOptions): Promise { + async swaggerJson(): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -1361,7 +1288,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = undefined @@ -1374,7 +1300,7 @@ export class AlgodApi { /** * Given TEAL source code in plain text, return base64 encoded program bytes and base32 SHA512_256 hash of program bytes (Address style). This endpoint is only enabled when a node's configuration file sets EnableDeveloperAPI to true. */ - async tealCompile(params?: { sourcemap?: boolean; body: string }, requestOptions?: ApiRequestOptions): Promise { + async tealCompile(params?: { sourcemap?: boolean; body: string }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -1393,7 +1319,6 @@ export class AlgodApi { headers, body: serializedBody, mediaType: mediaType, - ...(requestOptions ?? {}), }) const responseMeta = TealCompileMeta @@ -1406,7 +1331,7 @@ export class AlgodApi { /** * Given the program bytes, return the TEAL source code in plain text. This endpoint is only enabled when a node's configuration file sets EnableDeveloperAPI to true. */ - async tealDisassemble(params?: { body: Uint8Array }, requestOptions?: ApiRequestOptions): Promise { + async tealDisassemble(params?: { body: Uint8Array }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -1423,7 +1348,6 @@ export class AlgodApi { headers, body: serializedBody, mediaType: mediaType, - ...(requestOptions ?? {}), }) const responseMeta = TealDisassembleMeta @@ -1436,7 +1360,7 @@ export class AlgodApi { /** * Executes TEAL program(s) in context and returns debugging information about the execution. This endpoint is only enabled when a node's configuration file sets EnableDeveloperAPI to true. */ - async tealDryrun(params?: { body?: DryrunRequest }, requestOptions?: ApiRequestOptions): Promise { + async tealDryrun(params?: { body?: DryrunRequest }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'msgpack' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -1455,7 +1379,6 @@ export class AlgodApi { headers, body: serializedBody, mediaType: mediaType, - ...(requestOptions ?? {}), }) const responseMeta = TealDryrunMeta @@ -1465,7 +1388,7 @@ export class AlgodApi { return payload as TealDryrun } - async transactionParams(requestOptions?: ApiRequestOptions): Promise { + async transactionParams(): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -1478,7 +1401,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = TransactionParamsMeta @@ -1491,7 +1413,7 @@ export class AlgodApi { /** * Unset the ledger sync round. */ - async unsetSyncRound(requestOptions?: ApiRequestOptions): Promise { + async unsetSyncRound(): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -1504,7 +1426,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = undefined @@ -1517,7 +1438,7 @@ export class AlgodApi { /** * Waits for a block to appear after round {round} and returns the node's status at the time. There is a 1 minute timeout, when reached the current status is returned regardless of whether or not it is the round after the given round. */ - async waitForBlock(round: number | bigint, requestOptions?: ApiRequestOptions): Promise { + async waitForBlock(round: number | bigint): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -1530,7 +1451,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = WaitForBlockMeta diff --git a/packages/indexer_client/src/apis/api.service.ts b/packages/indexer_client/src/apis/api.service.ts index 14b1493fc..cd40f8f06 100644 --- a/packages/indexer_client/src/apis/api.service.ts +++ b/packages/indexer_client/src/apis/api.service.ts @@ -1,4 +1,4 @@ -import type { BaseHttpRequest, ApiRequestOptions } from '../core/base-http-request' +import type { BaseHttpRequest } from '../core/base-http-request' import { AlgorandSerializer } from '../core/model-runtime' import type { BodyFormat } from '../core/model-runtime' import type { @@ -65,7 +65,6 @@ export class IndexerApi { async lookupAccountAppLocalStates( accountId: string, params?: { applicationId?: number | bigint; includeAll?: boolean; limit?: number | bigint; next?: string }, - requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' @@ -84,7 +83,6 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = LookupAccountAppLocalStatesMeta @@ -100,7 +98,6 @@ export class IndexerApi { async lookupAccountAssets( accountId: string, params?: { assetId?: number | bigint; includeAll?: boolean; limit?: number | bigint; next?: string }, - requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' @@ -119,7 +116,6 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = LookupAccountAssetsMeta @@ -139,7 +135,6 @@ export class IndexerApi { includeAll?: boolean exclude?: 'all' | 'assets' | 'created-assets' | 'apps-local-state' | 'created-apps' | 'none'[] }, - requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' @@ -157,7 +152,6 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = LookupAccountByIdMeta @@ -173,7 +167,6 @@ export class IndexerApi { async lookupAccountCreatedApplications( accountId: string, params?: { applicationId?: number | bigint; includeAll?: boolean; limit?: number | bigint; next?: string }, - requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' @@ -192,7 +185,6 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = LookupAccountCreatedApplicationsMeta @@ -208,7 +200,6 @@ export class IndexerApi { async lookupAccountCreatedAssets( accountId: string, params?: { assetId?: number | bigint; includeAll?: boolean; limit?: number | bigint; next?: string }, - requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' @@ -227,7 +218,6 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = LookupAccountCreatedAssetsMeta @@ -259,7 +249,6 @@ export class IndexerApi { currencyLessThan?: number | bigint rekeyTo?: boolean }, - requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' @@ -293,7 +282,6 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = LookupAccountTransactionsMeta @@ -306,11 +294,7 @@ export class IndexerApi { /** * Given an application ID and box name, returns base64 encoded box name and value. Box names must be in the goal app call arg form 'encoding:value'. For ints, use the form 'int:1234'. For raw bytes, encode base 64 and use 'b64' prefix as in 'b64:A=='. For printable strings, use the form 'str:hello'. For addresses, use the form 'addr:XYZ...'. */ - async lookupApplicationBoxByIdAndName( - applicationId: number | bigint, - params?: { name: string }, - requestOptions?: ApiRequestOptions, - ): Promise { + async lookupApplicationBoxByIdAndName(applicationId: number | bigint, params?: { name: string }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = IndexerApi.acceptFor(responseFormat) @@ -323,7 +307,6 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = BoxMeta @@ -336,11 +319,7 @@ export class IndexerApi { /** * Lookup application. */ - async lookupApplicationById( - applicationId: number | bigint, - params?: { includeAll?: boolean }, - requestOptions?: ApiRequestOptions, - ): Promise { + async lookupApplicationById(applicationId: number | bigint, params?: { includeAll?: boolean }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = IndexerApi.acceptFor(responseFormat) @@ -353,7 +332,6 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = LookupApplicationByIdMeta @@ -376,7 +354,6 @@ export class IndexerApi { maxRound?: number | bigint senderAddress?: string }, - requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' @@ -397,7 +374,6 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = LookupApplicationLogsByIdMeta @@ -419,7 +395,6 @@ export class IndexerApi { currencyGreaterThan?: number | bigint currencyLessThan?: number | bigint }, - requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' @@ -443,7 +418,6 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = LookupAssetBalancesMeta @@ -456,11 +430,7 @@ export class IndexerApi { /** * Lookup asset information. */ - async lookupAssetById( - assetId: number | bigint, - params?: { includeAll?: boolean }, - requestOptions?: ApiRequestOptions, - ): Promise { + async lookupAssetById(assetId: number | bigint, params?: { includeAll?: boolean }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = IndexerApi.acceptFor(responseFormat) @@ -473,7 +443,6 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = LookupAssetByIdMeta @@ -507,7 +476,6 @@ export class IndexerApi { excludeCloseTo?: boolean rekeyTo?: boolean }, - requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' @@ -543,7 +511,6 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = LookupAssetTransactionsMeta @@ -556,7 +523,7 @@ export class IndexerApi { /** * Lookup block. */ - async lookupBlock(roundNumber: number | bigint, params?: { headerOnly?: boolean }, requestOptions?: ApiRequestOptions): Promise { + async lookupBlock(roundNumber: number | bigint, params?: { headerOnly?: boolean }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = IndexerApi.acceptFor(responseFormat) @@ -569,7 +536,6 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = BlockMeta @@ -582,7 +548,7 @@ export class IndexerApi { /** * Lookup a single transaction. */ - async lookupTransaction(txid: string, requestOptions?: ApiRequestOptions): Promise { + async lookupTransaction(txid: string): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = IndexerApi.acceptFor(responseFormat) @@ -595,7 +561,6 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = LookupTransactionMeta @@ -605,7 +570,7 @@ export class IndexerApi { return payload as LookupTransaction } - async makeHealthCheck(requestOptions?: ApiRequestOptions): Promise { + async makeHealthCheck(): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = IndexerApi.acceptFor(responseFormat) @@ -618,7 +583,6 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = HealthCheckMeta @@ -631,22 +595,19 @@ export class IndexerApi { /** * Search for accounts. */ - async searchForAccounts( - params?: { - assetId?: number | bigint - limit?: number | bigint - next?: string - currencyGreaterThan?: number | bigint - includeAll?: boolean - exclude?: 'all' | 'assets' | 'created-assets' | 'apps-local-state' | 'created-apps' | 'none'[] - currencyLessThan?: number | bigint - authAddr?: string - round?: number | bigint - applicationId?: number | bigint - onlineOnly?: boolean - }, - requestOptions?: ApiRequestOptions, - ): Promise { + async searchForAccounts(params?: { + assetId?: number | bigint + limit?: number | bigint + next?: string + currencyGreaterThan?: number | bigint + includeAll?: boolean + exclude?: 'all' | 'assets' | 'created-assets' | 'apps-local-state' | 'created-apps' | 'none'[] + currencyLessThan?: number | bigint + authAddr?: string + round?: number | bigint + applicationId?: number | bigint + onlineOnly?: boolean + }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = IndexerApi.acceptFor(responseFormat) @@ -675,7 +636,6 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = SearchForAccountsMeta @@ -691,7 +651,6 @@ export class IndexerApi { async searchForApplicationBoxes( applicationId: number | bigint, params?: { limit?: number | bigint; next?: string }, - requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' @@ -705,7 +664,6 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = SearchForApplicationBoxesMeta @@ -718,10 +676,13 @@ export class IndexerApi { /** * Search for applications */ - async searchForApplications( - params?: { applicationId?: number | bigint; creator?: string; includeAll?: boolean; limit?: number | bigint; next?: string }, - requestOptions?: ApiRequestOptions, - ): Promise { + async searchForApplications(params?: { + applicationId?: number | bigint + creator?: string + includeAll?: boolean + limit?: number | bigint + next?: string + }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = IndexerApi.acceptFor(responseFormat) @@ -740,7 +701,6 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = SearchForApplicationsMeta @@ -753,18 +713,15 @@ export class IndexerApi { /** * Search for assets. */ - async searchForAssets( - params?: { - includeAll?: boolean - limit?: number | bigint - next?: string - creator?: string - name?: string - unit?: string - assetId?: number | bigint - }, - requestOptions?: ApiRequestOptions, - ): Promise { + async searchForAssets(params?: { + includeAll?: boolean + limit?: number | bigint + next?: string + creator?: string + name?: string + unit?: string + assetId?: number | bigint + }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = IndexerApi.acceptFor(responseFormat) @@ -785,7 +742,6 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = SearchForAssetsMeta @@ -798,20 +754,17 @@ export class IndexerApi { /** * Search for block headers. Block headers are returned in ascending round order. Transactions are not included in the output. */ - async searchForBlockHeaders( - params?: { - limit?: number | bigint - next?: string - minRound?: number | bigint - maxRound?: number | bigint - beforeTime?: string - afterTime?: string - proposers?: string[] - expired?: string[] - absent?: string[] - }, - requestOptions?: ApiRequestOptions, - ): Promise { + async searchForBlockHeaders(params?: { + limit?: number | bigint + next?: string + minRound?: number | bigint + maxRound?: number | bigint + beforeTime?: string + afterTime?: string + proposers?: string[] + expired?: string[] + absent?: string[] + }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = IndexerApi.acceptFor(responseFormat) @@ -834,7 +787,6 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = SearchForBlockHeadersMeta @@ -847,31 +799,28 @@ export class IndexerApi { /** * Search for transactions. Transactions are returned oldest to newest unless the address parameter is used, in which case results are returned newest to oldest. */ - async searchForTransactions( - params?: { - limit?: number | bigint - next?: string - notePrefix?: string - txType?: 'pay' | 'keyreg' | 'acfg' | 'axfer' | 'afrz' | 'appl' | 'stpf' | 'hb' - sigType?: 'sig' | 'msig' | 'lsig' - groupId?: string - txid?: string - round?: number | bigint - minRound?: number | bigint - maxRound?: number | bigint - assetId?: number | bigint - beforeTime?: string - afterTime?: string - currencyGreaterThan?: number | bigint - currencyLessThan?: number | bigint - address?: string - addressRole?: 'sender' | 'receiver' | 'freeze-target' - excludeCloseTo?: boolean - rekeyTo?: boolean - applicationId?: number | bigint - }, - requestOptions?: ApiRequestOptions, - ): Promise { + async searchForTransactions(params?: { + limit?: number | bigint + next?: string + notePrefix?: string + txType?: 'pay' | 'keyreg' | 'acfg' | 'axfer' | 'afrz' | 'appl' | 'stpf' | 'hb' + sigType?: 'sig' | 'msig' | 'lsig' + groupId?: string + txid?: string + round?: number | bigint + minRound?: number | bigint + maxRound?: number | bigint + assetId?: number | bigint + beforeTime?: string + afterTime?: string + currencyGreaterThan?: number | bigint + currencyLessThan?: number | bigint + address?: string + addressRole?: 'sender' | 'receiver' | 'freeze-target' + excludeCloseTo?: boolean + rekeyTo?: boolean + applicationId?: number | bigint + }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = IndexerApi.acceptFor(responseFormat) @@ -909,7 +858,6 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = SearchForTransactionsMeta diff --git a/packages/kmd_client/src/apis/api.service.ts b/packages/kmd_client/src/apis/api.service.ts index 56e104c63..50b9c51b8 100644 --- a/packages/kmd_client/src/apis/api.service.ts +++ b/packages/kmd_client/src/apis/api.service.ts @@ -1,4 +1,4 @@ -import type { BaseHttpRequest, ApiRequestOptions } from '../core/base-http-request' +import type { BaseHttpRequest } from '../core/base-http-request' import { AlgorandSerializer } from '../core/model-runtime' import type { BodyFormat } from '../core/model-runtime' import type { @@ -100,7 +100,7 @@ export class KmdApi { /** * Create a new wallet (collection of keys) with the given parameters. */ - async createWallet(params?: { body: CreateWalletRequest }, requestOptions?: ApiRequestOptions): Promise { + async createWallet(params?: { body: CreateWalletRequest }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -119,7 +119,6 @@ export class KmdApi { headers, body: serializedBody, mediaType: mediaType, - ...(requestOptions ?? {}), }) const responseMeta = PostWalletResponseMeta @@ -132,7 +131,7 @@ export class KmdApi { /** * Deletes the key with the passed public key from the wallet. */ - async deleteKey(requestOptions?: ApiRequestOptions): Promise { + async deleteKey(): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -145,7 +144,6 @@ export class KmdApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = DeleteKeyResponseMeta @@ -158,7 +156,7 @@ export class KmdApi { /** * Deletes multisig preimage information for the passed address from the wallet. */ - async deleteMultisig(requestOptions?: ApiRequestOptions): Promise { + async deleteMultisig(): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -171,7 +169,6 @@ export class KmdApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = DeleteMultisigResponseMeta @@ -184,7 +181,7 @@ export class KmdApi { /** * Export the secret key associated with the passed public key. */ - async exportKey(params?: { body: ExportKeyRequest }, requestOptions?: ApiRequestOptions): Promise { + async exportKey(params?: { body: ExportKeyRequest }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -203,7 +200,6 @@ export class KmdApi { headers, body: serializedBody, mediaType: mediaType, - ...(requestOptions ?? {}), }) const responseMeta = PostKeyExportResponseMeta @@ -216,10 +212,7 @@ export class KmdApi { /** * Export the master derivation key from the wallet. This key is a master "backup" key for the underlying wallet. With it, you can regenerate all of the wallets that have been generated with this wallet's `POST /v1/key` endpoint. This key will not allow you to recover keys imported from other wallets, however. */ - async exportMasterKey( - params?: { body: ExportMasterKeyRequest }, - requestOptions?: ApiRequestOptions, - ): Promise { + async exportMasterKey(params?: { body: ExportMasterKeyRequest }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -238,7 +231,6 @@ export class KmdApi { headers, body: serializedBody, mediaType: mediaType, - ...(requestOptions ?? {}), }) const responseMeta = PostMasterKeyExportResponseMeta @@ -251,7 +243,7 @@ export class KmdApi { /** * Given a multisig address whose preimage this wallet stores, returns the information used to generate the address, including public keys, threshold, and multisig version. */ - async exportMultisig(params?: { body: ExportMultisigRequest }, requestOptions?: ApiRequestOptions): Promise { + async exportMultisig(params?: { body: ExportMultisigRequest }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -270,7 +262,6 @@ export class KmdApi { headers, body: serializedBody, mediaType: mediaType, - ...(requestOptions ?? {}), }) const responseMeta = PostMultisigExportResponseMeta @@ -283,7 +274,7 @@ export class KmdApi { /** * Generates the next key in the deterministic key sequence (as determined by the master derivation key) and adds it to the wallet, returning the public key. */ - async generateKey(params?: { body: GenerateKeyRequest }, requestOptions?: ApiRequestOptions): Promise { + async generateKey(params?: { body: GenerateKeyRequest }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -302,7 +293,6 @@ export class KmdApi { headers, body: serializedBody, mediaType: mediaType, - ...(requestOptions ?? {}), }) const responseMeta = PostKeyResponseMeta @@ -312,7 +302,7 @@ export class KmdApi { return payload as PostKeyResponse } - async getVersion(requestOptions?: ApiRequestOptions): Promise { + async getVersion(): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -325,7 +315,6 @@ export class KmdApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = VersionsResponseMeta @@ -338,7 +327,7 @@ export class KmdApi { /** * Returns information about the wallet associated with the passed wallet handle token. Additionally returns expiration information about the token itself. */ - async getWalletInfo(params?: { body: WalletInfoRequest }, requestOptions?: ApiRequestOptions): Promise { + async getWalletInfo(params?: { body: WalletInfoRequest }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -357,7 +346,6 @@ export class KmdApi { headers, body: serializedBody, mediaType: mediaType, - ...(requestOptions ?? {}), }) const responseMeta = PostWalletInfoResponseMeta @@ -370,7 +358,7 @@ export class KmdApi { /** * Import an externally generated key into the wallet. Note that if you wish to back up the imported key, you must do so by backing up the entire wallet database, because imported keys were not derived from the wallet's master derivation key. */ - async importKey(params?: { body: ImportKeyRequest }, requestOptions?: ApiRequestOptions): Promise { + async importKey(params?: { body: ImportKeyRequest }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -389,7 +377,6 @@ export class KmdApi { headers, body: serializedBody, mediaType: mediaType, - ...(requestOptions ?? {}), }) const responseMeta = PostKeyImportResponseMeta @@ -402,7 +389,7 @@ export class KmdApi { /** * Generates a multisig account from the passed public keys array and multisig metadata, and stores all of this in the wallet. */ - async importMultisig(params?: { body: ImportMultisigRequest }, requestOptions?: ApiRequestOptions): Promise { + async importMultisig(params?: { body: ImportMultisigRequest }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -421,7 +408,6 @@ export class KmdApi { headers, body: serializedBody, mediaType: mediaType, - ...(requestOptions ?? {}), }) const responseMeta = PostMultisigImportResponseMeta @@ -434,10 +420,7 @@ export class KmdApi { /** * Unlock the wallet and return a wallet handle token that can be used for subsequent operations. These tokens expire periodically and must be renewed. You can `POST` the token to `/v1/wallet/info` to see how much time remains until expiration, and renew it with `/v1/wallet/renew`. When you're done, you can invalidate the token with `/v1/wallet/release`. */ - async initWalletHandleToken( - params?: { body: InitWalletHandleTokenRequest }, - requestOptions?: ApiRequestOptions, - ): Promise { + async initWalletHandleToken(params?: { body: InitWalletHandleTokenRequest }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -456,7 +439,6 @@ export class KmdApi { headers, body: serializedBody, mediaType: mediaType, - ...(requestOptions ?? {}), }) const responseMeta = PostWalletInitResponseMeta @@ -469,7 +451,7 @@ export class KmdApi { /** * Lists all of the public keys in this wallet. All of them have a stored private key. */ - async listKeysInWallet(params?: { body: ListKeysRequest }, requestOptions?: ApiRequestOptions): Promise { + async listKeysInWallet(params?: { body: ListKeysRequest }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -488,7 +470,6 @@ export class KmdApi { headers, body: serializedBody, mediaType: mediaType, - ...(requestOptions ?? {}), }) const responseMeta = PostKeyListResponseMeta @@ -501,7 +482,7 @@ export class KmdApi { /** * Lists all of the multisig accounts whose preimages this wallet stores */ - async listMultisg(params?: { body: ListMultisigRequest }, requestOptions?: ApiRequestOptions): Promise { + async listMultisg(params?: { body: ListMultisigRequest }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -520,7 +501,6 @@ export class KmdApi { headers, body: serializedBody, mediaType: mediaType, - ...(requestOptions ?? {}), }) const responseMeta = PostMultisigListResponseMeta @@ -533,7 +513,7 @@ export class KmdApi { /** * Lists all of the wallets that kmd is aware of. */ - async listWallets(requestOptions?: ApiRequestOptions): Promise { + async listWallets(): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -546,7 +526,6 @@ export class KmdApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = GetWalletsResponseMeta @@ -559,10 +538,7 @@ export class KmdApi { /** * Invalidate the passed wallet handle token, making it invalid for use in subsequent requests. */ - async releaseWalletHandleToken( - params?: { body: ReleaseWalletHandleTokenRequest }, - requestOptions?: ApiRequestOptions, - ): Promise { + async releaseWalletHandleToken(params?: { body: ReleaseWalletHandleTokenRequest }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -581,7 +557,6 @@ export class KmdApi { headers, body: serializedBody, mediaType: mediaType, - ...(requestOptions ?? {}), }) const responseMeta = PostWalletReleaseResponseMeta @@ -594,7 +569,7 @@ export class KmdApi { /** * Rename the underlying wallet to something else */ - async renameWallet(params?: { body: RenameWalletRequest }, requestOptions?: ApiRequestOptions): Promise { + async renameWallet(params?: { body: RenameWalletRequest }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -613,7 +588,6 @@ export class KmdApi { headers, body: serializedBody, mediaType: mediaType, - ...(requestOptions ?? {}), }) const responseMeta = PostWalletRenameResponseMeta @@ -626,10 +600,7 @@ export class KmdApi { /** * Renew a wallet handle token, increasing its expiration duration to its initial value */ - async renewWalletHandleToken( - params?: { body: RenewWalletHandleTokenRequest }, - requestOptions?: ApiRequestOptions, - ): Promise { + async renewWalletHandleToken(params?: { body: RenewWalletHandleTokenRequest }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -648,7 +619,6 @@ export class KmdApi { headers, body: serializedBody, mediaType: mediaType, - ...(requestOptions ?? {}), }) const responseMeta = PostWalletRenewResponseMeta @@ -661,10 +631,7 @@ export class KmdApi { /** * Start a multisig signature, or add a signature to a partially completed multisig signature object. */ - async signMultisigProgram( - params?: { body: SignProgramMultisigRequest }, - requestOptions?: ApiRequestOptions, - ): Promise { + async signMultisigProgram(params?: { body: SignProgramMultisigRequest }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -683,7 +650,6 @@ export class KmdApi { headers, body: serializedBody, mediaType: mediaType, - ...(requestOptions ?? {}), }) const responseMeta = PostMultisigProgramSignResponseMeta @@ -696,10 +662,7 @@ export class KmdApi { /** * Start a multisig signature, or add a signature to a partially completed multisig signature object. */ - async signMultisigTransaction( - params?: { body: SignMultisigRequest }, - requestOptions?: ApiRequestOptions, - ): Promise { + async signMultisigTransaction(params?: { body: SignMultisigRequest }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -718,7 +681,6 @@ export class KmdApi { headers, body: serializedBody, mediaType: mediaType, - ...(requestOptions ?? {}), }) const responseMeta = PostMultisigTransactionSignResponseMeta @@ -731,7 +693,7 @@ export class KmdApi { /** * Signs the passed program with a key from the wallet, determined by the account named in the request. */ - async signProgram(params?: { body: SignProgramRequest }, requestOptions?: ApiRequestOptions): Promise { + async signProgram(params?: { body: SignProgramRequest }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -750,7 +712,6 @@ export class KmdApi { headers, body: serializedBody, mediaType: mediaType, - ...(requestOptions ?? {}), }) const responseMeta = PostProgramSignResponseMeta @@ -763,10 +724,7 @@ export class KmdApi { /** * Signs the passed transaction with a key from the wallet, determined by the sender encoded in the transaction. */ - async signTransaction( - params?: { body: SignTransactionRequest }, - requestOptions?: ApiRequestOptions, - ): Promise { + async signTransaction(params?: { body: SignTransactionRequest }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -785,7 +743,6 @@ export class KmdApi { headers, body: serializedBody, mediaType: mediaType, - ...(requestOptions ?? {}), }) const responseMeta = PostTransactionSignResponseMeta @@ -798,7 +755,7 @@ export class KmdApi { /** * Returns the entire swagger spec in json. */ - async swaggerHandler(requestOptions?: ApiRequestOptions): Promise { + async swaggerHandler(): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -811,7 +768,6 @@ export class KmdApi { headers, body: undefined, mediaType: undefined, - ...(requestOptions ?? {}), }) const responseMeta = undefined From 917a2ec9dba8a601f90365785f3ff3ee69251900 Mon Sep 17 00:00:00 2001 From: Neil Campbell Date: Sun, 2 Nov 2025 00:23:50 +0800 Subject: [PATCH 06/10] chore: move body outside of params --- .../templates/apis/service.ts.j2 | 16 ++-- packages/algod_client/src/apis/api.service.ts | 33 +++---- packages/kmd_client/src/apis/api.service.ts | 90 ++++++++----------- 3 files changed, 58 insertions(+), 81 deletions(-) diff --git a/oas-generator/src/oas_generator/templates/apis/service.ts.j2 b/oas-generator/src/oas_generator/templates/apis/service.ts.j2 index f1a6b2b4e..67cf8e4ab 100644 --- a/oas-generator/src/oas_generator/templates/apis/service.ts.j2 +++ b/oas-generator/src/oas_generator/templates/apis/service.ts.j2 @@ -93,14 +93,14 @@ export class {{ service_class_name }} { {%- for p in op.pathParameters %} {{ p.varName }}: {{ p.tsType }}, {%- endfor %} -{%- if op.otherParameters|length > 0 or (op.requestBody and op.method.upper() not in ['GET', 'HEAD', 'DELETE']) %} +{%- if op.requestBody and op.method.upper() not in ['GET', 'HEAD', 'DELETE'] %} + body{% if not op.requestBody.required %}?{% endif %}: {{ op.requestBody.tsType }}, +{%- endif %} +{%- if op.otherParameters|length > 0 %} params?: { {%- for p in op.otherParameters %} {{ p.varName }}{% if not p.required %}?{% endif %}: {{ p.tsType }}; {%- endfor %} -{%- if op.requestBody and op.method.upper() not in ['GET', 'HEAD', 'DELETE'] %} - body{% if not op.requestBody.required %}?{% endif %}: {{ op.requestBody.tsType }}; -{%- endif %} } {%- endif %} ): Promise<{{ op.responseTsType }}> { @@ -111,16 +111,16 @@ export class {{ service_class_name }} { {% if op.requestBody and op.method.upper() not in ['GET', 'HEAD', 'DELETE'] %} {% if is_raw_bytes_body %} - const serializedBody = params?.body ?? undefined; + const serializedBody = body ?? undefined; const mediaType = 'application/msgpack'; headers['Content-Type'] = mediaType; {% else %} const bodyMeta = {{ meta_expr(op.requestBody.tsType) }}; const mediaType = bodyMeta ? {{ service_class_name }}.mediaFor(responseFormat) : undefined; if (mediaType) headers['Content-Type'] = mediaType; - const serializedBody = bodyMeta && params?.body !== undefined - ? AlgorandSerializer.encode(params.body, bodyMeta, responseFormat) - : params?.body; + const serializedBody = bodyMeta && body !== undefined + ? AlgorandSerializer.encode(body, bodyMeta, responseFormat) + : body; {% endif %} {% endif %} diff --git a/packages/algod_client/src/apis/api.service.ts b/packages/algod_client/src/apis/api.service.ts index 208df3300..ec56b60a7 100644 --- a/packages/algod_client/src/apis/api.service.ts +++ b/packages/algod_client/src/apis/api.service.ts @@ -229,7 +229,7 @@ export class AlgodApi { return payload as Account } - async addParticipationKey(params?: { body: string }): Promise { + async addParticipationKey(body: string): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'msgpack' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -237,8 +237,7 @@ export class AlgodApi { const bodyMeta = undefined const mediaType = bodyMeta ? AlgodApi.mediaFor(responseFormat) : undefined if (mediaType) headers['Content-Type'] = mediaType - const serializedBody = - bodyMeta && params?.body !== undefined ? AlgorandSerializer.encode(params.body, bodyMeta, responseFormat) : params?.body + const serializedBody = bodyMeta && body !== undefined ? AlgorandSerializer.encode(body, bodyMeta, responseFormat) : body const payload = await this.httpRequest.request({ method: 'POST', @@ -260,7 +259,7 @@ export class AlgodApi { /** * Given a participation ID, append state proof keys to a particular set of participation keys */ - async appendKeys(participationId: string, params?: { body: string }): Promise { + async appendKeys(participationId: string, body: string): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'msgpack' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -268,8 +267,7 @@ export class AlgodApi { const bodyMeta = undefined const mediaType = bodyMeta ? AlgodApi.mediaFor(responseFormat) : undefined if (mediaType) headers['Content-Type'] = mediaType - const serializedBody = - bodyMeta && params?.body !== undefined ? AlgorandSerializer.encode(params.body, bodyMeta, responseFormat) : params?.body + const serializedBody = bodyMeta && body !== undefined ? AlgorandSerializer.encode(body, bodyMeta, responseFormat) : body const payload = await this.httpRequest.request({ method: 'POST', @@ -1118,12 +1116,12 @@ export class AlgodApi { return payload as DebugSettingsProf } - private async rawTransaction(params?: { body: Uint8Array }): Promise { + private async rawTransaction(body: Uint8Array): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) - const serializedBody = params?.body ?? undefined + const serializedBody = body ?? undefined const mediaType = 'application/msgpack' headers['Content-Type'] = mediaType @@ -1219,7 +1217,7 @@ export class AlgodApi { return payload as ShutdownNode } - async simulateTransaction(params?: { body: SimulateRequest }): Promise { + async simulateTransaction(body: SimulateRequest): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'msgpack' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -1227,8 +1225,7 @@ export class AlgodApi { const bodyMeta = SimulateRequestMeta const mediaType = bodyMeta ? AlgodApi.mediaFor(responseFormat) : undefined if (mediaType) headers['Content-Type'] = mediaType - const serializedBody = - bodyMeta && params?.body !== undefined ? AlgorandSerializer.encode(params.body, bodyMeta, responseFormat) : params?.body + const serializedBody = bodyMeta && body !== undefined ? AlgorandSerializer.encode(body, bodyMeta, responseFormat) : body const payload = await this.httpRequest.request({ method: 'POST', @@ -1300,7 +1297,7 @@ export class AlgodApi { /** * Given TEAL source code in plain text, return base64 encoded program bytes and base32 SHA512_256 hash of program bytes (Address style). This endpoint is only enabled when a node's configuration file sets EnableDeveloperAPI to true. */ - async tealCompile(params?: { sourcemap?: boolean; body: string }): Promise { + async tealCompile(body: string, params?: { sourcemap?: boolean }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -1308,8 +1305,7 @@ export class AlgodApi { const bodyMeta = undefined const mediaType = bodyMeta ? AlgodApi.mediaFor(responseFormat) : undefined if (mediaType) headers['Content-Type'] = mediaType - const serializedBody = - bodyMeta && params?.body !== undefined ? AlgorandSerializer.encode(params.body, bodyMeta, responseFormat) : params?.body + const serializedBody = bodyMeta && body !== undefined ? AlgorandSerializer.encode(body, bodyMeta, responseFormat) : body const payload = await this.httpRequest.request({ method: 'POST', @@ -1331,12 +1327,12 @@ export class AlgodApi { /** * Given the program bytes, return the TEAL source code in plain text. This endpoint is only enabled when a node's configuration file sets EnableDeveloperAPI to true. */ - async tealDisassemble(params?: { body: Uint8Array }): Promise { + async tealDisassemble(body: Uint8Array): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) - const serializedBody = params?.body ?? undefined + const serializedBody = body ?? undefined const mediaType = 'application/msgpack' headers['Content-Type'] = mediaType @@ -1360,7 +1356,7 @@ export class AlgodApi { /** * Executes TEAL program(s) in context and returns debugging information about the execution. This endpoint is only enabled when a node's configuration file sets EnableDeveloperAPI to true. */ - async tealDryrun(params?: { body?: DryrunRequest }): Promise { + async tealDryrun(body?: DryrunRequest): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'msgpack' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -1368,8 +1364,7 @@ export class AlgodApi { const bodyMeta = DryrunRequestMeta const mediaType = bodyMeta ? AlgodApi.mediaFor(responseFormat) : undefined if (mediaType) headers['Content-Type'] = mediaType - const serializedBody = - bodyMeta && params?.body !== undefined ? AlgorandSerializer.encode(params.body, bodyMeta, responseFormat) : params?.body + const serializedBody = bodyMeta && body !== undefined ? AlgorandSerializer.encode(body, bodyMeta, responseFormat) : body const payload = await this.httpRequest.request({ method: 'POST', diff --git a/packages/kmd_client/src/apis/api.service.ts b/packages/kmd_client/src/apis/api.service.ts index 50b9c51b8..0dc0da8c5 100644 --- a/packages/kmd_client/src/apis/api.service.ts +++ b/packages/kmd_client/src/apis/api.service.ts @@ -100,7 +100,7 @@ export class KmdApi { /** * Create a new wallet (collection of keys) with the given parameters. */ - async createWallet(params?: { body: CreateWalletRequest }): Promise { + async createWallet(body: CreateWalletRequest): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -108,8 +108,7 @@ export class KmdApi { const bodyMeta = CreateWalletRequestMeta const mediaType = bodyMeta ? KmdApi.mediaFor(responseFormat) : undefined if (mediaType) headers['Content-Type'] = mediaType - const serializedBody = - bodyMeta && params?.body !== undefined ? AlgorandSerializer.encode(params.body, bodyMeta, responseFormat) : params?.body + const serializedBody = bodyMeta && body !== undefined ? AlgorandSerializer.encode(body, bodyMeta, responseFormat) : body const payload = await this.httpRequest.request({ method: 'POST', @@ -181,7 +180,7 @@ export class KmdApi { /** * Export the secret key associated with the passed public key. */ - async exportKey(params?: { body: ExportKeyRequest }): Promise { + async exportKey(body: ExportKeyRequest): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -189,8 +188,7 @@ export class KmdApi { const bodyMeta = ExportKeyRequestMeta const mediaType = bodyMeta ? KmdApi.mediaFor(responseFormat) : undefined if (mediaType) headers['Content-Type'] = mediaType - const serializedBody = - bodyMeta && params?.body !== undefined ? AlgorandSerializer.encode(params.body, bodyMeta, responseFormat) : params?.body + const serializedBody = bodyMeta && body !== undefined ? AlgorandSerializer.encode(body, bodyMeta, responseFormat) : body const payload = await this.httpRequest.request({ method: 'POST', @@ -212,7 +210,7 @@ export class KmdApi { /** * Export the master derivation key from the wallet. This key is a master "backup" key for the underlying wallet. With it, you can regenerate all of the wallets that have been generated with this wallet's `POST /v1/key` endpoint. This key will not allow you to recover keys imported from other wallets, however. */ - async exportMasterKey(params?: { body: ExportMasterKeyRequest }): Promise { + async exportMasterKey(body: ExportMasterKeyRequest): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -220,8 +218,7 @@ export class KmdApi { const bodyMeta = ExportMasterKeyRequestMeta const mediaType = bodyMeta ? KmdApi.mediaFor(responseFormat) : undefined if (mediaType) headers['Content-Type'] = mediaType - const serializedBody = - bodyMeta && params?.body !== undefined ? AlgorandSerializer.encode(params.body, bodyMeta, responseFormat) : params?.body + const serializedBody = bodyMeta && body !== undefined ? AlgorandSerializer.encode(body, bodyMeta, responseFormat) : body const payload = await this.httpRequest.request({ method: 'POST', @@ -243,7 +240,7 @@ export class KmdApi { /** * Given a multisig address whose preimage this wallet stores, returns the information used to generate the address, including public keys, threshold, and multisig version. */ - async exportMultisig(params?: { body: ExportMultisigRequest }): Promise { + async exportMultisig(body: ExportMultisigRequest): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -251,8 +248,7 @@ export class KmdApi { const bodyMeta = ExportMultisigRequestMeta const mediaType = bodyMeta ? KmdApi.mediaFor(responseFormat) : undefined if (mediaType) headers['Content-Type'] = mediaType - const serializedBody = - bodyMeta && params?.body !== undefined ? AlgorandSerializer.encode(params.body, bodyMeta, responseFormat) : params?.body + const serializedBody = bodyMeta && body !== undefined ? AlgorandSerializer.encode(body, bodyMeta, responseFormat) : body const payload = await this.httpRequest.request({ method: 'POST', @@ -274,7 +270,7 @@ export class KmdApi { /** * Generates the next key in the deterministic key sequence (as determined by the master derivation key) and adds it to the wallet, returning the public key. */ - async generateKey(params?: { body: GenerateKeyRequest }): Promise { + async generateKey(body: GenerateKeyRequest): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -282,8 +278,7 @@ export class KmdApi { const bodyMeta = GenerateKeyRequestMeta const mediaType = bodyMeta ? KmdApi.mediaFor(responseFormat) : undefined if (mediaType) headers['Content-Type'] = mediaType - const serializedBody = - bodyMeta && params?.body !== undefined ? AlgorandSerializer.encode(params.body, bodyMeta, responseFormat) : params?.body + const serializedBody = bodyMeta && body !== undefined ? AlgorandSerializer.encode(body, bodyMeta, responseFormat) : body const payload = await this.httpRequest.request({ method: 'POST', @@ -327,7 +322,7 @@ export class KmdApi { /** * Returns information about the wallet associated with the passed wallet handle token. Additionally returns expiration information about the token itself. */ - async getWalletInfo(params?: { body: WalletInfoRequest }): Promise { + async getWalletInfo(body: WalletInfoRequest): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -335,8 +330,7 @@ export class KmdApi { const bodyMeta = WalletInfoRequestMeta const mediaType = bodyMeta ? KmdApi.mediaFor(responseFormat) : undefined if (mediaType) headers['Content-Type'] = mediaType - const serializedBody = - bodyMeta && params?.body !== undefined ? AlgorandSerializer.encode(params.body, bodyMeta, responseFormat) : params?.body + const serializedBody = bodyMeta && body !== undefined ? AlgorandSerializer.encode(body, bodyMeta, responseFormat) : body const payload = await this.httpRequest.request({ method: 'POST', @@ -358,7 +352,7 @@ export class KmdApi { /** * Import an externally generated key into the wallet. Note that if you wish to back up the imported key, you must do so by backing up the entire wallet database, because imported keys were not derived from the wallet's master derivation key. */ - async importKey(params?: { body: ImportKeyRequest }): Promise { + async importKey(body: ImportKeyRequest): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -366,8 +360,7 @@ export class KmdApi { const bodyMeta = ImportKeyRequestMeta const mediaType = bodyMeta ? KmdApi.mediaFor(responseFormat) : undefined if (mediaType) headers['Content-Type'] = mediaType - const serializedBody = - bodyMeta && params?.body !== undefined ? AlgorandSerializer.encode(params.body, bodyMeta, responseFormat) : params?.body + const serializedBody = bodyMeta && body !== undefined ? AlgorandSerializer.encode(body, bodyMeta, responseFormat) : body const payload = await this.httpRequest.request({ method: 'POST', @@ -389,7 +382,7 @@ export class KmdApi { /** * Generates a multisig account from the passed public keys array and multisig metadata, and stores all of this in the wallet. */ - async importMultisig(params?: { body: ImportMultisigRequest }): Promise { + async importMultisig(body: ImportMultisigRequest): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -397,8 +390,7 @@ export class KmdApi { const bodyMeta = ImportMultisigRequestMeta const mediaType = bodyMeta ? KmdApi.mediaFor(responseFormat) : undefined if (mediaType) headers['Content-Type'] = mediaType - const serializedBody = - bodyMeta && params?.body !== undefined ? AlgorandSerializer.encode(params.body, bodyMeta, responseFormat) : params?.body + const serializedBody = bodyMeta && body !== undefined ? AlgorandSerializer.encode(body, bodyMeta, responseFormat) : body const payload = await this.httpRequest.request({ method: 'POST', @@ -420,7 +412,7 @@ export class KmdApi { /** * Unlock the wallet and return a wallet handle token that can be used for subsequent operations. These tokens expire periodically and must be renewed. You can `POST` the token to `/v1/wallet/info` to see how much time remains until expiration, and renew it with `/v1/wallet/renew`. When you're done, you can invalidate the token with `/v1/wallet/release`. */ - async initWalletHandleToken(params?: { body: InitWalletHandleTokenRequest }): Promise { + async initWalletHandleToken(body: InitWalletHandleTokenRequest): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -428,8 +420,7 @@ export class KmdApi { const bodyMeta = InitWalletHandleTokenRequestMeta const mediaType = bodyMeta ? KmdApi.mediaFor(responseFormat) : undefined if (mediaType) headers['Content-Type'] = mediaType - const serializedBody = - bodyMeta && params?.body !== undefined ? AlgorandSerializer.encode(params.body, bodyMeta, responseFormat) : params?.body + const serializedBody = bodyMeta && body !== undefined ? AlgorandSerializer.encode(body, bodyMeta, responseFormat) : body const payload = await this.httpRequest.request({ method: 'POST', @@ -451,7 +442,7 @@ export class KmdApi { /** * Lists all of the public keys in this wallet. All of them have a stored private key. */ - async listKeysInWallet(params?: { body: ListKeysRequest }): Promise { + async listKeysInWallet(body: ListKeysRequest): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -459,8 +450,7 @@ export class KmdApi { const bodyMeta = ListKeysRequestMeta const mediaType = bodyMeta ? KmdApi.mediaFor(responseFormat) : undefined if (mediaType) headers['Content-Type'] = mediaType - const serializedBody = - bodyMeta && params?.body !== undefined ? AlgorandSerializer.encode(params.body, bodyMeta, responseFormat) : params?.body + const serializedBody = bodyMeta && body !== undefined ? AlgorandSerializer.encode(body, bodyMeta, responseFormat) : body const payload = await this.httpRequest.request({ method: 'POST', @@ -482,7 +472,7 @@ export class KmdApi { /** * Lists all of the multisig accounts whose preimages this wallet stores */ - async listMultisg(params?: { body: ListMultisigRequest }): Promise { + async listMultisg(body: ListMultisigRequest): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -490,8 +480,7 @@ export class KmdApi { const bodyMeta = ListMultisigRequestMeta const mediaType = bodyMeta ? KmdApi.mediaFor(responseFormat) : undefined if (mediaType) headers['Content-Type'] = mediaType - const serializedBody = - bodyMeta && params?.body !== undefined ? AlgorandSerializer.encode(params.body, bodyMeta, responseFormat) : params?.body + const serializedBody = bodyMeta && body !== undefined ? AlgorandSerializer.encode(body, bodyMeta, responseFormat) : body const payload = await this.httpRequest.request({ method: 'POST', @@ -538,7 +527,7 @@ export class KmdApi { /** * Invalidate the passed wallet handle token, making it invalid for use in subsequent requests. */ - async releaseWalletHandleToken(params?: { body: ReleaseWalletHandleTokenRequest }): Promise { + async releaseWalletHandleToken(body: ReleaseWalletHandleTokenRequest): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -546,8 +535,7 @@ export class KmdApi { const bodyMeta = ReleaseWalletHandleTokenRequestMeta const mediaType = bodyMeta ? KmdApi.mediaFor(responseFormat) : undefined if (mediaType) headers['Content-Type'] = mediaType - const serializedBody = - bodyMeta && params?.body !== undefined ? AlgorandSerializer.encode(params.body, bodyMeta, responseFormat) : params?.body + const serializedBody = bodyMeta && body !== undefined ? AlgorandSerializer.encode(body, bodyMeta, responseFormat) : body const payload = await this.httpRequest.request({ method: 'POST', @@ -569,7 +557,7 @@ export class KmdApi { /** * Rename the underlying wallet to something else */ - async renameWallet(params?: { body: RenameWalletRequest }): Promise { + async renameWallet(body: RenameWalletRequest): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -577,8 +565,7 @@ export class KmdApi { const bodyMeta = RenameWalletRequestMeta const mediaType = bodyMeta ? KmdApi.mediaFor(responseFormat) : undefined if (mediaType) headers['Content-Type'] = mediaType - const serializedBody = - bodyMeta && params?.body !== undefined ? AlgorandSerializer.encode(params.body, bodyMeta, responseFormat) : params?.body + const serializedBody = bodyMeta && body !== undefined ? AlgorandSerializer.encode(body, bodyMeta, responseFormat) : body const payload = await this.httpRequest.request({ method: 'POST', @@ -600,7 +587,7 @@ export class KmdApi { /** * Renew a wallet handle token, increasing its expiration duration to its initial value */ - async renewWalletHandleToken(params?: { body: RenewWalletHandleTokenRequest }): Promise { + async renewWalletHandleToken(body: RenewWalletHandleTokenRequest): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -608,8 +595,7 @@ export class KmdApi { const bodyMeta = RenewWalletHandleTokenRequestMeta const mediaType = bodyMeta ? KmdApi.mediaFor(responseFormat) : undefined if (mediaType) headers['Content-Type'] = mediaType - const serializedBody = - bodyMeta && params?.body !== undefined ? AlgorandSerializer.encode(params.body, bodyMeta, responseFormat) : params?.body + const serializedBody = bodyMeta && body !== undefined ? AlgorandSerializer.encode(body, bodyMeta, responseFormat) : body const payload = await this.httpRequest.request({ method: 'POST', @@ -631,7 +617,7 @@ export class KmdApi { /** * Start a multisig signature, or add a signature to a partially completed multisig signature object. */ - async signMultisigProgram(params?: { body: SignProgramMultisigRequest }): Promise { + async signMultisigProgram(body: SignProgramMultisigRequest): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -639,8 +625,7 @@ export class KmdApi { const bodyMeta = SignProgramMultisigRequestMeta const mediaType = bodyMeta ? KmdApi.mediaFor(responseFormat) : undefined if (mediaType) headers['Content-Type'] = mediaType - const serializedBody = - bodyMeta && params?.body !== undefined ? AlgorandSerializer.encode(params.body, bodyMeta, responseFormat) : params?.body + const serializedBody = bodyMeta && body !== undefined ? AlgorandSerializer.encode(body, bodyMeta, responseFormat) : body const payload = await this.httpRequest.request({ method: 'POST', @@ -662,7 +647,7 @@ export class KmdApi { /** * Start a multisig signature, or add a signature to a partially completed multisig signature object. */ - async signMultisigTransaction(params?: { body: SignMultisigRequest }): Promise { + async signMultisigTransaction(body: SignMultisigRequest): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -670,8 +655,7 @@ export class KmdApi { const bodyMeta = SignMultisigRequestMeta const mediaType = bodyMeta ? KmdApi.mediaFor(responseFormat) : undefined if (mediaType) headers['Content-Type'] = mediaType - const serializedBody = - bodyMeta && params?.body !== undefined ? AlgorandSerializer.encode(params.body, bodyMeta, responseFormat) : params?.body + const serializedBody = bodyMeta && body !== undefined ? AlgorandSerializer.encode(body, bodyMeta, responseFormat) : body const payload = await this.httpRequest.request({ method: 'POST', @@ -693,7 +677,7 @@ export class KmdApi { /** * Signs the passed program with a key from the wallet, determined by the account named in the request. */ - async signProgram(params?: { body: SignProgramRequest }): Promise { + async signProgram(body: SignProgramRequest): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -701,8 +685,7 @@ export class KmdApi { const bodyMeta = SignProgramRequestMeta const mediaType = bodyMeta ? KmdApi.mediaFor(responseFormat) : undefined if (mediaType) headers['Content-Type'] = mediaType - const serializedBody = - bodyMeta && params?.body !== undefined ? AlgorandSerializer.encode(params.body, bodyMeta, responseFormat) : params?.body + const serializedBody = bodyMeta && body !== undefined ? AlgorandSerializer.encode(body, bodyMeta, responseFormat) : body const payload = await this.httpRequest.request({ method: 'POST', @@ -724,7 +707,7 @@ export class KmdApi { /** * Signs the passed transaction with a key from the wallet, determined by the sender encoded in the transaction. */ - async signTransaction(params?: { body: SignTransactionRequest }): Promise { + async signTransaction(body: SignTransactionRequest): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) @@ -732,8 +715,7 @@ export class KmdApi { const bodyMeta = SignTransactionRequestMeta const mediaType = bodyMeta ? KmdApi.mediaFor(responseFormat) : undefined if (mediaType) headers['Content-Type'] = mediaType - const serializedBody = - bodyMeta && params?.body !== undefined ? AlgorandSerializer.encode(params.body, bodyMeta, responseFormat) : params?.body + const serializedBody = bodyMeta && body !== undefined ? AlgorandSerializer.encode(body, bodyMeta, responseFormat) : body const payload = await this.httpRequest.request({ method: 'POST', From bb025f937c16fa3b08593107fba78d756db4680e Mon Sep 17 00:00:00 2001 From: Neil Campbell Date: Sun, 2 Nov 2025 15:32:38 +0800 Subject: [PATCH 07/10] fix: correct some more algod handlings --- .../openapi-converter/specs/algod.oas3.json | 4 +- .../generator/template_engine.py | 2 +- .../templates/base/src/core/codecs.ts.j2 | 2 +- .../base/src/core/model-runtime.ts.j2 | 42 ++++++++++++++++++- packages/algod_client/src/apis/api.service.ts | 2 +- packages/algod_client/src/core/codecs.ts | 2 +- .../algod_client/src/core/model-runtime.ts | 42 ++++++++++++++++++- packages/algod_client/src/models/avm-value.ts | 4 +- .../algod_client/src/models/teal-value.ts | 4 +- packages/indexer_client/src/core/codecs.ts | 2 +- .../indexer_client/src/core/model-runtime.ts | 42 ++++++++++++++++++- packages/kmd_client/src/core/codecs.ts | 2 +- packages/kmd_client/src/core/model-runtime.ts | 42 ++++++++++++++++++- packages/sdk/src/composer.ts | 2 +- ...rm-atomic-transaction-composer-simulate.ts | 2 +- src/transaction/transaction.ts | 4 +- src/types/algorand-client.spec.ts | 6 +-- src/types/app-factory-and-client.spec.ts | 2 +- src/types/app-manager.ts | 2 +- tsconfig.base.json | 2 +- tsconfig.json | 4 +- 21 files changed, 185 insertions(+), 31 deletions(-) diff --git a/algokit-configs/openapi-converter/specs/algod.oas3.json b/algokit-configs/openapi-converter/specs/algod.oas3.json index e9e7ae640..9d21fdeaa 100644 --- a/algokit-configs/openapi-converter/specs/algod.oas3.json +++ b/algokit-configs/openapi-converter/specs/algod.oas3.json @@ -5306,7 +5306,7 @@ "type": { "type": "integer", "description": "\\[tt\\] value type. Value `1` refers to **bytes**, value `2` refers to **uint**", - "x-algokit-bigint": true + "format": "int32" }, "bytes": { "type": "string", @@ -5331,7 +5331,7 @@ "type": { "type": "integer", "description": "value type. Value `1` refers to **bytes**, value `2` refers to **uint64**", - "x-algokit-bigint": true + "format": "int32" }, "bytes": { "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", diff --git a/oas-generator/src/oas_generator/generator/template_engine.py b/oas-generator/src/oas_generator/generator/template_engine.py index 74d492e44..f8a453b27 100644 --- a/oas-generator/src/oas_generator/generator/template_engine.py +++ b/oas-generator/src/oas_generator/generator/template_engine.py @@ -345,7 +345,7 @@ def _get_custom_service_extensions(self, service_class_name: str) -> tuple[list[ } else if (!(rawTransactions instanceof Uint8Array)) { throw new Error('Argument must be byte array'); } - return this.rawTransaction({ body: rawTransactions }); + return this.rawTransaction(rawTransactions); }''' custom_methods = [send_raw_transaction_method] diff --git a/oas-generator/src/oas_generator/templates/base/src/core/codecs.ts.j2 b/oas-generator/src/oas_generator/templates/base/src/core/codecs.ts.j2 index 0476523ef..35549be3a 100644 --- a/oas-generator/src/oas_generator/templates/base/src/core/codecs.ts.j2 +++ b/oas-generator/src/oas_generator/templates/base/src/core/codecs.ts.j2 @@ -14,7 +14,7 @@ export function decodeMsgPack(buffer: Uint8Array): T { * Maps are converted to objects recursively, except for the special case * where the field name is "r" which remains as a Map. */ -export function mapToObject(value: unknown, fieldName?: string): unknown { +function mapToObject(value: unknown, fieldName?: string): unknown { // Preserve Uint8Array as-is if (value instanceof Uint8Array) { return value; diff --git a/oas-generator/src/oas_generator/templates/base/src/core/model-runtime.ts.j2 b/oas-generator/src/oas_generator/templates/base/src/core/model-runtime.ts.j2 index 72d16545d..dde27e9d1 100644 --- a/oas-generator/src/oas_generator/templates/base/src/core/model-runtime.ts.j2 +++ b/oas-generator/src/oas_generator/templates/base/src/core/model-runtime.ts.j2 @@ -6,7 +6,7 @@ import { import { encodeMsgPack, decodeMsgPack } from './codecs'; import { toBase64, fromBase64 } from './serialization'; -export type BodyFormat = 'json' | 'msgpack'; +export type BodyFormat = 'json' | 'msgpack' | 'map'; export interface ScalarFieldType { readonly kind: 'scalar'; @@ -90,7 +90,16 @@ export function getCodec(key: string): TypeCodec | undefined { } export class AlgorandSerializer { - static encode(value: unknown, meta: ModelMetadata, format: BodyFormat = 'msgpack'): Uint8Array | string { + static encode(value: unknown, meta: ModelMetadata, format: 'map'): Map + static encode(value: unknown, meta: ModelMetadata, format: 'json'): string + static encode(value: unknown, meta: ModelMetadata, format?: 'msgpack'): Uint8Array + static encode(value: unknown, meta: ModelMetadata, format: BodyFormat = 'msgpack'): Uint8Array | string | Map { + if (format === 'map') { + // For map format, use msgpack transformation to preserve types like bigint, then convert to nested Maps + const wire = this.transform(value, meta, { direction: 'encode', format: 'msgpack' }); + return this.convertToNestedMaps(wire) as Map; + } + const wire = this.transform(value, meta, { direction: 'encode', format }); if (format === 'msgpack') { return wire instanceof Uint8Array ? wire : encodeMsgPack(wire); @@ -258,6 +267,35 @@ export class AlgorandSerializer { ? codec.encode(value, ctx.format) : codec.decode(value, ctx.format); } + + private static convertToNestedMaps(value: unknown): Map | unknown[] | unknown { + if (value === null || value === undefined) { + return value; + } + + if (Array.isArray(value)) { + // Keep arrays as arrays but recursively convert nested objects to Maps + return value.map((item) => { + if (typeof item === 'object' && item !== null && !Array.isArray(item) && !(item instanceof Uint8Array)) { + return this.convertToNestedMaps(item); + } else if (Array.isArray(item)) { + return this.convertToNestedMaps(item); + } + return item; + }) + } + + if (typeof value === 'object' && value !== null && !(value instanceof Uint8Array)) { + const map = new Map(); + Object.entries(value as Record).forEach(([key, val]) => { + map.set(key, this.convertToNestedMaps(val)); + }); + return map; + } + + // For primitive values and Uint8Array, return them directly + return value; + } } type TransformDirection = 'encode' | 'decode'; diff --git a/packages/algod_client/src/apis/api.service.ts b/packages/algod_client/src/apis/api.service.ts index ec56b60a7..2cb359592 100644 --- a/packages/algod_client/src/apis/api.service.ts +++ b/packages/algod_client/src/apis/api.service.ts @@ -1468,6 +1468,6 @@ export class AlgodApi { } else if (!(rawTransactions instanceof Uint8Array)) { throw new Error('Argument must be byte array') } - return this.rawTransaction({ body: rawTransactions }) + return this.rawTransaction(rawTransactions) } } diff --git a/packages/algod_client/src/core/codecs.ts b/packages/algod_client/src/core/codecs.ts index 9215f7e64..829dcd7b5 100644 --- a/packages/algod_client/src/core/codecs.ts +++ b/packages/algod_client/src/core/codecs.ts @@ -14,7 +14,7 @@ export function decodeMsgPack(buffer: Uint8Array): T { * Maps are converted to objects recursively, except for the special case * where the field name is "r" which remains as a Map. */ -export function mapToObject(value: unknown, fieldName?: string): unknown { +function mapToObject(value: unknown, fieldName?: string): unknown { // Preserve Uint8Array as-is if (value instanceof Uint8Array) { return value diff --git a/packages/algod_client/src/core/model-runtime.ts b/packages/algod_client/src/core/model-runtime.ts index eecaf8bb8..ed41c1889 100644 --- a/packages/algod_client/src/core/model-runtime.ts +++ b/packages/algod_client/src/core/model-runtime.ts @@ -6,7 +6,7 @@ import { import { encodeMsgPack, decodeMsgPack } from './codecs' import { toBase64, fromBase64 } from './serialization' -export type BodyFormat = 'json' | 'msgpack' +export type BodyFormat = 'json' | 'msgpack' | 'map' export interface ScalarFieldType { readonly kind: 'scalar' @@ -90,7 +90,16 @@ export function getCodec(key: string): TypeCodec | undefined { } export class AlgorandSerializer { - static encode(value: unknown, meta: ModelMetadata, format: BodyFormat = 'msgpack'): Uint8Array | string { + static encode(value: unknown, meta: ModelMetadata, format: 'map'): Map + static encode(value: unknown, meta: ModelMetadata, format: 'json'): string + static encode(value: unknown, meta: ModelMetadata, format?: 'msgpack'): Uint8Array + static encode(value: unknown, meta: ModelMetadata, format: BodyFormat = 'msgpack'): Uint8Array | string | Map { + if (format === 'map') { + // For map format, use msgpack transformation to preserve types like bigint, then convert to nested Maps + const wire = this.transform(value, meta, { direction: 'encode', format: 'msgpack' }) + return this.convertToNestedMaps(wire) as Map + } + const wire = this.transform(value, meta, { direction: 'encode', format }) if (format === 'msgpack') { return wire instanceof Uint8Array ? wire : encodeMsgPack(wire) @@ -254,6 +263,35 @@ export class AlgorandSerializer { } return ctx.direction === 'encode' ? codec.encode(value, ctx.format) : codec.decode(value, ctx.format) } + + private static convertToNestedMaps(value: unknown): Map | unknown[] | unknown { + if (value === null || value === undefined) { + return value + } + + if (Array.isArray(value)) { + // Keep arrays as arrays but recursively convert nested objects to Maps + return value.map((item) => { + if (typeof item === 'object' && item !== null && !Array.isArray(item) && !(item instanceof Uint8Array)) { + return this.convertToNestedMaps(item) + } else if (Array.isArray(item)) { + return this.convertToNestedMaps(item) + } + return item + }) + } + + if (typeof value === 'object' && value !== null && !(value instanceof Uint8Array)) { + const map = new Map() + Object.entries(value as Record).forEach(([key, val]) => { + map.set(key, this.convertToNestedMaps(val)) + }) + return map + } + + // For primitive values and Uint8Array, return them directly + return value + } } type TransformDirection = 'encode' | 'decode' diff --git a/packages/algod_client/src/models/avm-value.ts b/packages/algod_client/src/models/avm-value.ts index bcb9cc157..95e1614f9 100644 --- a/packages/algod_client/src/models/avm-value.ts +++ b/packages/algod_client/src/models/avm-value.ts @@ -7,7 +7,7 @@ export type AvmValue = { /** * value type. Value `1` refers to **bytes**, value `2` refers to **uint64** */ - type: bigint + type: number /** * bytes value. @@ -29,7 +29,7 @@ export const AvmValueMeta: ModelMetadata = { wireKey: 'type', optional: false, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, { name: 'bytes', diff --git a/packages/algod_client/src/models/teal-value.ts b/packages/algod_client/src/models/teal-value.ts index f78bea8d8..30ac4318f 100644 --- a/packages/algod_client/src/models/teal-value.ts +++ b/packages/algod_client/src/models/teal-value.ts @@ -7,7 +7,7 @@ export type TealValue = { /** * \[tt\] value type. Value `1` refers to **bytes**, value `2` refers to **uint** */ - type: bigint + type: number /** * \[tb\] bytes value. @@ -29,7 +29,7 @@ export const TealValueMeta: ModelMetadata = { wireKey: 'type', optional: false, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, { name: 'bytes', diff --git a/packages/indexer_client/src/core/codecs.ts b/packages/indexer_client/src/core/codecs.ts index 9215f7e64..829dcd7b5 100644 --- a/packages/indexer_client/src/core/codecs.ts +++ b/packages/indexer_client/src/core/codecs.ts @@ -14,7 +14,7 @@ export function decodeMsgPack(buffer: Uint8Array): T { * Maps are converted to objects recursively, except for the special case * where the field name is "r" which remains as a Map. */ -export function mapToObject(value: unknown, fieldName?: string): unknown { +function mapToObject(value: unknown, fieldName?: string): unknown { // Preserve Uint8Array as-is if (value instanceof Uint8Array) { return value diff --git a/packages/indexer_client/src/core/model-runtime.ts b/packages/indexer_client/src/core/model-runtime.ts index eecaf8bb8..ed41c1889 100644 --- a/packages/indexer_client/src/core/model-runtime.ts +++ b/packages/indexer_client/src/core/model-runtime.ts @@ -6,7 +6,7 @@ import { import { encodeMsgPack, decodeMsgPack } from './codecs' import { toBase64, fromBase64 } from './serialization' -export type BodyFormat = 'json' | 'msgpack' +export type BodyFormat = 'json' | 'msgpack' | 'map' export interface ScalarFieldType { readonly kind: 'scalar' @@ -90,7 +90,16 @@ export function getCodec(key: string): TypeCodec | undefined { } export class AlgorandSerializer { - static encode(value: unknown, meta: ModelMetadata, format: BodyFormat = 'msgpack'): Uint8Array | string { + static encode(value: unknown, meta: ModelMetadata, format: 'map'): Map + static encode(value: unknown, meta: ModelMetadata, format: 'json'): string + static encode(value: unknown, meta: ModelMetadata, format?: 'msgpack'): Uint8Array + static encode(value: unknown, meta: ModelMetadata, format: BodyFormat = 'msgpack'): Uint8Array | string | Map { + if (format === 'map') { + // For map format, use msgpack transformation to preserve types like bigint, then convert to nested Maps + const wire = this.transform(value, meta, { direction: 'encode', format: 'msgpack' }) + return this.convertToNestedMaps(wire) as Map + } + const wire = this.transform(value, meta, { direction: 'encode', format }) if (format === 'msgpack') { return wire instanceof Uint8Array ? wire : encodeMsgPack(wire) @@ -254,6 +263,35 @@ export class AlgorandSerializer { } return ctx.direction === 'encode' ? codec.encode(value, ctx.format) : codec.decode(value, ctx.format) } + + private static convertToNestedMaps(value: unknown): Map | unknown[] | unknown { + if (value === null || value === undefined) { + return value + } + + if (Array.isArray(value)) { + // Keep arrays as arrays but recursively convert nested objects to Maps + return value.map((item) => { + if (typeof item === 'object' && item !== null && !Array.isArray(item) && !(item instanceof Uint8Array)) { + return this.convertToNestedMaps(item) + } else if (Array.isArray(item)) { + return this.convertToNestedMaps(item) + } + return item + }) + } + + if (typeof value === 'object' && value !== null && !(value instanceof Uint8Array)) { + const map = new Map() + Object.entries(value as Record).forEach(([key, val]) => { + map.set(key, this.convertToNestedMaps(val)) + }) + return map + } + + // For primitive values and Uint8Array, return them directly + return value + } } type TransformDirection = 'encode' | 'decode' diff --git a/packages/kmd_client/src/core/codecs.ts b/packages/kmd_client/src/core/codecs.ts index 9215f7e64..829dcd7b5 100644 --- a/packages/kmd_client/src/core/codecs.ts +++ b/packages/kmd_client/src/core/codecs.ts @@ -14,7 +14,7 @@ export function decodeMsgPack(buffer: Uint8Array): T { * Maps are converted to objects recursively, except for the special case * where the field name is "r" which remains as a Map. */ -export function mapToObject(value: unknown, fieldName?: string): unknown { +function mapToObject(value: unknown, fieldName?: string): unknown { // Preserve Uint8Array as-is if (value instanceof Uint8Array) { return value diff --git a/packages/kmd_client/src/core/model-runtime.ts b/packages/kmd_client/src/core/model-runtime.ts index eecaf8bb8..ed41c1889 100644 --- a/packages/kmd_client/src/core/model-runtime.ts +++ b/packages/kmd_client/src/core/model-runtime.ts @@ -6,7 +6,7 @@ import { import { encodeMsgPack, decodeMsgPack } from './codecs' import { toBase64, fromBase64 } from './serialization' -export type BodyFormat = 'json' | 'msgpack' +export type BodyFormat = 'json' | 'msgpack' | 'map' export interface ScalarFieldType { readonly kind: 'scalar' @@ -90,7 +90,16 @@ export function getCodec(key: string): TypeCodec | undefined { } export class AlgorandSerializer { - static encode(value: unknown, meta: ModelMetadata, format: BodyFormat = 'msgpack'): Uint8Array | string { + static encode(value: unknown, meta: ModelMetadata, format: 'map'): Map + static encode(value: unknown, meta: ModelMetadata, format: 'json'): string + static encode(value: unknown, meta: ModelMetadata, format?: 'msgpack'): Uint8Array + static encode(value: unknown, meta: ModelMetadata, format: BodyFormat = 'msgpack'): Uint8Array | string | Map { + if (format === 'map') { + // For map format, use msgpack transformation to preserve types like bigint, then convert to nested Maps + const wire = this.transform(value, meta, { direction: 'encode', format: 'msgpack' }) + return this.convertToNestedMaps(wire) as Map + } + const wire = this.transform(value, meta, { direction: 'encode', format }) if (format === 'msgpack') { return wire instanceof Uint8Array ? wire : encodeMsgPack(wire) @@ -254,6 +263,35 @@ export class AlgorandSerializer { } return ctx.direction === 'encode' ? codec.encode(value, ctx.format) : codec.decode(value, ctx.format) } + + private static convertToNestedMaps(value: unknown): Map | unknown[] | unknown { + if (value === null || value === undefined) { + return value + } + + if (Array.isArray(value)) { + // Keep arrays as arrays but recursively convert nested objects to Maps + return value.map((item) => { + if (typeof item === 'object' && item !== null && !Array.isArray(item) && !(item instanceof Uint8Array)) { + return this.convertToNestedMaps(item) + } else if (Array.isArray(item)) { + return this.convertToNestedMaps(item) + } + return item + }) + } + + if (typeof value === 'object' && value !== null && !(value instanceof Uint8Array)) { + const map = new Map() + Object.entries(value as Record).forEach(([key, val]) => { + map.set(key, this.convertToNestedMaps(val)) + }) + return map + } + + // For primitive values and Uint8Array, return them directly + return value + } } type TransformDirection = 'encode' | 'decode' diff --git a/packages/sdk/src/composer.ts b/packages/sdk/src/composer.ts index 52d29f128..7cc2dd1b9 100644 --- a/packages/sdk/src/composer.ts +++ b/packages/sdk/src/composer.ts @@ -612,7 +612,7 @@ export class AtomicTransactionComposer { }, ] - const simulateResponse = await client.simulateTransaction({ body: currentRequest }) + const simulateResponse = await client.simulateTransaction(currentRequest) // Parse method response const methodResults: ABIResult[] = [] diff --git a/src/transaction/perform-atomic-transaction-composer-simulate.ts b/src/transaction/perform-atomic-transaction-composer-simulate.ts index d32a9032e..27d9651c4 100644 --- a/src/transaction/perform-atomic-transaction-composer-simulate.ts +++ b/src/transaction/perform-atomic-transaction-composer-simulate.ts @@ -43,6 +43,6 @@ export async function performAtomicTransactionComposerSimulate( } satisfies SimulateRequestTransactionGroup, ], } satisfies SimulateRequest - const simulateResult = await algod.simulateTransaction({ body: simulateRequest }) + const simulateResult = await algod.simulateTransaction(simulateRequest) return simulateResult } diff --git a/src/transaction/transaction.ts b/src/transaction/transaction.ts index fd198ce54..a557c502f 100644 --- a/src/transaction/transaction.ts +++ b/src/transaction/transaction.ts @@ -1,10 +1,12 @@ import { AlgodClient, + AlgorandSerializer, ApplicationLocalReference, AssetHoldingReference, BoxReference, PendingTransactionResponse, SimulateRequest, + SimulationTransactionExecTraceMeta, } from '@algorandfoundation/algokit-algod-client' import type { AppCallTransactionFields } from '@algorandfoundation/algokit-transact' import { Transaction, TransactionType, encodeTransaction, getTransactionId } from '@algorandfoundation/algokit-transact' @@ -944,7 +946,7 @@ export const sendAtomicTransactionComposer = async function (atcSend: AtomicTran if (simulate && simulate.txnGroups[0].failedAt) { for (const txn of simulate.txnGroups[0].txnResults) { err.traces.push({ - trace: undefined, // TODO: PD - need to encode txn.execTrace?.toEncodingData(), SimulationTransactionExecTrace + trace: AlgorandSerializer.encode(txn.execTrace, SimulationTransactionExecTraceMeta, 'map'), appBudget: txn.appBudgetConsumed, logicSigBudget: txn.logicSigBudgetConsumed, logs: txn.txnResult.logs, diff --git a/src/types/algorand-client.spec.ts b/src/types/algorand-client.spec.ts index b8f6147b1..40f8b1591 100644 --- a/src/types/algorand-client.spec.ts +++ b/src/types/algorand-client.spec.ts @@ -1,7 +1,7 @@ -import { beforeAll, describe, expect, test } from 'vitest' -import { APP_SPEC, TestContractClient } from '../../tests/example-contracts/client/TestContractClient' import * as algosdk from '@algorandfoundation/sdk' import { Account, Address } from '@algorandfoundation/sdk' +import { beforeAll, describe, expect, test } from 'vitest' +import { APP_SPEC, TestContractClient } from '../../tests/example-contracts/client/TestContractClient' import { algorandFixture } from '../testing' import { AlgorandClient } from './algorand-client' import { AlgoAmount } from './amount' @@ -10,7 +10,7 @@ import { AppCallMethodCall } from './composer' async function compileProgram(algorand: AlgorandClient, b64Teal: string) { // Decode the base64-encoded TEAL source code const tealSource = Buffer.from(b64Teal, 'base64').toString('utf-8') - const result = await algorand.client.algod.tealCompile({ body: tealSource }) + const result = await algorand.client.algod.tealCompile(tealSource) return new Uint8Array(Buffer.from(result.result, 'base64')) } diff --git a/src/types/app-factory-and-client.spec.ts b/src/types/app-factory-and-client.spec.ts index c08a0497a..ada348083 100644 --- a/src/types/app-factory-and-client.spec.ts +++ b/src/types/app-factory-and-client.spec.ts @@ -535,7 +535,7 @@ describe('ARC32: app-factory-and-app-client', () => { invariant(false) // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (e: any) { - expect(e.stack).toContain('assert failed') + expect(e.message).toContain('assert failed') } newClient.importSourceMaps(JSON.parse(JSON.stringify(oldSourceMaps))) diff --git a/src/types/app-manager.ts b/src/types/app-manager.ts index 8ba483939..cfe41ede6 100644 --- a/src/types/app-manager.ts +++ b/src/types/app-manager.ts @@ -129,7 +129,7 @@ export class AppManager { return this._compilationResults[tealCode] } - const compiled = await this._algod.tealCompile({ body: tealCode, sourcemap: true }) + const compiled = await this._algod.tealCompile(tealCode, { sourcemap: true }) const result = { teal: tealCode, compiled: compiled.result, diff --git a/tsconfig.base.json b/tsconfig.base.json index ad96180ce..e90dc13b8 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -4,7 +4,7 @@ "target": "ES2022", "moduleResolution": "Bundler", "esModuleInterop": true, - "lib": ["es2020", "dom"], + "lib": ["ES2022", "dom"], "types": ["node"], "declaration": true, "importHelpers": true, diff --git a/tsconfig.json b/tsconfig.json index f6b25f169..10aeb1a6f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,10 +2,10 @@ "extends": "@tsconfig/node20/tsconfig.json", "compilerOptions": { "module": "ESNext", - "target": "ES2020", + "target": "ES2022", "moduleResolution": "Bundler", "esModuleInterop": true, - "lib": ["es2020", "dom"], + "lib": ["ES2022", "dom"], "types": ["node"], "outDir": "dist", "declaration": true, From c2911cee33bb8dc1413979a84fc1e1d18420c108 Mon Sep 17 00:00:00 2001 From: Neil Campbell Date: Mon, 3 Nov 2025 14:43:44 +0800 Subject: [PATCH 08/10] fix: more api client generator adjustments --- .../openapi-converter/specs/algod.oas3.json | 159 +++++----- .../openapi-converter/specs/indexer.oas3.json | 291 ++++++++++++------ .../src/oas_generator/generator/filters.py | 16 - packages/algod_client/src/apis/api.service.ts | 24 +- .../src/models/application-params.ts | 4 +- .../algod_client/src/models/build-version.ts | 6 +- .../algod_client/src/models/dryrun-request.ts | 2 +- .../algod_client/src/models/dryrun-state.ts | 4 +- .../src/models/genesis-allocation.ts | 2 +- packages/algod_client/src/models/genesis.ts | 2 +- .../src/models/get-block-time-stamp-offset.ts | 4 +- .../get-pending-transactions-by-address.ts | 2 +- .../src/models/get-pending-transactions.ts | 2 +- .../algod_client/src/models/get-status.ts | 32 +- .../src/models/light-block-header-proof.ts | 6 +- .../models/pending-transaction-response.ts | 2 +- .../algod_client/src/models/scratch-change.ts | 2 +- .../src/models/simulate-request.ts | 2 +- .../simulate-transaction-group-result.ts | 6 +- .../src/models/simulate-transaction.ts | 4 +- .../simulate-unnamed-resources-accessed.ts | 2 +- .../src/models/simulation-eval-overrides.ts | 6 +- .../models/simulation-opcode-trace-unit.ts | 6 +- .../src/models/transaction-proof.ts | 8 +- .../algod_client/src/models/wait-for-block.ts | 32 +- .../indexer_client/src/apis/api.service.ts | 56 ++-- packages/indexer_client/src/models/account.ts | 14 +- .../src/models/application-params.ts | 2 +- .../src/models/block-rewards.ts | 8 +- .../src/models/block-upgrade-state.ts | 6 +- .../src/models/block-upgrade-vote.ts | 2 +- packages/indexer_client/src/models/block.ts | 10 +- .../src/models/box-reference.ts | 2 +- .../indexer_client/src/models/hash-factory.ts | 2 +- .../indexer_client/src/models/holding-ref.ts | 2 +- .../indexer_client/src/models/locals-ref.ts | 2 +- .../models/lookup-account-app-local-states.ts | 2 +- .../src/models/lookup-account-assets.ts | 2 +- .../src/models/lookup-account-by-id.ts | 2 +- .../lookup-account-created-applications.ts | 2 +- .../models/lookup-account-created-assets.ts | 2 +- .../src/models/lookup-account-transactions.ts | 2 +- .../src/models/lookup-application-by-id.ts | 2 +- .../models/lookup-application-logs-by-id.ts | 4 +- .../src/models/lookup-asset-balances.ts | 2 +- .../src/models/lookup-asset-by-id.ts | 2 +- .../src/models/lookup-asset-transactions.ts | 2 +- .../src/models/lookup-transaction.ts | 2 +- .../src/models/merkle-array-proof.ts | 2 +- .../indexer_client/src/models/resource-ref.ts | 2 +- .../src/models/search-for-accounts.ts | 2 +- .../models/search-for-application-boxes.ts | 2 +- .../src/models/search-for-applications.ts | 2 +- .../src/models/search-for-assets.ts | 2 +- .../src/models/search-for-block-headers.ts | 2 +- .../src/models/search-for-transactions.ts | 2 +- .../src/models/state-proof-fields.ts | 2 +- .../src/models/state-proof-signature.ts | 2 +- .../src/models/state-proof-tracking.ts | 2 +- .../src/models/transaction-application.ts | 8 +- .../src/models/transaction-payment.ts | 2 +- .../models/transaction-signature-multisig.ts | 4 +- .../indexer_client/src/models/transaction.ts | 10 +- packages/kmd_client/src/models/digest.ts | 2 +- .../src/models/ed25519-private-key.ts | 2 +- .../src/models/ed25519-public-key.ts | 2 +- .../src/models/ed25519-signature.ts | 2 +- .../src/models/import-multisig-request.ts | 4 +- .../src/models/master-derivation-key.ts | 2 +- .../kmd_client/src/models/multisig-sig.ts | 4 +- .../models/post-multisig-export-response.ts | 4 +- .../kmd_client/src/models/wallet-handle.ts | 2 +- packages/kmd_client/src/models/wallet.ts | 2 +- 73 files changed, 454 insertions(+), 376 deletions(-) diff --git a/algokit-configs/openapi-converter/specs/algod.oas3.json b/algokit-configs/openapi-converter/specs/algod.oas3.json index 9d21fdeaa..95f6acf84 100644 --- a/algokit-configs/openapi-converter/specs/algod.oas3.json +++ b/algokit-configs/openapi-converter/specs/algod.oas3.json @@ -476,9 +476,9 @@ "description": "Maximum number of results to return.", "schema": { "type": "integer", - "x-algokit-bigint": true + "x-go-type": "uint64" }, - "x-algokit-bigint": true + "x-go-type": "uint64" }, { "name": "next", @@ -737,9 +737,9 @@ "description": "Truncated number of transactions to display. If max=0, returns all pending txns.", "schema": { "type": "integer", - "x-algokit-bigint": true + "x-go-type": "uint64" }, - "x-algokit-bigint": true + "x-go-type": "uint64" }, { "name": "format", @@ -1372,11 +1372,13 @@ "online-money": { "type": "integer", "description": "OnlineMoney", + "x-go-type": "uint64", "x-algokit-bigint": true }, "total-money": { "type": "integer", "description": "TotalMoney", + "x-go-type": "uint64", "x-algokit-bigint": true } }, @@ -2028,42 +2030,42 @@ "catchpoint-total-accounts": { "type": "integer", "description": "The total number of accounts included in the current catchpoint", - "x-algokit-bigint": true + "x-go-type": "uint64" }, "catchpoint-processed-accounts": { "type": "integer", "description": "The number of accounts from the current catchpoint that have been processed so far as part of the catchup", - "x-algokit-bigint": true + "x-go-type": "uint64" }, "catchpoint-verified-accounts": { "type": "integer", "description": "The number of accounts from the current catchpoint that have been verified so far as part of the catchup", - "x-algokit-bigint": true + "x-go-type": "uint64" }, "catchpoint-total-kvs": { "type": "integer", "description": "The total number of key-values (KVs) included in the current catchpoint", - "x-algokit-bigint": true + "x-go-type": "uint64" }, "catchpoint-processed-kvs": { "type": "integer", "description": "The number of key-values (KVs) from the current catchpoint that have been processed so far as part of the catchup", - "x-algokit-bigint": true + "x-go-type": "uint64" }, "catchpoint-verified-kvs": { "type": "integer", "description": "The number of key-values (KVs) from the current catchpoint that have been verified so far as part of the catchup", - "x-algokit-bigint": true + "x-go-type": "uint64" }, "catchpoint-total-blocks": { "type": "integer", "description": "The total number of blocks that are required to complete the current catchpoint catchup", - "x-algokit-bigint": true + "x-go-type": "uint64" }, "catchpoint-acquired-blocks": { "type": "integer", "description": "The number of blocks that have already been obtained by the node as part of the catchup", - "x-algokit-bigint": true + "x-go-type": "uint64" }, "upgrade-delay": { "type": "integer", @@ -2077,23 +2079,19 @@ }, "upgrade-votes-required": { "type": "integer", - "description": "Yes votes required for consensus upgrade", - "format": "int32" + "description": "Yes votes required for consensus upgrade" }, "upgrade-votes": { "type": "integer", - "description": "Total votes cast for consensus upgrade", - "format": "int32" + "description": "Total votes cast for consensus upgrade" }, "upgrade-yes-votes": { "type": "integer", - "description": "Yes votes cast for consensus upgrade", - "format": "int32" + "description": "Yes votes cast for consensus upgrade" }, "upgrade-no-votes": { "type": "integer", - "description": "No votes cast for consensus upgrade", - "format": "int32" + "description": "No votes cast for consensus upgrade" }, "upgrade-next-protocol-vote-before": { "type": "integer", @@ -2103,8 +2101,7 @@ }, "upgrade-vote-rounds": { "type": "integer", - "description": "Total voting rounds for current upgrade", - "format": "int32" + "description": "Total voting rounds for current upgrade" } }, "description": "NodeStatus contains the information about a node status" @@ -2233,42 +2230,42 @@ "catchpoint-total-accounts": { "type": "integer", "description": "The total number of accounts included in the current catchpoint", - "x-algokit-bigint": true + "x-go-type": "uint64" }, "catchpoint-processed-accounts": { "type": "integer", "description": "The number of accounts from the current catchpoint that have been processed so far as part of the catchup", - "x-algokit-bigint": true + "x-go-type": "uint64" }, "catchpoint-verified-accounts": { "type": "integer", "description": "The number of accounts from the current catchpoint that have been verified so far as part of the catchup", - "x-algokit-bigint": true + "x-go-type": "uint64" }, "catchpoint-total-kvs": { "type": "integer", "description": "The total number of key-values (KVs) included in the current catchpoint", - "x-algokit-bigint": true + "x-go-type": "uint64" }, "catchpoint-processed-kvs": { "type": "integer", "description": "The number of key-values (KVs) from the current catchpoint that have been processed so far as part of the catchup", - "x-algokit-bigint": true + "x-go-type": "uint64" }, "catchpoint-verified-kvs": { "type": "integer", "description": "The number of key-values (KVs) from the current catchpoint that have been verified so far as part of the catchup", - "x-algokit-bigint": true + "x-go-type": "uint64" }, "catchpoint-total-blocks": { "type": "integer", "description": "The total number of blocks that are required to complete the current catchpoint catchup", - "x-algokit-bigint": true + "x-go-type": "uint64" }, "catchpoint-acquired-blocks": { "type": "integer", "description": "The number of blocks that have already been obtained by the node as part of the catchup", - "x-algokit-bigint": true + "x-go-type": "uint64" }, "upgrade-delay": { "type": "integer", @@ -2282,23 +2279,19 @@ }, "upgrade-votes-required": { "type": "integer", - "description": "Yes votes required for consensus upgrade", - "format": "int32" + "description": "Yes votes required for consensus upgrade" }, "upgrade-votes": { "type": "integer", - "description": "Total votes cast for consensus upgrade", - "format": "int32" + "description": "Total votes cast for consensus upgrade" }, "upgrade-yes-votes": { "type": "integer", - "description": "Yes votes cast for consensus upgrade", - "format": "int32" + "description": "Yes votes cast for consensus upgrade" }, "upgrade-no-votes": { "type": "integer", - "description": "No votes cast for consensus upgrade", - "format": "int32" + "description": "No votes cast for consensus upgrade" }, "upgrade-next-protocol-vote-before": { "type": "integer", @@ -2308,8 +2301,7 @@ }, "upgrade-vote-rounds": { "type": "integer", - "description": "Total voting rounds for current upgrade", - "format": "int32" + "description": "Total voting rounds for current upgrade" } }, "description": "NodeStatus contains the information about a node status" @@ -2579,7 +2571,7 @@ "version": { "type": "integer", "description": "The version of this response object.", - "x-algokit-bigint": true + "x-go-type": "uint64" }, "last-round": { "type": "integer", @@ -2687,6 +2679,7 @@ "fee": { "type": "integer", "description": "Fee is the suggested transaction fee\nFee is in units of micro-Algos per byte.\nFee may fall to zero but transactions must still have a fee of\nat least MinTxnFee for the current network protocol.", + "x-go-type": "uint64", "x-algokit-bigint": true }, "genesis-hash": { @@ -2708,6 +2701,7 @@ "min-fee": { "type": "integer", "description": "The minimum transaction fee (not per byte) required for the\ntxn to validate for the current network protocol.", + "x-go-type": "uint64", "x-algokit-bigint": true } }, @@ -2769,9 +2763,9 @@ "description": "Truncated number of transactions to display. If max=0, returns all pending txns.", "schema": { "type": "integer", - "x-algokit-bigint": true + "x-go-type": "uint64" }, - "x-algokit-bigint": true + "x-go-type": "uint64" }, { "name": "format", @@ -3554,9 +3548,9 @@ "description": "Max number of box names to return. If max is not set, or max == 0, returns all box-names.", "schema": { "type": "integer", - "x-algokit-bigint": true + "x-go-type": "uint64" }, - "x-algokit-bigint": true + "x-go-type": "uint64" } ], "responses": { @@ -4542,7 +4536,7 @@ "offset": { "type": "integer", "description": "Timestamp offset in seconds.", - "x-algokit-bigint": true + "x-go-type": "uint64" } } } @@ -4584,9 +4578,9 @@ "schema": { "minimum": 0, "type": "integer", - "x-algokit-bigint": true + "x-go-type": "uint64" }, - "x-algokit-bigint": true + "x-go-type": "uint64" } ], "responses": { @@ -4978,6 +4972,7 @@ "vote-key-dilution": { "type": "integer", "description": "\\[voteKD\\] Number of subkeys in each batch of participation keys.", + "x-go-type": "uint64", "x-algokit-bigint": true }, "vote-last-valid": { @@ -5305,8 +5300,7 @@ "properties": { "type": { "type": "integer", - "description": "\\[tt\\] value type. Value `1` refers to **bytes**, value `2` refers to **uint**", - "format": "int32" + "description": "\\[tt\\] value type. Value `1` refers to **bytes**, value `2` refers to **uint**" }, "bytes": { "type": "string", @@ -5330,8 +5324,7 @@ "properties": { "type": { "type": "integer", - "description": "value type. Value `1` refers to **bytes**, value `2` refers to **uint64**", - "format": "int32" + "description": "value type. Value `1` refers to **bytes**, value `2` refers to **uint64**" }, "bytes": { "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", @@ -5491,7 +5484,7 @@ "version": { "type": "integer", "description": "\\[v\\] the number of updates to the application programs", - "x-algokit-bigint": true + "x-go-type": "uint64" } }, "description": "Stores the global information associated with an application." @@ -5963,16 +5956,19 @@ }, "close-rewards": { "type": "integer", - "description": "Rewards in microalgos applied to the close remainder to account." + "description": "Rewards in microalgos applied to the close remainder to account.", + "x-algokit-bigint": true }, "closing-amount": { "type": "integer", "description": "Closing amount for the transaction.", + "x-go-type": "uint64", "x-algokit-bigint": true }, "asset-closing-amount": { "type": "integer", "description": "The number of the asset's unit that were transferred to the close-to address.", + "x-go-type": "uint64", "x-algokit-bigint": true }, "confirmed-round": { @@ -5988,11 +5984,13 @@ "receiver-rewards": { "type": "integer", "description": "Rewards in microalgos applied to the receiver account.", + "x-go-type": "uint64", "x-algokit-bigint": true }, "sender-rewards": { "type": "integer", "description": "Rewards in microalgos applied to the sender account.", + "x-go-type": "uint64", "x-algokit-bigint": true }, "local-state-delta": { @@ -6129,7 +6127,7 @@ "index": { "type": "integer", "description": "The index of the light block header in the vector commitment tree", - "x-algokit-bigint": true + "x-go-type": "uint64" }, "treedepth": { "type": "integer", @@ -6547,12 +6545,12 @@ "treedepth": { "type": "integer", "description": "Represents the depth of the tree that is being proven, i.e. the number of edges from a leaf to the root.", - "x-algokit-bigint": true + "x-go-type": "uint64" }, "idx": { "type": "integer", "description": "Index of the transaction in the block's payset.", - "x-algokit-bigint": true + "x-go-type": "uint64" }, "hashtype": { "type": "string", @@ -6580,7 +6578,7 @@ "offset": { "type": "integer", "description": "Timestamp offset in seconds.", - "x-algokit-bigint": true + "x-go-type": "uint64" } } } @@ -6949,42 +6947,42 @@ "catchpoint-total-accounts": { "type": "integer", "description": "The total number of accounts included in the current catchpoint", - "x-algokit-bigint": true + "x-go-type": "uint64" }, "catchpoint-processed-accounts": { "type": "integer", "description": "The number of accounts from the current catchpoint that have been processed so far as part of the catchup", - "x-algokit-bigint": true + "x-go-type": "uint64" }, "catchpoint-verified-accounts": { "type": "integer", "description": "The number of accounts from the current catchpoint that have been verified so far as part of the catchup", - "x-algokit-bigint": true + "x-go-type": "uint64" }, "catchpoint-total-kvs": { "type": "integer", "description": "The total number of key-values (KVs) included in the current catchpoint", - "x-algokit-bigint": true + "x-go-type": "uint64" }, "catchpoint-processed-kvs": { "type": "integer", "description": "The number of key-values (KVs) from the current catchpoint that have been processed so far as part of the catchup", - "x-algokit-bigint": true + "x-go-type": "uint64" }, "catchpoint-verified-kvs": { "type": "integer", "description": "The number of key-values (KVs) from the current catchpoint that have been verified so far as part of the catchup", - "x-algokit-bigint": true + "x-go-type": "uint64" }, "catchpoint-total-blocks": { "type": "integer", "description": "The total number of blocks that are required to complete the current catchpoint catchup", - "x-algokit-bigint": true + "x-go-type": "uint64" }, "catchpoint-acquired-blocks": { "type": "integer", "description": "The number of blocks that have already been obtained by the node as part of the catchup", - "x-algokit-bigint": true + "x-go-type": "uint64" }, "upgrade-delay": { "type": "integer", @@ -6998,23 +6996,19 @@ }, "upgrade-votes-required": { "type": "integer", - "description": "Yes votes required for consensus upgrade", - "format": "int32" + "description": "Yes votes required for consensus upgrade" }, "upgrade-votes": { "type": "integer", - "description": "Total votes cast for consensus upgrade", - "format": "int32" + "description": "Total votes cast for consensus upgrade" }, "upgrade-yes-votes": { "type": "integer", - "description": "Yes votes cast for consensus upgrade", - "format": "int32" + "description": "Yes votes cast for consensus upgrade" }, "upgrade-no-votes": { "type": "integer", - "description": "No votes cast for consensus upgrade", - "format": "int32" + "description": "No votes cast for consensus upgrade" }, "upgrade-next-protocol-vote-before": { "type": "integer", @@ -7024,8 +7018,7 @@ }, "upgrade-vote-rounds": { "type": "integer", - "description": "Total voting rounds for current upgrade", - "format": "int32" + "description": "Total voting rounds for current upgrade" } }, "description": "NodeStatus contains the information about a node status" @@ -7140,7 +7133,7 @@ "version": { "type": "integer", "description": "The version of this response object.", - "x-algokit-bigint": true + "x-go-type": "uint64" }, "last-round": { "type": "integer", @@ -7211,11 +7204,13 @@ "online-money": { "type": "integer", "description": "OnlineMoney", + "x-go-type": "uint64", "x-algokit-bigint": true }, "total-money": { "type": "integer", "description": "TotalMoney", + "x-go-type": "uint64", "x-algokit-bigint": true } }, @@ -7246,6 +7241,7 @@ "fee": { "type": "integer", "description": "Fee is the suggested transaction fee\nFee is in units of micro-Algos per byte.\nFee may fall to zero but transactions must still have a fee of\nat least MinTxnFee for the current network protocol.", + "x-go-type": "uint64", "x-algokit-bigint": true }, "genesis-hash": { @@ -7267,6 +7263,7 @@ "min-fee": { "type": "integer", "description": "The minimum transaction fee (not per byte) required for the\ntxn to validate for the current network protocol.", + "x-go-type": "uint64", "x-algokit-bigint": true } }, @@ -7457,9 +7454,9 @@ "description": "Maximum number of results to return.", "schema": { "type": "integer", - "x-algokit-bigint": true + "x-go-type": "uint64" }, - "x-algokit-bigint": true + "x-go-type": "uint64" }, "max": { "name": "max", @@ -7467,9 +7464,9 @@ "description": "Truncated number of transactions to display. If max=0, returns all pending txns.", "schema": { "type": "integer", - "x-algokit-bigint": true + "x-go-type": "uint64" }, - "x-algokit-bigint": true + "x-go-type": "uint64" }, "next": { "name": "next", diff --git a/algokit-configs/openapi-converter/specs/indexer.oas3.json b/algokit-configs/openapi-converter/specs/indexer.oas3.json index 0b37fe3c7..c2ef5e927 100644 --- a/algokit-configs/openapi-converter/specs/indexer.oas3.json +++ b/algokit-configs/openapi-converter/specs/indexer.oas3.json @@ -64,7 +64,8 @@ "in": "query", "description": "Asset ID", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -88,7 +89,8 @@ "in": "query", "description": "Results should have an amount greater than this value. MicroAlgos are the default currency unless an asset-id is provided, in which case the asset will be used.", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -125,7 +127,8 @@ "in": "query", "description": "Results should have an amount less than this value. MicroAlgos are the default currency unless an asset-id is provided, in which case the asset will be used.", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -143,7 +146,8 @@ "in": "query", "description": "Include results for the specified round. For performance reasons, this parameter may be disabled on some configurations. Using application-id or asset-id filters will return both creator and opt-in accounts. Filtering by include-all will return creator and opt-in accounts for deleted assets and accounts. Non-opt-in managers are not included in the results when asset-id is used.", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -151,7 +155,8 @@ "in": "query", "description": "Application ID", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -183,7 +188,8 @@ }, "current-round": { "type": "integer", - "description": "Round at which the results were computed." + "description": "Round at which the results were computed.", + "x-algokit-bigint": true }, "next-token": { "type": "string", @@ -263,7 +269,8 @@ "in": "query", "description": "Include results for the specified round.", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -313,7 +320,8 @@ }, "current-round": { "type": "integer", - "description": "Round at which the results were computed." + "description": "Round at which the results were computed.", + "x-algokit-bigint": true } } } @@ -411,7 +419,8 @@ "in": "query", "description": "Asset ID", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -453,7 +462,8 @@ "properties": { "current-round": { "type": "integer", - "description": "Round at which the results were computed." + "description": "Round at which the results were computed.", + "x-algokit-bigint": true }, "next-token": { "type": "string", @@ -561,7 +571,8 @@ "in": "query", "description": "Asset ID", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -609,7 +620,8 @@ }, "current-round": { "type": "integer", - "description": "Round at which the results were computed." + "description": "Round at which the results were computed.", + "x-algokit-bigint": true }, "next-token": { "type": "string", @@ -711,7 +723,8 @@ "in": "query", "description": "Application ID", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -759,7 +772,8 @@ }, "current-round": { "type": "integer", - "description": "Round at which the results were computed." + "description": "Round at which the results were computed.", + "x-algokit-bigint": true }, "next-token": { "type": "string", @@ -861,7 +875,8 @@ "in": "query", "description": "Application ID", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -909,7 +924,8 @@ }, "current-round": { "type": "integer", - "description": "Round at which the results were computed." + "description": "Round at which the results were computed.", + "x-algokit-bigint": true }, "next-token": { "type": "string", @@ -1066,7 +1082,8 @@ "in": "query", "description": "Include results for the specified round.", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -1074,7 +1091,8 @@ "in": "query", "description": "Include results at or after the specified min-round.", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -1082,7 +1100,8 @@ "in": "query", "description": "Include results at or before the specified max-round.", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -1090,7 +1109,8 @@ "in": "query", "description": "Asset ID", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -1120,7 +1140,8 @@ "in": "query", "description": "Results should have an amount greater than this value. MicroAlgos are the default currency unless an asset-id is provided, in which case the asset will be used.", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -1128,7 +1149,8 @@ "in": "query", "description": "Results should have an amount less than this value. MicroAlgos are the default currency unless an asset-id is provided, in which case the asset will be used.", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -1163,7 +1185,8 @@ "properties": { "current-round": { "type": "integer", - "description": "Round at which the results were computed." + "description": "Round at which the results were computed.", + "x-algokit-bigint": true }, "next-token": { "type": "string", @@ -1240,7 +1263,8 @@ "in": "query", "description": "Application ID", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -1296,7 +1320,8 @@ }, "current-round": { "type": "integer", - "description": "Round at which the results were computed." + "description": "Round at which the results were computed.", + "x-algokit-bigint": true }, "next-token": { "type": "string", @@ -1345,7 +1370,8 @@ "in": "path", "required": true, "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -1373,7 +1399,8 @@ }, "current-round": { "type": "integer", - "description": "Round at which the results were computed." + "description": "Round at which the results were computed.", + "x-algokit-bigint": true } } } @@ -1441,7 +1468,8 @@ "in": "path", "required": true, "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -1475,7 +1503,8 @@ "properties": { "application-id": { "type": "integer", - "description": "\\[appidx\\] application index." + "description": "\\[appidx\\] application index.", + "x-algokit-bigint": true }, "boxes": { "type": "array", @@ -1575,7 +1604,8 @@ "in": "path", "required": true, "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -1681,7 +1711,8 @@ "in": "path", "required": true, "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -1713,7 +1744,8 @@ "in": "query", "description": "Include results at or after the specified min-round.", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -1721,7 +1753,8 @@ "in": "query", "description": "Include results at or before the specified max-round.", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -1749,11 +1782,13 @@ "properties": { "application-id": { "type": "integer", - "description": "\\[appidx\\] application index." + "description": "\\[appidx\\] application index.", + "x-algokit-bigint": true }, "current-round": { "type": "integer", - "description": "Round at which the results were computed." + "description": "Round at which the results were computed.", + "x-algokit-bigint": true }, "next-token": { "type": "string", @@ -1834,7 +1869,8 @@ "in": "query", "description": "Asset ID", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } } ], @@ -1858,7 +1894,8 @@ }, "current-round": { "type": "integer", - "description": "Round at which the results were computed." + "description": "Round at which the results were computed.", + "x-algokit-bigint": true }, "next-token": { "type": "string", @@ -1929,7 +1966,8 @@ "in": "path", "required": true, "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -1958,7 +1996,8 @@ }, "current-round": { "type": "integer", - "description": "Round at which the results were computed." + "description": "Round at which the results were computed.", + "x-algokit-bigint": true } } } @@ -2071,7 +2110,8 @@ "in": "query", "description": "Results should have an amount greater than this value. MicroAlgos are the default currency unless an asset-id is provided, in which case the asset will be used.", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -2079,7 +2119,8 @@ "in": "query", "description": "Results should have an amount less than this value. MicroAlgos are the default currency unless an asset-id is provided, in which case the asset will be used.", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -2087,7 +2128,8 @@ "in": "path", "required": true, "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } } ], @@ -2111,7 +2153,8 @@ }, "current-round": { "type": "integer", - "description": "Round at which the results were computed." + "description": "Round at which the results were computed.", + "x-algokit-bigint": true }, "next-token": { "type": "string", @@ -2246,7 +2289,8 @@ "in": "query", "description": "Include results for the specified round.", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -2254,7 +2298,8 @@ "in": "query", "description": "Include results at or after the specified min-round.", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -2262,7 +2307,8 @@ "in": "query", "description": "Include results at or before the specified max-round.", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -2292,7 +2338,8 @@ "in": "query", "description": "Results should have an amount greater than this value. MicroAlgos are the default currency unless an asset-id is provided, in which case the asset will be used.", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -2300,7 +2347,8 @@ "in": "query", "description": "Results should have an amount less than this value. MicroAlgos are the default currency unless an asset-id is provided, in which case the asset will be used.", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -2339,7 +2387,8 @@ "in": "path", "required": true, "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -2365,7 +2414,8 @@ "properties": { "current-round": { "type": "integer", - "description": "Round at which the results were computed." + "description": "Round at which the results were computed.", + "x-algokit-bigint": true }, "next-token": { "type": "string", @@ -2458,7 +2508,8 @@ "in": "query", "description": "Include results at or after the specified min-round.", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -2466,7 +2517,8 @@ "in": "query", "description": "Include results at or before the specified max-round.", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -2548,7 +2600,8 @@ "properties": { "current-round": { "type": "integer", - "description": "Round at which the results were computed." + "description": "Round at which the results were computed.", + "x-algokit-bigint": true }, "next-token": { "type": "string", @@ -2626,7 +2679,8 @@ "description": "Round number", "required": true, "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -2730,7 +2784,8 @@ }, "current-round": { "type": "integer", - "description": "Round at which the results were computed." + "description": "Round at which the results were computed.", + "x-algokit-bigint": true } } } @@ -2893,7 +2948,8 @@ "in": "query", "description": "Include results for the specified round.", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -2901,7 +2957,8 @@ "in": "query", "description": "Include results at or after the specified min-round.", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -2909,7 +2966,8 @@ "in": "query", "description": "Include results at or before the specified max-round.", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -2917,7 +2975,8 @@ "in": "query", "description": "Asset ID", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -2947,7 +3006,8 @@ "in": "query", "description": "Results should have an amount greater than this value. MicroAlgos are the default currency unless an asset-id is provided, in which case the asset will be used.", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -2955,7 +3015,8 @@ "in": "query", "description": "Results should have an amount less than this value. MicroAlgos are the default currency unless an asset-id is provided, in which case the asset will be used.", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, { @@ -3002,7 +3063,8 @@ "in": "query", "description": "Application ID", "schema": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } } ], @@ -3020,7 +3082,8 @@ "properties": { "current-round": { "type": "integer", - "description": "Round at which the results were computed." + "description": "Round at which the results were computed.", + "x-algokit-bigint": true }, "next-token": { "type": "string", @@ -3802,11 +3865,13 @@ }, "rewards-calculation-round": { "type": "integer", - "description": "\\[rwcalr\\] number of leftover MicroAlgos after the distribution of rewards-rate MicroAlgos for every reward unit in the next round." + "description": "\\[rwcalr\\] number of leftover MicroAlgos after the distribution of rewards-rate MicroAlgos for every reward unit in the next round.", + "x-algokit-bigint": true }, "rewards-level": { "type": "integer", - "description": "\\[earn\\] How many rewards, in MicroAlgos, have been distributed to each RewardUnit of MicroAlgos since genesis." + "description": "\\[earn\\] How many rewards, in MicroAlgos, have been distributed to each RewardUnit of MicroAlgos since genesis.", + "x-algokit-bigint": true }, "rewards-pool": { "type": "string", @@ -3814,11 +3879,13 @@ }, "rewards-rate": { "type": "integer", - "description": "\\[rate\\] Number of new MicroAlgos added to the participation stake from rewards at the next round." + "description": "\\[rate\\] Number of new MicroAlgos added to the participation stake from rewards at the next round.", + "x-algokit-bigint": true }, "rewards-residue": { "type": "integer", - "description": "\\[frac\\] Number of leftover MicroAlgos after the distribution of RewardsRate/rewardUnits MicroAlgos for every reward unit in the next round." + "description": "\\[frac\\] Number of leftover MicroAlgos after the distribution of RewardsRate/rewardUnits MicroAlgos for every reward unit in the next round.", + "x-algokit-bigint": true } }, "description": "Fields relating to rewards," @@ -3843,11 +3910,13 @@ }, "next-protocol-switch-on": { "type": "integer", - "description": "\\[nextswitch\\] Round on which the protocol upgrade will take effect." + "description": "\\[nextswitch\\] Round on which the protocol upgrade will take effect.", + "x-algokit-bigint": true }, "next-protocol-vote-before": { "type": "integer", - "description": "\\[nextbefore\\] Deadline round for this protocol upgrade (No votes will be consider after this round)." + "description": "\\[nextbefore\\] Deadline round for this protocol upgrade (No votes will be consider after this round).", + "x-algokit-bigint": true } }, "description": "Fields relating to a protocol upgrade." @@ -3861,7 +3930,8 @@ }, "upgrade-delay": { "type": "integer", - "description": "\\[upgradedelay\\] Indicates the time between acceptance and execution." + "description": "\\[upgradedelay\\] Indicates the time between acceptance and execution.", + "x-algokit-bigint": true }, "upgrade-propose": { "type": "string", @@ -3922,7 +3992,8 @@ "properties": { "app": { "type": "integer", - "description": "Application ID to which the box belongs, or zero if referring to the called application." + "description": "Application ID to which the box belongs, or zero if referring to the called application.", + "x-algokit-bigint": true }, "name": { "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", @@ -3987,7 +4058,8 @@ }, "asset": { "type": "integer", - "description": "\\[s\\] Asset ID for asset in access list." + "description": "\\[s\\] Asset ID for asset in access list.", + "x-algokit-bigint": true } }, "description": "HoldingRef names a holding by referring to an Address and Asset it belongs to." @@ -4006,7 +4078,8 @@ }, "app": { "type": "integer", - "description": "\\[p\\] Application ID for app in access list, or zero if referring to the called application." + "description": "\\[p\\] Application ID for app in access list, or zero if referring to the called application.", + "x-algokit-bigint": true } }, "description": "LocalsRef names a local state by referring to an Address and App it belongs to." @@ -4088,7 +4161,8 @@ }, "application-id": { "type": "integer", - "description": "\\[p\\] Application id whose GlobalState may be read by the executing\n ApprovalProgram or ClearStateProgram." + "description": "\\[p\\] Application id whose GlobalState may be read by the executing\n ApprovalProgram or ClearStateProgram.", + "x-algokit-bigint": true }, "asset-id": { "type": "integer", @@ -4225,7 +4299,8 @@ }, "close-rewards": { "type": "integer", - "description": "\\[rc\\] rewards applied to close-remainder-to account." + "description": "\\[rc\\] rewards applied to close-remainder-to account.", + "x-algokit-bigint": true }, "closing-amount": { "type": "integer", @@ -4304,7 +4379,8 @@ }, "receiver-rewards": { "type": "integer", - "description": "\\[rr\\] rewards applied to receiver account." + "description": "\\[rr\\] rewards applied to receiver account.", + "x-algokit-bigint": true }, "rekey-to": { "type": "string", @@ -4321,7 +4397,8 @@ }, "sender-rewards": { "type": "integer", - "description": "\\[rs\\] rewards applied to sender account." + "description": "\\[rs\\] rewards applied to sender account.", + "x-algokit-bigint": true }, "signature": { "$ref": "#/components/schemas/TransactionSignature" @@ -4379,7 +4456,8 @@ "properties": { "application-id": { "type": "integer", - "description": "\\[apid\\] ID of the application being configured or empty if creating." + "description": "\\[apid\\] ID of the application being configured or empty if creating.", + "x-algokit-bigint": true }, "on-completion": { "$ref": "#/components/schemas/OnCompletion" @@ -4417,14 +4495,16 @@ "type": "array", "description": "\\[apfa\\] Lists the applications in addition to the application-id whose global states may be accessed by this application's approval-program and clear-state-program. The access is read-only.", "items": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, "foreign-assets": { "type": "array", "description": "\\[apas\\] lists the assets whose parameters may be accessed by this application's ApprovalProgram and ClearStateProgram. The access is read-only.", "items": { - "type": "integer" + "type": "integer", + "x-algokit-bigint": true } }, "local-state-schema": { @@ -4647,7 +4727,8 @@ }, "close-amount": { "type": "integer", - "description": "Number of MicroAlgos that were sent to the close-remainder-to address when closing the sender account." + "description": "Number of MicroAlgos that were sent to the close-remainder-to address when closing the sender account.", + "x-algokit-bigint": true }, "close-remainder-to": { "type": "string", @@ -4957,7 +5038,8 @@ }, "online-total-weight": { "type": "integer", - "description": "\\[t\\] The total number of microalgos held by the online accounts during the StateProof round." + "description": "\\[t\\] The total number of microalgos held by the online accounts during the StateProof round.", + "x-algokit-bigint": true }, "next-round": { "type": "integer", @@ -5015,7 +5097,8 @@ }, "current-round": { "type": "integer", - "description": "Round at which the results were computed." + "description": "Round at which the results were computed.", + "x-algokit-bigint": true } } } @@ -5035,7 +5118,8 @@ "properties": { "current-round": { "type": "integer", - "description": "Round at which the results were computed." + "description": "Round at which the results were computed.", + "x-algokit-bigint": true }, "next-token": { "type": "string", @@ -5071,7 +5155,8 @@ }, "current-round": { "type": "integer", - "description": "Round at which the results were computed." + "description": "Round at which the results were computed.", + "x-algokit-bigint": true }, "next-token": { "type": "string", @@ -5101,7 +5186,8 @@ }, "current-round": { "type": "integer", - "description": "Round at which the results were computed." + "description": "Round at which the results were computed.", + "x-algokit-bigint": true }, "next-token": { "type": "string", @@ -5127,7 +5213,8 @@ }, "current-round": { "type": "integer", - "description": "Round at which the results were computed." + "description": "Round at which the results were computed.", + "x-algokit-bigint": true } } } @@ -5153,7 +5240,8 @@ }, "current-round": { "type": "integer", - "description": "Round at which the results were computed." + "description": "Round at which the results were computed.", + "x-algokit-bigint": true }, "next-token": { "type": "string", @@ -5177,11 +5265,13 @@ "properties": { "application-id": { "type": "integer", - "description": "\\[appidx\\] application index." + "description": "\\[appidx\\] application index.", + "x-algokit-bigint": true }, "current-round": { "type": "integer", - "description": "Round at which the results were computed." + "description": "Round at which the results were computed.", + "x-algokit-bigint": true }, "next-token": { "type": "string", @@ -5217,7 +5307,8 @@ }, "current-round": { "type": "integer", - "description": "Round at which the results were computed." + "description": "Round at which the results were computed.", + "x-algokit-bigint": true }, "next-token": { "type": "string", @@ -5244,7 +5335,8 @@ }, "current-round": { "type": "integer", - "description": "Round at which the results were computed." + "description": "Round at which the results were computed.", + "x-algokit-bigint": true } } } @@ -5264,7 +5356,8 @@ "properties": { "application-id": { "type": "integer", - "description": "\\[appidx\\] application index." + "description": "\\[appidx\\] application index.", + "x-algokit-bigint": true }, "boxes": { "type": "array", @@ -5332,7 +5425,8 @@ }, "current-round": { "type": "integer", - "description": "Round at which the results were computed." + "description": "Round at which the results were computed.", + "x-algokit-bigint": true }, "next-token": { "type": "string", @@ -5366,7 +5460,8 @@ "properties": { "current-round": { "type": "integer", - "description": "Round at which the results were computed." + "description": "Round at which the results were computed.", + "x-algokit-bigint": true }, "next-token": { "type": "string", @@ -5409,7 +5504,8 @@ }, "current-round": { "type": "integer", - "description": "Round at which the results were computed." + "description": "Round at which the results were computed.", + "x-algokit-bigint": true } } } @@ -5429,7 +5525,8 @@ "properties": { "current-round": { "type": "integer", - "description": "Round at which the results were computed." + "description": "Round at which the results were computed.", + "x-algokit-bigint": true }, "next-token": { "type": "string", diff --git a/oas-generator/src/oas_generator/generator/filters.py b/oas-generator/src/oas_generator/generator/filters.py index cdf92d913..1e9d6b63f 100644 --- a/oas-generator/src/oas_generator/generator/filters.py +++ b/oas-generator/src/oas_generator/generator/filters.py @@ -189,27 +189,11 @@ def _map_primitive(schema_type: str, schema_format: str | None, schema: Schema) if schema_type == "integer": schema_format = schema.get(SchemaKey.FORMAT) is_declared_bigint = schema.get(constants.X_ALGOKIT_BIGINT) is True - is_signed_32_bit = schema_format == "int32" - coerced_to_number = False - - if not is_declared_bigint and not is_signed_32_bit: - maximum: int | None = schema.get(SchemaKey.MAXIMUM) - minimum: int | None = schema.get(SchemaKey.MINIMUM) - description = str(schema.get("description", "")).lower() - - if ( - (maximum is not None and maximum <= _U32_MAX_VALUE) - or (minimum is not None and minimum >= 0 and maximum is not None and maximum <= _SMALL_INTEGER_MAX) - or any(keyword in description for keyword in _ENUM_KEYWORDS) - ): - coerced_to_number = True result = ( TypeScriptType.BIGINT if is_declared_bigint else TypeScriptType.NUMBER - if is_signed_32_bit or coerced_to_number - else TypeScriptType.BIGINT ) elif schema_type == "number": result = TypeScriptType.NUMBER diff --git a/packages/algod_client/src/apis/api.service.ts b/packages/algod_client/src/apis/api.service.ts index 2cb359592..6fbb49298 100644 --- a/packages/algod_client/src/apis/api.service.ts +++ b/packages/algod_client/src/apis/api.service.ts @@ -182,7 +182,7 @@ export class AlgodApi { /** * Lookup an account's asset holdings. */ - async accountAssetsInformation(address: string, params?: { limit?: number | bigint; next?: string }): Promise { + async accountAssetsInformation(address: string, params?: { limit?: number; next?: string }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -191,7 +191,7 @@ export class AlgodApi { method: 'GET', url: '/v2/accounts/{address}/assets', path: { address: address }, - query: { limit: typeof params?.limit === 'bigint' ? (params!.limit as bigint).toString() : params?.limit, next: params?.next }, + query: { limit: params?.limit, next: params?.next }, headers, body: undefined, mediaType: undefined, @@ -390,7 +390,7 @@ export class AlgodApi { /** * Given an application ID, return all Box names. No particular ordering is guaranteed. Request fails when client or server-side configured limits prevent returning all Box names. */ - async getApplicationBoxes(applicationId: number | bigint, params?: { max?: number | bigint }): Promise { + async getApplicationBoxes(applicationId: number | bigint, params?: { max?: number }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -399,7 +399,7 @@ export class AlgodApi { method: 'GET', url: '/v2/applications/{application-id}/boxes', path: { 'application-id': typeof applicationId === 'bigint' ? applicationId.toString() : applicationId }, - query: { max: typeof params?.max === 'bigint' ? (params!.max as bigint).toString() : params?.max }, + query: { max: params?.max }, headers, body: undefined, mediaType: undefined, @@ -782,7 +782,7 @@ export class AlgodApi { /** * Get the list of pending transactions, sorted by priority, in decreasing order, truncated at the end at MAX. If MAX = 0, returns all pending transactions. */ - async getPendingTransactions(params?: { max?: number | bigint }): Promise { + async getPendingTransactions(params?: { max?: number }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'msgpack' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -791,7 +791,7 @@ export class AlgodApi { method: 'GET', url: '/v2/transactions/pending', path: {}, - query: { max: typeof params?.max === 'bigint' ? (params!.max as bigint).toString() : params?.max, format: 'msgpack' }, + query: { max: params?.max, format: 'msgpack' }, headers, body: undefined, mediaType: undefined, @@ -807,7 +807,7 @@ export class AlgodApi { /** * Get the list of pending transactions by address, sorted by priority, in decreasing order, truncated at the end at MAX. If MAX = 0, returns all pending transactions. */ - async getPendingTransactionsByAddress(address: string, params?: { max?: number | bigint }): Promise { + async getPendingTransactionsByAddress(address: string, params?: { max?: number }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'msgpack' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -816,7 +816,7 @@ export class AlgodApi { method: 'GET', url: '/v2/accounts/{address}/transactions/pending', path: { address: address }, - query: { max: typeof params?.max === 'bigint' ? (params!.max as bigint).toString() : params?.max, format: 'msgpack' }, + query: { max: params?.max, format: 'msgpack' }, headers, body: undefined, mediaType: undefined, @@ -1145,7 +1145,7 @@ export class AlgodApi { /** * Sets the timestamp offset (seconds) for blocks in dev mode. Providing an offset of 0 will unset this value and try to use the real clock for the timestamp. */ - async setBlockTimeStampOffset(offset: number | bigint): Promise { + async setBlockTimeStampOffset(offset: number): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -1153,7 +1153,7 @@ export class AlgodApi { const payload = await this.httpRequest.request({ method: 'POST', url: '/v2/devmode/blocks/offset/{offset}', - path: { offset: typeof offset === 'bigint' ? offset.toString() : offset }, + path: { offset: offset }, query: {}, headers, body: undefined, @@ -1195,7 +1195,7 @@ export class AlgodApi { /** * Special management endpoint to shutdown the node. Optionally provide a timeout parameter to indicate that the node should begin shutting down after a number of seconds. */ - async shutdownNode(params?: { timeout?: number | bigint }): Promise { + async shutdownNode(params?: { timeout?: number }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -1204,7 +1204,7 @@ export class AlgodApi { method: 'POST', url: '/v2/shutdown', path: {}, - query: { timeout: typeof params?.timeout === 'bigint' ? (params!.timeout as bigint).toString() : params?.timeout }, + query: { timeout: params?.timeout }, headers, body: undefined, mediaType: undefined, diff --git a/packages/algod_client/src/models/application-params.ts b/packages/algod_client/src/models/application-params.ts index bc28dea8a..2a0451285 100644 --- a/packages/algod_client/src/models/application-params.ts +++ b/packages/algod_client/src/models/application-params.ts @@ -34,7 +34,7 @@ export type ApplicationParams = { /** * \[v\] the number of updates to the application programs */ - version?: bigint + version?: number } export const ApplicationParamsMeta: ModelMetadata = { @@ -95,7 +95,7 @@ export const ApplicationParamsMeta: ModelMetadata = { wireKey: 'version', optional: true, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, ], } diff --git a/packages/algod_client/src/models/build-version.ts b/packages/algod_client/src/models/build-version.ts index a7d1c36a6..d63142cd1 100644 --- a/packages/algod_client/src/models/build-version.ts +++ b/packages/algod_client/src/models/build-version.ts @@ -2,11 +2,11 @@ import type { ModelMetadata } from '../core/model-runtime' export type BuildVersion = { branch: string - buildNumber: bigint + buildNumber: number channel: string commitHash: string - major: bigint - minor: bigint + major: number + minor: number } export const BuildVersionMeta: ModelMetadata = { diff --git a/packages/algod_client/src/models/dryrun-request.ts b/packages/algod_client/src/models/dryrun-request.ts index fe165addb..4786220b1 100644 --- a/packages/algod_client/src/models/dryrun-request.ts +++ b/packages/algod_client/src/models/dryrun-request.ts @@ -28,7 +28,7 @@ export type DryrunRequest = { /** * LatestTimestamp is available to some TEAL scripts. Defaults to the latest confirmed timestamp this algod is attached to. */ - latestTimestamp: bigint + latestTimestamp: number sources: DryrunSource[] } diff --git a/packages/algod_client/src/models/dryrun-state.ts b/packages/algod_client/src/models/dryrun-state.ts index 653039fa4..4f10c8296 100644 --- a/packages/algod_client/src/models/dryrun-state.ts +++ b/packages/algod_client/src/models/dryrun-state.ts @@ -9,12 +9,12 @@ export type DryrunState = { /** * Line number */ - line: bigint + line: number /** * Program counter */ - pc: bigint + pc: number stack: TealValue[] scratch?: TealValue[] diff --git a/packages/algod_client/src/models/genesis-allocation.ts b/packages/algod_client/src/models/genesis-allocation.ts index e96e23fcc..46feb6347 100644 --- a/packages/algod_client/src/models/genesis-allocation.ts +++ b/packages/algod_client/src/models/genesis-allocation.ts @@ -5,7 +5,7 @@ export type GenesisAllocation = { comment: string state: { algo: bigint - onl: bigint + onl: number sel?: string stprf?: string vote?: string diff --git a/packages/algod_client/src/models/genesis.ts b/packages/algod_client/src/models/genesis.ts index 0b0e12ec7..ee3d13189 100644 --- a/packages/algod_client/src/models/genesis.ts +++ b/packages/algod_client/src/models/genesis.ts @@ -11,7 +11,7 @@ export type Genesis = { network: string proto: string rwd: string - timestamp: bigint + timestamp: number } export const GenesisMeta: ModelMetadata = { diff --git a/packages/algod_client/src/models/get-block-time-stamp-offset.ts b/packages/algod_client/src/models/get-block-time-stamp-offset.ts index 24f101b0f..22a5d94b8 100644 --- a/packages/algod_client/src/models/get-block-time-stamp-offset.ts +++ b/packages/algod_client/src/models/get-block-time-stamp-offset.ts @@ -4,7 +4,7 @@ export type GetBlockTimeStampOffset = { /** * Timestamp offset in seconds. */ - offset: bigint + offset: number } export const GetBlockTimeStampOffsetMeta: ModelMetadata = { @@ -16,7 +16,7 @@ export const GetBlockTimeStampOffsetMeta: ModelMetadata = { wireKey: 'offset', optional: false, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, ], } diff --git a/packages/algod_client/src/models/get-pending-transactions-by-address.ts b/packages/algod_client/src/models/get-pending-transactions-by-address.ts index f96c63251..25fc5f1ce 100644 --- a/packages/algod_client/src/models/get-pending-transactions-by-address.ts +++ b/packages/algod_client/src/models/get-pending-transactions-by-address.ts @@ -13,7 +13,7 @@ export type GetPendingTransactionsByAddress = { /** * Total number of transactions in the pool. */ - totalTransactions: bigint + totalTransactions: number } export const GetPendingTransactionsByAddressMeta: ModelMetadata = { diff --git a/packages/algod_client/src/models/get-pending-transactions.ts b/packages/algod_client/src/models/get-pending-transactions.ts index f1cbb8688..03bf7ded8 100644 --- a/packages/algod_client/src/models/get-pending-transactions.ts +++ b/packages/algod_client/src/models/get-pending-transactions.ts @@ -13,7 +13,7 @@ export type GetPendingTransactions = { /** * Total number of transactions in the pool. */ - totalTransactions: bigint + totalTransactions: number } export const GetPendingTransactionsMeta: ModelMetadata = { diff --git a/packages/algod_client/src/models/get-status.ts b/packages/algod_client/src/models/get-status.ts index a9c5f1bd9..1a42b633d 100644 --- a/packages/algod_client/src/models/get-status.ts +++ b/packages/algod_client/src/models/get-status.ts @@ -57,42 +57,42 @@ export type GetStatus = { /** * The total number of accounts included in the current catchpoint */ - catchpointTotalAccounts?: bigint + catchpointTotalAccounts?: number /** * The number of accounts from the current catchpoint that have been processed so far as part of the catchup */ - catchpointProcessedAccounts?: bigint + catchpointProcessedAccounts?: number /** * The number of accounts from the current catchpoint that have been verified so far as part of the catchup */ - catchpointVerifiedAccounts?: bigint + catchpointVerifiedAccounts?: number /** * The total number of key-values (KVs) included in the current catchpoint */ - catchpointTotalKvs?: bigint + catchpointTotalKvs?: number /** * The number of key-values (KVs) from the current catchpoint that have been processed so far as part of the catchup */ - catchpointProcessedKvs?: bigint + catchpointProcessedKvs?: number /** * The number of key-values (KVs) from the current catchpoint that have been verified so far as part of the catchup */ - catchpointVerifiedKvs?: bigint + catchpointVerifiedKvs?: number /** * The total number of blocks that are required to complete the current catchpoint catchup */ - catchpointTotalBlocks?: bigint + catchpointTotalBlocks?: number /** * The number of blocks that have already been obtained by the node as part of the catchup */ - catchpointAcquiredBlocks?: bigint + catchpointAcquiredBlocks?: number /** * Upgrade delay @@ -214,56 +214,56 @@ export const GetStatusMeta: ModelMetadata = { wireKey: 'catchpoint-total-accounts', optional: true, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, { name: 'catchpointProcessedAccounts', wireKey: 'catchpoint-processed-accounts', optional: true, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, { name: 'catchpointVerifiedAccounts', wireKey: 'catchpoint-verified-accounts', optional: true, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, { name: 'catchpointTotalKvs', wireKey: 'catchpoint-total-kvs', optional: true, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, { name: 'catchpointProcessedKvs', wireKey: 'catchpoint-processed-kvs', optional: true, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, { name: 'catchpointVerifiedKvs', wireKey: 'catchpoint-verified-kvs', optional: true, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, { name: 'catchpointTotalBlocks', wireKey: 'catchpoint-total-blocks', optional: true, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, { name: 'catchpointAcquiredBlocks', wireKey: 'catchpoint-acquired-blocks', optional: true, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, { name: 'upgradeDelay', diff --git a/packages/algod_client/src/models/light-block-header-proof.ts b/packages/algod_client/src/models/light-block-header-proof.ts index 72852ee49..2b9fc27be 100644 --- a/packages/algod_client/src/models/light-block-header-proof.ts +++ b/packages/algod_client/src/models/light-block-header-proof.ts @@ -7,12 +7,12 @@ export type LightBlockHeaderProof = { /** * The index of the light block header in the vector commitment tree */ - index: bigint + index: number /** * Represents the depth of the tree that is being proven, i.e. the number of edges from a leaf to the root. */ - treedepth: bigint + treedepth: number /** * The encoded proof. @@ -29,7 +29,7 @@ export const LightBlockHeaderProofMeta: ModelMetadata = { wireKey: 'index', optional: false, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, { name: 'treedepth', diff --git a/packages/algod_client/src/models/pending-transaction-response.ts b/packages/algod_client/src/models/pending-transaction-response.ts index 72f37c04c..d968f9534 100644 --- a/packages/algod_client/src/models/pending-transaction-response.ts +++ b/packages/algod_client/src/models/pending-transaction-response.ts @@ -99,7 +99,7 @@ export const PendingTransactionResponseMeta: ModelMetadata = { wireKey: 'close-rewards', optional: true, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'closingAmount', diff --git a/packages/algod_client/src/models/scratch-change.ts b/packages/algod_client/src/models/scratch-change.ts index c419be85d..b0c906f31 100644 --- a/packages/algod_client/src/models/scratch-change.ts +++ b/packages/algod_client/src/models/scratch-change.ts @@ -9,7 +9,7 @@ export type ScratchChange = { /** * The scratch slot written. */ - slot: bigint + slot: number newValue: AvmValue } diff --git a/packages/algod_client/src/models/simulate-request.ts b/packages/algod_client/src/models/simulate-request.ts index 6fc3caf92..01043297e 100644 --- a/packages/algod_client/src/models/simulate-request.ts +++ b/packages/algod_client/src/models/simulate-request.ts @@ -36,7 +36,7 @@ export type SimulateRequest = { /** * Applies extra opcode budget during simulation for each transaction group. */ - extraOpcodeBudget?: bigint + extraOpcodeBudget?: number execTraceConfig?: SimulateTraceConfig /** diff --git a/packages/algod_client/src/models/simulate-transaction-group-result.ts b/packages/algod_client/src/models/simulate-transaction-group-result.ts index 86d1a4efe..b091dd10b 100644 --- a/packages/algod_client/src/models/simulate-transaction-group-result.ts +++ b/packages/algod_client/src/models/simulate-transaction-group-result.ts @@ -21,17 +21,17 @@ export type SimulateTransactionGroupResult = { /** * If present, indicates which transaction in this group caused the failure. This array represents the path to the failing transaction. Indexes are zero based, the first element indicates the top-level transaction, and successive elements indicate deeper inner transactions. */ - failedAt?: bigint[] + failedAt?: number[] /** * Total budget added during execution of app calls in the transaction group. */ - appBudgetAdded?: bigint + appBudgetAdded?: number /** * Total budget consumed during execution of app calls in the transaction group. */ - appBudgetConsumed?: bigint + appBudgetConsumed?: number unnamedResourcesAccessed?: SimulateUnnamedResourcesAccessed } diff --git a/packages/algod_client/src/models/simulate-transaction.ts b/packages/algod_client/src/models/simulate-transaction.ts index 57e01423f..b8845dad1 100644 --- a/packages/algod_client/src/models/simulate-transaction.ts +++ b/packages/algod_client/src/models/simulate-transaction.ts @@ -12,7 +12,7 @@ export type SimulateTransaction = { /** * The version of this response object. */ - version: bigint + version: number /** * The round immediately preceding this simulation. State changes through this round were used to run this simulation. @@ -37,7 +37,7 @@ export const SimulateTransactionMeta: ModelMetadata = { wireKey: 'version', optional: false, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, { name: 'lastRound', diff --git a/packages/algod_client/src/models/simulate-unnamed-resources-accessed.ts b/packages/algod_client/src/models/simulate-unnamed-resources-accessed.ts index 7544d849d..cd515a0c0 100644 --- a/packages/algod_client/src/models/simulate-unnamed-resources-accessed.ts +++ b/packages/algod_client/src/models/simulate-unnamed-resources-accessed.ts @@ -33,7 +33,7 @@ export type SimulateUnnamedResourcesAccessed = { /** * The number of extra box references used to increase the IO budget. This is in addition to the references defined in the input transaction group and any referenced to unnamed boxes. */ - extraBoxRefs?: bigint + extraBoxRefs?: number /** * The unnamed asset holdings that were referenced. The order of this array is arbitrary. diff --git a/packages/algod_client/src/models/simulation-eval-overrides.ts b/packages/algod_client/src/models/simulation-eval-overrides.ts index ef2542247..76ed63f49 100644 --- a/packages/algod_client/src/models/simulation-eval-overrides.ts +++ b/packages/algod_client/src/models/simulation-eval-overrides.ts @@ -17,17 +17,17 @@ export type SimulationEvalOverrides = { /** * The maximum log calls one can make during simulation */ - maxLogCalls?: bigint + maxLogCalls?: number /** * The maximum byte number to log during simulation */ - maxLogSize?: bigint + maxLogSize?: number /** * The extra opcode budget added to each transaction group during simulation */ - extraOpcodeBudget?: bigint + extraOpcodeBudget?: number /** * If true, signers for transactions that are missing signatures will be fixed during evaluation. diff --git a/packages/algod_client/src/models/simulation-opcode-trace-unit.ts b/packages/algod_client/src/models/simulation-opcode-trace-unit.ts index b49230aef..4900df9bc 100644 --- a/packages/algod_client/src/models/simulation-opcode-trace-unit.ts +++ b/packages/algod_client/src/models/simulation-opcode-trace-unit.ts @@ -13,7 +13,7 @@ export type SimulationOpcodeTraceUnit = { /** * The program counter of the current opcode being evaluated. */ - pc: bigint + pc: number /** * The writes into scratch slots. @@ -28,12 +28,12 @@ export type SimulationOpcodeTraceUnit = { /** * The indexes of the traces for inner transactions spawned by this opcode, if any. */ - spawnedInners?: bigint[] + spawnedInners?: number[] /** * The number of deleted stack values by this opcode. */ - stackPopCount?: bigint + stackPopCount?: number /** * The values added by this opcode to the stack. diff --git a/packages/algod_client/src/models/transaction-proof.ts b/packages/algod_client/src/models/transaction-proof.ts index 6bed1a243..8632fb3a3 100644 --- a/packages/algod_client/src/models/transaction-proof.ts +++ b/packages/algod_client/src/models/transaction-proof.ts @@ -17,12 +17,12 @@ export type TransactionProof = { /** * Represents the depth of the tree that is being proven, i.e. the number of edges from a leaf to the root. */ - treedepth: bigint + treedepth: number /** * Index of the transaction in the block's payset. */ - idx: bigint + idx: number /** * The type of hash function used to create the proof, must be one of: @@ -55,14 +55,14 @@ export const TransactionProofMeta: ModelMetadata = { wireKey: 'treedepth', optional: false, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, { name: 'idx', wireKey: 'idx', optional: false, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, { name: 'hashtype', diff --git a/packages/algod_client/src/models/wait-for-block.ts b/packages/algod_client/src/models/wait-for-block.ts index 51984e5a4..21dc61cc8 100644 --- a/packages/algod_client/src/models/wait-for-block.ts +++ b/packages/algod_client/src/models/wait-for-block.ts @@ -57,42 +57,42 @@ export type WaitForBlock = { /** * The total number of accounts included in the current catchpoint */ - catchpointTotalAccounts?: bigint + catchpointTotalAccounts?: number /** * The number of accounts from the current catchpoint that have been processed so far as part of the catchup */ - catchpointProcessedAccounts?: bigint + catchpointProcessedAccounts?: number /** * The number of accounts from the current catchpoint that have been verified so far as part of the catchup */ - catchpointVerifiedAccounts?: bigint + catchpointVerifiedAccounts?: number /** * The total number of key-values (KVs) included in the current catchpoint */ - catchpointTotalKvs?: bigint + catchpointTotalKvs?: number /** * The number of key-values (KVs) from the current catchpoint that have been processed so far as part of the catchup */ - catchpointProcessedKvs?: bigint + catchpointProcessedKvs?: number /** * The number of key-values (KVs) from the current catchpoint that have been verified so far as part of the catchup */ - catchpointVerifiedKvs?: bigint + catchpointVerifiedKvs?: number /** * The total number of blocks that are required to complete the current catchpoint catchup */ - catchpointTotalBlocks?: bigint + catchpointTotalBlocks?: number /** * The number of blocks that have already been obtained by the node as part of the catchup */ - catchpointAcquiredBlocks?: bigint + catchpointAcquiredBlocks?: number /** * Upgrade delay @@ -214,56 +214,56 @@ export const WaitForBlockMeta: ModelMetadata = { wireKey: 'catchpoint-total-accounts', optional: true, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, { name: 'catchpointProcessedAccounts', wireKey: 'catchpoint-processed-accounts', optional: true, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, { name: 'catchpointVerifiedAccounts', wireKey: 'catchpoint-verified-accounts', optional: true, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, { name: 'catchpointTotalKvs', wireKey: 'catchpoint-total-kvs', optional: true, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, { name: 'catchpointProcessedKvs', wireKey: 'catchpoint-processed-kvs', optional: true, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, { name: 'catchpointVerifiedKvs', wireKey: 'catchpoint-verified-kvs', optional: true, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, { name: 'catchpointTotalBlocks', wireKey: 'catchpoint-total-blocks', optional: true, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, { name: 'catchpointAcquiredBlocks', wireKey: 'catchpoint-acquired-blocks', optional: true, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, { name: 'upgradeDelay', diff --git a/packages/indexer_client/src/apis/api.service.ts b/packages/indexer_client/src/apis/api.service.ts index cd40f8f06..a287be655 100644 --- a/packages/indexer_client/src/apis/api.service.ts +++ b/packages/indexer_client/src/apis/api.service.ts @@ -64,7 +64,7 @@ export class IndexerApi { */ async lookupAccountAppLocalStates( accountId: string, - params?: { applicationId?: number | bigint; includeAll?: boolean; limit?: number | bigint; next?: string }, + params?: { applicationId?: number | bigint; includeAll?: boolean; limit?: number; next?: string }, ): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' @@ -77,7 +77,7 @@ export class IndexerApi { query: { 'application-id': typeof params?.applicationId === 'bigint' ? (params!.applicationId as bigint).toString() : params?.applicationId, 'include-all': params?.includeAll, - limit: typeof params?.limit === 'bigint' ? (params!.limit as bigint).toString() : params?.limit, + limit: params?.limit, next: params?.next, }, headers, @@ -97,7 +97,7 @@ export class IndexerApi { */ async lookupAccountAssets( accountId: string, - params?: { assetId?: number | bigint; includeAll?: boolean; limit?: number | bigint; next?: string }, + params?: { assetId?: number | bigint; includeAll?: boolean; limit?: number; next?: string }, ): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' @@ -110,7 +110,7 @@ export class IndexerApi { query: { 'asset-id': typeof params?.assetId === 'bigint' ? (params!.assetId as bigint).toString() : params?.assetId, 'include-all': params?.includeAll, - limit: typeof params?.limit === 'bigint' ? (params!.limit as bigint).toString() : params?.limit, + limit: params?.limit, next: params?.next, }, headers, @@ -166,7 +166,7 @@ export class IndexerApi { */ async lookupAccountCreatedApplications( accountId: string, - params?: { applicationId?: number | bigint; includeAll?: boolean; limit?: number | bigint; next?: string }, + params?: { applicationId?: number | bigint; includeAll?: boolean; limit?: number; next?: string }, ): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' @@ -179,7 +179,7 @@ export class IndexerApi { query: { 'application-id': typeof params?.applicationId === 'bigint' ? (params!.applicationId as bigint).toString() : params?.applicationId, 'include-all': params?.includeAll, - limit: typeof params?.limit === 'bigint' ? (params!.limit as bigint).toString() : params?.limit, + limit: params?.limit, next: params?.next, }, headers, @@ -199,7 +199,7 @@ export class IndexerApi { */ async lookupAccountCreatedAssets( accountId: string, - params?: { assetId?: number | bigint; includeAll?: boolean; limit?: number | bigint; next?: string }, + params?: { assetId?: number | bigint; includeAll?: boolean; limit?: number; next?: string }, ): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' @@ -212,7 +212,7 @@ export class IndexerApi { query: { 'asset-id': typeof params?.assetId === 'bigint' ? (params!.assetId as bigint).toString() : params?.assetId, 'include-all': params?.includeAll, - limit: typeof params?.limit === 'bigint' ? (params!.limit as bigint).toString() : params?.limit, + limit: params?.limit, next: params?.next, }, headers, @@ -233,7 +233,7 @@ export class IndexerApi { async lookupAccountTransactions( accountId: string, params?: { - limit?: number | bigint + limit?: number next?: string notePrefix?: string txType?: 'pay' | 'keyreg' | 'acfg' | 'axfer' | 'afrz' | 'appl' | 'stpf' | 'hb' @@ -259,7 +259,7 @@ export class IndexerApi { url: '/v2/accounts/{account-id}/transactions', path: { 'account-id': accountId }, query: { - limit: typeof params?.limit === 'bigint' ? (params!.limit as bigint).toString() : params?.limit, + limit: params?.limit, next: params?.next, 'note-prefix': params?.notePrefix, 'tx-type': params?.txType, @@ -347,7 +347,7 @@ export class IndexerApi { async lookupApplicationLogsById( applicationId: number | bigint, params?: { - limit?: number | bigint + limit?: number next?: string txid?: string minRound?: number | bigint @@ -364,7 +364,7 @@ export class IndexerApi { url: '/v2/applications/{application-id}/logs', path: { 'application-id': typeof applicationId === 'bigint' ? applicationId.toString() : applicationId }, query: { - limit: typeof params?.limit === 'bigint' ? (params!.limit as bigint).toString() : params?.limit, + limit: params?.limit, next: params?.next, txid: params?.txid, 'min-round': typeof params?.minRound === 'bigint' ? (params!.minRound as bigint).toString() : params?.minRound, @@ -390,7 +390,7 @@ export class IndexerApi { assetId: number | bigint, params?: { includeAll?: boolean - limit?: number | bigint + limit?: number next?: string currencyGreaterThan?: number | bigint currencyLessThan?: number | bigint @@ -406,7 +406,7 @@ export class IndexerApi { path: { 'asset-id': typeof assetId === 'bigint' ? assetId.toString() : assetId }, query: { 'include-all': params?.includeAll, - limit: typeof params?.limit === 'bigint' ? (params!.limit as bigint).toString() : params?.limit, + limit: params?.limit, next: params?.next, 'currency-greater-than': typeof params?.currencyGreaterThan === 'bigint' @@ -458,7 +458,7 @@ export class IndexerApi { async lookupAssetTransactions( assetId: number | bigint, params?: { - limit?: number | bigint + limit?: number next?: string notePrefix?: string txType?: 'pay' | 'keyreg' | 'acfg' | 'axfer' | 'afrz' | 'appl' | 'stpf' | 'hb' @@ -486,7 +486,7 @@ export class IndexerApi { url: '/v2/assets/{asset-id}/transactions', path: { 'asset-id': typeof assetId === 'bigint' ? assetId.toString() : assetId }, query: { - limit: typeof params?.limit === 'bigint' ? (params!.limit as bigint).toString() : params?.limit, + limit: params?.limit, next: params?.next, 'note-prefix': params?.notePrefix, 'tx-type': params?.txType, @@ -597,7 +597,7 @@ export class IndexerApi { */ async searchForAccounts(params?: { assetId?: number | bigint - limit?: number | bigint + limit?: number next?: string currencyGreaterThan?: number | bigint includeAll?: boolean @@ -618,7 +618,7 @@ export class IndexerApi { path: {}, query: { 'asset-id': typeof params?.assetId === 'bigint' ? (params!.assetId as bigint).toString() : params?.assetId, - limit: typeof params?.limit === 'bigint' ? (params!.limit as bigint).toString() : params?.limit, + limit: params?.limit, next: params?.next, 'currency-greater-than': typeof params?.currencyGreaterThan === 'bigint' @@ -650,7 +650,7 @@ export class IndexerApi { */ async searchForApplicationBoxes( applicationId: number | bigint, - params?: { limit?: number | bigint; next?: string }, + params?: { limit?: number; next?: string }, ): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' @@ -660,7 +660,7 @@ export class IndexerApi { method: 'GET', url: '/v2/applications/{application-id}/boxes', path: { 'application-id': typeof applicationId === 'bigint' ? applicationId.toString() : applicationId }, - query: { limit: typeof params?.limit === 'bigint' ? (params!.limit as bigint).toString() : params?.limit, next: params?.next }, + query: { limit: params?.limit, next: params?.next }, headers, body: undefined, mediaType: undefined, @@ -680,7 +680,7 @@ export class IndexerApi { applicationId?: number | bigint creator?: string includeAll?: boolean - limit?: number | bigint + limit?: number next?: string }): Promise { const headers: Record = {} @@ -695,7 +695,7 @@ export class IndexerApi { 'application-id': typeof params?.applicationId === 'bigint' ? (params!.applicationId as bigint).toString() : params?.applicationId, creator: params?.creator, 'include-all': params?.includeAll, - limit: typeof params?.limit === 'bigint' ? (params!.limit as bigint).toString() : params?.limit, + limit: params?.limit, next: params?.next, }, headers, @@ -715,7 +715,7 @@ export class IndexerApi { */ async searchForAssets(params?: { includeAll?: boolean - limit?: number | bigint + limit?: number next?: string creator?: string name?: string @@ -732,7 +732,7 @@ export class IndexerApi { path: {}, query: { 'include-all': params?.includeAll, - limit: typeof params?.limit === 'bigint' ? (params!.limit as bigint).toString() : params?.limit, + limit: params?.limit, next: params?.next, creator: params?.creator, name: params?.name, @@ -755,7 +755,7 @@ export class IndexerApi { * Search for block headers. Block headers are returned in ascending round order. Transactions are not included in the output. */ async searchForBlockHeaders(params?: { - limit?: number | bigint + limit?: number next?: string minRound?: number | bigint maxRound?: number | bigint @@ -774,7 +774,7 @@ export class IndexerApi { url: '/v2/block-headers', path: {}, query: { - limit: typeof params?.limit === 'bigint' ? (params!.limit as bigint).toString() : params?.limit, + limit: params?.limit, next: params?.next, 'min-round': typeof params?.minRound === 'bigint' ? (params!.minRound as bigint).toString() : params?.minRound, 'max-round': typeof params?.maxRound === 'bigint' ? (params!.maxRound as bigint).toString() : params?.maxRound, @@ -800,7 +800,7 @@ export class IndexerApi { * Search for transactions. Transactions are returned oldest to newest unless the address parameter is used, in which case results are returned newest to oldest. */ async searchForTransactions(params?: { - limit?: number | bigint + limit?: number next?: string notePrefix?: string txType?: 'pay' | 'keyreg' | 'acfg' | 'axfer' | 'afrz' | 'appl' | 'stpf' | 'hb' @@ -830,7 +830,7 @@ export class IndexerApi { url: '/v2/transactions', path: {}, query: { - limit: typeof params?.limit === 'bigint' ? (params!.limit as bigint).toString() : params?.limit, + limit: params?.limit, next: params?.next, 'note-prefix': params?.notePrefix, 'tx-type': params?.txType, diff --git a/packages/indexer_client/src/models/account.ts b/packages/indexer_client/src/models/account.ts index b2f68170c..3323de017 100644 --- a/packages/indexer_client/src/models/account.ts +++ b/packages/indexer_client/src/models/account.ts @@ -52,7 +52,7 @@ export type Account = { /** * the sum of all extra application program pages for this account. */ - appsTotalExtraPages?: bigint + appsTotalExtraPages?: number /** * assets held by this account. @@ -121,32 +121,32 @@ export type Account = { /** * The count of all applications that have been opted in, equivalent to the count of application local data (AppLocalState objects) stored in this account. */ - totalAppsOptedIn: bigint + totalAppsOptedIn: number /** * The count of all assets that have been opted in, equivalent to the count of AssetHolding objects held by this account. */ - totalAssetsOptedIn: bigint + totalAssetsOptedIn: number /** * For app-accounts only. The total number of bytes allocated for the keys and values of boxes which belong to the associated application. */ - totalBoxBytes: bigint + totalBoxBytes: number /** * For app-accounts only. The total number of boxes which belong to the associated application. */ - totalBoxes: bigint + totalBoxes: number /** * The count of all apps (AppParams objects) created by this account. */ - totalCreatedApps: bigint + totalCreatedApps: number /** * The count of all assets (AssetParams objects) created by this account. */ - totalCreatedAssets: bigint + totalCreatedAssets: number /** * The address against which signing should be checked. If empty, the address of the current account is used. This field can be updated in any transaction by setting the RekeyTo field. diff --git a/packages/indexer_client/src/models/application-params.ts b/packages/indexer_client/src/models/application-params.ts index 1d274cc85..093fdb717 100644 --- a/packages/indexer_client/src/models/application-params.ts +++ b/packages/indexer_client/src/models/application-params.ts @@ -34,7 +34,7 @@ export type ApplicationParams = { /** * the number of updates to the application programs */ - version?: bigint + version?: number } export const ApplicationParamsMeta: ModelMetadata = { diff --git a/packages/indexer_client/src/models/block-rewards.ts b/packages/indexer_client/src/models/block-rewards.ts index 39c826b70..12706eb39 100644 --- a/packages/indexer_client/src/models/block-rewards.ts +++ b/packages/indexer_client/src/models/block-rewards.ts @@ -51,14 +51,14 @@ export const BlockRewardsMeta: ModelMetadata = { wireKey: 'rewards-calculation-round', optional: false, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'rewardsLevel', wireKey: 'rewards-level', optional: false, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'rewardsPool', @@ -72,14 +72,14 @@ export const BlockRewardsMeta: ModelMetadata = { wireKey: 'rewards-rate', optional: false, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'rewardsResidue', wireKey: 'rewards-residue', optional: false, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, ], } diff --git a/packages/indexer_client/src/models/block-upgrade-state.ts b/packages/indexer_client/src/models/block-upgrade-state.ts index 82a6ddaa6..e419a413a 100644 --- a/packages/indexer_client/src/models/block-upgrade-state.ts +++ b/packages/indexer_client/src/models/block-upgrade-state.ts @@ -17,7 +17,7 @@ export type BlockUpgradeState = { /** * \[nextyes\] Number of blocks which approved the protocol upgrade. */ - nextProtocolApprovals?: bigint + nextProtocolApprovals?: number /** * \[nextswitch\] Round on which the protocol upgrade will take effect. @@ -60,14 +60,14 @@ export const BlockUpgradeStateMeta: ModelMetadata = { wireKey: 'next-protocol-switch-on', optional: true, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'nextProtocolVoteBefore', wireKey: 'next-protocol-vote-before', optional: true, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, ], } diff --git a/packages/indexer_client/src/models/block-upgrade-vote.ts b/packages/indexer_client/src/models/block-upgrade-vote.ts index 2d0a91d76..c6532421f 100644 --- a/packages/indexer_client/src/models/block-upgrade-vote.ts +++ b/packages/indexer_client/src/models/block-upgrade-vote.ts @@ -36,7 +36,7 @@ export const BlockUpgradeVoteMeta: ModelMetadata = { wireKey: 'upgrade-delay', optional: true, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'upgradePropose', diff --git a/packages/indexer_client/src/models/block.ts b/packages/indexer_client/src/models/block.ts index 32ba63040..aadd3b226 100644 --- a/packages/indexer_client/src/models/block.ts +++ b/packages/indexer_client/src/models/block.ts @@ -27,17 +27,17 @@ export type Block = { /** * the sum of all fees paid by transactions in this block. */ - feesCollected?: bigint + feesCollected?: number /** * the potential bonus payout for this block. */ - bonus?: bigint + bonus?: number /** * the actual amount transferred to the proposer from the fee sink. */ - proposerPayout?: bigint + proposerPayout?: number /** * \[gh\] hash to which this block belongs. @@ -78,7 +78,7 @@ export type Block = { /** * \[ts\] Block creation timestamp in seconds since epoch */ - timestamp: bigint + timestamp: number /** * \[txns\] list of transactions corresponding to a given round. @@ -105,7 +105,7 @@ export type Block = { * * Specifically, TxnCounter is the number of the next transaction that will be committed after this block. It is 0 when no transactions have ever been committed (since TxnCounter started being supported). */ - txnCounter?: bigint + txnCounter?: number upgradeState?: BlockUpgradeState upgradeVote?: BlockUpgradeVote participationUpdates?: ParticipationUpdates diff --git a/packages/indexer_client/src/models/box-reference.ts b/packages/indexer_client/src/models/box-reference.ts index e5427cb25..8cc009e6a 100644 --- a/packages/indexer_client/src/models/box-reference.ts +++ b/packages/indexer_client/src/models/box-reference.ts @@ -24,7 +24,7 @@ export const BoxReferenceMeta: ModelMetadata = { wireKey: 'app', optional: false, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'name', diff --git a/packages/indexer_client/src/models/hash-factory.ts b/packages/indexer_client/src/models/hash-factory.ts index 6062e1dae..cd49af22b 100644 --- a/packages/indexer_client/src/models/hash-factory.ts +++ b/packages/indexer_client/src/models/hash-factory.ts @@ -4,7 +4,7 @@ export type HashFactory = { /** * \[t\] */ - hashType?: bigint + hashType?: number } export const HashFactoryMeta: ModelMetadata = { diff --git a/packages/indexer_client/src/models/holding-ref.ts b/packages/indexer_client/src/models/holding-ref.ts index 2481d157d..2cb06bfa0 100644 --- a/packages/indexer_client/src/models/holding-ref.ts +++ b/packages/indexer_client/src/models/holding-ref.ts @@ -31,7 +31,7 @@ export const HoldingRefMeta: ModelMetadata = { wireKey: 'asset', optional: false, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, ], } diff --git a/packages/indexer_client/src/models/locals-ref.ts b/packages/indexer_client/src/models/locals-ref.ts index d4054dec3..687b68658 100644 --- a/packages/indexer_client/src/models/locals-ref.ts +++ b/packages/indexer_client/src/models/locals-ref.ts @@ -31,7 +31,7 @@ export const LocalsRefMeta: ModelMetadata = { wireKey: 'app', optional: false, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, ], } diff --git a/packages/indexer_client/src/models/lookup-account-app-local-states.ts b/packages/indexer_client/src/models/lookup-account-app-local-states.ts index 3039ae959..d5ce57fbd 100644 --- a/packages/indexer_client/src/models/lookup-account-app-local-states.ts +++ b/packages/indexer_client/src/models/lookup-account-app-local-states.ts @@ -32,7 +32,7 @@ export const LookupAccountAppLocalStatesMeta: ModelMetadata = { wireKey: 'current-round', optional: false, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'nextToken', diff --git a/packages/indexer_client/src/models/lookup-account-assets.ts b/packages/indexer_client/src/models/lookup-account-assets.ts index 85a1a176a..6c59fccd1 100644 --- a/packages/indexer_client/src/models/lookup-account-assets.ts +++ b/packages/indexer_client/src/models/lookup-account-assets.ts @@ -24,7 +24,7 @@ export const LookupAccountAssetsMeta: ModelMetadata = { wireKey: 'current-round', optional: false, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'nextToken', diff --git a/packages/indexer_client/src/models/lookup-account-by-id.ts b/packages/indexer_client/src/models/lookup-account-by-id.ts index cd39cc33e..5e0e7e0ad 100644 --- a/packages/indexer_client/src/models/lookup-account-by-id.ts +++ b/packages/indexer_client/src/models/lookup-account-by-id.ts @@ -27,7 +27,7 @@ export const LookupAccountByIdMeta: ModelMetadata = { wireKey: 'current-round', optional: false, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, ], } diff --git a/packages/indexer_client/src/models/lookup-account-created-applications.ts b/packages/indexer_client/src/models/lookup-account-created-applications.ts index 7b535c1d0..e7b81b9a5 100644 --- a/packages/indexer_client/src/models/lookup-account-created-applications.ts +++ b/packages/indexer_client/src/models/lookup-account-created-applications.ts @@ -32,7 +32,7 @@ export const LookupAccountCreatedApplicationsMeta: ModelMetadata = { wireKey: 'current-round', optional: false, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'nextToken', diff --git a/packages/indexer_client/src/models/lookup-account-created-assets.ts b/packages/indexer_client/src/models/lookup-account-created-assets.ts index b29db2e0f..533c848bf 100644 --- a/packages/indexer_client/src/models/lookup-account-created-assets.ts +++ b/packages/indexer_client/src/models/lookup-account-created-assets.ts @@ -32,7 +32,7 @@ export const LookupAccountCreatedAssetsMeta: ModelMetadata = { wireKey: 'current-round', optional: false, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'nextToken', diff --git a/packages/indexer_client/src/models/lookup-account-transactions.ts b/packages/indexer_client/src/models/lookup-account-transactions.ts index 66b50627a..dde018d4c 100644 --- a/packages/indexer_client/src/models/lookup-account-transactions.ts +++ b/packages/indexer_client/src/models/lookup-account-transactions.ts @@ -24,7 +24,7 @@ export const LookupAccountTransactionsMeta: ModelMetadata = { wireKey: 'current-round', optional: false, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'nextToken', diff --git a/packages/indexer_client/src/models/lookup-application-by-id.ts b/packages/indexer_client/src/models/lookup-application-by-id.ts index 65e517083..a1ad544c7 100644 --- a/packages/indexer_client/src/models/lookup-application-by-id.ts +++ b/packages/indexer_client/src/models/lookup-application-by-id.ts @@ -27,7 +27,7 @@ export const LookupApplicationByIdMeta: ModelMetadata = { wireKey: 'current-round', optional: false, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, ], } diff --git a/packages/indexer_client/src/models/lookup-application-logs-by-id.ts b/packages/indexer_client/src/models/lookup-application-logs-by-id.ts index a79636e86..f50e3e303 100644 --- a/packages/indexer_client/src/models/lookup-application-logs-by-id.ts +++ b/packages/indexer_client/src/models/lookup-application-logs-by-id.ts @@ -29,14 +29,14 @@ export const LookupApplicationLogsByIdMeta: ModelMetadata = { wireKey: 'application-id', optional: false, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'currentRound', wireKey: 'current-round', optional: false, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'nextToken', diff --git a/packages/indexer_client/src/models/lookup-asset-balances.ts b/packages/indexer_client/src/models/lookup-asset-balances.ts index a8a6fc6e0..d1821577e 100644 --- a/packages/indexer_client/src/models/lookup-asset-balances.ts +++ b/packages/indexer_client/src/models/lookup-asset-balances.ts @@ -32,7 +32,7 @@ export const LookupAssetBalancesMeta: ModelMetadata = { wireKey: 'current-round', optional: false, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'nextToken', diff --git a/packages/indexer_client/src/models/lookup-asset-by-id.ts b/packages/indexer_client/src/models/lookup-asset-by-id.ts index ca529b682..ea8bd0fb1 100644 --- a/packages/indexer_client/src/models/lookup-asset-by-id.ts +++ b/packages/indexer_client/src/models/lookup-asset-by-id.ts @@ -27,7 +27,7 @@ export const LookupAssetByIdMeta: ModelMetadata = { wireKey: 'current-round', optional: false, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, ], } diff --git a/packages/indexer_client/src/models/lookup-asset-transactions.ts b/packages/indexer_client/src/models/lookup-asset-transactions.ts index 4f15cfc49..a5890f377 100644 --- a/packages/indexer_client/src/models/lookup-asset-transactions.ts +++ b/packages/indexer_client/src/models/lookup-asset-transactions.ts @@ -24,7 +24,7 @@ export const LookupAssetTransactionsMeta: ModelMetadata = { wireKey: 'current-round', optional: false, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'nextToken', diff --git a/packages/indexer_client/src/models/lookup-transaction.ts b/packages/indexer_client/src/models/lookup-transaction.ts index 8efd83134..8cab3ce4c 100644 --- a/packages/indexer_client/src/models/lookup-transaction.ts +++ b/packages/indexer_client/src/models/lookup-transaction.ts @@ -27,7 +27,7 @@ export const LookupTransactionMeta: ModelMetadata = { wireKey: 'current-round', optional: false, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, ], } diff --git a/packages/indexer_client/src/models/merkle-array-proof.ts b/packages/indexer_client/src/models/merkle-array-proof.ts index 45f9847d7..e94c01f79 100644 --- a/packages/indexer_client/src/models/merkle-array-proof.ts +++ b/packages/indexer_client/src/models/merkle-array-proof.ts @@ -12,7 +12,7 @@ export type MerkleArrayProof = { /** * \[td\] */ - treeDepth?: bigint + treeDepth?: number } export const MerkleArrayProofMeta: ModelMetadata = { diff --git a/packages/indexer_client/src/models/resource-ref.ts b/packages/indexer_client/src/models/resource-ref.ts index b0080ddd3..928a64bb3 100644 --- a/packages/indexer_client/src/models/resource-ref.ts +++ b/packages/indexer_client/src/models/resource-ref.ts @@ -47,7 +47,7 @@ export const ResourceRefMeta: ModelMetadata = { wireKey: 'application-id', optional: true, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'assetId', diff --git a/packages/indexer_client/src/models/search-for-accounts.ts b/packages/indexer_client/src/models/search-for-accounts.ts index 4109c48ae..7f38113e7 100644 --- a/packages/indexer_client/src/models/search-for-accounts.ts +++ b/packages/indexer_client/src/models/search-for-accounts.ts @@ -32,7 +32,7 @@ export const SearchForAccountsMeta: ModelMetadata = { wireKey: 'current-round', optional: false, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'nextToken', diff --git a/packages/indexer_client/src/models/search-for-application-boxes.ts b/packages/indexer_client/src/models/search-for-application-boxes.ts index aeabf21a5..7035587c4 100644 --- a/packages/indexer_client/src/models/search-for-application-boxes.ts +++ b/packages/indexer_client/src/models/search-for-application-boxes.ts @@ -24,7 +24,7 @@ export const SearchForApplicationBoxesMeta: ModelMetadata = { wireKey: 'application-id', optional: false, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'boxes', diff --git a/packages/indexer_client/src/models/search-for-applications.ts b/packages/indexer_client/src/models/search-for-applications.ts index c94b7ce14..5a4e05b59 100644 --- a/packages/indexer_client/src/models/search-for-applications.ts +++ b/packages/indexer_client/src/models/search-for-applications.ts @@ -32,7 +32,7 @@ export const SearchForApplicationsMeta: ModelMetadata = { wireKey: 'current-round', optional: false, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'nextToken', diff --git a/packages/indexer_client/src/models/search-for-assets.ts b/packages/indexer_client/src/models/search-for-assets.ts index 6e5e1b201..77d6d592c 100644 --- a/packages/indexer_client/src/models/search-for-assets.ts +++ b/packages/indexer_client/src/models/search-for-assets.ts @@ -32,7 +32,7 @@ export const SearchForAssetsMeta: ModelMetadata = { wireKey: 'current-round', optional: false, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'nextToken', diff --git a/packages/indexer_client/src/models/search-for-block-headers.ts b/packages/indexer_client/src/models/search-for-block-headers.ts index c5a93235b..33e09c5bf 100644 --- a/packages/indexer_client/src/models/search-for-block-headers.ts +++ b/packages/indexer_client/src/models/search-for-block-headers.ts @@ -24,7 +24,7 @@ export const SearchForBlockHeadersMeta: ModelMetadata = { wireKey: 'current-round', optional: false, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'nextToken', diff --git a/packages/indexer_client/src/models/search-for-transactions.ts b/packages/indexer_client/src/models/search-for-transactions.ts index 3f42e82c7..9af103f24 100644 --- a/packages/indexer_client/src/models/search-for-transactions.ts +++ b/packages/indexer_client/src/models/search-for-transactions.ts @@ -24,7 +24,7 @@ export const SearchForTransactionsMeta: ModelMetadata = { wireKey: 'current-round', optional: false, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'nextToken', diff --git a/packages/indexer_client/src/models/state-proof-fields.ts b/packages/indexer_client/src/models/state-proof-fields.ts index 637b7df30..e19175ee7 100644 --- a/packages/indexer_client/src/models/state-proof-fields.ts +++ b/packages/indexer_client/src/models/state-proof-fields.ts @@ -26,7 +26,7 @@ export type StateProofFields = { /** * \[v\] Salt version of the merkle signature. */ - saltVersion?: bigint + saltVersion?: number /** * \[r\] Note that this is actually stored as a map[uint64] - Reveal in the actual msgp diff --git a/packages/indexer_client/src/models/state-proof-signature.ts b/packages/indexer_client/src/models/state-proof-signature.ts index 19992e49a..3f03e57c1 100644 --- a/packages/indexer_client/src/models/state-proof-signature.ts +++ b/packages/indexer_client/src/models/state-proof-signature.ts @@ -4,7 +4,7 @@ import { MerkleArrayProofMeta } from './merkle-array-proof' export type StateProofSignature = { falconSignature?: Uint8Array - merkleArrayIndex?: bigint + merkleArrayIndex?: number proof?: MerkleArrayProof /** diff --git a/packages/indexer_client/src/models/state-proof-tracking.ts b/packages/indexer_client/src/models/state-proof-tracking.ts index c1e32280d..11f33b61c 100644 --- a/packages/indexer_client/src/models/state-proof-tracking.ts +++ b/packages/indexer_client/src/models/state-proof-tracking.ts @@ -45,7 +45,7 @@ export const StateProofTrackingMeta: ModelMetadata = { wireKey: 'online-total-weight', optional: true, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'nextRound', diff --git a/packages/indexer_client/src/models/transaction-application.ts b/packages/indexer_client/src/models/transaction-application.ts index f1783a1a5..69c8fe824 100644 --- a/packages/indexer_client/src/models/transaction-application.ts +++ b/packages/indexer_client/src/models/transaction-application.ts @@ -71,7 +71,7 @@ export type TransactionApplication = { /** * \[aprv\] the lowest application version for which this transaction should immediately fail. 0 indicates that no version check should be performed. */ - rejectVersion?: bigint + rejectVersion?: number } export const TransactionApplicationMeta: ModelMetadata = { @@ -83,7 +83,7 @@ export const TransactionApplicationMeta: ModelMetadata = { wireKey: 'application-id', optional: false, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'onCompletion', @@ -125,14 +125,14 @@ export const TransactionApplicationMeta: ModelMetadata = { wireKey: 'foreign-apps', optional: true, nullable: false, - type: { kind: 'array', item: { kind: 'scalar' } }, + type: { kind: 'array', item: { kind: 'scalar', isBigint: true } }, }, { name: 'foreignAssets', wireKey: 'foreign-assets', optional: true, nullable: false, - type: { kind: 'array', item: { kind: 'scalar' } }, + type: { kind: 'array', item: { kind: 'scalar', isBigint: true } }, }, { name: 'localStateSchema', diff --git a/packages/indexer_client/src/models/transaction-payment.ts b/packages/indexer_client/src/models/transaction-payment.ts index ddc4184bd..dfca661e0 100644 --- a/packages/indexer_client/src/models/transaction-payment.ts +++ b/packages/indexer_client/src/models/transaction-payment.ts @@ -44,7 +44,7 @@ export const TransactionPaymentMeta: ModelMetadata = { wireKey: 'close-amount', optional: true, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'closeRemainderTo', diff --git a/packages/indexer_client/src/models/transaction-signature-multisig.ts b/packages/indexer_client/src/models/transaction-signature-multisig.ts index a6e9c02df..0ba916dda 100644 --- a/packages/indexer_client/src/models/transaction-signature-multisig.ts +++ b/packages/indexer_client/src/models/transaction-signature-multisig.ts @@ -17,12 +17,12 @@ export type TransactionSignatureMultisig = { /** * \[thr\] */ - threshold?: bigint + threshold?: number /** * \[v\] */ - version?: bigint + version?: number } export const TransactionSignatureMultisigMeta: ModelMetadata = { diff --git a/packages/indexer_client/src/models/transaction.ts b/packages/indexer_client/src/models/transaction.ts index 03bb09e96..df40e6b47 100644 --- a/packages/indexer_client/src/models/transaction.ts +++ b/packages/indexer_client/src/models/transaction.ts @@ -100,7 +100,7 @@ export type Transaction = { /** * Offset into the round where this transaction was confirmed. */ - intraRoundOffset?: bigint + intraRoundOffset?: number keyregTransaction?: TransactionKeyreg /** @@ -132,7 +132,7 @@ export type Transaction = { /** * Time when the block this transaction is in was confirmed. */ - roundTime?: bigint + roundTime?: number /** * \[snd\] Sender's address. @@ -235,7 +235,7 @@ export const TransactionMeta: ModelMetadata = { wireKey: 'close-rewards', optional: true, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'closingAmount', @@ -354,7 +354,7 @@ export const TransactionMeta: ModelMetadata = { wireKey: 'receiver-rewards', optional: true, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'rekeyTo', @@ -382,7 +382,7 @@ export const TransactionMeta: ModelMetadata = { wireKey: 'sender-rewards', optional: true, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBigint: true }, }, { name: 'signature', diff --git a/packages/kmd_client/src/models/digest.ts b/packages/kmd_client/src/models/digest.ts index 067ce9c2e..be40a3e45 100644 --- a/packages/kmd_client/src/models/digest.ts +++ b/packages/kmd_client/src/models/digest.ts @@ -1,6 +1,6 @@ import type { ModelMetadata } from '../core/model-runtime' -export type Digest = bigint[] +export type Digest = number[] export const DigestMeta: ModelMetadata = { name: 'Digest', diff --git a/packages/kmd_client/src/models/ed25519-private-key.ts b/packages/kmd_client/src/models/ed25519-private-key.ts index 5824b57a8..41e02238b 100644 --- a/packages/kmd_client/src/models/ed25519-private-key.ts +++ b/packages/kmd_client/src/models/ed25519-private-key.ts @@ -1,6 +1,6 @@ import type { ModelMetadata } from '../core/model-runtime' -export type Ed25519PrivateKey = bigint[] +export type Ed25519PrivateKey = number[] export const Ed25519PrivateKeyMeta: ModelMetadata = { name: 'Ed25519PrivateKey', diff --git a/packages/kmd_client/src/models/ed25519-public-key.ts b/packages/kmd_client/src/models/ed25519-public-key.ts index 64d8f81bd..fbafdc4de 100644 --- a/packages/kmd_client/src/models/ed25519-public-key.ts +++ b/packages/kmd_client/src/models/ed25519-public-key.ts @@ -1,6 +1,6 @@ import type { ModelMetadata } from '../core/model-runtime' -export type Ed25519PublicKey = bigint[] +export type Ed25519PublicKey = number[] export const Ed25519PublicKeyMeta: ModelMetadata = { name: 'Ed25519PublicKey', diff --git a/packages/kmd_client/src/models/ed25519-signature.ts b/packages/kmd_client/src/models/ed25519-signature.ts index 26e7aced4..198535189 100644 --- a/packages/kmd_client/src/models/ed25519-signature.ts +++ b/packages/kmd_client/src/models/ed25519-signature.ts @@ -1,6 +1,6 @@ import type { ModelMetadata } from '../core/model-runtime' -export type Ed25519Signature = bigint[] +export type Ed25519Signature = number[] export const Ed25519SignatureMeta: ModelMetadata = { name: 'Ed25519Signature', diff --git a/packages/kmd_client/src/models/import-multisig-request.ts b/packages/kmd_client/src/models/import-multisig-request.ts index 9abfa0c9c..0b174d499 100644 --- a/packages/kmd_client/src/models/import-multisig-request.ts +++ b/packages/kmd_client/src/models/import-multisig-request.ts @@ -6,9 +6,9 @@ import { PublicKeyMeta } from './public-key' * APIV1POSTMultisigImportRequest is the request for `POST /v1/multisig/import` */ export type ImportMultisigRequest = { - multisigVersion?: bigint + multisigVersion?: number pks?: PublicKey[] - threshold?: bigint + threshold?: number walletHandleToken?: string } diff --git a/packages/kmd_client/src/models/master-derivation-key.ts b/packages/kmd_client/src/models/master-derivation-key.ts index aa97d978b..3e557cdd5 100644 --- a/packages/kmd_client/src/models/master-derivation-key.ts +++ b/packages/kmd_client/src/models/master-derivation-key.ts @@ -3,7 +3,7 @@ import type { ModelMetadata } from '../core/model-runtime' /** * MasterDerivationKey is used to derive ed25519 keys for use in wallets */ -export type MasterDerivationKey = bigint[] +export type MasterDerivationKey = number[] export const MasterDerivationKeyMeta: ModelMetadata = { name: 'MasterDerivationKey', diff --git a/packages/kmd_client/src/models/multisig-sig.ts b/packages/kmd_client/src/models/multisig-sig.ts index 456be8a93..fed037846 100644 --- a/packages/kmd_client/src/models/multisig-sig.ts +++ b/packages/kmd_client/src/models/multisig-sig.ts @@ -7,8 +7,8 @@ import { MultisigSubsigMeta } from './multisig-subsig' */ export type MultisigSig = { subsigs?: MultisigSubsig[] - threshold?: bigint - version?: bigint + threshold?: number + version?: number } export const MultisigSigMeta: ModelMetadata = { diff --git a/packages/kmd_client/src/models/post-multisig-export-response.ts b/packages/kmd_client/src/models/post-multisig-export-response.ts index 3410d2676..fd9243db0 100644 --- a/packages/kmd_client/src/models/post-multisig-export-response.ts +++ b/packages/kmd_client/src/models/post-multisig-export-response.ts @@ -9,9 +9,9 @@ import { PublicKeyMeta } from './public-key' export type PostMultisigExportResponse = { error?: boolean message?: string - multisigVersion?: bigint + multisigVersion?: number pks?: PublicKey[] - threshold?: bigint + threshold?: number } export const PostMultisigExportResponseMeta: ModelMetadata = { diff --git a/packages/kmd_client/src/models/wallet-handle.ts b/packages/kmd_client/src/models/wallet-handle.ts index 25474663f..650c2b2c9 100644 --- a/packages/kmd_client/src/models/wallet-handle.ts +++ b/packages/kmd_client/src/models/wallet-handle.ts @@ -7,7 +7,7 @@ import { WalletMeta } from './wallet' * and the number of number of seconds to expiration */ export type WalletHandle = { - expiresSeconds?: bigint + expiresSeconds?: number wallet?: Wallet } diff --git a/packages/kmd_client/src/models/wallet.ts b/packages/kmd_client/src/models/wallet.ts index 563163734..f558a0e2e 100644 --- a/packages/kmd_client/src/models/wallet.ts +++ b/packages/kmd_client/src/models/wallet.ts @@ -7,7 +7,7 @@ import { TxTypeMeta } from './tx-type' */ export type Wallet = { driverName?: string - driverVersion?: bigint + driverVersion?: number id?: string mnemonicUx?: boolean name?: string From 415278529513aa89e7e41587d3d24850f10e7ad6 Mon Sep 17 00:00:00 2001 From: Neil Campbell Date: Thu, 6 Nov 2025 12:24:27 +0800 Subject: [PATCH 09/10] fix: additional algod fixes --- .../openapi-converter/specs/algod.oas3.json | 52 +- .../openapi-converter/specs/indexer.oas3.json | 2 + .../generator/template_engine.py | 195 +++++-- .../templates/apis/service.ts.j2 | 8 +- .../transaction-params/suggested-params.ts.j2 | 14 + package.json | 2 +- packages/algod_client/src/apis/api.service.ts | 503 ++---------------- .../algod_client/src/models/abort-catchup.ts | 25 - .../src/models/account-asset-holding.ts | 34 -- .../src/models/account-assets-information.ts | 44 -- packages/algod_client/src/models/account.ts | 28 +- .../src/models/add-participation-key.ts | 22 - .../algod_client/src/models/app-call-logs.ts | 49 -- .../algod_client/src/models/asset-params.ts | 4 +- .../src/models/debug-settings-prof.ts | 37 -- .../algod_client/src/models/dryrun-source.ts | 8 +- .../algod_client/src/models/error-response.ts | 30 -- .../src/models/eval-delta-key-value.ts | 4 +- .../algod_client/src/models/get-block-logs.ts | 21 - ...get-block-txids.ts => get-block-tx-ids.ts} | 10 +- packages/algod_client/src/models/index.ts | 27 +- .../src/models/participation-key.ts | 107 ---- .../algod_client/src/models/shutdown-node.ts | 9 - .../algod_client/src/models/start-catchup.ts | 25 - .../src/models/suggested-params.ts | 14 + .../algod_client/src/models/teal-key-value.ts | 4 +- .../indexer_client/src/models/hashtype.ts | 14 - packages/indexer_client/src/models/index.ts | 2 - .../indexer_client/src/models/transaction.ts | 8 +- packages/kmd_client/src/apis/api.service.ts | 26 +- .../src/models/ed25519-private-key.ts | 9 - packages/kmd_client/src/models/index.ts | 8 - .../src/models/list-wallets-request.ts | 12 - packages/kmd_client/src/models/private-key.ts | 10 - .../kmd_client/src/models/versions-request.ts | 12 - packages/sdk/src/composer.ts | 5 +- packages/sdk/src/makeTxn.ts | 33 +- packages/sdk/src/types/transactions/base.ts | 4 +- src/app-deploy.spec.ts | 59 +- src/app-deploy.ts | 3 +- src/indexer-lookup.spec.ts | 12 +- src/transaction/legacy-bridge.ts | 8 +- src/transaction/transaction.ts | 21 +- src/types/account-manager.ts | 6 +- src/types/algorand-client.ts | 12 +- src/types/app-client.ts | 6 +- src/types/app-manager.ts | 10 +- src/types/app.ts | 6 +- src/types/asset.ts | 8 +- src/types/client-manager.ts | 6 +- src/types/composer.ts | 55 +- src/types/kmd-account-manager.ts | 4 +- src/types/transaction.ts | 5 +- src/types/transfer.ts | 10 +- 54 files changed, 421 insertions(+), 1231 deletions(-) create mode 100644 oas-generator/src/oas_generator/templates/models/transaction-params/suggested-params.ts.j2 delete mode 100644 packages/algod_client/src/models/abort-catchup.ts delete mode 100644 packages/algod_client/src/models/account-asset-holding.ts delete mode 100644 packages/algod_client/src/models/account-assets-information.ts delete mode 100644 packages/algod_client/src/models/add-participation-key.ts delete mode 100644 packages/algod_client/src/models/app-call-logs.ts delete mode 100644 packages/algod_client/src/models/debug-settings-prof.ts delete mode 100644 packages/algod_client/src/models/error-response.ts delete mode 100644 packages/algod_client/src/models/get-block-logs.ts rename packages/algod_client/src/models/{get-block-txids.ts => get-block-tx-ids.ts} (64%) delete mode 100644 packages/algod_client/src/models/participation-key.ts delete mode 100644 packages/algod_client/src/models/shutdown-node.ts delete mode 100644 packages/algod_client/src/models/start-catchup.ts create mode 100644 packages/algod_client/src/models/suggested-params.ts delete mode 100644 packages/indexer_client/src/models/hashtype.ts delete mode 100644 packages/kmd_client/src/models/ed25519-private-key.ts delete mode 100644 packages/kmd_client/src/models/list-wallets-request.ts delete mode 100644 packages/kmd_client/src/models/private-key.ts delete mode 100644 packages/kmd_client/src/models/versions-request.ts diff --git a/algokit-configs/openapi-converter/specs/algod.oas3.json b/algokit-configs/openapi-converter/specs/algod.oas3.json index 95f6acf84..629768e81 100644 --- a/algokit-configs/openapi-converter/specs/algod.oas3.json +++ b/algokit-configs/openapi-converter/specs/algod.oas3.json @@ -958,7 +958,7 @@ "nonparticipating" ], "summary": "Get the top level transaction IDs for the block on the given round.", - "operationId": "GetBlockTxids", + "operationId": "GetBlockTxIds", "parameters": [ { "name": "round", @@ -991,7 +991,8 @@ "description": "Block transaction IDs.", "items": { "type": "string" - } + }, + "x-algokit-field-rename": "block_tx_ids" } } } @@ -4804,18 +4805,14 @@ }, "total-apps-opted-in": { "type": "integer", - "description": "The count of all applications that have been opted in, equivalent to the count of application local data (AppLocalState objects) stored in this account.", - "format": "uint64", - "x-algokit-bigint": true + "description": "The count of all applications that have been opted in, equivalent to the count of application local data (AppLocalState objects) stored in this account." }, "apps-total-schema": { "$ref": "#/components/schemas/ApplicationStateSchema" }, "apps-total-extra-pages": { "type": "integer", - "description": "\\[teap\\] the sum of all extra application program pages for this account.", - "format": "uint64", - "x-algokit-bigint": true + "description": "\\[teap\\] the sum of all extra application program pages for this account." }, "assets": { "type": "array", @@ -4826,9 +4823,7 @@ }, "total-assets-opted-in": { "type": "integer", - "description": "The count of all assets that have been opted in, equivalent to the count of AssetHolding objects held by this account.", - "format": "uint64", - "x-algokit-bigint": true + "description": "The count of all assets that have been opted in, equivalent to the count of AssetHolding objects held by this account." }, "created-apps": { "type": "array", @@ -4839,9 +4834,7 @@ }, "total-created-apps": { "type": "integer", - "description": "The count of all apps (AppParams objects) created by this account.", - "format": "uint64", - "x-algokit-bigint": true + "description": "The count of all apps (AppParams objects) created by this account." }, "created-assets": { "type": "array", @@ -4852,21 +4845,15 @@ }, "total-created-assets": { "type": "integer", - "description": "The count of all assets (AssetParams objects) created by this account.", - "format": "uint64", - "x-algokit-bigint": true + "description": "The count of all assets (AssetParams objects) created by this account." }, "total-boxes": { "type": "integer", - "description": "\\[tbx\\] The number of existing boxes created by this account's app.", - "format": "uint64", - "x-algokit-bigint": true + "description": "\\[tbx\\] The number of existing boxes created by this account's app." }, "total-box-bytes": { "type": "integer", - "description": "\\[tbxb\\] The total number of bytes used by this account's app's box keys and values.", - "format": "uint64", - "x-algokit-bigint": true + "description": "\\[tbxb\\] The total number of bytes used by this account's app's box keys and values." }, "participation": { "$ref": "#/components/schemas/AccountParticipation" @@ -5063,9 +5050,7 @@ "maximum": 19, "minimum": 0, "type": "integer", - "description": "\\[dc\\] The number of digits to use after the decimal point when displaying this asset. 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, and so on. This value must be between 0 and 19 (inclusive).", - "format": "uint64", - "x-algokit-bigint": true + "description": "\\[dc\\] The number of digits to use after the decimal point when displaying this asset. 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, and so on. This value must be between 0 and 19 (inclusive)." }, "default-frozen": { "type": "boolean", @@ -5282,7 +5267,9 @@ "type": "object", "properties": { "key": { - "type": "string" + "type": "string", + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "format": "byte" }, "value": { "$ref": "#/components/schemas/TealValue" @@ -5389,7 +5376,9 @@ "type": "object", "properties": { "key": { - "type": "string" + "type": "string", + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", + "format": "byte" }, "value": { "$ref": "#/components/schemas/EvalDelta" @@ -5687,12 +5676,12 @@ "type": "string" }, "txn-index": { - "type": "integer", - "x-algokit-bigint": true + "type": "integer" }, "app-index": { "type": "integer", "x-go-type": "basics.AppIndex", + "x-algokit-field-rename": "app_id", "x-algokit-bigint": true } }, @@ -6804,7 +6793,8 @@ "description": "Block transaction IDs.", "items": { "type": "string" - } + }, + "x-algokit-field-rename": "block_tx_ids" } } } diff --git a/algokit-configs/openapi-converter/specs/indexer.oas3.json b/algokit-configs/openapi-converter/specs/indexer.oas3.json index c2ef5e927..9573accc1 100644 --- a/algokit-configs/openapi-converter/specs/indexer.oas3.json +++ b/algokit-configs/openapi-converter/specs/indexer.oas3.json @@ -4315,11 +4315,13 @@ "created-application-index": { "type": "integer", "description": "Specifies an application index (ID) if an application was created with this transaction.", + "x-algokit-field-rename": "created_app_id", "x-algokit-bigint": true }, "created-asset-index": { "type": "integer", "description": "Specifies an asset index (ID) if an asset was created with this transaction.", + "x-algokit-field-rename": "created_asset_id", "x-algokit-bigint": true }, "fee": { diff --git a/oas-generator/src/oas_generator/generator/template_engine.py b/oas-generator/src/oas_generator/generator/template_engine.py index f8a453b27..be1264e69 100644 --- a/oas-generator/src/oas_generator/generator/template_engine.py +++ b/oas-generator/src/oas_generator/generator/template_engine.py @@ -235,6 +235,74 @@ def _build_model_descriptor(self, name: str, schema: Schema, all_schemas: Schema return ModelDescriptor(model_name=model_name, fields=fields, is_object=is_object) + def _extract_types_from_schema(self, schema: Schema, all_schemas: Schemas) -> set[str]: + """Extract all type names referenced in a schema.""" + referenced_types = set() + + # Handle $ref directly + if isinstance(schema, dict) and "$ref" in schema: + ref = schema["$ref"].split("/")[-1] + referenced_types.add(ts_pascal_case(ref)) + + # Handle arrays + if isinstance(schema, dict) and schema.get("type") == "array": + items = schema.get("items", {}) + if isinstance(items, dict): + referenced_types.update(self._extract_types_from_schema(items, all_schemas)) + + # Handle object properties + if isinstance(schema, dict) and "properties" in schema: + for prop_schema in schema["properties"].values(): + if isinstance(prop_schema, dict): + referenced_types.update(self._extract_types_from_schema(prop_schema, all_schemas)) + + # Handle allOf, oneOf, anyOf + for key in ["allOf", "oneOf", "anyOf"]: + if isinstance(schema, dict) and key in schema: + items = schema[key] + if isinstance(items, list): + for item in items: + if isinstance(item, dict): + referenced_types.update(self._extract_types_from_schema(item, all_schemas)) + + # Convert to TypeScript type and extract model names using the same logic as in operations + if isinstance(schema, dict): + ts_type_str = ts_type(schema, all_schemas) + tokens = set(_TYPE_TOKEN_RE.findall(ts_type_str)) + model_names = {ts_pascal_case(name) for name in all_schemas.keys()} + referenced_types.update(tok for tok in tokens if tok in model_names) + + return referenced_types + + def collect_transitive_dependencies(self, used_types: set[str], all_schemas: Schemas) -> set[str]: + """Collect all types transitively referenced by the given used_types.""" + all_used_types = set(used_types) + to_process = set(used_types) + + while to_process: + current_type = to_process.pop() + + # Convert from TypeScript type name back to schema name + schema_name = None + for name in all_schemas.keys(): + if ts_pascal_case(name) == current_type: + schema_name = name + break + + if schema_name and schema_name in all_schemas: + schema = all_schemas[schema_name] + referenced_types = self._extract_types_from_schema(schema, all_schemas) + + # Add any new types to the processing queue + for ref_type in referenced_types: + if ref_type not in all_used_types: + all_used_types.add(ref_type) + to_process.add(ref_type) + + return all_used_types + + + class OperationProcessor: """Processes OpenAPI operations and generates API services.""" @@ -274,7 +342,7 @@ def generate_service( operations_by_tag: dict[str, list[OperationContext]], tags: set[str], service_class_name: str, - ) -> FileMap: + ) -> tuple[FileMap, set[str]]: """Generate API service files.""" apis_dir = output_dir / constants.DirectoryName.SRC / constants.DirectoryName.APIS files: FileMap = {} @@ -282,16 +350,13 @@ def generate_service( # Collect unique operations all_operations = self._collect_unique_operations(operations_by_tag, tags) - # Get private and skipped methods configurations for this service + # Get private method configurations for this service private_methods = self._get_private_methods(service_class_name) - skipped_methods = self._get_skipped_methods(service_class_name) # Mark operations as private or skipped, where required for operation in all_operations: if operation.operation_id in private_methods: operation.is_private = True - if operation.operation_id in skipped_methods: - operation.skip_generation = True # Filter out operations marked for skipping all_operations = [op for op in all_operations if not op.skip_generation] @@ -303,6 +368,10 @@ def generate_service( # Get custom imports and methods for this service custom_imports, custom_methods = self._get_custom_service_extensions(service_class_name) + # Add custom model imports for AlgodApi + if service_class_name == "AlgodApi": + import_types.add("SuggestedParams") + # Generate service file files[apis_dir / constants.API_SERVICE_FILE] = self.renderer.render( constants.API_SERVICE_TEMPLATE, @@ -321,7 +390,7 @@ def generate_service( constants.APIS_INDEX_TEMPLATE, {"service_class_name": service_class_name} ) - return files + return files, import_types def _get_custom_service_extensions(self, service_class_name: str) -> tuple[list[str], list[str]]: """Get custom imports and methods for specific service classes.""" @@ -345,10 +414,40 @@ def _get_custom_service_extensions(self, service_class_name: str) -> tuple[list[ } else if (!(rawTransactions instanceof Uint8Array)) { throw new Error('Argument must be byte array'); } - return this.rawTransaction(rawTransactions); + return this._rawTransaction(rawTransactions); }''' - - custom_methods = [send_raw_transaction_method] + get_application_box_by_name_method = '''/** + * Given an application ID and box name, it returns the round, box name, and value. + */ + async getApplicationBoxByName(applicationId: number | bigint, boxName: Uint8Array): Promise { + const name = `b64:${Buffer.from(boxName).toString('base64')}`; + return this._getApplicationBoxByName(applicationId, { name }); + } +''' + suggested_params_method = '''/** + * Returns the common needed parameters for a new transaction. + */ + async suggestedParams(): Promise { + const txnParams = await this._transactionParams(); + + return { + flatFee: false, + fee: txnParams.fee, + firstValid: txnParams.lastRound, + lastValid: txnParams.lastRound + 1000n, + genesisHash: txnParams.genesisHash, + genesisId: txnParams.genesisId, + minFee: txnParams.minFee, + consensusVersion: txnParams.consensusVersion, + }; + }''' + get_transaction_params_method = '''/** + * Returns the common needed parameters for a new transaction. + */ + async getTransactionParams(): Promise { + return await this.suggestedParams(); + }''' + custom_methods = [send_raw_transaction_method, get_application_box_by_name_method, suggested_params_method, get_transaction_params_method] return custom_imports, custom_methods @@ -357,7 +456,9 @@ def _get_private_methods(self, service_class_name: str) -> set[str]: # Default configuration for private methods by service class private_method_config = { "AlgodApi": { - "RawTransaction" # This is the raw transaction endpoint we're wrapping with sendRawTransaction + "RawTransaction", # Wrapped by custom method + "GetApplicationBoxByName", # Wrapped by custom method + "TransactionParams" # Wrapped by custom method }, "IndexerApi": set(), # No private methods by default "KmdApi": set(), # No private methods by default @@ -365,19 +466,6 @@ def _get_private_methods(self, service_class_name: str) -> set[str]: return private_method_config.get(service_class_name, set()) - def _get_skipped_methods(self, service_class_name: str) -> set[str]: - """Get set of operation IDs that should be skipped during generation for specific service classes.""" - # Default configuration for methods to skip generation by service class - skip_generation_config = { - "AlgodApi": { - "RawTransactionAsync", # Not exposed via algosdk - }, - "IndexerApi": set(), - "KmdApi": set(), - } - - return skip_generation_config.get(service_class_name, set()) - def _initialize_model_names(self, spec: Schema) -> None: """Initialize set of model names from spec.""" @@ -413,6 +501,13 @@ def _process_path_operations(self, path: str, path_item: Schema, spec: Schema) - context = self._create_operation_context(op_input) context.tags = operation.get(constants.OperationKey.TAGS, [constants.DEFAULT_TAG]) + + # Skip generation for operations tagged with "private" or "experimental" + # or with specific operation IDs + if (any(tag in context.tags for tag in ("private", "experimental")) or + context.operation_id in ("Metrics", "SwaggerJSON", "GetBlockLogs")): + context.skip_generation = True + operations.append(context) return operations @@ -618,15 +713,13 @@ def extract_types(type_str: str) -> set[str]: tokens = set(_TYPE_TOKEN_RE.findall(type_str)) types: set[str] = {tok for tok in tokens if tok in self._model_names and tok not in builtin_types} # Include synthetic models that aren't part of _model_names - if "AlgokitSignedTransaction" in tokens: - types.add("AlgokitSignedTransaction") return types # Collect from all type references context.import_types = extract_types(context.response_type) # Only include request body types if the method actually uses a body - if context.request_body and context.method.upper() not in ["GET", "HEAD", "DELETE"]: + if context.request_body and context.method.upper() not in ["GET", "HEAD"]: context.import_types |= extract_types(context.request_body.ts_type) for param in context.parameters: @@ -757,18 +850,36 @@ def generate( # Process operations and schemas ops_by_tag, tags, synthetic_models = self.operation_processor.process_spec(spec) + # Generate service first to get the used types + service_files, used_types = self.operation_processor.generate_service(output_dir, ops_by_tag, tags, service_class) + files.update(service_files) + # Merge schemas components = spec.get(constants.SchemaKey.COMPONENTS, {}) base_schemas = components.get(constants.SchemaKey.COMPONENTS_SCHEMAS, {}) all_schemas = {**base_schemas, **synthetic_models} - # Generate components - files.update(self.schema_processor.generate_models(output_dir, all_schemas)) + # Collect all transitive dependencies of used types + all_used_types = self.schema_processor.collect_transitive_dependencies(used_types, all_schemas) + + # Filter schemas to only include those used by non-skipped operations + used_schemas = {name: schema for name, schema in all_schemas.items() + if ts_pascal_case(name) in all_used_types} + + - # Inject custom Algod models if this spec targets Algod - client_type = self._detect_client_type(spec) - if client_type == "Algod": + # Generate components (only used schemas) + files.update(self.schema_processor.generate_models(output_dir, used_schemas)) + + if service_class == "AlgodApi": models_dir = output_dir / constants.DirectoryName.SRC / constants.DirectoryName.MODELS + + # Add SuggestedParams custom model + files[models_dir / "suggested-params.ts"] = self.renderer.render( + "models/transaction-params/suggested-params.ts.j2", + {"spec": spec}, + ) + # Custom typed block models # Block-specific models (prefixed to avoid shape collisions) files[models_dir / "block-eval-delta.ts"] = self.renderer.render( @@ -811,9 +922,10 @@ def generate( # Ensure index exports include the custom models index_path = models_dir / constants.INDEX_FILE - base_index = self.renderer.render(constants.MODELS_INDEX_TEMPLATE, {"schemas": all_schemas}) + base_index = self.renderer.render(constants.MODELS_INDEX_TEMPLATE, {"schemas": used_schemas}) extras = ( "\n" + "export type { SuggestedParams, SuggestedParamsMeta } from './suggested-params';\n" "export type { BlockEvalDelta } from './block-eval-delta';\n" "export { BlockEvalDeltaMeta } from './block-eval-delta';\n" "export type { BlockStateDelta } from './block-state-delta';\n" @@ -832,29 +944,10 @@ def generate( "export { SignedTxnInBlockMeta } from './signed-txn-in-block';\n" ) files[index_path] = base_index + extras - files.update(self.operation_processor.generate_service(output_dir, ops_by_tag, tags, service_class)) files.update(self._generate_client_files(output_dir, client_class, service_class)) return files - @staticmethod - def _detect_client_type(spec: Schema) -> str: - """Detect client type from the OpenAPI spec title.""" - try: - title = (spec.get("info", {}) or {}).get("title", "") - if not isinstance(title, str): - return "Api" - tl = title.lower() - if "algod" in tl: - return "Algod" - if "indexer" in tl: - return "Indexer" - if "kmd" in tl: - return "Kmd" - return (title.split()[0] or "Api").title() - except Exception: - return "Api" - def _generate_runtime( self, output_dir: Path, diff --git a/oas-generator/src/oas_generator/templates/apis/service.ts.j2 b/oas-generator/src/oas_generator/templates/apis/service.ts.j2 index 67cf8e4ab..9ec8a5ca6 100644 --- a/oas-generator/src/oas_generator/templates/apis/service.ts.j2 +++ b/oas-generator/src/oas_generator/templates/apis/service.ts.j2 @@ -89,11 +89,11 @@ export class {{ service_class_name }} { {% for op in operations %} {% set is_raw_bytes_body = op.requestBody and op.requestBody.tsType == 'Uint8Array' %} {{ op.description | ts_doc_comment }} - {% if op.isPrivate %}private {% endif %}async {{ op.operationId | ts_camel_case }}( + {% if op.isPrivate %}private async _{% else %}async {% endif %}{{ op.operationId | ts_camel_case }}( {%- for p in op.pathParameters %} {{ p.varName }}: {{ p.tsType }}, {%- endfor %} -{%- if op.requestBody and op.method.upper() not in ['GET', 'HEAD', 'DELETE'] %} +{%- if op.requestBody and op.method.upper() not in ['GET', 'HEAD'] %} body{% if not op.requestBody.required %}?{% endif %}: {{ op.requestBody.tsType }}, {%- endif %} {%- if op.otherParameters|length > 0 %} @@ -109,7 +109,7 @@ export class {{ service_class_name }} { const responseFormat: BodyFormat = {% if supports_msgpack %}{% if op.hasFormatParam and op.formatVarName %}(params?.{{ op.formatVarName }} as BodyFormat | undefined) ?? 'msgpack'{% else %}'msgpack'{% endif %}{% else %}'json'{% endif %}; headers['Accept'] = {{ service_class_name }}.acceptFor(responseFormat); - {% if op.requestBody and op.method.upper() not in ['GET', 'HEAD', 'DELETE'] %} + {% if op.requestBody and op.method.upper() not in ['GET', 'HEAD'] %} {% if is_raw_bytes_body %} const serializedBody = body ?? undefined; const mediaType = 'application/msgpack'; @@ -149,7 +149,7 @@ export class {{ service_class_name }} { {%- endif %} }, headers, - {% if op.requestBody and op.method.upper() not in ['GET', 'HEAD', 'DELETE'] %} + {% if op.requestBody and op.method.upper() not in ['GET', 'HEAD'] %} body: serializedBody, mediaType: mediaType, {% else %} diff --git a/oas-generator/src/oas_generator/templates/models/transaction-params/suggested-params.ts.j2 b/oas-generator/src/oas_generator/templates/models/transaction-params/suggested-params.ts.j2 new file mode 100644 index 000000000..9f481c154 --- /dev/null +++ b/oas-generator/src/oas_generator/templates/models/transaction-params/suggested-params.ts.j2 @@ -0,0 +1,14 @@ +import { Expand } from '@algorandfoundation/algokit-common'; +import type { TransactionParams } from './transaction-params'; + +/** Contains parameters relevant to the creation of a new transaction in a specific network at a specific time. */ +export type SuggestedParams = Expand< + Omit & { + flatFee: boolean + firstValid: bigint + lastValid: bigint + } +>; + +// This is never used, just to satisfy the import generator pattern +export type SuggestedParamsMeta = undefined diff --git a/package.json b/package.json index ed5631d4b..d4f925dc5 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "semantic-release": "semantic-release", "generate:code-docs": "typedoc", "pre-commit": "run-s check-types lint:fix audit format test generate:code-docs && npm run pre-commit --workspaces --if-present", - "generate:clients": "run-s generate:client-*", + "generate:clients": "run-p generate:client-*", "generate:client-algod": "cd oas-generator && uv run oas-generator ../algokit-configs/openapi-converter/specs/algod.oas3.json --output ../packages/algod_client/ --package-name algod_client --description \"TypeScript client for algod interaction.\" --verbose && prettier --write ../packages/algod_client/src/ && cd ..", "generate:client-indexer": "cd oas-generator && uv run oas-generator ../algokit-configs/openapi-converter/specs/indexer.oas3.json --output ../packages/indexer_client/ --package-name indexer_client --description \"TypeScript client for indexer interaction.\" --verbose && prettier --write ../packages/indexer_client/src/ && cd ..", "generate:client-kmd": "cd oas-generator && uv run oas-generator ../algokit-configs/openapi-converter/specs/kmd.oas3.json --output ../packages/kmd_client/ --package-name kmd_client --description \"TypeScript client for kmd interaction.\" --verbose && prettier --write ../packages/kmd_client/src/ && cd .." diff --git a/packages/algod_client/src/apis/api.service.ts b/packages/algod_client/src/apis/api.service.ts index 6fbb49298..de3fce433 100644 --- a/packages/algod_client/src/apis/api.service.ts +++ b/packages/algod_client/src/apis/api.service.ts @@ -3,24 +3,19 @@ import { AlgorandSerializer } from '../core/model-runtime' import type { BodyFormat } from '../core/model-runtime' import { concatArrays } from '@algorandfoundation/algokit-common' import type { - AbortCatchup, Account, AccountApplicationInformation, AccountAssetInformation, - AccountAssetsInformation, - AddParticipationKey, Application, Asset, Box, - DebugSettingsProf, DryrunRequest, Genesis, GetApplicationBoxes, GetBlock, GetBlockHash, - GetBlockLogs, GetBlockTimeStampOffset, - GetBlockTxids, + GetBlockTxIds, GetPendingTransactions, GetPendingTransactionsByAddress, GetStatus, @@ -29,14 +24,12 @@ import type { GetTransactionGroupLedgerStateDeltasForRound, LedgerStateDelta, LightBlockHeaderProof, - ParticipationKey, PendingTransactionResponse, RawTransaction, - ShutdownNode, SimulateRequest, SimulateTransaction, - StartCatchup, StateProof, + SuggestedParams, TealCompile, TealDisassemble, TealDryrun, @@ -46,24 +39,19 @@ import type { WaitForBlock, } from '../models/index' import { - AbortCatchupMeta, AccountMeta, AccountApplicationInformationMeta, AccountAssetInformationMeta, - AccountAssetsInformationMeta, - AddParticipationKeyMeta, ApplicationMeta, AssetMeta, BoxMeta, - DebugSettingsProfMeta, DryrunRequestMeta, GenesisMeta, GetApplicationBoxesMeta, GetBlockMeta, GetBlockHashMeta, - GetBlockLogsMeta, GetBlockTimeStampOffsetMeta, - GetBlockTxidsMeta, + GetBlockTxIdsMeta, GetPendingTransactionsMeta, GetPendingTransactionsByAddressMeta, GetStatusMeta, @@ -72,14 +60,12 @@ import { GetTransactionGroupLedgerStateDeltasForRoundMeta, LedgerStateDeltaMeta, LightBlockHeaderProofMeta, - ParticipationKeyMeta, PendingTransactionResponseMeta, RawTransactionMeta, - ShutdownNodeMeta, SimulateRequestMeta, SimulateTransactionMeta, - StartCatchupMeta, StateProofMeta, + SuggestedParamsMeta, TealCompileMeta, TealDisassembleMeta, TealDryrunMeta, @@ -100,31 +86,6 @@ export class AlgodApi { return format === 'json' ? 'application/json' : 'application/msgpack' } - /** - * Given a catchpoint, it aborts catching up to this catchpoint - */ - async abortCatchup(catchpoint: string): Promise { - const headers: Record = {} - const responseFormat: BodyFormat = 'json' - headers['Accept'] = AlgodApi.acceptFor(responseFormat) - - const payload = await this.httpRequest.request({ - method: 'DELETE', - url: '/v2/catchup/{catchpoint}', - path: { catchpoint: catchpoint }, - query: {}, - headers, - body: undefined, - mediaType: undefined, - }) - - const responseMeta = AbortCatchupMeta - if (responseMeta) { - return AlgorandSerializer.decode(payload, responseMeta, responseFormat) - } - return payload as AbortCatchup - } - /** * Given a specific account public key and application ID, this call returns the account's application local state and global state (AppLocalState and AppParams, if either exists). Global state will only be returned if the provided address is the application's creator. */ @@ -179,31 +140,6 @@ export class AlgodApi { return payload as AccountAssetInformation } - /** - * Lookup an account's asset holdings. - */ - async accountAssetsInformation(address: string, params?: { limit?: number; next?: string }): Promise { - const headers: Record = {} - const responseFormat: BodyFormat = 'json' - headers['Accept'] = AlgodApi.acceptFor(responseFormat) - - const payload = await this.httpRequest.request({ - method: 'GET', - url: '/v2/accounts/{address}/assets', - path: { address: address }, - query: { limit: params?.limit, next: params?.next }, - headers, - body: undefined, - mediaType: undefined, - }) - - const responseMeta = AccountAssetsInformationMeta - if (responseMeta) { - return AlgorandSerializer.decode(payload, responseMeta, responseFormat) - } - return payload as AccountAssetsInformation - } - /** * Given a specific account public key, this call returns the account's status, balance and spendable amounts */ @@ -229,143 +165,10 @@ export class AlgodApi { return payload as Account } - async addParticipationKey(body: string): Promise { - const headers: Record = {} - const responseFormat: BodyFormat = 'msgpack' - headers['Accept'] = AlgodApi.acceptFor(responseFormat) - - const bodyMeta = undefined - const mediaType = bodyMeta ? AlgodApi.mediaFor(responseFormat) : undefined - if (mediaType) headers['Content-Type'] = mediaType - const serializedBody = bodyMeta && body !== undefined ? AlgorandSerializer.encode(body, bodyMeta, responseFormat) : body - - const payload = await this.httpRequest.request({ - method: 'POST', - url: '/v2/participation', - path: {}, - query: {}, - headers, - body: serializedBody, - mediaType: mediaType, - }) - - const responseMeta = AddParticipationKeyMeta - if (responseMeta) { - return AlgorandSerializer.decode(payload, responseMeta, responseFormat) - } - return payload as AddParticipationKey - } - - /** - * Given a participation ID, append state proof keys to a particular set of participation keys - */ - async appendKeys(participationId: string, body: string): Promise { - const headers: Record = {} - const responseFormat: BodyFormat = 'msgpack' - headers['Accept'] = AlgodApi.acceptFor(responseFormat) - - const bodyMeta = undefined - const mediaType = bodyMeta ? AlgodApi.mediaFor(responseFormat) : undefined - if (mediaType) headers['Content-Type'] = mediaType - const serializedBody = bodyMeta && body !== undefined ? AlgorandSerializer.encode(body, bodyMeta, responseFormat) : body - - const payload = await this.httpRequest.request({ - method: 'POST', - url: '/v2/participation/{participation-id}', - path: { 'participation-id': participationId }, - query: {}, - headers, - body: serializedBody, - mediaType: mediaType, - }) - - const responseMeta = ParticipationKeyMeta - if (responseMeta) { - return AlgorandSerializer.decode(payload, responseMeta, responseFormat) - } - return payload as ParticipationKey - } - - /** - * Delete a given participation key by ID - */ - async deleteParticipationKeyById(participationId: string): Promise { - const headers: Record = {} - const responseFormat: BodyFormat = 'json' - headers['Accept'] = AlgodApi.acceptFor(responseFormat) - - const payload = await this.httpRequest.request({ - method: 'DELETE', - url: '/v2/participation/{participation-id}', - path: { 'participation-id': participationId }, - query: {}, - headers, - body: undefined, - mediaType: undefined, - }) - - const responseMeta = undefined - if (responseMeta) { - return AlgorandSerializer.decode(payload, responseMeta, responseFormat) - } - return payload as void - } - - async experimentalCheck(): Promise { - const headers: Record = {} - const responseFormat: BodyFormat = 'json' - headers['Accept'] = AlgodApi.acceptFor(responseFormat) - - const payload = await this.httpRequest.request({ - method: 'GET', - url: '/v2/experimental', - path: {}, - query: {}, - headers, - body: undefined, - mediaType: undefined, - }) - - const responseMeta = undefined - if (responseMeta) { - return AlgorandSerializer.decode(payload, responseMeta, responseFormat) - } - return payload as void - } - - async generateParticipationKeys( - address: string, - params?: { dilution?: number | bigint; first: number | bigint; last: number | bigint }, - ): Promise { - const headers: Record = {} - const responseFormat: BodyFormat = 'json' - headers['Accept'] = AlgodApi.acceptFor(responseFormat) - - const payload = await this.httpRequest.request({ - method: 'POST', - url: '/v2/participation/generate/{address}', - path: { address: address }, - query: { - dilution: typeof params?.dilution === 'bigint' ? (params!.dilution as bigint).toString() : params?.dilution, - first: typeof params?.first === 'bigint' ? (params!.first as bigint).toString() : params?.first, - last: typeof params?.last === 'bigint' ? (params!.last as bigint).toString() : params?.last, - }, - headers, - body: undefined, - mediaType: undefined, - }) - - const responseMeta = undefined - if (responseMeta) { - return AlgorandSerializer.decode(payload, responseMeta, responseFormat) - } - return payload as string - } - /** * Given an application ID and box name, it returns the round, box name, and value (each base64 encoded). Box names must be in the goal app call arg encoding form 'encoding:value'. For ints, use the form 'int:1234'. For raw bytes, use the form 'b64:A=='. For printable strings, use the form 'str:hello'. For addresses, use the form 'addr:XYZ...'. */ - async getApplicationBoxByName(applicationId: number | bigint, params?: { name: string }): Promise { + private async _getApplicationBoxByName(applicationId: number | bigint, params?: { name: string }): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -506,31 +309,6 @@ export class AlgodApi { return payload as GetBlockHash } - /** - * Get all of the logs from outer and inner app calls in the given round - */ - async getBlockLogs(round: number | bigint): Promise { - const headers: Record = {} - const responseFormat: BodyFormat = 'json' - headers['Accept'] = AlgodApi.acceptFor(responseFormat) - - const payload = await this.httpRequest.request({ - method: 'GET', - url: '/v2/blocks/{round}/logs', - path: { round: typeof round === 'bigint' ? round.toString() : round }, - query: {}, - headers, - body: undefined, - mediaType: undefined, - }) - - const responseMeta = GetBlockLogsMeta - if (responseMeta) { - return AlgorandSerializer.decode(payload, responseMeta, responseFormat) - } - return payload as GetBlockLogs - } - /** * Gets the current timestamp offset. */ @@ -556,7 +334,7 @@ export class AlgodApi { return payload as GetBlockTimeStampOffset } - async getBlockTxids(round: number | bigint): Promise { + async getBlockTxIds(round: number | bigint): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -571,61 +349,11 @@ export class AlgodApi { mediaType: undefined, }) - const responseMeta = GetBlockTxidsMeta + const responseMeta = GetBlockTxIdsMeta if (responseMeta) { return AlgorandSerializer.decode(payload, responseMeta, responseFormat) } - return payload as GetBlockTxids - } - - /** - * Returns the merged (defaults + overrides) config file in json. - */ - async getConfig(): Promise { - const headers: Record = {} - const responseFormat: BodyFormat = 'json' - headers['Accept'] = AlgodApi.acceptFor(responseFormat) - - const payload = await this.httpRequest.request({ - method: 'GET', - url: '/debug/settings/config', - path: {}, - query: {}, - headers, - body: undefined, - mediaType: undefined, - }) - - const responseMeta = undefined - if (responseMeta) { - return AlgorandSerializer.decode(payload, responseMeta, responseFormat) - } - return payload as string - } - - /** - * Retrieves the current settings for blocking and mutex profiles - */ - async getDebugSettingsProf(): Promise { - const headers: Record = {} - const responseFormat: BodyFormat = 'json' - headers['Accept'] = AlgodApi.acceptFor(responseFormat) - - const payload = await this.httpRequest.request({ - method: 'GET', - url: '/debug/settings/pprof', - path: {}, - query: {}, - headers, - body: undefined, - mediaType: undefined, - }) - - const responseMeta = DebugSettingsProfMeta - if (responseMeta) { - return AlgorandSerializer.decode(payload, responseMeta, responseFormat) - } - return payload as DebugSettingsProf + return payload as GetBlockTxIds } /** @@ -725,60 +453,6 @@ export class AlgodApi { return payload as LightBlockHeaderProof } - /** - * Given a participation ID, return information about that participation key - */ - async getParticipationKeyById(participationId: string): Promise { - const headers: Record = {} - const responseFormat: BodyFormat = 'json' - headers['Accept'] = AlgodApi.acceptFor(responseFormat) - - const payload = await this.httpRequest.request({ - method: 'GET', - url: '/v2/participation/{participation-id}', - path: { 'participation-id': participationId }, - query: {}, - headers, - body: undefined, - mediaType: undefined, - }) - - const responseMeta = ParticipationKeyMeta - if (responseMeta) { - return AlgorandSerializer.decode(payload, responseMeta, responseFormat) - } - return payload as ParticipationKey - } - - /** - * Return a list of participation keys - */ - async getParticipationKeys(): Promise { - const headers: Record = {} - const responseFormat: BodyFormat = 'json' - headers['Accept'] = AlgodApi.acceptFor(responseFormat) - - const payload = await this.httpRequest.request({ - method: 'GET', - url: '/v2/participation', - path: {}, - query: {}, - headers, - body: undefined, - mediaType: undefined, - }) - - const responseMeta = { - name: 'ParticipationKey[]', - kind: 'array', - arrayItems: { kind: 'model', meta: () => ParticipationKeyMeta } as const, - } as const - if (responseMeta) { - return AlgorandSerializer.decode(payload, responseMeta, responseFormat) - } - return payload as ParticipationKey[] - } - /** * Get the list of pending transactions, sorted by priority, in decreasing order, truncated at the end at MAX. If MAX = 0, returns all pending transactions. */ @@ -1040,28 +714,6 @@ export class AlgodApi { return payload as void } - async metrics(): Promise { - const headers: Record = {} - const responseFormat: BodyFormat = 'json' - headers['Accept'] = AlgodApi.acceptFor(responseFormat) - - const payload = await this.httpRequest.request({ - method: 'GET', - url: '/metrics', - path: {}, - query: {}, - headers, - body: undefined, - mediaType: undefined, - }) - - const responseMeta = undefined - if (responseMeta) { - return AlgorandSerializer.decode(payload, responseMeta, responseFormat) - } - return payload as void - } - /** * Given a transaction ID of a recently submitted transaction, it returns information about it. There are several cases when this might succeed: * - transaction committed (committed round > 0) @@ -1091,32 +743,7 @@ export class AlgodApi { return payload as PendingTransactionResponse } - /** - * Enables blocking and mutex profiles, and returns the old settings - */ - async putDebugSettingsProf(): Promise { - const headers: Record = {} - const responseFormat: BodyFormat = 'json' - headers['Accept'] = AlgodApi.acceptFor(responseFormat) - - const payload = await this.httpRequest.request({ - method: 'PUT', - url: '/debug/settings/pprof', - path: {}, - query: {}, - headers, - body: undefined, - mediaType: undefined, - }) - - const responseMeta = DebugSettingsProfMeta - if (responseMeta) { - return AlgorandSerializer.decode(payload, responseMeta, responseFormat) - } - return payload as DebugSettingsProf - } - - private async rawTransaction(body: Uint8Array): Promise { + private async _rawTransaction(body: Uint8Array): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -1192,31 +819,6 @@ export class AlgodApi { return payload as void } - /** - * Special management endpoint to shutdown the node. Optionally provide a timeout parameter to indicate that the node should begin shutting down after a number of seconds. - */ - async shutdownNode(params?: { timeout?: number }): Promise { - const headers: Record = {} - const responseFormat: BodyFormat = 'json' - headers['Accept'] = AlgodApi.acceptFor(responseFormat) - - const payload = await this.httpRequest.request({ - method: 'POST', - url: '/v2/shutdown', - path: {}, - query: { timeout: params?.timeout }, - headers, - body: undefined, - mediaType: undefined, - }) - - const responseMeta = ShutdownNodeMeta - if (responseMeta) { - return AlgorandSerializer.decode(payload, responseMeta, responseFormat) - } - return payload as ShutdownNode - } - async simulateTransaction(body: SimulateRequest): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'msgpack' @@ -1244,56 +846,6 @@ export class AlgodApi { return payload as SimulateTransaction } - /** - * Given a catchpoint, it starts catching up to this catchpoint - */ - async startCatchup(catchpoint: string, params?: { min?: number | bigint }): Promise { - const headers: Record = {} - const responseFormat: BodyFormat = 'json' - headers['Accept'] = AlgodApi.acceptFor(responseFormat) - - const payload = await this.httpRequest.request({ - method: 'POST', - url: '/v2/catchup/{catchpoint}', - path: { catchpoint: catchpoint }, - query: { min: typeof params?.min === 'bigint' ? (params!.min as bigint).toString() : params?.min }, - headers, - body: undefined, - mediaType: undefined, - }) - - const responseMeta = StartCatchupMeta - if (responseMeta) { - return AlgorandSerializer.decode(payload, responseMeta, responseFormat) - } - return payload as StartCatchup - } - - /** - * Returns the entire swagger spec in json. - */ - async swaggerJson(): Promise { - const headers: Record = {} - const responseFormat: BodyFormat = 'json' - headers['Accept'] = AlgodApi.acceptFor(responseFormat) - - const payload = await this.httpRequest.request({ - method: 'GET', - url: '/swagger.json', - path: {}, - query: {}, - headers, - body: undefined, - mediaType: undefined, - }) - - const responseMeta = undefined - if (responseMeta) { - return AlgorandSerializer.decode(payload, responseMeta, responseFormat) - } - return payload as string - } - /** * Given TEAL source code in plain text, return base64 encoded program bytes and base32 SHA512_256 hash of program bytes (Address style). This endpoint is only enabled when a node's configuration file sets EnableDeveloperAPI to true. */ @@ -1383,7 +935,7 @@ export class AlgodApi { return payload as TealDryrun } - async transactionParams(): Promise { + private async _transactionParams(): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) @@ -1468,6 +1020,39 @@ export class AlgodApi { } else if (!(rawTransactions instanceof Uint8Array)) { throw new Error('Argument must be byte array') } - return this.rawTransaction(rawTransactions) + return this._rawTransaction(rawTransactions) + } + + /** + * Given an application ID and box name, it returns the round, box name, and value. + */ + async getApplicationBoxByName(applicationId: number | bigint, boxName: Uint8Array): Promise { + const name = `b64:${Buffer.from(boxName).toString('base64')}` + return this._getApplicationBoxByName(applicationId, { name }) + } + + /** + * Returns the common needed parameters for a new transaction. + */ + async suggestedParams(): Promise { + const txnParams = await this._transactionParams() + + return { + flatFee: false, + fee: txnParams.fee, + firstValid: txnParams.lastRound, + lastValid: txnParams.lastRound + 1000n, + genesisHash: txnParams.genesisHash, + genesisId: txnParams.genesisId, + minFee: txnParams.minFee, + consensusVersion: txnParams.consensusVersion, + } + } + + /** + * Returns the common needed parameters for a new transaction. + */ + async getTransactionParams(): Promise { + return await this.suggestedParams() } } diff --git a/packages/algod_client/src/models/abort-catchup.ts b/packages/algod_client/src/models/abort-catchup.ts deleted file mode 100644 index d08b63c14..000000000 --- a/packages/algod_client/src/models/abort-catchup.ts +++ /dev/null @@ -1,25 +0,0 @@ -import type { ModelMetadata } from '../core/model-runtime' - -/** - * An catchpoint abort response. - */ -export type AbortCatchup = { - /** - * Catchup abort response string - */ - catchupMessage: string -} - -export const AbortCatchupMeta: ModelMetadata = { - name: 'AbortCatchup', - kind: 'object', - fields: [ - { - name: 'catchupMessage', - wireKey: 'catchup-message', - optional: false, - nullable: false, - type: { kind: 'scalar' }, - }, - ], -} diff --git a/packages/algod_client/src/models/account-asset-holding.ts b/packages/algod_client/src/models/account-asset-holding.ts deleted file mode 100644 index 1d7e9532a..000000000 --- a/packages/algod_client/src/models/account-asset-holding.ts +++ /dev/null @@ -1,34 +0,0 @@ -import type { ModelMetadata } from '../core/model-runtime' -import type { AssetHolding } from './asset-holding' -import { AssetHoldingMeta } from './asset-holding' -import type { AssetParams } from './asset-params' -import { AssetParamsMeta } from './asset-params' - -/** - * AccountAssetHolding describes the account's asset holding and asset parameters (if either exist) for a specific asset ID. - */ -export type AccountAssetHolding = { - assetHolding: AssetHolding - assetParams?: AssetParams -} - -export const AccountAssetHoldingMeta: ModelMetadata = { - name: 'AccountAssetHolding', - kind: 'object', - fields: [ - { - name: 'assetHolding', - wireKey: 'asset-holding', - optional: false, - nullable: false, - type: { kind: 'model', meta: () => AssetHoldingMeta }, - }, - { - name: 'assetParams', - wireKey: 'asset-params', - optional: true, - nullable: false, - type: { kind: 'model', meta: () => AssetParamsMeta }, - }, - ], -} diff --git a/packages/algod_client/src/models/account-assets-information.ts b/packages/algod_client/src/models/account-assets-information.ts deleted file mode 100644 index fe704d6e3..000000000 --- a/packages/algod_client/src/models/account-assets-information.ts +++ /dev/null @@ -1,44 +0,0 @@ -import type { ModelMetadata } from '../core/model-runtime' -import type { AccountAssetHolding } from './account-asset-holding' -import { AccountAssetHoldingMeta } from './account-asset-holding' - -export type AccountAssetsInformation = { - /** - * The round for which this information is relevant. - */ - round: bigint - - /** - * Used for pagination, when making another request provide this token with the next parameter. - */ - nextToken?: string - assetHoldings?: AccountAssetHolding[] -} - -export const AccountAssetsInformationMeta: ModelMetadata = { - name: 'AccountAssetsInformation', - kind: 'object', - fields: [ - { - name: 'round', - wireKey: 'round', - optional: false, - nullable: false, - type: { kind: 'scalar', isBigint: true }, - }, - { - name: 'nextToken', - wireKey: 'next-token', - optional: true, - nullable: false, - type: { kind: 'scalar' }, - }, - { - name: 'assetHoldings', - wireKey: 'asset-holdings', - optional: true, - nullable: false, - type: { kind: 'array', item: { kind: 'model', meta: () => AccountAssetHoldingMeta } }, - }, - ], -} diff --git a/packages/algod_client/src/models/account.ts b/packages/algod_client/src/models/account.ts index 21ee98fa9..7824c468c 100644 --- a/packages/algod_client/src/models/account.ts +++ b/packages/algod_client/src/models/account.ts @@ -51,13 +51,13 @@ export type Account = { /** * The count of all applications that have been opted in, equivalent to the count of application local data (AppLocalState objects) stored in this account. */ - totalAppsOptedIn: bigint + totalAppsOptedIn: number appsTotalSchema?: ApplicationStateSchema /** * \[teap\] the sum of all extra application program pages for this account. */ - appsTotalExtraPages?: bigint + appsTotalExtraPages?: number /** * \[asset\] assets held by this account. @@ -69,7 +69,7 @@ export type Account = { /** * The count of all assets that have been opted in, equivalent to the count of AssetHolding objects held by this account. */ - totalAssetsOptedIn: bigint + totalAssetsOptedIn: number /** * \[appp\] parameters of applications created by this account including app global data. @@ -81,7 +81,7 @@ export type Account = { /** * The count of all apps (AppParams objects) created by this account. */ - totalCreatedApps: bigint + totalCreatedApps: number /** * \[apar\] parameters of assets created by this account. @@ -93,17 +93,17 @@ export type Account = { /** * The count of all assets (AssetParams objects) created by this account. */ - totalCreatedAssets: bigint + totalCreatedAssets: number /** * \[tbx\] The number of existing boxes created by this account's app. */ - totalBoxes?: bigint + totalBoxes?: number /** * \[tbxb\] The total number of bytes used by this account's app's box keys and values. */ - totalBoxBytes?: bigint + totalBoxBytes?: number participation?: AccountParticipation /** @@ -207,7 +207,7 @@ export const AccountMeta: ModelMetadata = { wireKey: 'total-apps-opted-in', optional: false, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, { name: 'appsTotalSchema', @@ -221,7 +221,7 @@ export const AccountMeta: ModelMetadata = { wireKey: 'apps-total-extra-pages', optional: true, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, { name: 'assets', @@ -235,7 +235,7 @@ export const AccountMeta: ModelMetadata = { wireKey: 'total-assets-opted-in', optional: false, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, { name: 'createdApps', @@ -249,7 +249,7 @@ export const AccountMeta: ModelMetadata = { wireKey: 'total-created-apps', optional: false, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, { name: 'createdAssets', @@ -263,21 +263,21 @@ export const AccountMeta: ModelMetadata = { wireKey: 'total-created-assets', optional: false, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, { name: 'totalBoxes', wireKey: 'total-boxes', optional: true, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, { name: 'totalBoxBytes', wireKey: 'total-box-bytes', optional: true, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, { name: 'participation', diff --git a/packages/algod_client/src/models/add-participation-key.ts b/packages/algod_client/src/models/add-participation-key.ts deleted file mode 100644 index 4a35b00fd..000000000 --- a/packages/algod_client/src/models/add-participation-key.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { ModelMetadata } from '../core/model-runtime' - -export type AddParticipationKey = { - /** - * encoding of the participation ID. - */ - partId: string -} - -export const AddParticipationKeyMeta: ModelMetadata = { - name: 'AddParticipationKey', - kind: 'object', - fields: [ - { - name: 'partId', - wireKey: 'partId', - optional: false, - nullable: false, - type: { kind: 'scalar' }, - }, - ], -} diff --git a/packages/algod_client/src/models/app-call-logs.ts b/packages/algod_client/src/models/app-call-logs.ts deleted file mode 100644 index b7b2172b7..000000000 --- a/packages/algod_client/src/models/app-call-logs.ts +++ /dev/null @@ -1,49 +0,0 @@ -import type { ModelMetadata } from '../core/model-runtime' - -/** - * The logged messages from an app call along with the app ID and outer transaction ID. Logs appear in the same order that they were emitted. - */ -export type AppCallLogs = { - /** - * An array of logs - */ - logs: Uint8Array[] - - /** - * The application from which the logs were generated - */ - appId: bigint - - /** - * The transaction ID of the outer app call that lead to these logs - */ - txId: string -} - -export const AppCallLogsMeta: ModelMetadata = { - name: 'AppCallLogs', - kind: 'object', - fields: [ - { - name: 'logs', - wireKey: 'logs', - optional: false, - nullable: false, - type: { kind: 'array', item: { kind: 'scalar', isBytes: true } }, - }, - { - name: 'appId', - wireKey: 'application-index', - optional: false, - nullable: false, - type: { kind: 'scalar', isBigint: true }, - }, - { - name: 'txId', - wireKey: 'txId', - optional: false, - nullable: false, - type: { kind: 'scalar' }, - }, - ], -} diff --git a/packages/algod_client/src/models/asset-params.ts b/packages/algod_client/src/models/asset-params.ts index a760ebdef..48c0ae279 100644 --- a/packages/algod_client/src/models/asset-params.ts +++ b/packages/algod_client/src/models/asset-params.ts @@ -22,7 +22,7 @@ export type AssetParams = { /** * \[dc\] The number of digits to use after the decimal point when displaying this asset. 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, and so on. This value must be between 0 and 19 (inclusive). */ - decimals: bigint + decimals: number /** * \[df\] Whether holdings of this asset are frozen by default. @@ -108,7 +108,7 @@ export const AssetParamsMeta: ModelMetadata = { wireKey: 'decimals', optional: false, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, { name: 'defaultFrozen', diff --git a/packages/algod_client/src/models/debug-settings-prof.ts b/packages/algod_client/src/models/debug-settings-prof.ts deleted file mode 100644 index 8f8ffc9c0..000000000 --- a/packages/algod_client/src/models/debug-settings-prof.ts +++ /dev/null @@ -1,37 +0,0 @@ -import type { ModelMetadata } from '../core/model-runtime' - -/** - * algod mutex and blocking profiling state. - */ -export type DebugSettingsProf = { - /** - * The rate of blocking events. The profiler aims to sample an average of one blocking event per rate nanoseconds spent blocked. To turn off profiling entirely, pass rate 0. - */ - blockRate?: bigint - - /** - * The rate of mutex events. On average 1/rate events are reported. To turn off profiling entirely, pass rate 0 - */ - mutexRate?: bigint -} - -export const DebugSettingsProfMeta: ModelMetadata = { - name: 'DebugSettingsProf', - kind: 'object', - fields: [ - { - name: 'blockRate', - wireKey: 'block-rate', - optional: true, - nullable: false, - type: { kind: 'scalar', isBigint: true }, - }, - { - name: 'mutexRate', - wireKey: 'mutex-rate', - optional: true, - nullable: false, - type: { kind: 'scalar', isBigint: true }, - }, - ], -} diff --git a/packages/algod_client/src/models/dryrun-source.ts b/packages/algod_client/src/models/dryrun-source.ts index dbdd2e5b6..efd6be332 100644 --- a/packages/algod_client/src/models/dryrun-source.ts +++ b/packages/algod_client/src/models/dryrun-source.ts @@ -9,8 +9,8 @@ export type DryrunSource = { */ fieldName: string source: string - txnIndex: bigint - appIndex: bigint + txnIndex: number + appId: bigint } export const DryrunSourceMeta: ModelMetadata = { @@ -36,10 +36,10 @@ export const DryrunSourceMeta: ModelMetadata = { wireKey: 'txn-index', optional: false, nullable: false, - type: { kind: 'scalar', isBigint: true }, + type: { kind: 'scalar' }, }, { - name: 'appIndex', + name: 'appId', wireKey: 'app-index', optional: false, nullable: false, diff --git a/packages/algod_client/src/models/error-response.ts b/packages/algod_client/src/models/error-response.ts deleted file mode 100644 index cfa8d98aa..000000000 --- a/packages/algod_client/src/models/error-response.ts +++ /dev/null @@ -1,30 +0,0 @@ -import type { ModelMetadata } from '../core/model-runtime' - -/** - * An error response with optional data field. - */ -export type ErrorResponse = { - data?: Record - message: string -} - -export const ErrorResponseMeta: ModelMetadata = { - name: 'ErrorResponse', - kind: 'object', - fields: [ - { - name: 'data', - wireKey: 'data', - optional: true, - nullable: false, - type: { kind: 'scalar' }, - }, - { - name: 'message', - wireKey: 'message', - optional: false, - nullable: false, - type: { kind: 'scalar' }, - }, - ], -} diff --git a/packages/algod_client/src/models/eval-delta-key-value.ts b/packages/algod_client/src/models/eval-delta-key-value.ts index 80097c504..31a0689a9 100644 --- a/packages/algod_client/src/models/eval-delta-key-value.ts +++ b/packages/algod_client/src/models/eval-delta-key-value.ts @@ -6,7 +6,7 @@ import { EvalDeltaMeta } from './eval-delta' * Key-value pairs for StateDelta. */ export type EvalDeltaKeyValue = { - key: string + key: Uint8Array value: EvalDelta } @@ -19,7 +19,7 @@ export const EvalDeltaKeyValueMeta: ModelMetadata = { wireKey: 'key', optional: false, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBytes: true }, }, { name: 'value', diff --git a/packages/algod_client/src/models/get-block-logs.ts b/packages/algod_client/src/models/get-block-logs.ts deleted file mode 100644 index b54191360..000000000 --- a/packages/algod_client/src/models/get-block-logs.ts +++ /dev/null @@ -1,21 +0,0 @@ -import type { ModelMetadata } from '../core/model-runtime' -import type { AppCallLogs } from './app-call-logs' -import { AppCallLogsMeta } from './app-call-logs' - -export type GetBlockLogs = { - logs: AppCallLogs[] -} - -export const GetBlockLogsMeta: ModelMetadata = { - name: 'GetBlockLogs', - kind: 'object', - fields: [ - { - name: 'logs', - wireKey: 'logs', - optional: false, - nullable: false, - type: { kind: 'array', item: { kind: 'model', meta: () => AppCallLogsMeta } }, - }, - ], -} diff --git a/packages/algod_client/src/models/get-block-txids.ts b/packages/algod_client/src/models/get-block-tx-ids.ts similarity index 64% rename from packages/algod_client/src/models/get-block-txids.ts rename to packages/algod_client/src/models/get-block-tx-ids.ts index 8382d6650..45ffef3ae 100644 --- a/packages/algod_client/src/models/get-block-txids.ts +++ b/packages/algod_client/src/models/get-block-tx-ids.ts @@ -1,18 +1,18 @@ import type { ModelMetadata } from '../core/model-runtime' -export type GetBlockTxids = { +export type GetBlockTxIds = { /** * Block transaction IDs. */ - blockTxids: string[] + blockTxIds: string[] } -export const GetBlockTxidsMeta: ModelMetadata = { - name: 'GetBlockTxids', +export const GetBlockTxIdsMeta: ModelMetadata = { + name: 'GetBlockTxIds', kind: 'object', fields: [ { - name: 'blockTxids', + name: 'blockTxIds', wireKey: 'blockTxids', optional: false, nullable: false, diff --git a/packages/algod_client/src/models/index.ts b/packages/algod_client/src/models/index.ts index fb0bedf6a..ee5b69edc 100644 --- a/packages/algod_client/src/models/index.ts +++ b/packages/algod_client/src/models/index.ts @@ -8,8 +8,6 @@ export type { LedgerStateDeltaForTransactionGroup } from './ledger-state-delta-f export { LedgerStateDeltaForTransactionGroupMeta } from './ledger-state-delta-for-transaction-group' export type { Account } from './account' export { AccountMeta } from './account' -export type { AccountAssetHolding } from './account-asset-holding' -export { AccountAssetHoldingMeta } from './account-asset-holding' export type { AccountParticipation } from './account-participation' export { AccountParticipationMeta } from './account-participation' export type { Asset } from './asset' @@ -26,8 +24,6 @@ export type { ApplicationStateSchema } from './application-state-schema' export { ApplicationStateSchemaMeta } from './application-state-schema' export type { ApplicationLocalState } from './application-local-state' export { ApplicationLocalStateMeta } from './application-local-state' -export type { ParticipationKey } from './participation-key' -export { ParticipationKeyMeta } from './participation-key' export type { TealKeyValueStore } from './teal-key-value-store' export { TealKeyValueStoreMeta } from './teal-key-value-store' export type { TealKeyValue } from './teal-key-value' @@ -54,8 +50,6 @@ export type { DryrunState } from './dryrun-state' export { DryrunStateMeta } from './dryrun-state' export type { DryrunTxnResult } from './dryrun-txn-result' export { DryrunTxnResultMeta } from './dryrun-txn-result' -export type { ErrorResponse } from './error-response' -export { ErrorResponseMeta } from './error-response' export type { DryrunRequest } from './dryrun-request' export { DryrunRequestMeta } from './dryrun-request' export type { DryrunSource } from './dryrun-source' @@ -74,8 +68,6 @@ export type { BoxReference } from './box-reference' export { BoxReferenceMeta } from './box-reference' export type { Version } from './version' export { VersionMeta } from './version' -export type { DebugSettingsProf } from './debug-settings-prof' -export { DebugSettingsProfMeta } from './debug-settings-prof' export type { BuildVersion } from './build-version' export { BuildVersionMeta } from './build-version' export type { PendingTransactionResponse } from './pending-transaction-response' @@ -108,32 +100,22 @@ export type { SimulateUnnamedResourcesAccessed } from './simulate-unnamed-resour export { SimulateUnnamedResourcesAccessedMeta } from './simulate-unnamed-resources-accessed' export type { SimulateInitialStates } from './simulate-initial-states' export { SimulateInitialStatesMeta } from './simulate-initial-states' -export type { AppCallLogs } from './app-call-logs' -export { AppCallLogsMeta } from './app-call-logs' export type { TransactionProof } from './transaction-proof' export { TransactionProofMeta } from './transaction-proof' export type { AccountAssetInformation } from './account-asset-information' export { AccountAssetInformationMeta } from './account-asset-information' -export type { AccountAssetsInformation } from './account-assets-information' -export { AccountAssetsInformationMeta } from './account-assets-information' export type { AccountApplicationInformation } from './account-application-information' export { AccountApplicationInformationMeta } from './account-application-information' export type { GetPendingTransactionsByAddress } from './get-pending-transactions-by-address' export { GetPendingTransactionsByAddressMeta } from './get-pending-transactions-by-address' export type { GetBlock } from './get-block' export { GetBlockMeta } from './get-block' -export type { GetBlockTxids } from './get-block-txids' -export { GetBlockTxidsMeta } from './get-block-txids' +export type { GetBlockTxIds } from './get-block-tx-ids' +export { GetBlockTxIdsMeta } from './get-block-tx-ids' export type { GetBlockHash } from './get-block-hash' export { GetBlockHashMeta } from './get-block-hash' -export type { GetBlockLogs } from './get-block-logs' -export { GetBlockLogsMeta } from './get-block-logs' export type { GetSupply } from './get-supply' export { GetSupplyMeta } from './get-supply' -export type { AddParticipationKey } from './add-participation-key' -export { AddParticipationKeyMeta } from './add-participation-key' -export type { ShutdownNode } from './shutdown-node' -export { ShutdownNodeMeta } from './shutdown-node' export type { GetStatus } from './get-status' export { GetStatusMeta } from './get-status' export type { WaitForBlock } from './wait-for-block' @@ -156,15 +138,12 @@ export type { TealCompile } from './teal-compile' export { TealCompileMeta } from './teal-compile' export type { TealDisassemble } from './teal-disassemble' export { TealDisassembleMeta } from './teal-disassemble' -export type { StartCatchup } from './start-catchup' -export { StartCatchupMeta } from './start-catchup' -export type { AbortCatchup } from './abort-catchup' -export { AbortCatchupMeta } from './abort-catchup' export type { TealDryrun } from './teal-dryrun' export { TealDryrunMeta } from './teal-dryrun' export type { GetBlockTimeStampOffset } from './get-block-time-stamp-offset' export { GetBlockTimeStampOffsetMeta } from './get-block-time-stamp-offset' +export type { SuggestedParams, SuggestedParamsMeta } from './suggested-params' export type { BlockEvalDelta } from './block-eval-delta' export { BlockEvalDeltaMeta } from './block-eval-delta' export type { BlockStateDelta } from './block-state-delta' diff --git a/packages/algod_client/src/models/participation-key.ts b/packages/algod_client/src/models/participation-key.ts deleted file mode 100644 index 4cf92f731..000000000 --- a/packages/algod_client/src/models/participation-key.ts +++ /dev/null @@ -1,107 +0,0 @@ -import type { ModelMetadata } from '../core/model-runtime' -import type { AccountParticipation } from './account-participation' -import { AccountParticipationMeta } from './account-participation' - -/** - * Represents a participation key used by the node. - */ -export type ParticipationKey = { - /** - * The key's ParticipationID. - */ - id: string - - /** - * Address the key was generated for. - */ - address: string - - /** - * When registered, this is the first round it may be used. - */ - effectiveFirstValid?: bigint - - /** - * When registered, this is the last round it may be used. - */ - effectiveLastValid?: bigint - - /** - * Round when this key was last used to vote. - */ - lastVote?: bigint - - /** - * Round when this key was last used to propose a block. - */ - lastBlockProposal?: bigint - - /** - * Round when this key was last used to generate a state proof. - */ - lastStateProof?: bigint - key: AccountParticipation -} - -export const ParticipationKeyMeta: ModelMetadata = { - name: 'ParticipationKey', - kind: 'object', - fields: [ - { - name: 'id', - wireKey: 'id', - optional: false, - nullable: false, - type: { kind: 'scalar' }, - }, - { - name: 'address', - wireKey: 'address', - optional: false, - nullable: false, - type: { kind: 'scalar' }, - }, - { - name: 'effectiveFirstValid', - wireKey: 'effective-first-valid', - optional: true, - nullable: false, - type: { kind: 'scalar', isBigint: true }, - }, - { - name: 'effectiveLastValid', - wireKey: 'effective-last-valid', - optional: true, - nullable: false, - type: { kind: 'scalar', isBigint: true }, - }, - { - name: 'lastVote', - wireKey: 'last-vote', - optional: true, - nullable: false, - type: { kind: 'scalar', isBigint: true }, - }, - { - name: 'lastBlockProposal', - wireKey: 'last-block-proposal', - optional: true, - nullable: false, - type: { kind: 'scalar', isBigint: true }, - }, - { - name: 'lastStateProof', - wireKey: 'last-state-proof', - optional: true, - nullable: false, - type: { kind: 'scalar', isBigint: true }, - }, - { - name: 'key', - wireKey: 'key', - optional: false, - nullable: false, - type: { kind: 'model', meta: () => AccountParticipationMeta }, - }, - ], -} diff --git a/packages/algod_client/src/models/shutdown-node.ts b/packages/algod_client/src/models/shutdown-node.ts deleted file mode 100644 index 46fba9026..000000000 --- a/packages/algod_client/src/models/shutdown-node.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { ModelMetadata } from '../core/model-runtime' - -export type ShutdownNode = Record - -export const ShutdownNodeMeta: ModelMetadata = { - name: 'ShutdownNode', - kind: 'object', - fields: [], -} diff --git a/packages/algod_client/src/models/start-catchup.ts b/packages/algod_client/src/models/start-catchup.ts deleted file mode 100644 index eb972b368..000000000 --- a/packages/algod_client/src/models/start-catchup.ts +++ /dev/null @@ -1,25 +0,0 @@ -import type { ModelMetadata } from '../core/model-runtime' - -/** - * An catchpoint start response. - */ -export type StartCatchup = { - /** - * Catchup start response string - */ - catchupMessage: string -} - -export const StartCatchupMeta: ModelMetadata = { - name: 'StartCatchup', - kind: 'object', - fields: [ - { - name: 'catchupMessage', - wireKey: 'catchup-message', - optional: false, - nullable: false, - type: { kind: 'scalar' }, - }, - ], -} diff --git a/packages/algod_client/src/models/suggested-params.ts b/packages/algod_client/src/models/suggested-params.ts new file mode 100644 index 000000000..c3236353c --- /dev/null +++ b/packages/algod_client/src/models/suggested-params.ts @@ -0,0 +1,14 @@ +import { Expand } from '@algorandfoundation/algokit-common' +import type { TransactionParams } from './transaction-params' + +/** Contains parameters relevant to the creation of a new transaction in a specific network at a specific time. */ +export type SuggestedParams = Expand< + Omit & { + flatFee: boolean + firstValid: bigint + lastValid: bigint + } +> + +// This is never used, just to satisfy the import generator pattern +export type SuggestedParamsMeta = undefined diff --git a/packages/algod_client/src/models/teal-key-value.ts b/packages/algod_client/src/models/teal-key-value.ts index 73575a78d..1905fe410 100644 --- a/packages/algod_client/src/models/teal-key-value.ts +++ b/packages/algod_client/src/models/teal-key-value.ts @@ -6,7 +6,7 @@ import { TealValueMeta } from './teal-value' * Represents a key-value pair in an application store. */ export type TealKeyValue = { - key: string + key: Uint8Array value: TealValue } @@ -19,7 +19,7 @@ export const TealKeyValueMeta: ModelMetadata = { wireKey: 'key', optional: false, nullable: false, - type: { kind: 'scalar' }, + type: { kind: 'scalar', isBytes: true }, }, { name: 'value', diff --git a/packages/indexer_client/src/models/hashtype.ts b/packages/indexer_client/src/models/hashtype.ts deleted file mode 100644 index 7265f003b..000000000 --- a/packages/indexer_client/src/models/hashtype.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { ModelMetadata } from '../core/model-runtime' - -/** - * The type of hash function used to create the proof, must be one of: - * * sha512_256 - * * sha256 - */ -export type Hashtype = 'sha512_256' | 'sha256' - -export const HashtypeMeta: ModelMetadata = { - name: 'Hashtype', - kind: 'passthrough', - passThrough: { kind: 'scalar' }, -} diff --git a/packages/indexer_client/src/models/index.ts b/packages/indexer_client/src/models/index.ts index 6bd24affe..1903c0a25 100644 --- a/packages/indexer_client/src/models/index.ts +++ b/packages/indexer_client/src/models/index.ts @@ -1,5 +1,3 @@ -export type { Hashtype } from './hashtype' -export { HashtypeMeta } from './hashtype' export type { Account } from './account' export { AccountMeta } from './account' export type { AccountParticipation } from './account-participation' diff --git a/packages/indexer_client/src/models/transaction.ts b/packages/indexer_client/src/models/transaction.ts index df40e6b47..86f2222b0 100644 --- a/packages/indexer_client/src/models/transaction.ts +++ b/packages/indexer_client/src/models/transaction.ts @@ -60,12 +60,12 @@ export type Transaction = { /** * Specifies an application index (ID) if an application was created with this transaction. */ - createdApplicationIndex?: bigint + createdAppId?: bigint /** * Specifies an asset index (ID) if an asset was created with this transaction. */ - createdAssetIndex?: bigint + createdAssetId?: bigint /** * \[fee\] Transaction fee. @@ -252,14 +252,14 @@ export const TransactionMeta: ModelMetadata = { type: { kind: 'scalar', isBigint: true }, }, { - name: 'createdApplicationIndex', + name: 'createdAppId', wireKey: 'created-application-index', optional: true, nullable: false, type: { kind: 'scalar', isBigint: true }, }, { - name: 'createdAssetIndex', + name: 'createdAssetId', wireKey: 'created-asset-index', optional: true, nullable: false, diff --git a/packages/kmd_client/src/apis/api.service.ts b/packages/kmd_client/src/apis/api.service.ts index 0dc0da8c5..a1858bd89 100644 --- a/packages/kmd_client/src/apis/api.service.ts +++ b/packages/kmd_client/src/apis/api.service.ts @@ -3,7 +3,9 @@ import { AlgorandSerializer } from '../core/model-runtime' import type { BodyFormat } from '../core/model-runtime' import type { CreateWalletRequest, + DeleteKeyRequest, DeleteKeyResponse, + DeleteMultisigRequest, DeleteMultisigResponse, ExportKeyRequest, ExportMasterKeyRequest, @@ -45,7 +47,9 @@ import type { } from '../models/index' import { CreateWalletRequestMeta, + DeleteKeyRequestMeta, DeleteKeyResponseMeta, + DeleteMultisigRequestMeta, DeleteMultisigResponseMeta, ExportKeyRequestMeta, ExportMasterKeyRequestMeta, @@ -130,19 +134,24 @@ export class KmdApi { /** * Deletes the key with the passed public key from the wallet. */ - async deleteKey(): Promise { + async deleteKey(body: DeleteKeyRequest): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) + const bodyMeta = DeleteKeyRequestMeta + const mediaType = bodyMeta ? KmdApi.mediaFor(responseFormat) : undefined + if (mediaType) headers['Content-Type'] = mediaType + const serializedBody = bodyMeta && body !== undefined ? AlgorandSerializer.encode(body, bodyMeta, responseFormat) : body + const payload = await this.httpRequest.request({ method: 'DELETE', url: '/v1/key', path: {}, query: {}, headers, - body: undefined, - mediaType: undefined, + body: serializedBody, + mediaType: mediaType, }) const responseMeta = DeleteKeyResponseMeta @@ -155,19 +164,24 @@ export class KmdApi { /** * Deletes multisig preimage information for the passed address from the wallet. */ - async deleteMultisig(): Promise { + async deleteMultisig(body: DeleteMultisigRequest): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' headers['Accept'] = KmdApi.acceptFor(responseFormat) + const bodyMeta = DeleteMultisigRequestMeta + const mediaType = bodyMeta ? KmdApi.mediaFor(responseFormat) : undefined + if (mediaType) headers['Content-Type'] = mediaType + const serializedBody = bodyMeta && body !== undefined ? AlgorandSerializer.encode(body, bodyMeta, responseFormat) : body + const payload = await this.httpRequest.request({ method: 'DELETE', url: '/v1/multisig', path: {}, query: {}, headers, - body: undefined, - mediaType: undefined, + body: serializedBody, + mediaType: mediaType, }) const responseMeta = DeleteMultisigResponseMeta diff --git a/packages/kmd_client/src/models/ed25519-private-key.ts b/packages/kmd_client/src/models/ed25519-private-key.ts deleted file mode 100644 index 41e02238b..000000000 --- a/packages/kmd_client/src/models/ed25519-private-key.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { ModelMetadata } from '../core/model-runtime' - -export type Ed25519PrivateKey = number[] - -export const Ed25519PrivateKeyMeta: ModelMetadata = { - name: 'Ed25519PrivateKey', - kind: 'array', - arrayItems: { kind: 'scalar' }, -} diff --git a/packages/kmd_client/src/models/index.ts b/packages/kmd_client/src/models/index.ts index 2fb35b4c0..df36e5b45 100644 --- a/packages/kmd_client/src/models/index.ts +++ b/packages/kmd_client/src/models/index.ts @@ -70,16 +70,12 @@ export type { ListKeysRequest } from './list-keys-request' export { ListKeysRequestMeta } from './list-keys-request' export type { ListMultisigRequest } from './list-multisig-request' export { ListMultisigRequestMeta } from './list-multisig-request' -export type { ListWalletsRequest } from './list-wallets-request' -export { ListWalletsRequestMeta } from './list-wallets-request' export type { MasterDerivationKey } from './master-derivation-key' export { MasterDerivationKeyMeta } from './master-derivation-key' export type { MultisigSig } from './multisig-sig' export { MultisigSigMeta } from './multisig-sig' export type { MultisigSubsig } from './multisig-subsig' export { MultisigSubsigMeta } from './multisig-subsig' -export type { PrivateKey } from './private-key' -export { PrivateKeyMeta } from './private-key' export type { PublicKey } from './public-key' export { PublicKeyMeta } from './public-key' export type { ReleaseWalletHandleTokenRequest } from './release-wallet-handle-token-request' @@ -100,14 +96,10 @@ export type { Signature } from './signature' export { SignatureMeta } from './signature' export type { TxType } from './tx-type' export { TxTypeMeta } from './tx-type' -export type { VersionsRequest } from './versions-request' -export { VersionsRequestMeta } from './versions-request' export type { VersionsResponse } from './versions-response' export { VersionsResponseMeta } from './versions-response' export type { WalletInfoRequest } from './wallet-info-request' export { WalletInfoRequestMeta } from './wallet-info-request' -export type { Ed25519PrivateKey } from './ed25519-private-key' -export { Ed25519PrivateKeyMeta } from './ed25519-private-key' export type { Ed25519PublicKey } from './ed25519-public-key' export { Ed25519PublicKeyMeta } from './ed25519-public-key' export type { Ed25519Signature } from './ed25519-signature' diff --git a/packages/kmd_client/src/models/list-wallets-request.ts b/packages/kmd_client/src/models/list-wallets-request.ts deleted file mode 100644 index 3993c2025..000000000 --- a/packages/kmd_client/src/models/list-wallets-request.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { ModelMetadata } from '../core/model-runtime' - -/** - * APIV1GETWalletsRequest is the request for `GET /v1/wallets` - */ -export type ListWalletsRequest = Record - -export const ListWalletsRequestMeta: ModelMetadata = { - name: 'ListWalletsRequest', - kind: 'object', - fields: [], -} diff --git a/packages/kmd_client/src/models/private-key.ts b/packages/kmd_client/src/models/private-key.ts deleted file mode 100644 index ac3b88fe6..000000000 --- a/packages/kmd_client/src/models/private-key.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { ModelMetadata } from '../core/model-runtime' -import type { Ed25519PrivateKey } from './ed25519-private-key' - -export type PrivateKey = Ed25519PrivateKey - -export const PrivateKeyMeta: ModelMetadata = { - name: 'PrivateKey', - kind: 'passthrough', - passThrough: { kind: 'scalar' }, -} diff --git a/packages/kmd_client/src/models/versions-request.ts b/packages/kmd_client/src/models/versions-request.ts deleted file mode 100644 index 9321e4fa0..000000000 --- a/packages/kmd_client/src/models/versions-request.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { ModelMetadata } from '../core/model-runtime' - -/** - * VersionsRequest is the request for `GET /versions` - */ -export type VersionsRequest = Record - -export const VersionsRequestMeta: ModelMetadata = { - name: 'VersionsRequest', - kind: 'object', - fields: [], -} diff --git a/packages/sdk/src/composer.ts b/packages/sdk/src/composer.ts index 7cc2dd1b9..6db3549ad 100644 --- a/packages/sdk/src/composer.ts +++ b/packages/sdk/src/composer.ts @@ -3,6 +3,7 @@ import type { PendingTransactionResponse, SimulateRequest, SimulateTransaction, + SuggestedParams, } from '@algorandfoundation/algokit-algod-client' import type { AccessReference, BoxReference, SignedTransaction } from '@algorandfoundation/algokit-transact' import { OnApplicationComplete, decodeSignedTransaction, getTransactionId } from '@algorandfoundation/algokit-transact' @@ -20,7 +21,7 @@ import { } from './abi/index.js' import { Address } from './encoding/address.js' import { assignGroupID } from './group.js' -import { SdkTransactionParams, makeApplicationCallTxnFromObject } from './makeTxn.js' +import { makeApplicationCallTxnFromObject } from './makeTxn.js' import { TransactionSigner, TransactionWithSigner, isTransactionWithSigner } from './signer.js' import { arrayEqual, ensureUint64, stringifyJSON } from './utils/utils.js' import { waitForConfirmation } from './wait.js' @@ -214,7 +215,7 @@ export class AtomicTransactionComposer { /** The address of the sender of this application call */ sender: string | Address /** Transactions params to use for this application call */ - suggestedParams: SdkTransactionParams + suggestedParams: SuggestedParams /** The OnComplete action to take for this application call. If omitted, OnApplicationComplete.NoOp will be used. */ onComplete?: OnApplicationComplete /** The approval program for this application call. Only set this if this is an application creation call, or if onComplete is OnApplicationComplete.UpdateApplication */ diff --git a/packages/sdk/src/makeTxn.ts b/packages/sdk/src/makeTxn.ts index 059e87b79..1cab14a2a 100644 --- a/packages/sdk/src/makeTxn.ts +++ b/packages/sdk/src/makeTxn.ts @@ -1,3 +1,4 @@ +import { SuggestedParams } from '@algorandfoundation/algokit-algod-client' import type { Transaction } from '@algorandfoundation/algokit-transact' import { OnApplicationComplete, TransactionType } from '@algorandfoundation/algokit-transact' import { foreignArraysToResourceReferences } from './appAccess.js' @@ -24,18 +25,12 @@ function ensureBigInt(value: number | bigint | undefined): bigint | undefined { return typeof value === 'bigint' ? value : BigInt(value) } -import { TransactionParams as AlgodTransactionParams } from '@algorandfoundation/algokit-algod-client' - -export type SdkTransactionParams = AlgodTransactionParams & { - firstRound: bigint -} - /** Contains parameters common to every transaction type */ export interface CommonTransactionParams { /** Algorand address of sender */ sender: string | Address /** Suggested parameters relevant to the network that will accept this transaction */ - suggestedParams: SdkTransactionParams + suggestedParams: SuggestedParams /** Optional, arbitrary data to be stored in the transaction's note field */ note?: Uint8Array /** @@ -67,8 +62,8 @@ export function makePaymentTxnWithSuggestedParamsFromObject({ const txn: Transaction = { type: TransactionType.Payment, sender: addressToString(sender)!, - firstValid: BigInt(suggestedParams.firstRound), - lastValid: BigInt(suggestedParams.lastRound), + firstValid: BigInt(suggestedParams.firstValid), + lastValid: BigInt(suggestedParams.lastValid), genesisHash: suggestedParams.genesisHash, genesisId: suggestedParams.genesisId, note, @@ -106,8 +101,8 @@ export function makeKeyRegistrationTxnWithSuggestedParamsFromObject({ const txn: Transaction = { type: TransactionType.KeyRegistration, sender: addressToString(sender)!, - firstValid: BigInt(suggestedParams.firstRound), - lastValid: BigInt(suggestedParams.lastRound), + firstValid: BigInt(suggestedParams.firstValid), + lastValid: BigInt(suggestedParams.lastValid), genesisHash: suggestedParams.genesisHash, genesisId: suggestedParams.genesisId, note, @@ -154,8 +149,8 @@ export function makeBaseAssetConfigTxn({ const txn: Transaction = { type: TransactionType.AssetConfig, sender: addressToString(sender)!, - firstValid: BigInt(suggestedParams.firstRound), - lastValid: BigInt(suggestedParams.lastRound), + firstValid: BigInt(suggestedParams.firstValid), + lastValid: BigInt(suggestedParams.lastValid), genesisHash: suggestedParams.genesisHash, genesisId: suggestedParams.genesisId, note, @@ -361,8 +356,8 @@ export function makeAssetFreezeTxnWithSuggestedParamsFromObject({ const txn: Transaction = { type: TransactionType.AssetFreeze, sender: addressToString(sender)!, - firstValid: BigInt(suggestedParams.firstRound), - lastValid: BigInt(suggestedParams.lastRound), + firstValid: BigInt(suggestedParams.firstValid), + lastValid: BigInt(suggestedParams.lastValid), genesisHash: suggestedParams.genesisHash, genesisId: suggestedParams.genesisId, note, @@ -404,8 +399,8 @@ export function makeAssetTransferTxnWithSuggestedParamsFromObject({ const txn: Transaction = { type: TransactionType.AssetTransfer, sender: addressToString(sender)!, - firstValid: BigInt(suggestedParams.firstRound), - lastValid: BigInt(suggestedParams.lastRound), + firstValid: BigInt(suggestedParams.firstValid), + lastValid: BigInt(suggestedParams.lastValid), genesisHash: suggestedParams.genesisHash, genesisId: suggestedParams.genesisId, note, @@ -490,8 +485,8 @@ export function makeApplicationCallTxnFromObject({ const txn: Transaction = { type: TransactionType.AppCall, sender: addressToString(sender)!, - firstValid: BigInt(suggestedParams.firstRound), - lastValid: BigInt(suggestedParams.lastRound), + firstValid: BigInt(suggestedParams.firstValid), + lastValid: BigInt(suggestedParams.lastValid), genesisHash: suggestedParams.genesisHash, genesisId: suggestedParams.genesisId, note, diff --git a/packages/sdk/src/types/transactions/base.ts b/packages/sdk/src/types/transactions/base.ts index 774ed4f50..2eb4254e5 100644 --- a/packages/sdk/src/types/transactions/base.ts +++ b/packages/sdk/src/types/transactions/base.ts @@ -1,3 +1,4 @@ +import { SuggestedParams } from '@algorandfoundation/algokit-algod-client' import { AccessReference, BoxReference, @@ -8,7 +9,6 @@ import { } from '@algorandfoundation/algokit-transact' import { Address } from '../../encoding/address.js' import { HeartbeatProof } from '../../heartbeat.js' -import { SdkTransactionParams } from '../../makeTxn.js' import { StateProof, StateProofMessage } from '../../stateproof.js' /** @@ -401,7 +401,7 @@ export interface TransactionParams { /** * Suggested parameters relevant to the network that will accept this transaction */ - suggestedParams: SdkTransactionParams + suggestedParams: SuggestedParams /** * Payment transaction parameters. Only set if type is TransactionType.pay diff --git a/src/app-deploy.spec.ts b/src/app-deploy.spec.ts index b6a0b3ef1..d23b3ba4c 100644 --- a/src/app-deploy.spec.ts +++ b/src/app-deploy.spec.ts @@ -1,4 +1,3 @@ -import { getTransactionId } from '@algorandfoundation/algokit-transact' import { getApplicationAddress } from '@algorandfoundation/sdk' import invariant from 'tiny-invariant' import { afterEach, beforeEach, describe, expect, test } from 'vitest' @@ -21,10 +20,10 @@ describe('deploy-app', () => { const name = 'MY_APP' test('Created app is retrieved by name with deployment metadata', async () => { - const { algorand, testAccount, waitForIndexerTransaction } = localnet.context + const { algorand, testAccount, waitForIndexer } = localnet.context const creationMetadata = { name, version: '1.0', updatable: true, deletable: false } const app1 = await algorand.send.appCreate(await getTestingAppCreateParams(testAccount, creationMetadata)) - await waitForIndexerTransaction(getTransactionId(app1.transaction)) + await waitForIndexer() const apps = await algorand.appDeployer.getCreatorAppsByName(testAccount) @@ -43,12 +42,12 @@ describe('deploy-app', () => { }) test('Latest created app is retrieved', async () => { - const { algorand, testAccount, waitForIndexerTransaction } = localnet.context + const { algorand, testAccount, waitForIndexer } = localnet.context const creationMetadata = { name, version: '1.0', updatable: true, deletable: false } const app1 = await algorand.send.appCreate({ ...(await getTestingAppCreateParams(testAccount, creationMetadata)), lease: '1' }) const app2 = await algorand.send.appCreate({ ...(await getTestingAppCreateParams(testAccount, creationMetadata)), lease: '2' }) const app3 = await algorand.send.appCreate({ ...(await getTestingAppCreateParams(testAccount, creationMetadata)), lease: '3' }) - await waitForIndexerTransaction(getTransactionId(app3.transaction)) + await waitForIndexer() const apps = await algorand.appDeployer.getCreatorAppsByName(testAccount) @@ -58,7 +57,7 @@ describe('deploy-app', () => { }) test('Created, updated and deleted apps are retrieved by name with deployment metadata', async () => { - const { algorand, testAccount, waitForIndexerTransaction } = localnet.context + const { algorand, testAccount, waitForIndexer } = localnet.context const creationMetadata = { name, version: '1.0', updatable: true, deletable: true } const name2 = 'APP_2' @@ -69,8 +68,8 @@ describe('deploy-app', () => { const updateMetadata = { name, version: '2.0', updatable: false, deletable: false } const update1 = await algorand.send.appUpdate({ ...(await getTestingAppCreateParams(testAccount, updateMetadata)), appId: app1.appId }) - const delete3 = await algorand.send.appDelete({ appId: app3.appId, sender: testAccount }) - await waitForIndexerTransaction(getTransactionId(delete3.transaction)) + const _delete3 = await algorand.send.appDelete({ appId: app3.appId, sender: testAccount }) + await waitForIndexer() const apps = await algorand.appDeployer.getCreatorAppsByName(testAccount) @@ -151,7 +150,7 @@ describe('deploy-app', () => { }) test('Deploy update to updatable updated app', async () => { - const { algorand, testAccount, waitForIndexerTransaction } = localnet.context + const { algorand, testAccount, waitForIndexer } = localnet.context const metadata = getMetadata({ updatable: true }) const deployment1 = await getTestingAppDeployParams({ sender: testAccount, @@ -159,7 +158,7 @@ describe('deploy-app', () => { }) const result1 = await algorand.appDeployer.deploy(deployment1) if (result1.operationPerformed !== 'nothing') { - await waitForIndexerTransaction(getTransactionId(result1.transaction)) + await waitForIndexer() } logging.testLogger.clear() @@ -194,7 +193,7 @@ describe('deploy-app', () => { }) test('Deploy update to immutable updated app fails', async () => { - const { algorand, testAccount, waitForIndexerTransaction } = localnet.context + const { algorand, testAccount, waitForIndexer } = localnet.context const metadata = getMetadata({ updatable: false }) const deployment1 = await getTestingAppDeployParams({ sender: testAccount, @@ -202,7 +201,7 @@ describe('deploy-app', () => { }) const result1 = await algorand.appDeployer.deploy(deployment1) if (result1.operationPerformed !== 'nothing') { - await waitForIndexerTransaction(getTransactionId(result1.transaction)) + await waitForIndexer() } logging.testLogger.clear() @@ -232,7 +231,7 @@ describe('deploy-app', () => { }) test('Deploy failure for updated app fails if onupdate = Fail', async () => { - const { algorand, testAccount, waitForIndexerTransaction } = localnet.context + const { algorand, testAccount, waitForIndexer } = localnet.context const metadata = getMetadata() const deployment1 = await getTestingAppDeployParams({ sender: testAccount, @@ -240,7 +239,7 @@ describe('deploy-app', () => { }) const result1 = await algorand.appDeployer.deploy(deployment1) if (result1.operationPerformed !== 'nothing') { - await waitForIndexerTransaction(getTransactionId(result1.transaction)) + await waitForIndexer() } logging.testLogger.clear() @@ -265,7 +264,7 @@ describe('deploy-app', () => { }) test('Deploy replacement to deletable, updated app', async () => { - const { algorand, testAccount, waitForIndexerTransaction } = localnet.context + const { algorand, testAccount, waitForIndexer } = localnet.context const metadata = getMetadata({ deletable: true }) const deployment1 = await getTestingAppDeployParams({ sender: testAccount, @@ -273,7 +272,7 @@ describe('deploy-app', () => { }) const result1 = await algorand.appDeployer.deploy(deployment1) if (result1.operationPerformed !== 'nothing') { - await waitForIndexerTransaction(getTransactionId(result1.transaction)) + await waitForIndexer() } logging.testLogger.clear() @@ -311,7 +310,7 @@ describe('deploy-app', () => { test('Deploy failure for replacement of permanent, updated app', async () => { Config.configure({ debug: false }) // Remove noise from snapshot - const { algorand, testAccount, waitForIndexerTransaction } = localnet.context + const { algorand, testAccount, waitForIndexer } = localnet.context const metadata = getMetadata({ deletable: false }) const deployment1 = (await getTestingAppDeployParams({ sender: testAccount, @@ -320,7 +319,7 @@ describe('deploy-app', () => { const result1 = await algorand.appDeployer.deploy(deployment1) if (result1.operationPerformed !== 'nothing') { - await waitForIndexerTransaction(getTransactionId(result1.transaction)) + await waitForIndexer() } logging.testLogger.clear() @@ -351,7 +350,7 @@ describe('deploy-app', () => { }) test('Deploy replacement of deletable schema broken app', async () => { - const { algorand, testAccount, waitForIndexerTransaction } = localnet.context + const { algorand, testAccount, waitForIndexer } = localnet.context const metadata = getMetadata({ deletable: true }) const deployment1 = await getTestingAppDeployParams({ sender: testAccount, @@ -359,7 +358,7 @@ describe('deploy-app', () => { }) const result1 = await algorand.appDeployer.deploy(deployment1) if (result1.operationPerformed !== 'nothing') { - await waitForIndexerTransaction(getTransactionId(result1.transaction)) + await waitForIndexer() } logging.testLogger.clear() @@ -397,7 +396,7 @@ describe('deploy-app', () => { test('Deploy replacement to schema broken, permanent app fails', async () => { Config.configure({ debug: false }) // Remove noise from snapshot - const { algorand, testAccount, waitForIndexerTransaction } = localnet.context + const { algorand, testAccount, waitForIndexer } = localnet.context const metadata = getMetadata({ deletable: false }) const deployment1 = (await getTestingAppDeployParams({ sender: testAccount, @@ -406,7 +405,7 @@ describe('deploy-app', () => { const result1 = await algorand.appDeployer.deploy(deployment1) if (result1.operationPerformed !== 'nothing') { - await waitForIndexerTransaction(getTransactionId(result1.transaction)) + await waitForIndexer() } logging.testLogger.clear() @@ -437,7 +436,7 @@ describe('deploy-app', () => { }) test('Deploy failure for replacement of schema broken app fails if onSchemaBreak = Fail', async () => { - const { algorand, testAccount, waitForIndexerTransaction } = localnet.context + const { algorand, testAccount, waitForIndexer } = localnet.context const metadata = getMetadata() const deployment1 = await getTestingAppDeployParams({ sender: testAccount, @@ -445,7 +444,7 @@ describe('deploy-app', () => { }) const result1 = await algorand.appDeployer.deploy(deployment1) if (result1.operationPerformed !== 'nothing') { - await waitForIndexerTransaction(getTransactionId(result1.transaction)) + await waitForIndexer() } logging.testLogger.clear() @@ -472,14 +471,14 @@ describe('deploy-app', () => { }) test('Do nothing if deploying app with no changes', async () => { - const { algorand, testAccount, waitForIndexerTransaction } = localnet.context + const { algorand, testAccount, waitForIndexer } = localnet.context const deployment = await getTestingAppDeployParams({ sender: testAccount, metadata: getMetadata(), }) const initialDeployment = await algorand.appDeployer.deploy(deployment) if (initialDeployment.operationPerformed !== 'nothing') { - await waitForIndexerTransaction(getTransactionId(initialDeployment.transaction)) + await waitForIndexer() } logging.testLogger.clear() @@ -507,7 +506,7 @@ describe('deploy-app', () => { }) test('Deploy append for schema broken app if onSchemaBreak = AppendApp', async () => { - const { algorand, testAccount, waitForIndexerTransaction } = localnet.context + const { algorand, testAccount, waitForIndexer } = localnet.context const metadata = getMetadata() const deployment1 = await getTestingAppDeployParams({ sender: testAccount, @@ -515,7 +514,7 @@ describe('deploy-app', () => { }) const result1 = await algorand.appDeployer.deploy(deployment1) if (result1.operationPerformed !== 'nothing') { - await waitForIndexerTransaction(getTransactionId(result1.transaction)) + await waitForIndexer() } logging.testLogger.clear() @@ -549,7 +548,7 @@ describe('deploy-app', () => { }) test('Deploy append for update app if onUpdate = AppendApp', async () => { - const { algorand, testAccount, waitForIndexerTransaction } = localnet.context + const { algorand, testAccount, waitForIndexer } = localnet.context const metadata = getMetadata() const deployment1 = await getTestingAppDeployParams({ sender: testAccount, @@ -557,7 +556,7 @@ describe('deploy-app', () => { }) const result1 = await algorand.appDeployer.deploy(deployment1) if (result1.operationPerformed !== 'nothing') { - await waitForIndexerTransaction(getTransactionId(result1.transaction)) + await waitForIndexer() } logging.testLogger.clear() diff --git a/src/app-deploy.ts b/src/app-deploy.ts index d3bc40465..c7b05bb6f 100644 --- a/src/app-deploy.ts +++ b/src/app-deploy.ts @@ -71,8 +71,7 @@ export async function deployApp( new TransactionComposer({ algod, getSigner: () => getSenderTransactionSigner(deployment.from), - getSuggestedParams: async () => - deployment.transactionParams ? { ...deployment.transactionParams } : await algod.transactionParams(), + getSuggestedParams: async () => (deployment.transactionParams ? { ...deployment.transactionParams } : await algod.suggestedParams()), appManager, }) const deployer = new AppDeployer( diff --git a/src/indexer-lookup.spec.ts b/src/indexer-lookup.spec.ts index 6f450543b..898d782a4 100644 --- a/src/indexer-lookup.spec.ts +++ b/src/indexer-lookup.spec.ts @@ -19,9 +19,9 @@ describe('indexer-lookup', () => { } test('Transaction is found by id', async () => { - const { algorand, waitForIndexerTransaction } = localnet.context + const { algorand, waitForIndexer } = localnet.context const { transaction } = await sendTestTransaction() - await waitForIndexerTransaction(transaction.txID()) + await waitForIndexer() const txn = await algorand.client.indexer.lookupTransactionByID(transaction.txID()).do() @@ -39,7 +39,7 @@ describe('indexer-lookup', () => { }, 20_000) test('Transactions are searched with pagination', async () => { - const { algorand, testAccount, generateAccount, waitForIndexerTransaction } = localnet.context + const { algorand, testAccount, generateAccount, waitForIndexer } = localnet.context const secondAccount = await generateAccount({ initialFunds: (1).algo(), suppressLog: true, @@ -47,7 +47,7 @@ describe('indexer-lookup', () => { const { transaction: transaction1 } = await sendTestTransaction((1).microAlgo()) const { transaction: transaction2 } = await sendTestTransaction((2).microAlgo()) await sendTestTransaction((1).microAlgo(), secondAccount) - await waitForIndexerTransaction(getTransactionId(transaction2)) + await waitForIndexer() const transactions = await indexer.searchTransactions( algorand.client.indexer, @@ -62,7 +62,7 @@ describe('indexer-lookup', () => { }, 20_000) test('Application create transactions are found by creator with pagination', async () => { - const { algorand, testAccount, generateAccount, waitForIndexerTransaction } = localnet.context + const { algorand, testAccount, generateAccount, waitForIndexer } = localnet.context const secondAccount = await generateAccount({ initialFunds: (1).algo(), suppressLog: true, @@ -79,7 +79,7 @@ describe('indexer-lookup', () => { const { result: app1 } = await factory.send.bare.create() const { result: app2 } = await factory.send.bare.create({ deployTimeParams: { VALUE: 2 } }) await factory.send.bare.create({ sender: secondAccount }) - await waitForIndexerTransaction(getTransactionId(app2.transaction)) + await waitForIndexer() const apps = await indexer.lookupAccountCreatedApplicationByAddress(algorand.client.indexer, testAccount, true, 1) diff --git a/src/transaction/legacy-bridge.ts b/src/transaction/legacy-bridge.ts index eedc47e06..2b898301f 100644 --- a/src/transaction/legacy-bridge.ts +++ b/src/transaction/legacy-bridge.ts @@ -1,4 +1,4 @@ -import { AlgodClient, TransactionParams } from '@algorandfoundation/algokit-algod-client' +import { AlgodClient, SuggestedParams } from '@algorandfoundation/algokit-algod-client' import { BoxReference as TransactBoxReference, Transaction } from '@algorandfoundation/algokit-transact' import * as algosdk from '@algorandfoundation/sdk' import { ABIMethod } from '@algorandfoundation/sdk' @@ -41,14 +41,14 @@ export async function legacySendTransactionBridge (params: T) => Promise) | ((c: AlgorandClientTransactionCreator) => (params: T) => Promise), send: (c: AlgorandClientTransactionSender) => (params: T & SendParams) => Promise, - suggestedParams?: TransactionParams, + suggestedParams?: SuggestedParams, ): Promise<(SendTransactionResult | TResult) & { transactions: TransactionWrapper[] }> { const appManager = new AppManager(algod) const newGroup = () => new TransactionComposer({ algod, getSigner: () => getSenderTransactionSigner(from), - getSuggestedParams: async () => (suggestedParams ? { ...suggestedParams } : await algod.transactionParams()), + getSuggestedParams: async () => (suggestedParams ? { ...suggestedParams } : await algod.suggestedParams()), appManager, }) const transactionSender = new AlgorandClientTransactionSender(newGroup, new AssetManager(algod, newGroup), appManager) @@ -107,7 +107,7 @@ export async function legacySendAppTransactionBridge< | ((c: AlgorandClientTransactionCreator) => (params: T) => Promise) | ((c: AlgorandClientTransactionCreator) => (params: T) => Promise), send: (c: AlgorandClientTransactionSender) => (params: T & SendParams) => Promise, - suggestedParams?: TransactionParams, + suggestedParams?: SuggestedParams, ): Promise<(SendTransactionResult | TResult) & { transactions: TransactionWrapper[] }> { const encoder = new TextEncoder() diff --git a/src/transaction/transaction.ts b/src/transaction/transaction.ts index a557c502f..c824c628d 100644 --- a/src/transaction/transaction.ts +++ b/src/transaction/transaction.ts @@ -7,6 +7,7 @@ import { PendingTransactionResponse, SimulateRequest, SimulationTransactionExecTraceMeta, + SuggestedParams, } from '@algorandfoundation/algokit-algod-client' import type { AppCallTransactionFields } from '@algorandfoundation/algokit-transact' import { Transaction, TransactionType, encodeTransaction, getTransactionId } from '@algorandfoundation/algokit-transact' @@ -1109,7 +1110,7 @@ export const waitForConfirmation = async function ( * @param transaction The transaction to cap or suggested params object about to be used to create a transaction * @param maxAcceptableFee The maximum acceptable fee to pay */ -export function capTransactionFee(transaction: Transaction | algosdk.SdkTransactionParams, maxAcceptableFee: AlgoAmount) { +export function capTransactionFee(transaction: Transaction | SuggestedParams, maxAcceptableFee: AlgoAmount) { // If a flat fee hasn't already been defined if (!('flatFee' in transaction) || !transaction.flatFee) { // Once a transaction has been constructed by algosdk, transaction.fee indicates what the total transaction fee @@ -1136,7 +1137,7 @@ export function capTransactionFee(transaction: Transaction | algosdk.SdkTransact * @param transaction The transaction or suggested params * @param feeControl The fee control parameters */ -export function controlFees( +export function controlFees( transaction: T, feeControl: { fee?: AlgoAmount; maxFee?: AlgoAmount }, ) { @@ -1163,23 +1164,11 @@ export function controlFees { +export async function getTransactionParams(params: SuggestedParams | undefined, algod: AlgodClient): Promise { if (params) { return { ...params } } - const p = await algod.transactionParams() - return { - fee: p.fee, - firstRound: p.lastRound, - lastRound: p.lastRound + 1000n, - genesisId: p.genesisId, - genesisHash: p.genesisHash, - minFee: p.minFee, - consensusVersion: p.consensusVersion, - } + return await algod.suggestedParams() } /** diff --git a/src/types/account-manager.ts b/src/types/account-manager.ts index 6415732b5..60d74df16 100644 --- a/src/types/account-manager.ts +++ b/src/types/account-manager.ts @@ -1,4 +1,4 @@ -import { TransactionParams } from '@algorandfoundation/algokit-algod-client' +import { SuggestedParams } from '@algorandfoundation/algokit-algod-client' import type { Account } from '@algorandfoundation/sdk' import * as algosdk from '@algorandfoundation/sdk' import { Address, LogicSigAccount, TransactionSigner } from '@algorandfoundation/sdk' @@ -62,11 +62,11 @@ export class AccountManager { this._kmdAccountManager = new KmdAccountManager(clientManager) } - private _getComposer(getSuggestedParams?: () => Promise) { + private _getComposer(getSuggestedParams?: () => Promise) { return new TransactionComposer({ algod: this._clientManager.algod, getSigner: this.getSigner.bind(this), - getSuggestedParams: getSuggestedParams ?? (() => this._clientManager.algod.transactionParams()), + getSuggestedParams: getSuggestedParams ?? this._clientManager.algod.suggestedParams, }) } diff --git a/src/types/algorand-client.ts b/src/types/algorand-client.ts index bf2073563..4445a290c 100644 --- a/src/types/algorand-client.ts +++ b/src/types/algorand-client.ts @@ -1,4 +1,4 @@ -import { TransactionParams } from '@algorandfoundation/algokit-algod-client' +import { SuggestedParams } from '@algorandfoundation/algokit-algod-client' import type { Account } from '@algorandfoundation/sdk' import * as algosdk from '@algorandfoundation/sdk' import { Address, LogicSigAccount } from '@algorandfoundation/sdk' @@ -25,7 +25,7 @@ export class AlgorandClient { private _transactionSender: AlgorandClientTransactionSender private _transactionCreator: AlgorandClientTransactionCreator - private _cachedSuggestedParams?: TransactionParams + private _cachedSuggestedParams?: SuggestedParams private _cachedSuggestedParamsExpiry?: Date private _cachedSuggestedParamsTimeout: number = 3_000 // three seconds @@ -123,7 +123,7 @@ export class AlgorandClient { * const algorand = AlgorandClient.mainNet().setSuggestedParamsCache(suggestedParams, new Date(+new Date() + 3_600_000)) * ``` */ - public setSuggestedParamsCache(suggestedParams: TransactionParams, until?: Date) { + public setSuggestedParamsCache(suggestedParams: SuggestedParams, until?: Date) { this._cachedSuggestedParams = suggestedParams this._cachedSuggestedParamsExpiry = until ?? new Date(+new Date() + this._cachedSuggestedParamsTimeout) return this @@ -149,14 +149,14 @@ export class AlgorandClient { * @example * const params = await AlgorandClient.mainNet().getSuggestedParams(); */ - public async getSuggestedParams(): Promise { + public async getSuggestedParams(): Promise { if (this._cachedSuggestedParams && (!this._cachedSuggestedParamsExpiry || this._cachedSuggestedParamsExpiry > new Date())) { return { ...this._cachedSuggestedParams, } } - this._cachedSuggestedParams = await this._clientManager.algod.transactionParams() + this._cachedSuggestedParams = await this._clientManager.algod.suggestedParams() this._cachedSuggestedParamsExpiry = new Date(new Date().getTime() + this._cachedSuggestedParamsTimeout) return { @@ -236,7 +236,7 @@ export class AlgorandClient { return new TransactionComposer({ algod: this.client.algod, getSigner: (addr: string | Address) => this.account.getSigner(addr), - getSuggestedParams: () => this.getSuggestedParams(), + getSuggestedParams: this.getSuggestedParams, defaultValidityWindow: this._defaultValidityWindow, appManager: this._appManager, errorTransformers: [...this._errorTransformers], diff --git a/src/types/app-client.ts b/src/types/app-client.ts index ad6106e6f..625c0b0c0 100644 --- a/src/types/app-client.ts +++ b/src/types/app-client.ts @@ -1,4 +1,4 @@ -import { AlgodClient, TransactionParams } from '@algorandfoundation/algokit-algod-client' +import { AlgodClient, SuggestedParams } from '@algorandfoundation/algokit-algod-client' import { OnApplicationComplete } from '@algorandfoundation/algokit-transact' import * as algosdk from '@algorandfoundation/sdk' import { @@ -137,7 +137,7 @@ export type AppDetailsBase = { /** Default sender to use for transactions issued by this application client */ sender?: SendTransactionFrom /** Default suggested params object to use */ - params?: TransactionParams + params?: SuggestedParams /** Optionally provide any deploy-time parameters to replace in the TEAL code; if specified here will get * used in calls to `deploy`, `create` and `update` unless overridden in those calls */ @@ -1811,7 +1811,7 @@ export class ApplicationClient { private indexer?: algosdk.Indexer private appSpec: AppSpec private sender: SendTransactionFrom | undefined - private params: TransactionParams | undefined + private params: SuggestedParams | undefined private existingDeployments: LegacyAppLookup | undefined private deployTimeParams?: TealTemplateParams diff --git a/src/types/app-manager.ts b/src/types/app-manager.ts index cfe41ede6..c1e831d2b 100644 --- a/src/types/app-manager.ts +++ b/src/types/app-manager.ts @@ -203,9 +203,8 @@ export class AppManager { */ public async getById(appId: bigint): Promise { const app = await this._algod.getApplicationById(appId) - // Convert global state from new format (key: string) to old format (key: Uint8Array) const convertedGlobalState = (app.params.globalState ?? []).map((kv) => ({ - key: new Uint8Array(Buffer.from(kv.key, 'base64')), + key: kv.key, value: kv.value, })) @@ -262,7 +261,7 @@ export class AppManager { } const convertedState = appInfo.appLocalState.keyValue.map((kv) => ({ - key: new Uint8Array(Buffer.from(kv.key, 'base64')), + key: kv.key, value: kv.value, })) @@ -301,9 +300,8 @@ export class AppManager { */ public async getBoxValue(appId: bigint, boxName: BoxIdentifier | BoxName): Promise { const boxId = typeof boxName === 'object' && 'nameRaw' in boxName ? boxName.nameRaw : boxName - const nameBytes = AppManager.getBoxReference(boxId).name - const nameBase64 = Buffer.from(nameBytes).toString('base64') - const boxResult = await this._algod.getApplicationBoxByName(Number(appId), { name: `b64:${nameBase64}` }) + const name = AppManager.getBoxReference(boxId).name + const boxResult = await this._algod.getApplicationBoxByName(Number(appId), name) return boxResult.value } diff --git a/src/types/app.ts b/src/types/app.ts index 3a31ecd7c..fea73d46e 100644 --- a/src/types/app.ts +++ b/src/types/app.ts @@ -1,4 +1,4 @@ -import { TransactionParams } from '@algorandfoundation/algokit-algod-client' +import { SuggestedParams } from '@algorandfoundation/algokit-algod-client' import { OnApplicationComplete, BoxReference as TransactBoxReference, Transaction } from '@algorandfoundation/algokit-transact' import { ABIArgument, ABIMethod, ABIMethodParams, ABIType, ABIValue, Address, ProgramSourceMap } from '@algorandfoundation/sdk' import { Expand } from './expand' @@ -129,7 +129,7 @@ interface CreateOrUpdateAppParams extends SendTransactionParams { /** The clear state program as raw teal (string) or compiled teal, base 64 encoded as a byte array (Uint8Array) */ clearStateProgram: Uint8Array | string /** Optional transaction parameters */ - transactionParams?: TransactionParams + transactionParams?: SuggestedParams /** The (optional) transaction note */ note?: TransactionNote /** The arguments passed in to the app call */ @@ -181,7 +181,7 @@ export interface AppCallParams extends SendTransactionParams { /** The account to make the call from */ from: SendTransactionFrom /** Optional transaction parameters */ - transactionParams?: TransactionParams + transactionParams?: SuggestedParams /** The (optional) transaction note */ note?: TransactionNote /** The arguments passed in to the app call */ diff --git a/src/types/asset.ts b/src/types/asset.ts index e28f11c40..5a4d60b85 100644 --- a/src/types/asset.ts +++ b/src/types/asset.ts @@ -1,4 +1,4 @@ -import { SdkTransactionParams } from '@algorandfoundation/sdk' +import { SuggestedParams } from '@algorandfoundation/algokit-algod-client' import { AlgoAmount } from './amount' import { SendTransactionFrom, SendTransactionParams, TransactionNote } from './transaction' @@ -58,7 +58,7 @@ export interface CreateAssetParams extends SendTransactionParams { frozenByDefault?: boolean /** Optional transaction parameters */ - transactionParams?: SdkTransactionParams + transactionParams?: SuggestedParams /** The (optional) transaction note */ note?: TransactionNote /** An (optional) [transaction lease](https://dev.algorand.co/concepts/transactions/leases) to apply */ @@ -72,7 +72,7 @@ export interface AssetOptInParams extends SendTransactionParams { /** The ID of the assets to opt in for / out of */ assetId: number /** Optional transaction parameters */ - transactionParams?: SdkTransactionParams + transactionParams?: SuggestedParams /** The (optional) transaction note */ note?: TransactionNote /** An (optional) [transaction lease](https://dev.algorand.co/concepts/transactions/leases) to apply */ @@ -96,7 +96,7 @@ export interface AssetBulkOptInOutParams { /** Whether or not to validate the opt-in/out is valid before issuing transactions; default = true */ validateBalances?: boolean /** Optional transaction parameters */ - transactionParams?: SdkTransactionParams + transactionParams?: SuggestedParams /** The (optional) transaction note */ note?: TransactionNote /** The maximum fee that you are happy to pay per transaction (default: unbounded) - if this is set it's possible the transaction could get rejected during network congestion */ diff --git a/src/types/client-manager.ts b/src/types/client-manager.ts index 5ba127e28..23324b34b 100644 --- a/src/types/client-manager.ts +++ b/src/types/client-manager.ts @@ -1,4 +1,4 @@ -import { AlgodClient, TransactionParams } from '@algorandfoundation/algokit-algod-client' +import { AlgodClient, SuggestedParams } from '@algorandfoundation/algokit-algod-client' import * as algosdk from '@algorandfoundation/sdk' import { Indexer, Kmd } from '@algorandfoundation/sdk' import { AlgoHttpClientWithRetry } from './algo-http-client-with-retry' @@ -121,7 +121,7 @@ export class ClientManager { return this._kmd } - private _getNetworkPromise: Promise | undefined + private _getNetworkPromise: Promise | undefined /** * Get details about the current network. * @example Getting genesis ID @@ -133,7 +133,7 @@ export class ClientManager { */ public async network(): Promise { if (!this._getNetworkPromise) { - this._getNetworkPromise = this._algod.transactionParams() + this._getNetworkPromise = this._algod.suggestedParams() } const params = await this._getNetworkPromise diff --git a/src/types/composer.ts b/src/types/composer.ts index d4e89c992..eeb518a18 100644 --- a/src/types/composer.ts +++ b/src/types/composer.ts @@ -1,11 +1,10 @@ -import { AlgodClient, SimulateRequest, SimulateTransaction, TransactionParams } from '@algorandfoundation/algokit-algod-client' +import { AlgodClient, SimulateRequest, SimulateTransaction, SuggestedParams } from '@algorandfoundation/algokit-algod-client' import { AccessReference, OnApplicationComplete, Transaction, assignFee, getTransactionId } from '@algorandfoundation/algokit-transact' import * as algosdk from '@algorandfoundation/sdk' import { ABIMethod, Address, AtomicTransactionComposer, - SdkTransactionParams, TransactionSigner, TransactionWithSigner, isTransactionWithSigner, @@ -507,7 +506,7 @@ export type TransactionComposerParams = { /** The function used to get the TransactionSigner for a given address */ getSigner: (address: string | Address) => algosdk.TransactionSigner /** The method used to get SuggestedParams for transactions in the group */ - getSuggestedParams?: () => Promise + getSuggestedParams?: () => Promise /** How many rounds a transaction should be valid for by default; if not specified * then will be 10 rounds (or 1000 rounds if issuing transactions to LocalNet). */ @@ -568,7 +567,7 @@ export class TransactionComposer { private algod: AlgodClient /** An async function that will return suggested params for the transaction. */ - private getSuggestedParams: () => Promise + private getSuggestedParams: () => Promise /** A function that takes in an address and return a signer function for that address. */ private getSigner: (address: string | Address) => algosdk.TransactionSigner @@ -612,7 +611,7 @@ export class TransactionComposer { */ constructor(params: TransactionComposerParams) { this.algod = params.algod - const defaultGetSuggestedParams = () => params.algod.transactionParams() + const defaultGetSuggestedParams = () => params.algod.suggestedParams() this.getSuggestedParams = params.getSuggestedParams ?? defaultGetSuggestedParams this.getSigner = params.getSigner this.defaultValidityWindow = params.defaultValidityWindow ?? this.defaultValidityWindow @@ -1469,11 +1468,11 @@ export class TransactionComposer { txnParams.note = (typeof params.note === 'string' ? encoder.encode(params.note) : params.note) satisfies Transaction['note'] if (params.firstValidRound) { - txnParams.suggestedParams.firstRound = params.firstValidRound + txnParams.suggestedParams.firstValid = params.firstValidRound } if (params.lastValidRound) { - txnParams.suggestedParams.lastRound = params.lastValidRound + txnParams.suggestedParams.lastValid = params.lastValidRound } else { // If the validity window isn't set in this transaction or by default and we are pointing at // LocalNet set a bigger window to avoid dead transactions @@ -1482,7 +1481,7 @@ export class TransactionComposer { : !this.defaultValidityWindowIsExplicit && genesisIdIsLocalNet(txnParams.suggestedParams.genesisId ?? 'unknown') ? 1000n : this.defaultValidityWindow - txnParams.suggestedParams.lastRound = BigInt(txnParams.suggestedParams.firstRound) + window + txnParams.suggestedParams.lastValid = BigInt(txnParams.suggestedParams.firstValid) + window } if (params.staticFee !== undefined && params.extraFee !== undefined) { @@ -1515,7 +1514,7 @@ export class TransactionComposer { */ private async buildMethodCall( params: AppCallMethodCall | AppCreateMethodCall | AppUpdateMethodCall, - suggestedParams: SdkTransactionParams, + suggestedParams: SuggestedParams, includeSigner: boolean, ): Promise { const methodArgs: (algosdk.ABIArgument | TransactionWithSignerAndContext)[] = [] @@ -1715,7 +1714,7 @@ export class TransactionComposer { }) } - private buildPayment(params: PaymentParams, suggestedParams: SdkTransactionParams) { + private buildPayment(params: PaymentParams, suggestedParams: SuggestedParams) { return this.commonTxnBuildStep(algosdk.makePaymentTxnWithSuggestedParamsFromObject, params, { sender: params.sender, receiver: params.receiver, @@ -1725,7 +1724,7 @@ export class TransactionComposer { }) } - private buildAssetCreate(params: AssetCreateParams, suggestedParams: SdkTransactionParams) { + private buildAssetCreate(params: AssetCreateParams, suggestedParams: SuggestedParams) { return this.commonTxnBuildStep(algosdk.makeAssetCreateTxnWithSuggestedParamsFromObject, params, { sender: params.sender, total: params.total, @@ -1743,7 +1742,7 @@ export class TransactionComposer { }) } - private buildAssetConfig(params: AssetConfigParams, suggestedParams: SdkTransactionParams) { + private buildAssetConfig(params: AssetConfigParams, suggestedParams: SuggestedParams) { return this.commonTxnBuildStep(algosdk.makeAssetConfigTxnWithSuggestedParamsFromObject, params, { sender: params.sender, assetIndex: params.assetId, @@ -1756,7 +1755,7 @@ export class TransactionComposer { }) } - private buildAssetDestroy(params: AssetDestroyParams, suggestedParams: SdkTransactionParams) { + private buildAssetDestroy(params: AssetDestroyParams, suggestedParams: SuggestedParams) { return this.commonTxnBuildStep(algosdk.makeAssetDestroyTxnWithSuggestedParamsFromObject, params, { sender: params.sender, assetIndex: params.assetId, @@ -1764,7 +1763,7 @@ export class TransactionComposer { }) } - private buildAssetFreeze(params: AssetFreezeParams, suggestedParams: SdkTransactionParams) { + private buildAssetFreeze(params: AssetFreezeParams, suggestedParams: SuggestedParams) { return this.commonTxnBuildStep(algosdk.makeAssetFreezeTxnWithSuggestedParamsFromObject, params, { sender: params.sender, assetIndex: params.assetId, @@ -1774,7 +1773,7 @@ export class TransactionComposer { }) } - private buildAssetTransfer(params: AssetTransferParams, suggestedParams: SdkTransactionParams) { + private buildAssetTransfer(params: AssetTransferParams, suggestedParams: SuggestedParams) { return this.commonTxnBuildStep(algosdk.makeAssetTransferTxnWithSuggestedParamsFromObject, params, { sender: params.sender, receiver: params.receiver, @@ -1786,7 +1785,7 @@ export class TransactionComposer { }) } - private async buildAppCall(params: AppCallParams | AppUpdateParams | AppCreateParams, suggestedParams: SdkTransactionParams) { + private async buildAppCall(params: AppCallParams | AppUpdateParams | AppCreateParams, suggestedParams: SuggestedParams) { const appId = 'appId' in params ? params.appId : 0n const approvalProgram = 'approvalProgram' in params @@ -1844,7 +1843,7 @@ export class TransactionComposer { } } - private buildKeyReg(params: OnlineKeyRegistrationParams | OfflineKeyRegistrationParams, suggestedParams: SdkTransactionParams) { + private buildKeyReg(params: OnlineKeyRegistrationParams | OfflineKeyRegistrationParams, suggestedParams: SuggestedParams) { if ('voteKey' in params) { return this.commonTxnBuildStep(algosdk.makeKeyRegistrationTxnWithSuggestedParamsFromObject, params, { sender: params.sender, @@ -1867,7 +1866,7 @@ export class TransactionComposer { } /** Builds all transaction types apart from `txnWithSigner`, `atc` and `methodCall` since those ones can have custom signers that need to be retrieved. */ - private async buildTxn(txn: Txn, suggestedParams: SdkTransactionParams): Promise { + private async buildTxn(txn: Txn, suggestedParams: SuggestedParams): Promise { switch (txn.type) { case 'pay': return [this.buildPayment(txn, suggestedParams)] @@ -1894,7 +1893,7 @@ export class TransactionComposer { } } - private async buildTxnWithSigner(txn: Txn, suggestedParams: SdkTransactionParams): Promise { + private async buildTxnWithSigner(txn: Txn, suggestedParams: SuggestedParams): Promise { if (txn.type === 'txnWithSigner') { return [ { @@ -1928,11 +1927,6 @@ export class TransactionComposer { */ async buildTransactions(): Promise { const suggestedParams = await this.getSuggestedParams() - const sdkTransactionParams: SdkTransactionParams = { - ...suggestedParams, - firstRound: suggestedParams.lastRound, - lastRound: suggestedParams.lastRound + 1000n, - } const transactions: Transaction[] = [] const methodCalls = new Map() @@ -1940,7 +1934,7 @@ export class TransactionComposer { for (const txn of this.txns) { if (!['txnWithSigner', 'atc', 'methodCall'].includes(txn.type)) { - transactions.push(...(await this.buildTxn(txn, sdkTransactionParams)).map((txn) => txn.txn)) + transactions.push(...(await this.buildTxn(txn, suggestedParams)).map((txn) => txn.txn)) } else { const transactionsWithSigner = txn.type === 'txnWithSigner' @@ -1948,7 +1942,7 @@ export class TransactionComposer { : txn.type === 'atc' ? this.buildAtc(txn.atc) : txn.type === 'methodCall' - ? await this.buildMethodCall(txn, sdkTransactionParams, false) + ? await this.buildMethodCall(txn, suggestedParams, false) : [] transactionsWithSigner.forEach((ts) => { @@ -1992,15 +1986,10 @@ export class TransactionComposer { async build() { if (this.atc.getStatus() === algosdk.AtomicTransactionComposerStatus.BUILDING) { const suggestedParams = await this.getSuggestedParams() - const sdkTransactionParams: SdkTransactionParams = { - ...suggestedParams, - firstRound: suggestedParams.lastRound, - lastRound: suggestedParams.lastRound + 1000n, - } // Build all of the transactions const txnWithSigners: TransactionWithSignerAndContext[] = [] for (const txn of this.txns) { - txnWithSigners.push(...(await this.buildTxnWithSigner(txn, sdkTransactionParams))) + txnWithSigners.push(...(await this.buildTxnWithSigner(txn, suggestedParams))) } // Add all of the transactions to the underlying ATC @@ -2056,7 +2045,7 @@ export class TransactionComposer { if (waitRounds === undefined) { const lastRound = group.reduce((max, txn) => (txn.txn.lastValid > max ? txn.txn.lastValid : BigInt(max)), 0n) - const { lastRound: firstRound } = suggestedParams! + const { firstValid: firstRound } = suggestedParams! waitRounds = Number(BigInt(lastRound) - BigInt(firstRound)) + 1 } diff --git a/src/types/kmd-account-manager.ts b/src/types/kmd-account-manager.ts index 7b3053e7d..454c5c3e5 100644 --- a/src/types/kmd-account-manager.ts +++ b/src/types/kmd-account-manager.ts @@ -1,6 +1,6 @@ -import { Config } from '../config' import * as algosdk from '@algorandfoundation/sdk' import { Address } from '@algorandfoundation/sdk' +import { Config } from '../config' import { SigningAccount, TransactionSignerAccount } from './account' import { AlgoAmount } from './amount' import { ClientManager } from './client-manager' @@ -164,7 +164,7 @@ export class KmdAccountManager { await new TransactionComposer({ algod: this._clientManager.algod, getSigner: () => dispenser.signer, - getSuggestedParams: () => this._clientManager.algod.transactionParams(), + getSuggestedParams: () => this._clientManager.algod.suggestedParams(), }) .addPayment({ amount: fundWith ?? AlgoAmount.Algo(1000), diff --git a/src/types/transaction.ts b/src/types/transaction.ts index 5f4a8e8d0..795d4fb3b 100644 --- a/src/types/transaction.ts +++ b/src/types/transaction.ts @@ -1,4 +1,4 @@ -import { PendingTransactionResponse } from '@algorandfoundation/algokit-algod-client' +import { PendingTransactionResponse, SuggestedParams } from '@algorandfoundation/algokit-algod-client' import { AppCallTransactionFields, AssetConfigTransactionFields, @@ -13,7 +13,6 @@ import { } from '@algorandfoundation/algokit-transact' import { HeartbeatTransactionFields } from '@algorandfoundation/algokit-transact/transactions/heartbeat' import { StateProofTransactionFields } from '@algorandfoundation/algokit-transact/transactions/state-proof' -import * as algosdk from '@algorandfoundation/sdk' import { AtomicTransactionComposer, LogicSigAccount, type Account } from '@algorandfoundation/sdk' import { MultisigAccount, SigningAccount, TransactionSignerAccount } from './account' import { AlgoAmount } from './amount' @@ -159,7 +158,7 @@ export interface AdditionalAtomicTransactionComposerContext { maxFees: Map /* The suggested params info relevant to transactions in the `AtomicTransactionComposer` */ - suggestedParams: Pick + suggestedParams: Pick } /** An `AtomicTransactionComposer` with transactions to send. */ diff --git a/src/types/transfer.ts b/src/types/transfer.ts index 8bd1d34fe..88f968b41 100644 --- a/src/types/transfer.ts +++ b/src/types/transfer.ts @@ -1,4 +1,4 @@ -import { SdkTransactionParams } from '@algorandfoundation/sdk' +import { SuggestedParams } from '@algorandfoundation/algokit-algod-client' import { AlgoAmount } from './amount' import { TestNetDispenserApiClient } from './dispenser-client' import { SendTransactionFrom, SendTransactionParams, TransactionNote } from './transaction' @@ -12,7 +12,7 @@ export interface AlgoTransferParams extends SendTransactionParams { /** The amount to send */ amount: AlgoAmount /** Optional transaction parameters */ - transactionParams?: SdkTransactionParams + transactionParams?: SuggestedParams /** The (optional) transaction note */ note?: TransactionNote /** An (optional) [transaction lease](https://dev.algorand.co/concepts/transactions/leases) to apply */ @@ -26,7 +26,7 @@ export interface AlgoRekeyParams extends SendTransactionParams { /** The account / account address that will have the private key that is authorised to transact on behalf of the from account from now on */ rekeyTo: SendTransactionFrom | string /** Optional transaction parameters */ - transactionParams?: SdkTransactionParams + transactionParams?: SuggestedParams /** The (optional) transaction note */ note?: TransactionNote /** An (optional) [transaction lease](https://dev.algorand.co/concepts/transactions/leases) to apply */ @@ -44,7 +44,7 @@ export interface EnsureFundedParams extends SendTransactionParams { /** When issuing a funding amount, the minimum amount to transfer (avoids many small transfers if this gets called often on an active account) */ minFundingIncrement?: AlgoAmount /** Optional transaction parameters */ - transactionParams?: SdkTransactionParams + transactionParams?: SuggestedParams /** The (optional) transaction note, default: "Funding account to meet minimum requirement" */ note?: TransactionNote /** An (optional) [transaction lease](https://dev.algorand.co/concepts/transactions/leases) to apply */ @@ -62,7 +62,7 @@ export interface TransferAssetParams extends SendTransactionParams { /** The amount to send as the smallest divisible unit value */ amount: number | bigint /** Optional transaction parameters */ - transactionParams?: SdkTransactionParams + transactionParams?: SuggestedParams /** An address of a target account from which to perform a clawback operation. Please note, in such cases senderAccount must be equal to clawback field on ASA metadata. */ clawbackFrom?: SendTransactionFrom | string /** The (optional) transaction note */ From a8ccc52f61bf0211d959ddca4946d5a18264e188 Mon Sep 17 00:00:00 2001 From: Neil Campbell Date: Fri, 7 Nov 2025 13:04:06 +0800 Subject: [PATCH 10/10] fix: additional algod fixes --- .../src/oas_generator/generator/models.py | 4 ---- .../oas_generator/generator/template_engine.py | 18 +++--------------- .../oas_generator/templates/apis/service.ts.j2 | 2 +- packages/algod_client/src/apis/api.service.ts | 16 ++++++---------- src/testing/fixtures/algorand-fixture.ts | 7 +++---- src/types/account-manager.ts | 2 +- src/types/algorand-client.ts | 2 +- src/types/app-client.ts | 2 +- src/types/composer.spec.ts | 2 +- 9 files changed, 17 insertions(+), 38 deletions(-) diff --git a/oas-generator/src/oas_generator/generator/models.py b/oas-generator/src/oas_generator/generator/models.py index 6992bf5a2..c12d28dba 100644 --- a/oas-generator/src/oas_generator/generator/models.py +++ b/oas-generator/src/oas_generator/generator/models.py @@ -48,8 +48,6 @@ class OperationContext: import_types: set[str] tags: list[str] | None = None returns_msgpack: bool = False - has_format_param: bool = False - format_var_name: str | None = None # When the original spec had a query param `format` with enum ['msgpack'] only, # we don't expose it to callers but still need to set it implicitly on requests force_msgpack_query: bool = False @@ -70,8 +68,6 @@ def to_dict(self) -> dict[str, Any]: "requestBody": self._request_body_to_dict(self.request_body) if self.request_body else None, "responseTsType": self.response_type, "returnsMsgpack": self.returns_msgpack, - "hasFormatParam": self.has_format_param, - "formatVarName": self.format_var_name, "forceMsgpackQuery": self.force_msgpack_query, "errorTypes": [self._error_to_dict(e) for e in (self.error_types or [])], "isPrivate": self.is_private, diff --git a/oas-generator/src/oas_generator/generator/template_engine.py b/oas-generator/src/oas_generator/generator/template_engine.py index be1264e69..5fdc0a0df 100644 --- a/oas-generator/src/oas_generator/generator/template_engine.py +++ b/oas-generator/src/oas_generator/generator/template_engine.py @@ -541,7 +541,6 @@ def _create_operation_context(self, op_input: OperationInput) -> OperationContex ) # Compute additional properties - self._compute_format_param(context) self._compute_force_msgpack_query(context, op_input.operation, op_input.spec) self._compute_import_types(context) @@ -560,14 +559,11 @@ def _process_parameters(self, params: list[Schema], spec: Schema) -> list[Parame # Extract parameter details raw_name = str(param.get("name")) - # Skip `format` query param when it's constrained to a single format (json or msgpack) + # Always skip `format` query param - we default to JSON and don't expose format selection location_candidate = param.get(constants.OperationKey.IN, constants.ParamLocation.QUERY) if location_candidate == constants.ParamLocation.QUERY and raw_name == constants.FORMAT_PARAM_NAME: - schema_obj = param.get("schema", {}) or {} - enum_vals = schema_obj.get(constants.SchemaKey.ENUM) - if isinstance(enum_vals, list) and len(enum_vals) == 1 and enum_vals[0] in ("msgpack", "json"): - # Endpoint only supports a single format; do not expose/append `format` - continue + # Skip format parameter entirely - always default to JSON + continue var_name = self._sanitize_variable_name(ts_camel_case(raw_name), used_names) used_names.add(var_name) @@ -677,14 +673,6 @@ def _process_responses(self, responses: Schema, operation_id: str, spec: Schema) return response_type, returns_msgpack - def _compute_format_param(self, context: OperationContext) -> None: - """Detect and set format parameter for content negotiation.""" - for param in context.parameters: - if param.location == constants.ParamLocation.QUERY and param.name == constants.FORMAT_PARAM_NAME: - context.has_format_param = True - context.format_var_name = param.var_name - break - def _compute_force_msgpack_query(self, context: OperationContext, raw_operation: Schema, spec: Schema) -> None: """Detect if the raw spec constrains query format to only 'msgpack' and mark for implicit query injection.""" params = raw_operation.get(constants.OperationKey.PARAMETERS, []) or [] diff --git a/oas-generator/src/oas_generator/templates/apis/service.ts.j2 b/oas-generator/src/oas_generator/templates/apis/service.ts.j2 index 9ec8a5ca6..a262320fc 100644 --- a/oas-generator/src/oas_generator/templates/apis/service.ts.j2 +++ b/oas-generator/src/oas_generator/templates/apis/service.ts.j2 @@ -106,7 +106,7 @@ export class {{ service_class_name }} { ): Promise<{{ op.responseTsType }}> { const headers: Record = {}; {% set supports_msgpack = op.returnsMsgpack or (op.requestBody and op.requestBody.supportsMsgpack) %} - const responseFormat: BodyFormat = {% if supports_msgpack %}{% if op.hasFormatParam and op.formatVarName %}(params?.{{ op.formatVarName }} as BodyFormat | undefined) ?? 'msgpack'{% else %}'msgpack'{% endif %}{% else %}'json'{% endif %}; + const responseFormat: BodyFormat = {% if op.forceMsgpackQuery %}'msgpack'{% elif supports_msgpack %}'json'{% else %}'json'{% endif %}; headers['Accept'] = {{ service_class_name }}.acceptFor(responseFormat); {% if op.requestBody and op.method.upper() not in ['GET', 'HEAD'] %} diff --git a/packages/algod_client/src/apis/api.service.ts b/packages/algod_client/src/apis/api.service.ts index de3fce433..21678eace 100644 --- a/packages/algod_client/src/apis/api.service.ts +++ b/packages/algod_client/src/apis/api.service.ts @@ -89,20 +89,16 @@ export class AlgodApi { /** * Given a specific account public key and application ID, this call returns the account's application local state and global state (AppLocalState and AppParams, if either exists). Global state will only be returned if the provided address is the application's creator. */ - async accountApplicationInformation( - address: string, - applicationId: number | bigint, - params?: { format?: 'json' | 'msgpack' }, - ): Promise { + async accountApplicationInformation(address: string, applicationId: number | bigint): Promise { const headers: Record = {} - const responseFormat: BodyFormat = (params?.format as BodyFormat | undefined) ?? 'msgpack' + const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) const payload = await this.httpRequest.request({ method: 'GET', url: '/v2/accounts/{address}/applications/{application-id}', path: { address: address, 'application-id': typeof applicationId === 'bigint' ? applicationId.toString() : applicationId }, - query: { format: params?.format }, + query: {}, headers, body: undefined, mediaType: undefined, @@ -644,7 +640,7 @@ export class AlgodApi { async getTransactionProof( round: number | bigint, txid: string, - params?: { hashtype?: 'sha512_256' | 'sha256'; format?: 'json' | 'msgpack' }, + params?: { hashtype?: 'sha512_256' | 'sha256' }, ): Promise { const headers: Record = {} const responseFormat: BodyFormat = 'json' @@ -654,7 +650,7 @@ export class AlgodApi { method: 'GET', url: '/v2/blocks/{round}/transactions/{txid}/proof', path: { round: typeof round === 'bigint' ? round.toString() : round, txid: txid }, - query: { hashtype: params?.hashtype, format: params?.format }, + query: { hashtype: params?.hashtype }, headers, body: undefined, mediaType: undefined, @@ -910,7 +906,7 @@ export class AlgodApi { */ async tealDryrun(body?: DryrunRequest): Promise { const headers: Record = {} - const responseFormat: BodyFormat = 'msgpack' + const responseFormat: BodyFormat = 'json' headers['Accept'] = AlgodApi.acceptFor(responseFormat) const bodyMeta = DryrunRequestMeta diff --git a/src/testing/fixtures/algorand-fixture.ts b/src/testing/fixtures/algorand-fixture.ts index 3d4d785a1..ce3e455f6 100644 --- a/src/testing/fixtures/algorand-fixture.ts +++ b/src/testing/fixtures/algorand-fixture.ts @@ -89,10 +89,9 @@ export function algorandFixture(fixtureConfig?: AlgorandFixtureConfig, config?: const newScope = async () => { Config.configure({ debug: true }) const transactionLogger = new TransactionLogger() - // TODO: implement the logic for wait for indexer - // const transactionLoggerAlgod = transactionLogger.capture(algod) + const transactionLoggerAlgod = transactionLogger.capture(algod) - algorand = AlgorandClient.fromClients({ algod: algod, indexer, kmd }).setSuggestedParamsCacheTimeout(0) + algorand = AlgorandClient.fromClients({ algod: transactionLoggerAlgod, indexer, kmd }).setSuggestedParamsCacheTimeout(0) const testAccount = await getTestAccount({ initialFunds: fixtureConfig?.testAccountFunding ?? algos(10), suppressLog: true }, algorand) algorand.setSignerFromAccount(testAccount) @@ -104,7 +103,7 @@ export function algorandFixture(fixtureConfig?: AlgorandFixtureConfig, config?: } context = { algorand, - algod: algod, + algod: transactionLoggerAlgod, indexer: indexer, kmd: kmd, testAccount, diff --git a/src/types/account-manager.ts b/src/types/account-manager.ts index 60d74df16..57218a4a5 100644 --- a/src/types/account-manager.ts +++ b/src/types/account-manager.ts @@ -66,7 +66,7 @@ export class AccountManager { return new TransactionComposer({ algod: this._clientManager.algod, getSigner: this.getSigner.bind(this), - getSuggestedParams: getSuggestedParams ?? this._clientManager.algod.suggestedParams, + getSuggestedParams: getSuggestedParams ?? (() => this._clientManager.algod.suggestedParams()), }) } diff --git a/src/types/algorand-client.ts b/src/types/algorand-client.ts index 4445a290c..1d42e97d8 100644 --- a/src/types/algorand-client.ts +++ b/src/types/algorand-client.ts @@ -236,7 +236,7 @@ export class AlgorandClient { return new TransactionComposer({ algod: this.client.algod, getSigner: (addr: string | Address) => this.account.getSigner(addr), - getSuggestedParams: this.getSuggestedParams, + getSuggestedParams: () => this.getSuggestedParams(), defaultValidityWindow: this._defaultValidityWindow, appManager: this._appManager, errorTransformers: [...this._errorTransformers], diff --git a/src/types/app-client.ts b/src/types/app-client.ts index 625c0b0c0..cb79d9a39 100644 --- a/src/types/app-client.ts +++ b/src/types/app-client.ts @@ -98,7 +98,7 @@ import { } from './transaction' /** The maximum opcode budget for a simulate call as per https://github.com/algorand/go-algorand/blob/807b29a91c371d225e12b9287c5d56e9b33c4e4c/ledger/simulation/trace.go#L104 */ -const MAX_SIMULATE_OPCODE_BUDGET = BigInt(20_000 * 16) +const MAX_SIMULATE_OPCODE_BUDGET = 20_000 * 16 /** Configuration to resolve app by creator and name `getCreatorAppsByName` */ export type ResolveAppByCreatorAndNameBase = { diff --git a/src/types/composer.spec.ts b/src/types/composer.spec.ts index 2f3d1ba40..f09410fe2 100644 --- a/src/types/composer.spec.ts +++ b/src/types/composer.spec.ts @@ -5,7 +5,7 @@ describe('TransactionComposer', () => { const fixture = algorandFixture() beforeEach(async () => { - await fixture.beforeEach() + await fixture.newScope() }) describe('error transformers', () => {