From 3c450892981bec7922558e2d62eeb08759067569 Mon Sep 17 00:00:00 2001 From: Altynbek Orumbayev Date: Thu, 4 Sep 2025 17:22:15 +0200 Subject: [PATCH 1/4] feat: ts api jinja generator --- .github/workflows/api_ci.yml | 49 +- .gitignore | 3 + .../ts_oas_generator/__init__.py | 0 api/oas_generator/ts_oas_generator/cli.py | 189 +++ .../ts_oas_generator/generator/__init__.py | 0 .../ts_oas_generator/generator/filters.py | 283 ++++ .../generator/template_engine.py | 499 +++++++ .../templates/apis/index.ts.j2 | 2 + .../templates/apis/service.ts.j2 | 83 ++ .../templates/base/.prettierignore.j2 | 3 + .../templates/base/README.md.j2 | 24 + .../templates/base/package.json.j2 | 24 + .../templates/base/src/core/ApiError.ts.j2 | 12 + .../base/src/core/BaseHttpRequest.ts.j2 | 21 + .../base/src/core/CancelablePromise.ts.j2 | 49 + .../base/src/core/FetchHttpRequest.ts.j2 | 10 + .../templates/base/src/core/OpenAPI.ts.j2 | 22 + .../templates/base/src/core/json.ts.j2 | 66 + .../templates/base/src/core/msgpack.ts.j2 | 59 + .../templates/base/src/core/request.ts.j2 | 87 ++ .../templates/base/src/index.ts.j2 | 11 + .../templates/base/tsconfig.json.j2 | 14 + .../ts_oas_generator/templates/client.ts.j2 | 13 + .../templates/full/src/index.ts.j2 | 10 + .../templates/full/tests/smoke.spec.ts.j2 | 49 + .../templates/models/index.ts.j2 | 4 + .../templates/models/model.ts.j2 | 22 + .../ts_oas_generator/utils/__init__.py | 0 .../ts_oas_generator/utils/file_utils.py | 19 + .../typescript/algod_client/.prettierignore | 3 + packages/typescript/algod_client/README.md | 24 + packages/typescript/algod_client/package.json | 24 + .../algod_client/src/apis/api.service.ts | 1232 +++++++++++++++++ .../typescript/algod_client/src/apis/index.ts | 2 + .../typescript/algod_client/src/client.ts | 13 + .../algod_client/src/core/ApiError.ts | 12 + .../algod_client/src/core/BaseHttpRequest.ts | 21 + .../src/core/CancelablePromise.ts | 52 + .../algod_client/src/core/FetchHttpRequest.ts | 10 + .../algod_client/src/core/OpenAPI.ts | 22 + .../typescript/algod_client/src/core/json.ts | 70 + .../algod_client/src/core/msgpack.ts | 61 + .../algod_client/src/core/request.ts | 90 ++ packages/typescript/algod_client/src/index.ts | 10 + .../algod_client/src/models/abortcatchup.ts | 4 + .../algod_client/src/models/account.ts | 37 + .../models/accountapplicationinformation.ts | 6 + .../src/models/accountassetholding.ts | 6 + .../src/models/accountassetinformation.ts | 6 + .../src/models/accountassetsinformation.ts | 6 + .../src/models/accountparticipation.ts | 11 + .../src/models/accountstatedelta.ts | 6 + .../src/models/addparticipationkey.ts | 4 + .../algod_client/src/models/appcalllogs.ts | 4 + .../algod_client/src/models/application.ts | 6 + .../src/models/applicationinitialstates.ts | 11 + .../src/models/applicationkvstorage.ts | 6 + .../src/models/applicationlocalreference.ts | 4 + .../src/models/applicationlocalstate.ts | 6 + .../src/models/applicationparams.ts | 15 + .../src/models/applicationstateoperation.ts | 12 + .../src/models/applicationstateschema.ts | 4 + .../algod_client/src/models/asset.ts | 6 + .../algod_client/src/models/assetholding.ts | 7 + .../src/models/assetholdingreference.ts | 4 + .../algod_client/src/models/assetparams.ts | 25 + .../algod_client/src/models/avmkeyvalue.ts | 6 + .../algod_client/src/models/avmvalue.ts | 4 + .../typescript/algod_client/src/models/box.ts | 4 + .../algod_client/src/models/boxdescriptor.ts | 4 + .../algod_client/src/models/boxreference.ts | 4 + .../algod_client/src/models/buildversion.ts | 1 + .../src/models/debugsettingsprof.ts | 4 + .../algod_client/src/models/dryrunrequest.ts | 14 + .../algod_client/src/models/dryrunsource.ts | 4 + .../algod_client/src/models/dryrunstate.ts | 6 + .../src/models/dryruntxnresult.ts | 18 + .../algod_client/src/models/errorresponse.ts | 4 + .../algod_client/src/models/evaldelta.ts | 4 + .../src/models/evaldeltakeyvalue.ts | 6 + .../algod_client/src/models/genesis.ts | 13 + .../src/models/genesisallocation.ts | 5 + .../src/models/getapplicationboxes.ts | 6 + .../algod_client/src/models/getblock.ts | 4 + .../algod_client/src/models/getblockhash.ts | 4 + .../algod_client/src/models/getblocklogs.ts | 6 + .../src/models/getblocktimestampoffset.ts | 4 + .../algod_client/src/models/getblocktxids.ts | 4 + .../src/models/getpendingtransactions.ts | 4 + .../models/getpendingtransactionsbyaddress.ts | 4 + .../algod_client/src/models/getstatus.ts | 31 + .../algod_client/src/models/getsupply.ts | 4 + .../algod_client/src/models/getsyncround.ts | 4 + ...ansactiongroupledgerstatedeltasforround.ts | 6 + .../algod_client/src/models/index.ts | 84 ++ .../src/models/ledgerstatedelta.ts | 4 + .../ledgerstatedeltafortransactiongroup.ts | 6 + .../src/models/lightblockheaderproof.ts | 4 + .../src/models/participationkey.ts | 15 + .../src/models/pendingtransactionresponse.ts | 21 + .../algod_client/src/models/rawtransaction.ts | 4 + .../algod_client/src/models/scratchchange.ts | 6 + .../algod_client/src/models/shutdownnode.ts | 1 + .../src/models/simulateinitialstates.ts | 6 + .../src/models/simulaterequest.ts | 15 + .../models/simulaterequesttransactiongroup.ts | 4 + .../src/models/simulatetraceconfig.ts | 4 + .../src/models/simulatetransaction.ts | 13 + .../models/simulatetransactiongroupresult.ts | 13 + .../src/models/simulatetransactionresult.ts | 13 + .../simulateunnamedresourcesaccessed.ts | 14 + .../src/models/simulationevaloverrides.ts | 11 + .../src/models/simulationopcodetraceunit.ts | 13 + .../models/simulationtransactionexectrace.ts | 16 + .../algod_client/src/models/startcatchup.ts | 4 + .../algod_client/src/models/statedelta.ts | 6 + .../algod_client/src/models/stateproof.ts | 6 + .../src/models/stateproofmessage.ts | 10 + .../algod_client/src/models/tealcompile.ts | 4 + .../src/models/tealdisassemble.ts | 4 + .../algod_client/src/models/tealdryrun.ts | 6 + .../algod_client/src/models/tealkeyvalue.ts | 6 + .../src/models/tealkeyvaluestore.ts | 6 + .../algod_client/src/models/tealvalue.ts | 4 + .../src/models/transactionparams.ts | 12 + .../src/models/transactionproof.ts | 4 + .../algod_client/src/models/version.ts | 6 + .../algod_client/src/models/waitforblock.ts | 31 + .../tests/generated/smoke.generated.spec.ts | 49 + .../algod_client/tests/helpers/env.ts | 49 + .../algod_client/tests/helpers/wait.ts | 16 + .../tests/pendingTransaction.spec.ts | 46 + .../algod_client/tests/smoke.spec.ts | 46 + .../algod_client/tests/src/client.ts | 12 + .../tests/transactionParams.spec.ts | 18 + .../typescript/algod_client/tsconfig.json | 14 + .../typescript/indexer_client/.prettierignore | 3 + packages/typescript/indexer_client/README.md | 24 + .../typescript/indexer_client/package.json | 24 + .../indexer_client/src/apis/api.service.ts | 671 +++++++++ .../indexer_client/src/apis/index.ts | 2 + .../typescript/indexer_client/src/client.ts | 13 + .../indexer_client/src/core/ApiError.ts | 12 + .../src/core/BaseHttpRequest.ts | 21 + .../src/core/CancelablePromise.ts | 52 + .../src/core/FetchHttpRequest.ts | 10 + .../indexer_client/src/core/OpenAPI.ts | 22 + .../indexer_client/src/core/json.ts | 70 + .../indexer_client/src/core/msgpack.ts | 61 + .../indexer_client/src/core/request.ts | 90 ++ .../typescript/indexer_client/src/index.ts | 10 + .../indexer_client/src/models/account.ts | 40 + .../src/models/accountparticipation.ts | 11 + .../src/models/accountstatedelta.ts | 6 + .../indexer_client/src/models/application.ts | 12 + .../src/models/applicationlocalstate.ts | 13 + .../src/models/applicationlogdata.ts | 4 + .../src/models/applicationparams.ts | 15 + .../src/models/applicationstateschema.ts | 4 + .../indexer_client/src/models/asset.ts | 6 + .../indexer_client/src/models/assetholding.ts | 14 + .../indexer_client/src/models/assetparams.ts | 25 + .../indexer_client/src/models/block.ts | 29 + .../indexer_client/src/models/blockrewards.ts | 11 + .../src/models/blockupgradestate.ts | 10 + .../src/models/blockupgradevote.ts | 4 + .../indexer_client/src/models/box.ts | 4 + .../src/models/boxdescriptor.ts | 4 + .../indexer_client/src/models/boxreference.ts | 4 + .../indexer_client/src/models/evaldelta.ts | 4 + .../src/models/evaldeltakeyvalue.ts | 6 + .../indexer_client/src/models/hashfactory.ts | 1 + .../indexer_client/src/models/hashtype.ts | 6 + .../src/models/hbprooffields.ts | 4 + .../indexer_client/src/models/healthcheck.ts | 12 + .../indexer_client/src/models/index.ts | 73 + .../src/models/indexerstateproofmessage.ts | 7 + .../src/models/lookupaccountapplocalstates.ts | 6 + .../src/models/lookupaccountassets.ts | 6 + .../src/models/lookupaccountbyid.ts | 6 + .../lookupaccountcreatedapplications.ts | 6 + .../src/models/lookupaccountcreatedassets.ts | 6 + .../src/models/lookupaccounttransactions.ts | 6 + .../src/models/lookupapplicationbyid.ts | 6 + .../src/models/lookupapplicationlogsbyid.ts | 11 + .../src/models/lookupassetbalances.ts | 6 + .../src/models/lookupassetbyid.ts | 6 + .../src/models/lookupassettransactions.ts | 6 + .../src/models/lookuptransaction.ts | 6 + .../src/models/merklearrayproof.ts | 3 + .../src/models/miniassetholding.ts | 11 + .../indexer_client/src/models/oncompletion.ts | 12 + .../src/models/participationupdates.ts | 4 + .../src/models/searchforaccounts.ts | 6 + .../src/models/searchforapplicationboxes.ts | 6 + .../src/models/searchforapplications.ts | 6 + .../src/models/searchforassets.ts | 6 + .../src/models/searchforblockheaders.ts | 6 + .../src/models/searchfortransactions.ts | 6 + .../indexer_client/src/models/statedelta.ts | 6 + .../src/models/stateprooffields.ts | 17 + .../src/models/stateproofparticipant.ts | 3 + .../src/models/stateproofreveal.ts | 3 + .../src/models/stateproofsignature.ts | 8 + .../src/models/stateproofsigslot.ts | 3 + .../src/models/stateprooftracking.ts | 1 + .../src/models/stateproofverifier.ts | 1 + .../indexer_client/src/models/stateschema.ts | 4 + .../indexer_client/src/models/tealkeyvalue.ts | 6 + .../src/models/tealkeyvaluestore.ts | 6 + .../indexer_client/src/models/tealvalue.ts | 4 + .../indexer_client/src/models/transaction.ts | 58 + .../src/models/transactionapplication.ts | 23 + .../src/models/transactionassetconfig.ts | 13 + .../src/models/transactionassetfreeze.ts | 7 + .../src/models/transactionassettransfer.ts | 14 + .../src/models/transactionheartbeat.ts | 15 + .../src/models/transactionkeyreg.ts | 15 + .../src/models/transactionpayment.ts | 7 + .../src/models/transactionsignature.ts | 6 + .../models/transactionsignaturelogicsig.ts | 14 + .../models/transactionsignaturemultisig.ts | 13 + ...ransactionsignaturemultisigsubsignature.ts | 1 + .../src/models/transactionstateproof.ts | 9 + .../tests/generated/smoke.generated.spec.ts | 49 + .../indexer_client/tests/helpers/env.ts | 18 + .../indexer_client/tests/helpers/wait.ts | 16 + .../tests/searchTransactions.spec.ts | 15 + .../indexer_client/tests/smoke.spec.ts | 46 + .../indexer_client/tests/src/client.ts | 10 + .../typescript/indexer_client/tsconfig.json | 14 + tools/api_tools/src/main.rs | 118 ++ 232 files changed, 6372 insertions(+), 5 deletions(-) create mode 100644 api/oas_generator/ts_oas_generator/__init__.py create mode 100644 api/oas_generator/ts_oas_generator/cli.py create mode 100644 api/oas_generator/ts_oas_generator/generator/__init__.py create mode 100644 api/oas_generator/ts_oas_generator/generator/filters.py create mode 100644 api/oas_generator/ts_oas_generator/generator/template_engine.py create mode 100644 api/oas_generator/ts_oas_generator/templates/apis/index.ts.j2 create mode 100644 api/oas_generator/ts_oas_generator/templates/apis/service.ts.j2 create mode 100644 api/oas_generator/ts_oas_generator/templates/base/.prettierignore.j2 create mode 100644 api/oas_generator/ts_oas_generator/templates/base/README.md.j2 create mode 100644 api/oas_generator/ts_oas_generator/templates/base/package.json.j2 create mode 100644 api/oas_generator/ts_oas_generator/templates/base/src/core/ApiError.ts.j2 create mode 100644 api/oas_generator/ts_oas_generator/templates/base/src/core/BaseHttpRequest.ts.j2 create mode 100644 api/oas_generator/ts_oas_generator/templates/base/src/core/CancelablePromise.ts.j2 create mode 100644 api/oas_generator/ts_oas_generator/templates/base/src/core/FetchHttpRequest.ts.j2 create mode 100644 api/oas_generator/ts_oas_generator/templates/base/src/core/OpenAPI.ts.j2 create mode 100644 api/oas_generator/ts_oas_generator/templates/base/src/core/json.ts.j2 create mode 100644 api/oas_generator/ts_oas_generator/templates/base/src/core/msgpack.ts.j2 create mode 100644 api/oas_generator/ts_oas_generator/templates/base/src/core/request.ts.j2 create mode 100644 api/oas_generator/ts_oas_generator/templates/base/src/index.ts.j2 create mode 100644 api/oas_generator/ts_oas_generator/templates/base/tsconfig.json.j2 create mode 100644 api/oas_generator/ts_oas_generator/templates/client.ts.j2 create mode 100644 api/oas_generator/ts_oas_generator/templates/full/src/index.ts.j2 create mode 100644 api/oas_generator/ts_oas_generator/templates/full/tests/smoke.spec.ts.j2 create mode 100644 api/oas_generator/ts_oas_generator/templates/models/index.ts.j2 create mode 100644 api/oas_generator/ts_oas_generator/templates/models/model.ts.j2 create mode 100644 api/oas_generator/ts_oas_generator/utils/__init__.py create mode 100644 api/oas_generator/ts_oas_generator/utils/file_utils.py create mode 100644 packages/typescript/algod_client/.prettierignore create mode 100644 packages/typescript/algod_client/README.md create mode 100644 packages/typescript/algod_client/package.json create mode 100644 packages/typescript/algod_client/src/apis/api.service.ts create mode 100644 packages/typescript/algod_client/src/apis/index.ts create mode 100644 packages/typescript/algod_client/src/client.ts create mode 100644 packages/typescript/algod_client/src/core/ApiError.ts create mode 100644 packages/typescript/algod_client/src/core/BaseHttpRequest.ts create mode 100644 packages/typescript/algod_client/src/core/CancelablePromise.ts create mode 100644 packages/typescript/algod_client/src/core/FetchHttpRequest.ts create mode 100644 packages/typescript/algod_client/src/core/OpenAPI.ts create mode 100644 packages/typescript/algod_client/src/core/json.ts create mode 100644 packages/typescript/algod_client/src/core/msgpack.ts create mode 100644 packages/typescript/algod_client/src/core/request.ts create mode 100644 packages/typescript/algod_client/src/index.ts create mode 100644 packages/typescript/algod_client/src/models/abortcatchup.ts create mode 100644 packages/typescript/algod_client/src/models/account.ts create mode 100644 packages/typescript/algod_client/src/models/accountapplicationinformation.ts create mode 100644 packages/typescript/algod_client/src/models/accountassetholding.ts create mode 100644 packages/typescript/algod_client/src/models/accountassetinformation.ts create mode 100644 packages/typescript/algod_client/src/models/accountassetsinformation.ts create mode 100644 packages/typescript/algod_client/src/models/accountparticipation.ts create mode 100644 packages/typescript/algod_client/src/models/accountstatedelta.ts create mode 100644 packages/typescript/algod_client/src/models/addparticipationkey.ts create mode 100644 packages/typescript/algod_client/src/models/appcalllogs.ts create mode 100644 packages/typescript/algod_client/src/models/application.ts create mode 100644 packages/typescript/algod_client/src/models/applicationinitialstates.ts create mode 100644 packages/typescript/algod_client/src/models/applicationkvstorage.ts create mode 100644 packages/typescript/algod_client/src/models/applicationlocalreference.ts create mode 100644 packages/typescript/algod_client/src/models/applicationlocalstate.ts create mode 100644 packages/typescript/algod_client/src/models/applicationparams.ts create mode 100644 packages/typescript/algod_client/src/models/applicationstateoperation.ts create mode 100644 packages/typescript/algod_client/src/models/applicationstateschema.ts create mode 100644 packages/typescript/algod_client/src/models/asset.ts create mode 100644 packages/typescript/algod_client/src/models/assetholding.ts create mode 100644 packages/typescript/algod_client/src/models/assetholdingreference.ts create mode 100644 packages/typescript/algod_client/src/models/assetparams.ts create mode 100644 packages/typescript/algod_client/src/models/avmkeyvalue.ts create mode 100644 packages/typescript/algod_client/src/models/avmvalue.ts create mode 100644 packages/typescript/algod_client/src/models/box.ts create mode 100644 packages/typescript/algod_client/src/models/boxdescriptor.ts create mode 100644 packages/typescript/algod_client/src/models/boxreference.ts create mode 100644 packages/typescript/algod_client/src/models/buildversion.ts create mode 100644 packages/typescript/algod_client/src/models/debugsettingsprof.ts create mode 100644 packages/typescript/algod_client/src/models/dryrunrequest.ts create mode 100644 packages/typescript/algod_client/src/models/dryrunsource.ts create mode 100644 packages/typescript/algod_client/src/models/dryrunstate.ts create mode 100644 packages/typescript/algod_client/src/models/dryruntxnresult.ts create mode 100644 packages/typescript/algod_client/src/models/errorresponse.ts create mode 100644 packages/typescript/algod_client/src/models/evaldelta.ts create mode 100644 packages/typescript/algod_client/src/models/evaldeltakeyvalue.ts create mode 100644 packages/typescript/algod_client/src/models/genesis.ts create mode 100644 packages/typescript/algod_client/src/models/genesisallocation.ts create mode 100644 packages/typescript/algod_client/src/models/getapplicationboxes.ts create mode 100644 packages/typescript/algod_client/src/models/getblock.ts create mode 100644 packages/typescript/algod_client/src/models/getblockhash.ts create mode 100644 packages/typescript/algod_client/src/models/getblocklogs.ts create mode 100644 packages/typescript/algod_client/src/models/getblocktimestampoffset.ts create mode 100644 packages/typescript/algod_client/src/models/getblocktxids.ts create mode 100644 packages/typescript/algod_client/src/models/getpendingtransactions.ts create mode 100644 packages/typescript/algod_client/src/models/getpendingtransactionsbyaddress.ts create mode 100644 packages/typescript/algod_client/src/models/getstatus.ts create mode 100644 packages/typescript/algod_client/src/models/getsupply.ts create mode 100644 packages/typescript/algod_client/src/models/getsyncround.ts create mode 100644 packages/typescript/algod_client/src/models/gettransactiongroupledgerstatedeltasforround.ts create mode 100644 packages/typescript/algod_client/src/models/index.ts create mode 100644 packages/typescript/algod_client/src/models/ledgerstatedelta.ts create mode 100644 packages/typescript/algod_client/src/models/ledgerstatedeltafortransactiongroup.ts create mode 100644 packages/typescript/algod_client/src/models/lightblockheaderproof.ts create mode 100644 packages/typescript/algod_client/src/models/participationkey.ts create mode 100644 packages/typescript/algod_client/src/models/pendingtransactionresponse.ts create mode 100644 packages/typescript/algod_client/src/models/rawtransaction.ts create mode 100644 packages/typescript/algod_client/src/models/scratchchange.ts create mode 100644 packages/typescript/algod_client/src/models/shutdownnode.ts create mode 100644 packages/typescript/algod_client/src/models/simulateinitialstates.ts create mode 100644 packages/typescript/algod_client/src/models/simulaterequest.ts create mode 100644 packages/typescript/algod_client/src/models/simulaterequesttransactiongroup.ts create mode 100644 packages/typescript/algod_client/src/models/simulatetraceconfig.ts create mode 100644 packages/typescript/algod_client/src/models/simulatetransaction.ts create mode 100644 packages/typescript/algod_client/src/models/simulatetransactiongroupresult.ts create mode 100644 packages/typescript/algod_client/src/models/simulatetransactionresult.ts create mode 100644 packages/typescript/algod_client/src/models/simulateunnamedresourcesaccessed.ts create mode 100644 packages/typescript/algod_client/src/models/simulationevaloverrides.ts create mode 100644 packages/typescript/algod_client/src/models/simulationopcodetraceunit.ts create mode 100644 packages/typescript/algod_client/src/models/simulationtransactionexectrace.ts create mode 100644 packages/typescript/algod_client/src/models/startcatchup.ts create mode 100644 packages/typescript/algod_client/src/models/statedelta.ts create mode 100644 packages/typescript/algod_client/src/models/stateproof.ts create mode 100644 packages/typescript/algod_client/src/models/stateproofmessage.ts create mode 100644 packages/typescript/algod_client/src/models/tealcompile.ts create mode 100644 packages/typescript/algod_client/src/models/tealdisassemble.ts create mode 100644 packages/typescript/algod_client/src/models/tealdryrun.ts create mode 100644 packages/typescript/algod_client/src/models/tealkeyvalue.ts create mode 100644 packages/typescript/algod_client/src/models/tealkeyvaluestore.ts create mode 100644 packages/typescript/algod_client/src/models/tealvalue.ts create mode 100644 packages/typescript/algod_client/src/models/transactionparams.ts create mode 100644 packages/typescript/algod_client/src/models/transactionproof.ts create mode 100644 packages/typescript/algod_client/src/models/version.ts create mode 100644 packages/typescript/algod_client/src/models/waitforblock.ts create mode 100644 packages/typescript/algod_client/tests/generated/smoke.generated.spec.ts create mode 100644 packages/typescript/algod_client/tests/helpers/env.ts create mode 100644 packages/typescript/algod_client/tests/helpers/wait.ts create mode 100644 packages/typescript/algod_client/tests/pendingTransaction.spec.ts create mode 100644 packages/typescript/algod_client/tests/smoke.spec.ts create mode 100644 packages/typescript/algod_client/tests/src/client.ts create mode 100644 packages/typescript/algod_client/tests/transactionParams.spec.ts create mode 100644 packages/typescript/algod_client/tsconfig.json create mode 100644 packages/typescript/indexer_client/.prettierignore create mode 100644 packages/typescript/indexer_client/README.md create mode 100644 packages/typescript/indexer_client/package.json create mode 100644 packages/typescript/indexer_client/src/apis/api.service.ts create mode 100644 packages/typescript/indexer_client/src/apis/index.ts create mode 100644 packages/typescript/indexer_client/src/client.ts create mode 100644 packages/typescript/indexer_client/src/core/ApiError.ts create mode 100644 packages/typescript/indexer_client/src/core/BaseHttpRequest.ts create mode 100644 packages/typescript/indexer_client/src/core/CancelablePromise.ts create mode 100644 packages/typescript/indexer_client/src/core/FetchHttpRequest.ts create mode 100644 packages/typescript/indexer_client/src/core/OpenAPI.ts create mode 100644 packages/typescript/indexer_client/src/core/json.ts create mode 100644 packages/typescript/indexer_client/src/core/msgpack.ts create mode 100644 packages/typescript/indexer_client/src/core/request.ts create mode 100644 packages/typescript/indexer_client/src/index.ts create mode 100644 packages/typescript/indexer_client/src/models/account.ts create mode 100644 packages/typescript/indexer_client/src/models/accountparticipation.ts create mode 100644 packages/typescript/indexer_client/src/models/accountstatedelta.ts create mode 100644 packages/typescript/indexer_client/src/models/application.ts create mode 100644 packages/typescript/indexer_client/src/models/applicationlocalstate.ts create mode 100644 packages/typescript/indexer_client/src/models/applicationlogdata.ts create mode 100644 packages/typescript/indexer_client/src/models/applicationparams.ts create mode 100644 packages/typescript/indexer_client/src/models/applicationstateschema.ts create mode 100644 packages/typescript/indexer_client/src/models/asset.ts create mode 100644 packages/typescript/indexer_client/src/models/assetholding.ts create mode 100644 packages/typescript/indexer_client/src/models/assetparams.ts create mode 100644 packages/typescript/indexer_client/src/models/block.ts create mode 100644 packages/typescript/indexer_client/src/models/blockrewards.ts create mode 100644 packages/typescript/indexer_client/src/models/blockupgradestate.ts create mode 100644 packages/typescript/indexer_client/src/models/blockupgradevote.ts create mode 100644 packages/typescript/indexer_client/src/models/box.ts create mode 100644 packages/typescript/indexer_client/src/models/boxdescriptor.ts create mode 100644 packages/typescript/indexer_client/src/models/boxreference.ts create mode 100644 packages/typescript/indexer_client/src/models/evaldelta.ts create mode 100644 packages/typescript/indexer_client/src/models/evaldeltakeyvalue.ts create mode 100644 packages/typescript/indexer_client/src/models/hashfactory.ts create mode 100644 packages/typescript/indexer_client/src/models/hashtype.ts create mode 100644 packages/typescript/indexer_client/src/models/hbprooffields.ts create mode 100644 packages/typescript/indexer_client/src/models/healthcheck.ts create mode 100644 packages/typescript/indexer_client/src/models/index.ts create mode 100644 packages/typescript/indexer_client/src/models/indexerstateproofmessage.ts create mode 100644 packages/typescript/indexer_client/src/models/lookupaccountapplocalstates.ts create mode 100644 packages/typescript/indexer_client/src/models/lookupaccountassets.ts create mode 100644 packages/typescript/indexer_client/src/models/lookupaccountbyid.ts create mode 100644 packages/typescript/indexer_client/src/models/lookupaccountcreatedapplications.ts create mode 100644 packages/typescript/indexer_client/src/models/lookupaccountcreatedassets.ts create mode 100644 packages/typescript/indexer_client/src/models/lookupaccounttransactions.ts create mode 100644 packages/typescript/indexer_client/src/models/lookupapplicationbyid.ts create mode 100644 packages/typescript/indexer_client/src/models/lookupapplicationlogsbyid.ts create mode 100644 packages/typescript/indexer_client/src/models/lookupassetbalances.ts create mode 100644 packages/typescript/indexer_client/src/models/lookupassetbyid.ts create mode 100644 packages/typescript/indexer_client/src/models/lookupassettransactions.ts create mode 100644 packages/typescript/indexer_client/src/models/lookuptransaction.ts create mode 100644 packages/typescript/indexer_client/src/models/merklearrayproof.ts create mode 100644 packages/typescript/indexer_client/src/models/miniassetholding.ts create mode 100644 packages/typescript/indexer_client/src/models/oncompletion.ts create mode 100644 packages/typescript/indexer_client/src/models/participationupdates.ts create mode 100644 packages/typescript/indexer_client/src/models/searchforaccounts.ts create mode 100644 packages/typescript/indexer_client/src/models/searchforapplicationboxes.ts create mode 100644 packages/typescript/indexer_client/src/models/searchforapplications.ts create mode 100644 packages/typescript/indexer_client/src/models/searchforassets.ts create mode 100644 packages/typescript/indexer_client/src/models/searchforblockheaders.ts create mode 100644 packages/typescript/indexer_client/src/models/searchfortransactions.ts create mode 100644 packages/typescript/indexer_client/src/models/statedelta.ts create mode 100644 packages/typescript/indexer_client/src/models/stateprooffields.ts create mode 100644 packages/typescript/indexer_client/src/models/stateproofparticipant.ts create mode 100644 packages/typescript/indexer_client/src/models/stateproofreveal.ts create mode 100644 packages/typescript/indexer_client/src/models/stateproofsignature.ts create mode 100644 packages/typescript/indexer_client/src/models/stateproofsigslot.ts create mode 100644 packages/typescript/indexer_client/src/models/stateprooftracking.ts create mode 100644 packages/typescript/indexer_client/src/models/stateproofverifier.ts create mode 100644 packages/typescript/indexer_client/src/models/stateschema.ts create mode 100644 packages/typescript/indexer_client/src/models/tealkeyvalue.ts create mode 100644 packages/typescript/indexer_client/src/models/tealkeyvaluestore.ts create mode 100644 packages/typescript/indexer_client/src/models/tealvalue.ts create mode 100644 packages/typescript/indexer_client/src/models/transaction.ts create mode 100644 packages/typescript/indexer_client/src/models/transactionapplication.ts create mode 100644 packages/typescript/indexer_client/src/models/transactionassetconfig.ts create mode 100644 packages/typescript/indexer_client/src/models/transactionassetfreeze.ts create mode 100644 packages/typescript/indexer_client/src/models/transactionassettransfer.ts create mode 100644 packages/typescript/indexer_client/src/models/transactionheartbeat.ts create mode 100644 packages/typescript/indexer_client/src/models/transactionkeyreg.ts create mode 100644 packages/typescript/indexer_client/src/models/transactionpayment.ts create mode 100644 packages/typescript/indexer_client/src/models/transactionsignature.ts create mode 100644 packages/typescript/indexer_client/src/models/transactionsignaturelogicsig.ts create mode 100644 packages/typescript/indexer_client/src/models/transactionsignaturemultisig.ts create mode 100644 packages/typescript/indexer_client/src/models/transactionsignaturemultisigsubsignature.ts create mode 100644 packages/typescript/indexer_client/src/models/transactionstateproof.ts create mode 100644 packages/typescript/indexer_client/tests/generated/smoke.generated.spec.ts create mode 100644 packages/typescript/indexer_client/tests/helpers/env.ts create mode 100644 packages/typescript/indexer_client/tests/helpers/wait.ts create mode 100644 packages/typescript/indexer_client/tests/searchTransactions.spec.ts create mode 100644 packages/typescript/indexer_client/tests/smoke.spec.ts create mode 100644 packages/typescript/indexer_client/tests/src/client.ts create mode 100644 packages/typescript/indexer_client/tsconfig.json diff --git a/.github/workflows/api_ci.yml b/.github/workflows/api_ci.yml index f1cc50a6c..fb45ade6b 100644 --- a/.github/workflows/api_ci.yml +++ b/.github/workflows/api_ci.yml @@ -12,6 +12,7 @@ on: - "tools/api_tools/**" - "crates/algod_client/**" - "crates/indexer_client/**" + - "packages/typescript/**" - ".github/workflows/api_ci.yml" pull_request: branches: @@ -21,6 +22,7 @@ on: - "tools/api_tools/**" - "crates/algod_client/**" - "crates/indexer_client/**" + - "packages/typescript/**" - ".github/workflows/api_ci.yml" workflow_dispatch: @@ -33,10 +35,10 @@ jobs: steps: - uses: actions/checkout@v4 - uses: ./.github/actions/setup-api-tools - + - name: Run OAS generator linting run: cargo api lint-oas - + - name: Run OAS generator tests run: cargo api test-oas @@ -54,10 +56,10 @@ jobs: steps: - uses: actions/checkout@v4 - uses: ./.github/actions/setup-api-tools - + - name: Generate ${{ matrix.client }} API client run: cargo api generate-${{ matrix.client }} - + - name: Check for output stability run: | git add -N ${{ matrix.output_dir }} @@ -66,6 +68,43 @@ jobs: echo "🔧 To fix: Run 'cargo api generate-${{ matrix.client }}' locally and commit the changes" exit 1 fi - + - name: Verify generated code compiles run: cargo check --manifest-path Cargo.toml -p ${{ matrix.client }}_client + + ts_api_client_generation: + runs-on: ubuntu-latest + needs: oas_lint_and_test + strategy: + matrix: + pkg: [algod_client, indexer_client] + steps: + - uses: actions/checkout@v4 + - uses: ./.github/actions/setup-api-tools + - uses: actions/setup-node@v4 + with: + node-version: "20" + + - name: Generate TypeScript API clients + run: cargo api generate-ts-all + + - name: Check output stability for ${{ matrix.pkg }} + run: | + git add -N packages/typescript/${{ matrix.pkg }} + if ! git diff --exit-code --minimal packages/typescript/${{ matrix.pkg }}; then + echo "❌ Generated ${{ matrix.pkg }} TS client differs from committed version!" + echo "🔧 To fix: Run 'cargo api generate-ts-all' locally and commit the changes" + exit 1 + fi + + - name: Install dependencies (${{ matrix.pkg }}) + working-directory: packages/typescript/${{ matrix.pkg }} + run: bun install + + - name: Format check (${{ matrix.pkg }}) + working-directory: packages/typescript/${{ matrix.pkg }} + run: npx prettier --check . + + - name: Build (tsc) ${{ matrix.pkg }} + working-directory: packages/typescript/${{ matrix.pkg }} + run: bun run build diff --git a/.gitignore b/.gitignore index acfe2dc66..b1e115f80 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,6 @@ AGENTS.md .references/ .kiro/ + +packages/typescript/algod_client/dist/ +packages/typescript/indexer_client/dist/ diff --git a/api/oas_generator/ts_oas_generator/__init__.py b/api/oas_generator/ts_oas_generator/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/api/oas_generator/ts_oas_generator/cli.py b/api/oas_generator/ts_oas_generator/cli.py new file mode 100644 index 000000000..63933a095 --- /dev/null +++ b/api/oas_generator/ts_oas_generator/cli.py @@ -0,0 +1,189 @@ +#!/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 ts_oas_generator.generator.template_engine import TsCodeGenerator +from ts_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 --runtime-only --output ./packages/algod_client --package-name algod_client + %(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", + nargs="?", + type=Path, + help="Path to OpenAPI specification file (JSON or YAML)", + metavar="SPEC_FILE", + ) + parser.add_argument( + "--runtime-only", + action="store_true", + help="Generate only the base runtime files (no models/APIs); does not require a spec file", + ) + parser.add_argument( + "--output", + "-o", + type=Path, + default=Path("./generated_ts"), + help="Output directory for generated files (default: %(default)s)", + dest="output_dir", + ) + parser.add_argument( + "--package-name", + "-p", + default="api_ts_client", + 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.runtime_only and parsed_args.spec_file is None: + parser.error("SPEC_FILE is required unless --runtime-only is provided") + + if parsed_args.spec_file is not None and not parsed_args.spec_file.exists(): + parser.error(f"Specification file not found: {parsed_args.spec_file}") + + 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}") + print(f"\nTypeScript client generated successfully in {output_dir}") + + +@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="tsgen_bak_")) + 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 = TsCodeGenerator(template_dir=parsed_args.template_dir) + + if parsed_args.runtime_only: + generated_files = generator.generate_runtime( + parsed_args.output_dir, + parsed_args.package_name, + custom_description=parsed_args.custom_description, + ) + else: + generated_files = generator.generate_full( + 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}") + + return EXIT_SUCCESS + + except FileNotFoundError: + print( + f"Error: Specification file not found: {parsed_args.spec_file}", + file=sys.stderr, + ) + return EXIT_FILE_NOT_FOUND + except json.JSONDecodeError as e: + print(f"Error: Invalid JSON in specification file: {e}", file=sys.stderr) + return EXIT_INVALID_JSON + except Exception as e: + print(f"Error: {e}", file=sys.stderr) + if parsed_args.verbose: + traceback.print_exc() + return EXIT_GENERATION_ERROR + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/api/oas_generator/ts_oas_generator/generator/__init__.py b/api/oas_generator/ts_oas_generator/generator/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/api/oas_generator/ts_oas_generator/generator/filters.py b/api/oas_generator/ts_oas_generator/generator/filters.py new file mode 100644 index 000000000..c1d02e30c --- /dev/null +++ b/api/oas_generator/ts_oas_generator/generator/filters.py @@ -0,0 +1,283 @@ +""" +TypeScript-specific Jinja2 filters and helpers. +Phase 2 adds OpenAPI -> TS type mapping and naming utilities. +""" + +from __future__ import annotations + +import re +from typing import Any + +_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 = str(text).strip().split("\n") + body = "\n".join(f" * {line.strip()}" if line.strip() 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}>" + + +# ---------- Naming helpers ---------- + + +def _split_words(name: str) -> list[str]: + name = re.sub(r"([a-z0-9])([A-Z])", r"\1 \2", name) + name = re.sub(r"[^A-Za-z0-9]+", " ", name) + parts = [p for p in name.strip().split() if p] + return parts or [name] + + +def ts_pascal_case(name: str) -> str: + parts = _split_words(name) + return "".join(p.capitalize() for p in parts) + + +def ts_camel_case(name: str) -> str: + pas = ts_pascal_case(name) + return pas[:1].lower() + pas[1:] if pas else pas + + +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: list[str]) -> str: + uniq: list[str] = [] + for t in types: + if t not in uniq: + uniq.append(t) + return " | ".join(uniq) if uniq else "never" + + +def _intersection(types: list[str]) -> str: + parts = [t for t in types if t and t != "any"] + return " & ".join(parts) if parts else "any" + + +def _nullable(type_str: str, schema: dict[str, Any]) -> str: + # OpenAPI 3.0 nullable flag + if schema.get("nullable") is True: + return _union([type_str, "null"]) + + # OpenAPI 3.1 union type with null + t = schema.get("type") + if isinstance(t, list) and "null" in t: + non_nulls = [x for x in t if x != "null"] + # If there's exactly one non-null type, union with null + if len(non_nulls) == 1: + return _union([ts_type({"type": non_nulls[0]}, None), "null"]) + # Else, build a union of all non-nulls + null + return _union([_union([ts_type({"type": n}, None) for n in non_nulls]), "null"]) + + return type_str + + +def _inline_object(schema: dict[str, Any], schemas: dict[str, Any] | None) -> str: + properties: dict[str, Any] = schema.get("properties", {}) or {} + required = set(schema.get("required", []) or []) + parts: list[str] = [] + + for prop_name, prop_schema in properties.items(): + ts_name = ts_property_name(prop_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]: any;") + elif isinstance(addl, dict): + parts.append(f"[key: string]: {ts_type(addl, schemas)};") + + return "{" + (" ".join(parts)) + "}" + + +def _map_primitive(schema_type: str, _schema_format: str | None, schema: dict[str, Any]) -> str: + if schema.get("x-algokit-bigint") is True and schema_type == "integer": + return "bigint" + + if schema_type == "integer": + return "number" + + if schema_type in ("number",): + return "number" + + if schema_type == "string": + # bytes/base64 remain string for JSON representation + return "string" + + if schema_type == "boolean": + return "boolean" + + return "any" + + +def ts_enum_type(schema: dict[str, Any]) -> str | None: + if "enum" not in schema: + return None + + if schema.get("x-algokit-bigint") is True: + # For bigint-marked enums, use bigint type directly + return "bigint" + + type_val = schema.get("type") + values = schema.get("enum", []) + + if type_val == "string": + return " | ".join([f"'{v!s}'" for v in values]) + + if type_val == "integer": + 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: dict[str, Any] | None, schemas: dict[str, Any] | None = None) -> str: # noqa: PLR0911 + """Map OpenAPI schema to a TypeScript type string.""" + if not schema: + return "any" + + # Handle references + if "$ref" in schema: + ref_name = _extract_ref_name(schema["$ref"]) # e.g. #/components/schemas/Foo + return ts_pascal_case(ref_name) + + # Handle composed schemas + if "allOf" in schema: + return _intersection([ts_type(s, schemas) for s in schema.get("allOf", [])]) + + if "oneOf" in schema: + return _union([ts_type(s, schemas) for s in schema.get("oneOf", [])]) + + if "anyOf" in schema: + return _union([ts_type(s, schemas) for s in schema.get("anyOf", [])]) + + # Enums + enum_t = ts_enum_type(schema) + if enum_t: + return enum_t + + schema_type = schema.get("type") + + # Handle array of items + if schema_type == "array": + items_schema = schema.get("items", {}) + items_type = ts_type(items_schema, schemas) + return f"{items_type}[]" + + # Object type + if schema_type == "object" or (not schema_type and ("properties" in schema or "additionalProperties" in schema)): + type_str = _inline_object(schema, schemas) + return _nullable(type_str, schema) + + # Primitive types + type_str = _map_primitive(str(schema_type), schema.get("format"), schema) + return _nullable(type_str, schema) + + +# ---------- Response helpers ---------- + + +def has_msgpack_2xx(responses: dict[str, Any]) -> bool: + for status, resp in (responses or {}).items(): + if not str(status).startswith("2"): + continue + content = (resp or {}).get("content", {}) + if any(ct in (content or {}) for ct in ("application/msgpack", "application/x-binary")): + return True + return False + + +def response_content_types(responses: dict[str, Any]) -> list[str]: + cts: set[str] = set() + for status, resp in (responses or {}).items(): + if not str(status).startswith("2"): + continue + content = (resp or {}).get("content", {}) + for ct in content: + cts.add(ct) + return sorted(cts) + + +def collect_schema_refs(schema: dict[str, Any], current_schema_name: str | None = None) -> list[str]: # noqa: C901 + """Recursively collect all $ref model names from a schema, excluding self-references.""" + refs: set[str] = set() + + def _traverse(obj: dict[str, Any]) -> None: # noqa: C901 + if not obj or not isinstance(obj, dict): + return + + # Direct $ref + if "$ref" in obj: + ref_name = ts_pascal_case(_extract_ref_name(obj["$ref"])) + # Exclude self-references + if current_schema_name and ref_name != ts_pascal_case(current_schema_name): + refs.add(ref_name) + return # Don't traverse further if this is a ref + + # Properties + if "properties" in obj and isinstance(obj["properties"], dict): + for prop_schema in obj["properties"].values(): + _traverse(prop_schema) + + # Array items + if "items" in obj: + _traverse(obj["items"]) + + # Composed schemas + for key in ["allOf", "oneOf", "anyOf"]: + if key in obj and isinstance(obj[key], list): + for sub_schema in obj[key]: + _traverse(sub_schema) + + # Additional properties + if "additionalProperties" in obj and isinstance(obj["additionalProperties"], dict): + _traverse(obj["additionalProperties"]) + + _traverse(schema) + return sorted(refs) + + +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_property_name": ts_property_name, + "has_msgpack_2xx": has_msgpack_2xx, + "response_content_types": response_content_types, + "collect_schema_refs": collect_schema_refs, +} diff --git a/api/oas_generator/ts_oas_generator/generator/template_engine.py b/api/oas_generator/ts_oas_generator/generator/template_engine.py new file mode 100644 index 000000000..7e6359045 --- /dev/null +++ b/api/oas_generator/ts_oas_generator/generator/template_engine.py @@ -0,0 +1,499 @@ +""" +TypeScript Template Engine for OpenAPI Client Generation (Phase 2) + +Generates runtime plus models/services when a spec is provided. +""" + +from __future__ import annotations + +import re +from pathlib import Path +from typing import Any + +from jinja2 import Environment, FileSystemLoader, select_autoescape + +from rust_oas_generator.parser.oas_parser import OASParser +from ts_oas_generator.generator.filters import FILTERS, ts_camel_case, ts_pascal_case, ts_type + +_HTTP_METHODS = {"get", "post", "put", "delete", "patch", "head", "options"} + +# Compact alias for the build context tuple to keep lines within ruff's E501 limit +BuildContext = tuple[ + dict[str, list[dict[str, Any]]], + set[str], + dict[str, Any], +] + + +class TsTemplateEngine: + """Template engine for generating TypeScript client code.""" + + def __init__(self, template_dir: Path | None = None) -> None: + if template_dir is None: + current_dir = Path(__file__).parent + template_dir = current_dir.parent / "templates" + + self.template_dir = Path(template_dir) + self.env = Environment( + loader=FileSystemLoader(str(self.template_dir)), + autoescape=select_autoescape(["html", "xml"]), + trim_blocks=True, + lstrip_blocks=True, + ) + + self._register_filters() + self._register_globals() + + def _register_filters(self) -> None: + self.env.filters.update(FILTERS) + + def _register_globals(self) -> None: + self.env.globals.update({}) + + def render_template(self, template_name: str, context: dict[str, Any]) -> str: + template = self.env.get_template(template_name) + return template.render(**context) + + +class TsCodeGenerator: + """Generates TypeScript runtime and code from templates.""" + + def __init__(self, template_dir: Path | None = None) -> None: + self.template_engine = TsTemplateEngine(template_dir) + + def generate_runtime( + self, + output_dir: Path, + package_name: str = "api_ts_client", + *, + custom_description: str | None = None, + ) -> dict[Path, str]: + """Generate runtime files under the provided output directory.""" + output_dir = Path(output_dir) + src_core = output_dir / "src" / "core" + context = { + "package_name": package_name, + "custom_description": custom_description, + } + + files: dict[Path, str] = {} + # Core runtime files + files[src_core / "OpenAPI.ts"] = self.template_engine.render_template("base/src/core/OpenAPI.ts.j2", context) + files[src_core / "BaseHttpRequest.ts"] = self.template_engine.render_template( + "base/src/core/BaseHttpRequest.ts.j2", context + ) + files[src_core / "FetchHttpRequest.ts"] = self.template_engine.render_template( + "base/src/core/FetchHttpRequest.ts.j2", context + ) + files[src_core / "ApiError.ts"] = self.template_engine.render_template("base/src/core/ApiError.ts.j2", context) + files[src_core / "request.ts"] = self.template_engine.render_template("base/src/core/request.ts.j2", context) + files[src_core / "CancelablePromise.ts"] = self.template_engine.render_template( + "base/src/core/CancelablePromise.ts.j2", context + ) + files[src_core / "json.ts"] = self.template_engine.render_template("base/src/core/json.ts.j2", context) + files[src_core / "msgpack.ts"] = self.template_engine.render_template("base/src/core/msgpack.ts.j2", context) + + # Index barrel (runtime-only) + files[output_dir / "src" / "index.ts"] = self.template_engine.render_template("base/src/index.ts.j2", context) + + # Project files + files[output_dir / "package.json"] = self.template_engine.render_template("base/package.json.j2", context) + files[output_dir / "tsconfig.json"] = self.template_engine.render_template("base/tsconfig.json.j2", context) + files[output_dir / "README.md"] = self.template_engine.render_template("base/README.md.j2", context) + files[output_dir / ".prettierignore"] = self.template_engine.render_template("base/.prettierignore.j2", context) + + return files + + def _build_services_context(self, spec: dict[str, Any]) -> BuildContext: # noqa: C901, PLR0912, PLR0915 + """Build a per-tag mapping of operations for service generation. + + Returns (ops_by_tag, tags_set) + """ + paths = spec.get("paths", {}) + components = spec.get("components", {}) + schemas = components.get("schemas", {}) + model_names = {ts_pascal_case(name) for name in schemas} + builtin_types = {"Uint8Array", "void", "never", "string", "number", "bigint", "boolean"} + + ops_by_tag: dict[str, list[dict[str, Any]]] = {} + tags_set: set[str] = set() + synthetic_models: dict[str, Any] = {} + + token_re = re.compile(r"\b[A-Z][A-Za-z0-9_]*\b") + + def collect_model_types(type_str: str) -> set[str]: + found: set[str] = set() + for tok in token_re.findall(type_str or ""): + if tok in model_names and tok not in builtin_types: + found.add(tok) + return found + + for path, path_item in paths.items(): + if not isinstance(path_item, dict): + continue + for method, op in path_item.items(): + if method.lower() not in _HTTP_METHODS: + continue + if not isinstance(op, dict): + continue + operation_id = op.get("operationId") + if not operation_id: + # Fallback to verb + normalized path + operation_id = ts_camel_case(f"{method.lower()}_{path}") + + tags = op.get("tags", []) or ["default"] + parameters = op.get("parameters", []) + # Gather params from path level too + if isinstance(path_item.get("parameters"), list): + parameters = [*path_item.get("parameters", []), *parameters] + + # Prepare parameters + param_contexts: list[dict[str, Any]] = [] + # Track used variable names per operation to ensure uniqueness + used_var_names: set[str] = set() + reserved_words = { + "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", + } + for p in parameters: + param = p + if "$ref" in param: + # Resolve $ref + ref_path = param["$ref"].split("/")[1:] + node: Any = spec + for part in ref_path: + node = node.get(part, {}) + param = node + schema = param.get("schema", {}) or {} + t = ts_type(schema, schemas) + # BigInt params accept number | bigint + if schema.get("x-algokit-bigint") is True and t == "bigint": + t_sig = "number | bigint" + stringify_bigint = True + else: + t_sig = t + stringify_bigint = "bigint" in t_sig + + raw_name = str(param.get("name")) + base_var_name = ts_camel_case(raw_name) + # Avoid reserved words + if base_var_name in reserved_words: + base_var_name = f"{base_var_name}_" + var_name = base_var_name + # Ensure uniqueness by suffixing with numeric counter + if var_name in used_var_names: + i = 2 + while f"{base_var_name}{i}" in used_var_names: + i += 1 + var_name = f"{base_var_name}{i}" + used_var_names.add(var_name) + + param_contexts.append( + { + "name": raw_name, # original name used in path/query/header keys + "varName": var_name, # sanitized TS identifier for function signature + "in": param.get("in", "query"), + "required": param.get("required", False) or (param.get("in") == "path"), + "tsType": t_sig, + "description": param.get("description"), + "stringifyBigInt": stringify_bigint, + } + ) + + # Request body (pick json if present, else msgpack/text) + request_body_ctx: dict[str, Any] | None = None + rb = op.get("requestBody") + if isinstance(rb, dict): + content = rb.get("content", {}) + if "application/json" in content: + sch = (content["application/json"] or {}).get("schema", {}) + request_body_ctx = { + "mediaType": "application/json", + "tsType": ts_type(sch, schemas), + "required": rb.get("required", False), + } + elif "application/msgpack" in content: + request_body_ctx = { + "mediaType": "application/msgpack", + "tsType": "Uint8Array", + "required": rb.get("required", False), + } + elif "application/x-binary" in content or "application/octet-stream" in content: + # Raw binary transaction submission etc. + mt = "application/x-binary" if "application/x-binary" in content else "application/octet-stream" + request_body_ctx = { + "mediaType": mt, + "tsType": "Uint8Array", + "required": rb.get("required", False), + } + elif "text/plain" in content: + sch = (content["text/plain"] or {}).get("schema", {}) + request_body_ctx = { + "mediaType": "text/plain", + "tsType": ts_type(sch, schemas), + "required": rb.get("required", False), + } + + # Responses + responses = op.get("responses", {}) or {} + return_types: list[str] = [] + returns_msgpack = False + supports_json = False + for status, resp in responses.items(): + if not str(status).startswith("2"): + continue + content = (resp or {}).get("content", {}) + if "application/msgpack" in content: + returns_msgpack = True + # Prefer JSON schema for typing + if "application/json" in content: + supports_json = True + sch = (content["application/json"] or {}).get("schema", {}) + if sch: + # If inline object schema without $ref, synthesize a named model from operationId + if ( + isinstance(sch, dict) + and "$ref" not in sch + and ( + sch.get("type") == "object" or "properties" in sch or "additionalProperties" in sch + ) + ): + model_name = ts_pascal_case(operation_id) + if model_name not in model_names: + synthetic_models[model_name] = sch + model_names.add(model_name) + return_types.append(model_name) + else: + return_types.append(ts_type(sch, schemas)) + elif content: + # Fallback: take first content schema + first_ct = next(iter(content.values())) + sch = (first_ct or {}).get("schema", {}) + if sch: + return_types.append(ts_type(sch, schemas)) + + response_ts_type = "never" + if supports_json and return_types: + # Prefer JSON typing when available + uniq: list[str] = [] + for t in return_types: + if t not in uniq: + uniq.append(t) + response_ts_type = " | ".join(uniq) + elif returns_msgpack: + response_ts_type = "Uint8Array" + else: + response_ts_type = "void" + + # Build signature with required path params first, then params object and request options + path_params = [p for p in param_contexts if p.get("in") == "path"] + other_params = [p for p in param_contexts if p.get("in") in {"query", "header"}] + + # detect optional format param for content negotiation + has_format_param = False + format_var_name = None + for qp in other_params: + if qp.get("in") == "query" and qp.get("name") == "format": + has_format_param = True + format_var_name = qp.get("varName") + + sig_parts: list[str] = [f"{p['varName']}: {p['tsType']}" for p in path_params] + # params bag and request options + param_sigs: list[str] = [ + f"{p['varName']}{'' if p['required'] else '?'}: {p['tsType']}" for p in other_params + ] + if request_body_ctx: + body_required = bool((request_body_ctx or {}).get("required")) + body_type = str(request_body_ctx["tsType"]) + body_param_sig = f"body{'' if body_required else '?'}: {body_type}" + param_sigs.append(body_param_sig) + sig_parts.append("params?: { " + ", ".join(param_sigs) + " }") + sig_parts.append("requestOptions?: ApiRequestOptions") + + # Import types from embedded types + import_types: set[str] = set() + import_types |= collect_model_types(response_ts_type) + if request_body_ctx: + import_types |= collect_model_types(str(request_body_ctx.get("tsType") or "")) + # Also from parameter types (e.g., enums not needed as imports) + for p in param_contexts: + import_types |= collect_model_types(p.get("tsType") or "") + + op_ctx = { + "operationId": operation_id, + "method": method.upper(), + "path": path, + "parameters": param_contexts, + "pathParameters": path_params, + "otherParameters": other_params, + "requestBody": request_body_ctx, + "responseTsType": response_ts_type, + "acceptsMsgpack": returns_msgpack, + "returnsMsgpack": returns_msgpack, + "supportsJson": supports_json, + "hasFormatParam": has_format_param, + "formatVarName": format_var_name, + "signature": ", ".join(sig_parts), + "importTypes": sorted(import_types), + } + + for tag in tags: + tags_set.add(tag) + ops_by_tag.setdefault(tag, []).append(op_ctx) + + # Stable sort operations per tag by operationId + for _tag, ops in ops_by_tag.items(): + ops.sort(key=lambda o: o.get("operationId") or "") + + return ops_by_tag, tags_set, synthetic_models + + def generate_full( + self, + spec_path: Path, + output_dir: Path, + package_name: str, + *, + custom_description: str | None = None, + ) -> dict[Path, str]: + """Generate runtime + models + apis from a spec.""" + parser = OASParser() + parser.parse_file(spec_path) + + files = self.generate_runtime(output_dir, package_name, custom_description=custom_description) + + spec_dict: dict[str, Any] = parser.spec_data or {} + components = spec_dict.get("components", {}) + raw_schemas: dict[str, Any] = components.get("schemas", {}) + + # Build operations and synthetic models + ops_by_tag, tags_set, synthetic_models = self._build_services_context(spec_dict) + + # Merge component schemas with synthetic models + combined_schemas: dict[str, Any] = dict(raw_schemas) + for m_name, m_schema in synthetic_models.items(): + if m_name not in combined_schemas: + combined_schemas[m_name] = m_schema + + # Models + models_dir = Path(output_dir) / "src" / "models" + for name, schema in combined_schemas.items(): + content = self.template_engine.render_template( + "models/model.ts.j2", + {"schema_name": name, "schema": schema, "schemas": combined_schemas}, + ) + files[models_dir / f"{name.lower()}.ts"] = content + + # Models barrel + files[models_dir / "index.ts"] = self.template_engine.render_template( + "models/index.ts.j2", + {"schemas": combined_schemas}, + ) + + # Consolidated single service with all operations + apis_dir = Path(output_dir) / "src" / "apis" + all_ops: list[dict[str, Any]] = [] + seen_keys: set[tuple[str, str]] = set() + for tag in sorted(tags_set): + for op in ops_by_tag.get(tag, []): + key = (str(op.get("method")), str(op.get("path"))) + if key in seen_keys: + continue + seen_keys.add(key) + all_ops.append(op) + # Stable sort by operationId + all_ops.sort(key=lambda o: o.get("operationId") or "") + + # Aggregate imports + import_types: set[str] = set() + for op in all_ops: + for t in op.get("importTypes", []): + import_types.add(t) + + svc_content = self.template_engine.render_template( + "apis/service.ts.j2", + {"tag_name": "api", "operations": all_ops, "import_types": sorted(import_types)}, + ) + files[apis_dir / "api.service.ts"] = svc_content + + files[apis_dir / "index.ts"] = self.template_engine.render_template( + "apis/index.ts.j2", + {}, + ) + + # Client (single service) + files[Path(output_dir) / "src" / "client.ts"] = self.template_engine.render_template( + "client.ts.j2", + {}, + ) + + # Replace index with full barrel + files[Path(output_dir) / "src" / "index.ts"] = self.template_engine.render_template( + "full/src/index.ts.j2", + {}, + ) + + # Smoke tests (generated) + files[Path(output_dir) / "tests" / "generated" / "smoke.generated.spec.ts"] = ( + self.template_engine.render_template( + "full/tests/smoke.spec.ts.j2", + {}, + ) + ) + + return files diff --git a/api/oas_generator/ts_oas_generator/templates/apis/index.ts.j2 b/api/oas_generator/ts_oas_generator/templates/apis/index.ts.j2 new file mode 100644 index 000000000..0a3830c78 --- /dev/null +++ b/api/oas_generator/ts_oas_generator/templates/apis/index.ts.j2 @@ -0,0 +1,2 @@ +// Barrel file for services +export { ApiService } from './api.service'; diff --git a/api/oas_generator/ts_oas_generator/templates/apis/service.ts.j2 b/api/oas_generator/ts_oas_generator/templates/apis/service.ts.j2 new file mode 100644 index 000000000..adef08ed7 --- /dev/null +++ b/api/oas_generator/ts_oas_generator/templates/apis/service.ts.j2 @@ -0,0 +1,83 @@ +import type { BaseHttpRequest, ApiRequestOptions } from '../core/BaseHttpRequest'; +{% if import_types and import_types|length > 0 %} +import type { {{ import_types | sort | join(', ') }} } from '../models/index'; +{% endif %} + +export class ApiService { + constructor(public readonly httpRequest: BaseHttpRequest) {} + +{% for op in operations %} + {{ op.operationId | ts_camel_case }}( +{%- for p in op.pathParameters %} + {{ p.varName }}: {{ p.tsType }}, +{%- endfor %} +{%- if op.otherParameters|length > 0 or op.requestBody %} + params?: { +{%- for p in op.otherParameters %} + {{ p.varName }}{% if not p.required %}?{% endif %}: {{ p.tsType }}; +{%- endfor %} +{%- if op.requestBody %} + body{% if not op.requestBody.required %}?{% endif %}: {{ op.requestBody.tsType }}; +{%- endif %} + }, +{%- endif %} + requestOptions?: ApiRequestOptions + ): Promise<{{ op.responseTsType }}> { + const headers: Record = {}; +{% if op.acceptsMsgpack %} + // Content negotiation: + // - If explicit format=json, prefer JSON + // - Else if server supports JSON, prefer JSON by default + // - Else fall back to msgpack +{% if op.hasFormatParam and op.formatVarName %} + const hasExplicitJson = params?.{{ op.formatVarName }} === 'json'; + const prefersJson = hasExplicitJson || {{ 'true' if op.supportsJson else 'false' }}; + headers['Accept'] = prefersJson ? 'application/json' : 'application/msgpack'; +{% else %} + headers['Accept'] = {{ "'application/json'" if op.supportsJson else "'application/msgpack'" }}; +{% endif %} +{% else %} + headers['Accept'] = 'application/json'; +{% endif %} +{% if op.requestBody and op.requestBody.get('mediaType') %} + headers['Content-Type'] = '{{ op.requestBody['mediaType'] }}'; +{% endif %} + + // Header parameters +{% for p in op.otherParameters if p['in'] == 'header' %} + if (params?.{{ p.varName }} !== undefined) { + headers['{{ p.name }}'] = String(params.{{ p.varName }}); + } +{% endfor %} + + return 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 op.otherParameters if p['in'] == 'query' %} + '{{ 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 %} + }, + headers, + body: {% if op.requestBody %}params?.body{% else %}undefined{% endif %}, + mediaType: {% if op.requestBody %}'{{ op.requestBody['mediaType'] }}'{% else %}undefined{% endif %}, +{% if op.returnsMsgpack %} +{% if op.hasFormatParam and op.formatVarName %} + expectBinary: params?.{{ op.formatVarName }} === 'json' ? false : {{ 'false' if op.supportsJson else 'true' }}, +{% else %} + expectBinary: {{ 'false' if op.supportsJson else 'true' }}, +{% endif %} +{% else %} + expectBinary: false, +{% endif %} + ...(requestOptions ?? {}), + }); + } + +{% endfor %} +} diff --git a/api/oas_generator/ts_oas_generator/templates/base/.prettierignore.j2 b/api/oas_generator/ts_oas_generator/templates/base/.prettierignore.j2 new file mode 100644 index 000000000..99fea360b --- /dev/null +++ b/api/oas_generator/ts_oas_generator/templates/base/.prettierignore.j2 @@ -0,0 +1,3 @@ +# Ignore compiled output + +dist/ diff --git a/api/oas_generator/ts_oas_generator/templates/base/README.md.j2 b/api/oas_generator/ts_oas_generator/templates/base/README.md.j2 new file mode 100644 index 000000000..e9278b203 --- /dev/null +++ b/api/oas_generator/ts_oas_generator/templates/base/README.md.j2 @@ -0,0 +1,24 @@ +# {{ package_name }} + +{{ custom_description or 'TypeScript OpenAPI client runtime' }} + +## Usage + +Install dependencies and build: + +- bun install (or pnpm/yarn) +- bun run build + +### Configure base URL and issue requests + +```ts +import { OpenAPI, FetchHttpRequest } from './dist/index.js'; + +OpenAPI.BASE = 'http://localhost:4001'; + +const client = new FetchHttpRequest(OpenAPI); +// Example call once APIs are available in Phase 2: +// await client.request({ method: 'GET', url: '/health' }); +``` + +To inject a custom client, implement your own HttpRequest class extending `BaseHttpRequest` and use it where needed. diff --git a/api/oas_generator/ts_oas_generator/templates/base/package.json.j2 b/api/oas_generator/ts_oas_generator/templates/base/package.json.j2 new file mode 100644 index 000000000..9c6aedb1b --- /dev/null +++ b/api/oas_generator/ts_oas_generator/templates/base/package.json.j2 @@ -0,0 +1,24 @@ +{ + "name": "{{ package_name }}", + "version": "0.1.0", + "private": true, + "type": "module", + "description": {{ (custom_description or 'TypeScript OpenAPI client runtime') | tojson }}, + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "build": "tsc -p tsconfig.json", + "test": "vitest run" + }, + "dependencies": { + "json-bigint": "^1.0.0", + "algo-msgpack-with-bigint": "^2.1.1" + }, + "devDependencies": { + "typescript": "^5.5.0", + "@types/json-bigint": "^1.0.0", + "vitest": "^2.0.0", + "@types/node": "^20.0.0", + "algosdk": "^2.7.0" + } +} diff --git a/api/oas_generator/ts_oas_generator/templates/base/src/core/ApiError.ts.j2 b/api/oas_generator/ts_oas_generator/templates/base/src/core/ApiError.ts.j2 new file mode 100644 index 000000000..17a9213f8 --- /dev/null +++ b/api/oas_generator/ts_oas_generator/templates/base/src/core/ApiError.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/api/oas_generator/ts_oas_generator/templates/base/src/core/BaseHttpRequest.ts.j2 b/api/oas_generator/ts_oas_generator/templates/base/src/core/BaseHttpRequest.ts.j2 new file mode 100644 index 000000000..33781c051 --- /dev/null +++ b/api/oas_generator/ts_oas_generator/templates/base/src/core/BaseHttpRequest.ts.j2 @@ -0,0 +1,21 @@ +import type { OpenAPIConfig } from './OpenAPI'; + +export interface RequestOptions { + method: string; + url: string; + path?: Record; + query?: Record; + headers?: Record; + body?: any; + mediaType?: string; + responseHeader?: string; + expectBinary?: boolean; +} + +// Backwards/ergonomic alias used by generated services +export type ApiRequestOptions = RequestOptions; + +export abstract class BaseHttpRequest { + constructor(public readonly config: OpenAPIConfig) {} + abstract request(options: RequestOptions): Promise; +} diff --git a/api/oas_generator/ts_oas_generator/templates/base/src/core/CancelablePromise.ts.j2 b/api/oas_generator/ts_oas_generator/templates/base/src/core/CancelablePromise.ts.j2 new file mode 100644 index 000000000..fb1f35437 --- /dev/null +++ b/api/oas_generator/ts_oas_generator/templates/base/src/core/CancelablePromise.ts.j2 @@ -0,0 +1,49 @@ +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 _isCancelled = false; + private _cancelHandlers: Array<() => void> = []; + + constructor(executor: (resolve: (value: T | PromiseLike) => void, reject: (reason?: any) => void, onCancel: OnCancel) => void) { + const onCancel: OnCancel = (handler) => { + if (this._isCancelled) { + handler(); + } else { + this._cancelHandlers.push(handler); + } + }; + + this._promise = new Promise((resolve, reject) => executor(resolve, reject, onCancel)); + } + + private _promise: Promise; + + public cancel(): void { + if (!this._isCancelled) { + this._isCancelled = true; + for (const fn of this._cancelHandlers) fn(); + this._cancelHandlers.length = 0; + } + } + + then(onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null): Promise { + return this._promise.then(onfulfilled, onrejected); + } + + catch(onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): Promise { + return this._promise.catch(onrejected); + } + + finally(onfinally?: (() => void) | undefined | null): Promise { + return this._promise.finally(onfinally); + } +} diff --git a/api/oas_generator/ts_oas_generator/templates/base/src/core/FetchHttpRequest.ts.j2 b/api/oas_generator/ts_oas_generator/templates/base/src/core/FetchHttpRequest.ts.j2 new file mode 100644 index 000000000..d2b463ba3 --- /dev/null +++ b/api/oas_generator/ts_oas_generator/templates/base/src/core/FetchHttpRequest.ts.j2 @@ -0,0 +1,10 @@ +import { BaseHttpRequest, type RequestOptions } from './BaseHttpRequest'; +import { OpenAPI } from './OpenAPI'; +import { request as defaultRequest } from './request'; + +export class FetchHttpRequest extends BaseHttpRequest { + async request(options: RequestOptions): Promise { + const request = defaultRequest; + return request(this.config, options); + } +} diff --git a/api/oas_generator/ts_oas_generator/templates/base/src/core/OpenAPI.ts.j2 b/api/oas_generator/ts_oas_generator/templates/base/src/core/OpenAPI.ts.j2 new file mode 100644 index 000000000..97d63df9d --- /dev/null +++ b/api/oas_generator/ts_oas_generator/templates/base/src/core/OpenAPI.ts.j2 @@ -0,0 +1,22 @@ +/* + Minimal OpenAPI runtime config holder +*/ +export type BaseURL = string; + +export interface OpenAPIConfig { + BASE: BaseURL; + VERSION?: string; + WITH_CREDENTIALS?: boolean; + CREDENTIALS?: 'include' | 'omit' | 'same-origin'; + TOKEN?: string | (() => string | Promise); + USERNAME?: string; + PASSWORD?: string; + HEADERS?: Record | (() => Record | Promise>); + ENCODE_PATH?: (path: string) => string; + INT_DECODING?: 'safe' | 'unsafe' | 'mixed' | 'bigint'; +} + +export const OpenAPI: OpenAPIConfig = { + BASE: '', + INT_DECODING: 'mixed', +}; diff --git a/api/oas_generator/ts_oas_generator/templates/base/src/core/json.ts.j2 b/api/oas_generator/ts_oas_generator/templates/base/src/core/json.ts.j2 new file mode 100644 index 000000000..d68276975 --- /dev/null +++ b/api/oas_generator/ts_oas_generator/templates/base/src/core/json.ts.j2 @@ -0,0 +1,66 @@ +// Use require to avoid ESM/CJS interop issues in consumers +// eslint-disable-next-line @typescript-eslint/no-explicit-any +declare const require: any; +// eslint-disable-next-line @typescript-eslint/no-var-requires +const JSONBigFactory = require('json-bigint'); + +export type IntDecoding = 'safe' | 'unsafe' | 'mixed' | 'bigint'; + +// Instances +const JSONBigMixed = JSONBigFactory({ useNativeBigInt: true, alwaysParseAsBig: false }); +const JSONBigAllBig = JSONBigFactory({ useNativeBigInt: true, alwaysParseAsBig: true }); + +function traverseAndThrowOnBigInt(obj: any): void { // eslint-disable-line @typescript-eslint/no-explicit-any + if (obj === null || obj === undefined) return; + const t = typeof obj; + if (t === 'bigint') { + throw new Error('Integer exceeds safe range while INT_DECODING is "safe"'); + } + if (t !== 'object') return; + if (Array.isArray(obj)) { + for (const v of obj) traverseAndThrowOnBigInt(v); + } else { + for (const v of Object.values(obj)) traverseAndThrowOnBigInt(v); + } +} + +function convertLargeNumericStrings(obj: any): any { // eslint-disable-line @typescript-eslint/no-explicit-any + if (obj == null) return obj; + if (typeof obj === 'string') { + if (/^\d+$/.test(obj)) { + const asNum = Number(obj); + if (!Number.isSafeInteger(asNum)) return BigInt(obj); + } + return obj; + } + if (Array.isArray(obj)) return obj.map(convertLargeNumericStrings); + if (typeof obj === 'object') { + for (const k of Object.keys(obj)) obj[k] = convertLargeNumericStrings(obj[k]); + } + return obj; +} + +export function parseJson(text: string, intDecoding: IntDecoding = 'mixed'): any { // eslint-disable-line @typescript-eslint/no-explicit-any + switch (intDecoding) { + case 'unsafe': + return JSON.parse(text); + case 'bigint': { + const v = JSONBigAllBig.parse(text); + return convertLargeNumericStrings(v); + } + case 'safe': { + const value = JSONBigMixed.parse(text); + traverseAndThrowOnBigInt(value); + return value; + } + case 'mixed': + default: { + const v = JSONBigMixed.parse(text); + return convertLargeNumericStrings(v); + } + } +} + +export function stringifyJson(value: any): string { // eslint-disable-line @typescript-eslint/no-explicit-any + return JSON.stringify(value, (_k, v) => (typeof v === 'bigint' ? v.toString() : v)); +} diff --git a/api/oas_generator/ts_oas_generator/templates/base/src/core/msgpack.ts.j2 b/api/oas_generator/ts_oas_generator/templates/base/src/core/msgpack.ts.j2 new file mode 100644 index 000000000..92cd41b8c --- /dev/null +++ b/api/oas_generator/ts_oas_generator/templates/base/src/core/msgpack.ts.j2 @@ -0,0 +1,59 @@ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +declare const require: any; +// eslint-disable-next-line @typescript-eslint/no-var-requires +const { decode } = require('algo-msgpack-with-bigint'); + +import type { IntDecoding } from './json'; + +export function decodeMsgPack(buffer: Uint8Array): any { // eslint-disable-line @typescript-eslint/no-explicit-any + return decode(buffer); +} + +export function normalizeMsgPackIntegers(value: any, intDecoding: IntDecoding): any { // eslint-disable-line @typescript-eslint/no-explicit-any + switch (intDecoding) { + case 'bigint': + return value; + case 'unsafe': + return mapBigInts(value, (bi) => Number(bi)); + case 'safe': + // Throw if any bigint is not safely representable + traverse(value, (v) => { + if (typeof v === 'bigint' && !Number.isSafeInteger(Number(v))) { + throw new Error('Integer exceeds safe range while INT_DECODING is "safe"'); + } + }); + return mapBigInts(value, (bi) => Number(bi)); + case 'mixed': + default: + return mapBigInts(value, (bi) => { + const asNum = Number(bi); + return Number.isSafeInteger(asNum) ? asNum : bi; + }); + } +} + +function traverse(obj: any, fn: (v: any) => void): void { // eslint-disable-line @typescript-eslint/no-explicit-any + if (obj == null) return; + fn(obj); + if (Array.isArray(obj)) { + for (const v of obj) traverse(v, fn); + } else if (typeof obj === 'object') { + for (const v of Object.values(obj)) traverse(v, fn); + } +} + +function mapBigInts(obj: any, mapFn: (bi: bigint) => any): any { // eslint-disable-line @typescript-eslint/no-explicit-any + if (obj == null) return obj; + if (typeof obj === 'bigint') return mapFn(obj); + if (Array.isArray(obj)) return obj.map((v) => mapBigInts(v, mapFn)); + if (typeof obj === 'object') { + const out: any = Array.isArray(obj) ? [] : { ...obj }; // eslint-disable-line @typescript-eslint/no-explicit-any + for (const [k, v] of Object.entries(obj)) { + out[k] = mapBigInts(v, mapFn); + } + return out; + } + return obj; +} + + diff --git a/api/oas_generator/ts_oas_generator/templates/base/src/core/request.ts.j2 b/api/oas_generator/ts_oas_generator/templates/base/src/core/request.ts.j2 new file mode 100644 index 000000000..85b18aa98 --- /dev/null +++ b/api/oas_generator/ts_oas_generator/templates/base/src/core/request.ts.j2 @@ -0,0 +1,87 @@ +import type { OpenAPIConfig } from './OpenAPI'; +import { ApiError } from './ApiError'; +import { parseJson, stringifyJson } from './json'; +import { decodeMsgPack, normalizeMsgPackIntegers } from './msgpack'; + +const encodeURIPath = (path: string): string => encodeURI(path).replace(/%5B/g, '[').replace(/%5D/g, ']'); + +export async function request(config: OpenAPIConfig, options: { + method: string; + url: string; + path?: Record; + query?: Record; + headers?: Record; + body?: any; + mediaType?: string; + responseHeader?: string; + expectBinary?: boolean; +}): Promise { + // Replace path params before constructing URL to avoid encoded braces preventing replacement + 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.ENCODE_PATH ? config.ENCODE_PATH(raw) : encodeURIPath(raw); + rawPath = rawPath.replace(`{${key}}`, replace); + } + } + + const url = new URL(rawPath, config.BASE); + + // Query params + if (options.query) { + for (const [key, value] of Object.entries(options.query)) { + if (value === undefined || value === null) continue; + const v = typeof value === 'bigint' ? value.toString() : String(value); + url.searchParams.append(key, v); + } + } + + const headers: Record = { + ...(typeof config.HEADERS === 'function' ? await config.HEADERS() : config.HEADERS ?? {}), + ...(options.headers ?? {}), + }; + + // Auth: Bearer or Basic + 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}`)}`; + } + + const response = await fetch(url.toString(), { + method: options.method, + headers, + body: options.body != null ? (options.mediaType?.includes('json') ? stringifyJson(options.body) : options.body) : undefined, + credentials: config.CREDENTIALS, + }); + + if (!response.ok) { + let body: any = undefined; + try { + const ct = response.headers.get('content-type'); + if (ct && ct.includes('application/json')) body = parseJson(await response.text(), config.INT_DECODING); + else body = await response.text(); + } catch {} + throw new ApiError(url.toString(), response.status, body); + } + + if (options.responseHeader) { + const value = response.headers.get(options.responseHeader); + return value as unknown as T; + } + + // Parse by content-type first + const contentType = response.headers.get('content-type') || ''; + if (contentType.includes('application/msgpack') || contentType.includes('application/x-binary')) { + const buf = new Uint8Array(await response.arrayBuffer()); + const decoded = decodeMsgPack(buf); + return normalizeMsgPackIntegers(decoded, config.INT_DECODING ?? 'mixed') as T; + } + if (contentType.includes('application/json')) { + const text = await response.text(); + return parseJson(text, config.INT_DECODING) as T; + } + // Fallback to text + return (await response.text()) as unknown as T; +} diff --git a/api/oas_generator/ts_oas_generator/templates/base/src/index.ts.j2 b/api/oas_generator/ts_oas_generator/templates/base/src/index.ts.j2 new file mode 100644 index 000000000..78b47df1d --- /dev/null +++ b/api/oas_generator/ts_oas_generator/templates/base/src/index.ts.j2 @@ -0,0 +1,11 @@ +export * from './core/OpenAPI'; +export * from './core/BaseHttpRequest'; +export * from './core/FetchHttpRequest'; +export * from './core/ApiError'; +export * from './core/CancelablePromise'; +export * from './core/json'; + +// Generated +export * from './models'; +export * from './apis'; +export * from './client'; diff --git a/api/oas_generator/ts_oas_generator/templates/base/tsconfig.json.j2 b/api/oas_generator/ts_oas_generator/templates/base/tsconfig.json.j2 new file mode 100644 index 000000000..7a538edc0 --- /dev/null +++ b/api/oas_generator/ts_oas_generator/templates/base/tsconfig.json.j2 @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "ES2020", + "moduleResolution": "node", + "declaration": true, + "outDir": "dist", + "rootDir": "src", + "strict": true, + "skipLibCheck": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/api/oas_generator/ts_oas_generator/templates/client.ts.j2 b/api/oas_generator/ts_oas_generator/templates/client.ts.j2 new file mode 100644 index 000000000..c8efb1749 --- /dev/null +++ b/api/oas_generator/ts_oas_generator/templates/client.ts.j2 @@ -0,0 +1,13 @@ +import type { OpenAPIConfig } from './core/OpenAPI'; +import { FetchHttpRequest } from './core/FetchHttpRequest'; +import { ApiService } from './apis/api.service'; + +export class Client { + public readonly request: FetchHttpRequest; + public readonly api: ApiService; + + constructor(config: OpenAPIConfig) { + this.request = new FetchHttpRequest(config); + this.api = new ApiService(this.request); + } +} diff --git a/api/oas_generator/ts_oas_generator/templates/full/src/index.ts.j2 b/api/oas_generator/ts_oas_generator/templates/full/src/index.ts.j2 new file mode 100644 index 000000000..2803e335f --- /dev/null +++ b/api/oas_generator/ts_oas_generator/templates/full/src/index.ts.j2 @@ -0,0 +1,10 @@ +export * from './core/OpenAPI'; +export * from './core/BaseHttpRequest'; +export * from './core/FetchHttpRequest'; +export * from './core/ApiError'; +export * from './core/CancelablePromise'; +export * from './core/json'; + +export * from './models'; +export * from './apis'; +export * from './client'; diff --git a/api/oas_generator/ts_oas_generator/templates/full/tests/smoke.spec.ts.j2 b/api/oas_generator/ts_oas_generator/templates/full/tests/smoke.spec.ts.j2 new file mode 100644 index 000000000..751751a8a --- /dev/null +++ b/api/oas_generator/ts_oas_generator/templates/full/tests/smoke.spec.ts.j2 @@ -0,0 +1,49 @@ +/* AUTO-GENERATED FILE - DO NOT EDIT DIRECTLY. + * This smoke test is generated by ts_oas_generator. + * Location: tests/generated/smoke.generated.spec.ts + */ +import { describe, expect, it } from 'vitest'; +import { Client } from '../src/client'; + +const BASE = 'http://localhost/'; + +declare global { + // eslint-disable-next-line no-var, vars-on-top + var fetch: any; +} + +describe('JSON BigInt parsing', () => { + it('parses bigint values using json-bigint', async () => { + const big = '18446744073709551615'; // > Number.MAX_SAFE_INTEGER + global.fetch = async () => ({ + ok: true, + headers: new Map([['content-type', 'application/json']]), + text: async () => JSON.stringify({ value: big }), + arrayBuffer: async () => new ArrayBuffer(0), + }); + + const client = new Client({ BASE }); + // Directly use request core to keep template-agnostic + const res = await client.request.request<{ value: bigint }>({ method: 'GET', url: '/foo' }); + expect(typeof res.value).toBe('bigint'); + }); +}); + +describe('Msgpack binary response', () => { + it('decodes msgpack into structured data', async () => { + // eslint-disable-next-line @typescript-eslint/no-var-requires + const { encode } = require('algo-msgpack-with-bigint'); + const msg = { ok: 1n, small: 2 }; + const bytes: Uint8Array = encode(msg); + global.fetch = async () => ({ + ok: true, + headers: new Map([['content-type', 'application/msgpack']]), + text: async () => '', + arrayBuffer: async () => bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength), + }); + + const client = new Client({ BASE }); + const res = await client.request.request<{ ok: bigint | number; small: number }>({ method: 'GET', url: '/foo', expectBinary: true }); + expect(res).toHaveProperty('ok'); + }); +}); diff --git a/api/oas_generator/ts_oas_generator/templates/models/index.ts.j2 b/api/oas_generator/ts_oas_generator/templates/models/index.ts.j2 new file mode 100644 index 000000000..0d7569af1 --- /dev/null +++ b/api/oas_generator/ts_oas_generator/templates/models/index.ts.j2 @@ -0,0 +1,4 @@ +// Barrel file for models +{% for name, _ in schemas.items() %} +export type { {{ name | ts_pascal_case }} } from './{{ name | lower }}'; +{% endfor %} diff --git a/api/oas_generator/ts_oas_generator/templates/models/model.ts.j2 b/api/oas_generator/ts_oas_generator/templates/models/model.ts.j2 new file mode 100644 index 000000000..1881449af --- /dev/null +++ b/api/oas_generator/ts_oas_generator/templates/models/model.ts.j2 @@ -0,0 +1,22 @@ +{% set refTypes = schema | collect_schema_refs(schema_name) %} +{% if refTypes and refTypes|length > 0 %} +import type { {{ refTypes | join(', ') }} } from './index'; + +{% endif %} +{{ schema.description | ts_doc_comment }} +{% set modelName = schema_name | ts_pascal_case %} +{% set isObject = schema.get('type') == 'object' or ('properties' in schema) %} +{% 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 prop_name, prop_schema in (schema.get('properties') or {}).items() %} + {{ prop_name | ts_property_name }}{{ '' if (schema.get('required') or []) | list | select('equalto', prop_name) | list | length > 0 else '?' }}: {{ prop_schema | ts_type(schemas) }}; +{% endfor %} +{% if schema.get('additionalProperties') is sameas true %} + [key: string]: any; +{% elif schema.get('additionalProperties') %} + [key: string]: {{ schema.get('additionalProperties') | ts_type(schemas) }}; +{% endif %} +} +{% else %} +export type {{ modelName }} = {{ schema | ts_type(schemas) }}; +{% endif %} diff --git a/api/oas_generator/ts_oas_generator/utils/__init__.py b/api/oas_generator/ts_oas_generator/utils/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/api/oas_generator/ts_oas_generator/utils/file_utils.py b/api/oas_generator/ts_oas_generator/utils/file_utils.py new file mode 100644 index 000000000..b67f85fb6 --- /dev/null +++ b/api/oas_generator/ts_oas_generator/utils/file_utils.py @@ -0,0 +1,19 @@ +""" +File utilities for the TS OAS generator (Phase 1). + +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/packages/typescript/algod_client/.prettierignore b/packages/typescript/algod_client/.prettierignore new file mode 100644 index 000000000..454dee356 --- /dev/null +++ b/packages/typescript/algod_client/.prettierignore @@ -0,0 +1,3 @@ +# Ignore compiled output + +dist/ \ No newline at end of file diff --git a/packages/typescript/algod_client/README.md b/packages/typescript/algod_client/README.md new file mode 100644 index 000000000..990b6a9da --- /dev/null +++ b/packages/typescript/algod_client/README.md @@ -0,0 +1,24 @@ +# algod_client + +TypeScript client for algod interaction. + +## Usage + +Install dependencies and build: + +- bun install (or pnpm/yarn) +- bun run build + +### Configure base URL and issue requests + +```ts +import { OpenAPI, FetchHttpRequest } from "./dist/index.js"; + +OpenAPI.BASE = "http://localhost:4001"; + +const client = new FetchHttpRequest(OpenAPI); +// Example call once APIs are available in Phase 2: +// await client.request({ method: 'GET', url: '/health' }); +``` + +To inject a custom client, implement your own HttpRequest class extending `BaseHttpRequest` and use it where needed. diff --git a/packages/typescript/algod_client/package.json b/packages/typescript/algod_client/package.json new file mode 100644 index 000000000..d239f4357 --- /dev/null +++ b/packages/typescript/algod_client/package.json @@ -0,0 +1,24 @@ +{ + "name": "algod_client", + "version": "0.1.0", + "private": true, + "type": "module", + "description": "TypeScript client for algod interaction.", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "build": "tsc -p tsconfig.json", + "test": "vitest run" + }, + "dependencies": { + "json-bigint": "^1.0.0", + "algo-msgpack-with-bigint": "^2.1.1" + }, + "devDependencies": { + "typescript": "^5.5.0", + "@types/json-bigint": "^1.0.0", + "vitest": "^2.0.0", + "@types/node": "^20.0.0", + "algosdk": "^2.7.0" + } +} diff --git a/packages/typescript/algod_client/src/apis/api.service.ts b/packages/typescript/algod_client/src/apis/api.service.ts new file mode 100644 index 000000000..0d43b44f4 --- /dev/null +++ b/packages/typescript/algod_client/src/apis/api.service.ts @@ -0,0 +1,1232 @@ +import type { BaseHttpRequest, ApiRequestOptions } from "../core/BaseHttpRequest"; +import type { + AbortCatchup, + Account, + AccountApplicationInformation, + AccountAssetInformation, + AccountAssetsInformation, + AddParticipationKey, + Application, + Asset, + Box, + DebugSettingsProf, + DryrunRequest, + Genesis, + GetApplicationBoxes, + GetBlock, + GetBlockHash, + GetBlockLogs, + GetBlockTimeStampOffset, + GetBlockTxids, + GetPendingTransactions, + GetPendingTransactionsByAddress, + GetStatus, + GetSupply, + GetSyncRound, + GetTransactionGroupLedgerStateDeltasForRound, + LedgerStateDelta, + LightBlockHeaderProof, + ParticipationKey, + PendingTransactionResponse, + RawTransaction, + ShutdownNode, + SimulateRequest, + SimulateTransaction, + StartCatchup, + StateProof, + TealCompile, + TealDisassemble, + TealDryrun, + TransactionParams, + TransactionProof, + Version, + WaitForBlock, +} from "../models/index"; + +export class ApiService { + constructor(public readonly httpRequest: BaseHttpRequest) {} + + abortCatchup(catchpoint: string, requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "DELETE", + url: "/v2/catchup/{catchpoint}", + path: { catchpoint: catchpoint }, + query: {}, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + accountApplicationInformation( + address: string, + applicationId: number, + params?: { format?: "json" | "msgpack" }, + requestOptions?: ApiRequestOptions, + ): Promise { + const headers: Record = {}; + // Content negotiation: + // - If explicit format=json, prefer JSON + // - Else if server supports JSON, prefer JSON by default + // - Else fall back to msgpack + const hasExplicitJson = params?.format === "json"; + const prefersJson = hasExplicitJson || true; + headers["Accept"] = prefersJson ? "application/json" : "application/msgpack"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/accounts/{address}/applications/{application-id}", + path: { address: address, "application-id": applicationId }, + query: { format: params?.format }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: params?.format === "json" ? false : false, + ...(requestOptions ?? {}), + }); + } + + accountAssetInformation( + address: string, + assetId: number, + params?: { format?: "json" | "msgpack" }, + requestOptions?: ApiRequestOptions, + ): Promise { + const headers: Record = {}; + // Content negotiation: + // - If explicit format=json, prefer JSON + // - Else if server supports JSON, prefer JSON by default + // - Else fall back to msgpack + const hasExplicitJson = params?.format === "json"; + const prefersJson = hasExplicitJson || true; + headers["Accept"] = prefersJson ? "application/json" : "application/msgpack"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/accounts/{address}/assets/{asset-id}", + path: { address: address, "asset-id": assetId }, + query: { format: params?.format }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: params?.format === "json" ? false : false, + ...(requestOptions ?? {}), + }); + } + + accountAssetsInformation( + address: string, + params?: { limit?: number | bigint; next?: string }, + requestOptions?: ApiRequestOptions, + ): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + 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 }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + accountInformation( + address: string, + params?: { exclude?: "all" | "none"; format?: "json" | "msgpack" }, + requestOptions?: ApiRequestOptions, + ): Promise { + const headers: Record = {}; + // Content negotiation: + // - If explicit format=json, prefer JSON + // - Else if server supports JSON, prefer JSON by default + // - Else fall back to msgpack + const hasExplicitJson = params?.format === "json"; + const prefersJson = hasExplicitJson || true; + headers["Accept"] = prefersJson ? "application/json" : "application/msgpack"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/accounts/{address}", + path: { address: address }, + query: { exclude: params?.exclude, format: params?.format }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: params?.format === "json" ? false : false, + ...(requestOptions ?? {}), + }); + } + + addParticipationKey(params?: { body: Uint8Array }, requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + headers["Content-Type"] = "application/msgpack"; + + // Header parameters + + return this.httpRequest.request({ + method: "POST", + url: "/v2/participation", + path: {}, + query: {}, + headers, + body: params?.body, + mediaType: "application/msgpack", + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + appendKeys(participationId: string, params?: { body: Uint8Array }, requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + headers["Content-Type"] = "application/msgpack"; + + // Header parameters + + return this.httpRequest.request({ + method: "POST", + url: "/v2/participation/{participation-id}", + path: { "participation-id": participationId }, + query: {}, + headers, + body: params?.body, + mediaType: "application/msgpack", + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + deleteParticipationKeyById(participationId: string, requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "DELETE", + url: "/v2/participation/{participation-id}", + path: { "participation-id": participationId }, + query: {}, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + experimentalCheck(requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/experimental", + path: {}, + query: {}, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + generateParticipationKeys( + address: string, + params?: { dilution?: number | bigint; first: number | bigint; last: number | bigint }, + requestOptions?: ApiRequestOptions, + ): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return 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, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + getApplicationBoxByName(applicationId: number, params?: { name: string }, requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/applications/{application-id}/box", + path: { "application-id": applicationId }, + query: { name: params?.name }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + getApplicationBoxes( + applicationId: number, + params?: { max?: number | bigint }, + requestOptions?: ApiRequestOptions, + ): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/applications/{application-id}/boxes", + path: { "application-id": applicationId }, + query: { max: typeof params?.max === "bigint" ? (params!.max as bigint).toString() : params?.max }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + getApplicationById(applicationId: number, requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/applications/{application-id}", + path: { "application-id": applicationId }, + query: {}, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + getAssetById(assetId: number, requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/assets/{asset-id}", + path: { "asset-id": assetId }, + query: {}, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + getBlock( + round: number, + params?: { headerOnly?: boolean; format?: "json" | "msgpack" }, + requestOptions?: ApiRequestOptions, + ): Promise { + const headers: Record = {}; + // Content negotiation: + // - If explicit format=json, prefer JSON + // - Else if server supports JSON, prefer JSON by default + // - Else fall back to msgpack + const hasExplicitJson = params?.format === "json"; + const prefersJson = hasExplicitJson || true; + headers["Accept"] = prefersJson ? "application/json" : "application/msgpack"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/blocks/{round}", + path: { round: round }, + query: { "header-only": params?.headerOnly, format: params?.format }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: params?.format === "json" ? false : false, + ...(requestOptions ?? {}), + }); + } + + getBlockHash(round: number, requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/blocks/{round}/hash", + path: { round: round }, + query: {}, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + getBlockLogs(round: number, requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/blocks/{round}/logs", + path: { round: round }, + query: {}, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + getBlockTimeStampOffset(requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/devmode/blocks/offset", + path: {}, + query: {}, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + getBlockTxids(round: number, requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/blocks/{round}/txids", + path: { round: round }, + query: {}, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + getConfig(requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/debug/settings/config", + path: {}, + query: {}, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + getDebugSettingsProf(requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/debug/settings/pprof", + path: {}, + query: {}, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + getGenesis(requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/genesis", + path: {}, + query: {}, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + getLedgerStateDelta( + round: number, + params?: { format?: "json" | "msgpack" }, + requestOptions?: ApiRequestOptions, + ): Promise { + const headers: Record = {}; + // Content negotiation: + // - If explicit format=json, prefer JSON + // - Else if server supports JSON, prefer JSON by default + // - Else fall back to msgpack + const hasExplicitJson = params?.format === "json"; + const prefersJson = hasExplicitJson || true; + headers["Accept"] = prefersJson ? "application/json" : "application/msgpack"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/deltas/{round}", + path: { round: round }, + query: { format: params?.format }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: params?.format === "json" ? false : false, + ...(requestOptions ?? {}), + }); + } + + getLedgerStateDeltaForTransactionGroup( + id: string, + params?: { format?: "json" | "msgpack" }, + requestOptions?: ApiRequestOptions, + ): Promise { + const headers: Record = {}; + // Content negotiation: + // - If explicit format=json, prefer JSON + // - Else if server supports JSON, prefer JSON by default + // - Else fall back to msgpack + const hasExplicitJson = params?.format === "json"; + const prefersJson = hasExplicitJson || true; + headers["Accept"] = prefersJson ? "application/json" : "application/msgpack"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/deltas/txn/group/{id}", + path: { id: id }, + query: { format: params?.format }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: params?.format === "json" ? false : false, + ...(requestOptions ?? {}), + }); + } + + getLightBlockHeaderProof(round: number, requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/blocks/{round}/lightheader/proof", + path: { round: round }, + query: {}, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + getParticipationKeyById(participationId: string, requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/participation/{participation-id}", + path: { "participation-id": participationId }, + query: {}, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + getParticipationKeys(requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/participation", + path: {}, + query: {}, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + getPendingTransactions( + params?: { max?: number | bigint; format?: "json" | "msgpack" }, + requestOptions?: ApiRequestOptions, + ): Promise { + const headers: Record = {}; + // Content negotiation: + // - If explicit format=json, prefer JSON + // - Else if server supports JSON, prefer JSON by default + // - Else fall back to msgpack + const hasExplicitJson = params?.format === "json"; + const prefersJson = hasExplicitJson || true; + headers["Accept"] = prefersJson ? "application/json" : "application/msgpack"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/transactions/pending", + path: {}, + query: { max: typeof params?.max === "bigint" ? (params!.max as bigint).toString() : params?.max, format: params?.format }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: params?.format === "json" ? false : false, + ...(requestOptions ?? {}), + }); + } + + getPendingTransactionsByAddress( + address: string, + params?: { max?: number | bigint; format?: "json" | "msgpack" }, + requestOptions?: ApiRequestOptions, + ): Promise { + const headers: Record = {}; + // Content negotiation: + // - If explicit format=json, prefer JSON + // - Else if server supports JSON, prefer JSON by default + // - Else fall back to msgpack + const hasExplicitJson = params?.format === "json"; + const prefersJson = hasExplicitJson || true; + headers["Accept"] = prefersJson ? "application/json" : "application/msgpack"; + + // Header parameters + + return this.httpRequest.request({ + 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: params?.format }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: params?.format === "json" ? false : false, + ...(requestOptions ?? {}), + }); + } + + getReady(requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/ready", + path: {}, + query: {}, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + getStateProof(round: number, requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/stateproofs/{round}", + path: { round: round }, + query: {}, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + getStatus(requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/status", + path: {}, + query: {}, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + getSupply(requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/ledger/supply", + path: {}, + query: {}, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + getSyncRound(requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/ledger/sync", + path: {}, + query: {}, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + getTransactionGroupLedgerStateDeltasForRound( + round: number, + params?: { format?: "json" | "msgpack" }, + requestOptions?: ApiRequestOptions, + ): Promise { + const headers: Record = {}; + // Content negotiation: + // - If explicit format=json, prefer JSON + // - Else if server supports JSON, prefer JSON by default + // - Else fall back to msgpack + const hasExplicitJson = params?.format === "json"; + const prefersJson = hasExplicitJson || true; + headers["Accept"] = prefersJson ? "application/json" : "application/msgpack"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/deltas/{round}/txn/group", + path: { round: round }, + query: { format: params?.format }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: params?.format === "json" ? false : false, + ...(requestOptions ?? {}), + }); + } + + getTransactionProof( + round: number, + txid: string, + params?: { hashtype?: "sha512_256" | "sha256"; format?: "json" | "msgpack" }, + requestOptions?: ApiRequestOptions, + ): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/blocks/{round}/transactions/{txid}/proof", + path: { round: round, txid: txid }, + query: { hashtype: params?.hashtype, format: params?.format }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + getVersion(requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/versions", + path: {}, + query: {}, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + healthCheck(requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/health", + path: {}, + query: {}, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + metrics(requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/metrics", + path: {}, + query: {}, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + pendingTransactionInformation( + txid: string, + params?: { format?: "json" | "msgpack" }, + requestOptions?: ApiRequestOptions, + ): Promise { + const headers: Record = {}; + // Content negotiation: + // - If explicit format=json, prefer JSON + // - Else if server supports JSON, prefer JSON by default + // - Else fall back to msgpack + const hasExplicitJson = params?.format === "json"; + const prefersJson = hasExplicitJson || true; + headers["Accept"] = prefersJson ? "application/json" : "application/msgpack"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/transactions/pending/{txid}", + path: { txid: txid }, + query: { format: params?.format }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: params?.format === "json" ? false : false, + ...(requestOptions ?? {}), + }); + } + + putDebugSettingsProf(requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "PUT", + url: "/debug/settings/pprof", + path: {}, + query: {}, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + rawTransaction(params?: { body: Uint8Array }, requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + headers["Content-Type"] = "application/x-binary"; + + // Header parameters + + return this.httpRequest.request({ + method: "POST", + url: "/v2/transactions", + path: {}, + query: {}, + headers, + body: params?.body, + mediaType: "application/x-binary", + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + rawTransactionAsync(params?: { body: Uint8Array }, requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + headers["Content-Type"] = "application/x-binary"; + + // Header parameters + + return this.httpRequest.request({ + method: "POST", + url: "/v2/transactions/async", + path: {}, + query: {}, + headers, + body: params?.body, + mediaType: "application/x-binary", + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + setBlockTimeStampOffset(offset: number | bigint, requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "POST", + url: "/v2/devmode/blocks/offset/{offset}", + path: { offset: typeof offset === "bigint" ? offset.toString() : offset }, + query: {}, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + setSyncRound(round: number, requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "POST", + url: "/v2/ledger/sync/{round}", + path: { round: round }, + query: {}, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + shutdownNode(params?: { timeout?: number }, requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "POST", + url: "/v2/shutdown", + path: {}, + query: { timeout: params?.timeout }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + simulateTransaction( + params?: { format?: "json" | "msgpack"; body: SimulateRequest }, + requestOptions?: ApiRequestOptions, + ): Promise { + const headers: Record = {}; + // Content negotiation: + // - If explicit format=json, prefer JSON + // - Else if server supports JSON, prefer JSON by default + // - Else fall back to msgpack + const hasExplicitJson = params?.format === "json"; + const prefersJson = hasExplicitJson || true; + headers["Accept"] = prefersJson ? "application/json" : "application/msgpack"; + headers["Content-Type"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "POST", + url: "/v2/transactions/simulate", + path: {}, + query: { format: params?.format }, + headers, + body: params?.body, + mediaType: "application/json", + expectBinary: params?.format === "json" ? false : false, + ...(requestOptions ?? {}), + }); + } + + startCatchup(catchpoint: string, params?: { min?: number }, requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "POST", + url: "/v2/catchup/{catchpoint}", + path: { catchpoint: catchpoint }, + query: { min: params?.min }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + swaggerJson(requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/swagger.json", + path: {}, + query: {}, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + tealCompile(params?: { sourcemap?: boolean; body: string }, requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + headers["Content-Type"] = "text/plain"; + + // Header parameters + + return this.httpRequest.request({ + method: "POST", + url: "/v2/teal/compile", + path: {}, + query: { sourcemap: params?.sourcemap }, + headers, + body: params?.body, + mediaType: "text/plain", + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + tealDisassemble(params?: { body: Uint8Array }, requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + headers["Content-Type"] = "application/x-binary"; + + // Header parameters + + return this.httpRequest.request({ + method: "POST", + url: "/v2/teal/disassemble", + path: {}, + query: {}, + headers, + body: params?.body, + mediaType: "application/x-binary", + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + tealDryrun(params?: { body?: DryrunRequest }, requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + headers["Content-Type"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "POST", + url: "/v2/teal/dryrun", + path: {}, + query: {}, + headers, + body: params?.body, + mediaType: "application/json", + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + transactionParams(requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/transactions/params", + path: {}, + query: {}, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + unsetSyncRound(requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "DELETE", + url: "/v2/ledger/sync", + path: {}, + query: {}, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + waitForBlock(round: number, requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/status/wait-for-block-after/{round}", + path: { round: round }, + query: {}, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } +} diff --git a/packages/typescript/algod_client/src/apis/index.ts b/packages/typescript/algod_client/src/apis/index.ts new file mode 100644 index 000000000..c8244b99b --- /dev/null +++ b/packages/typescript/algod_client/src/apis/index.ts @@ -0,0 +1,2 @@ +// Barrel file for services +export { ApiService } from "./api.service"; diff --git a/packages/typescript/algod_client/src/client.ts b/packages/typescript/algod_client/src/client.ts new file mode 100644 index 000000000..310bdaba7 --- /dev/null +++ b/packages/typescript/algod_client/src/client.ts @@ -0,0 +1,13 @@ +import type { OpenAPIConfig } from "./core/OpenAPI"; +import { FetchHttpRequest } from "./core/FetchHttpRequest"; +import { ApiService } from "./apis/api.service"; + +export class Client { + public readonly request: FetchHttpRequest; + public readonly api: ApiService; + + constructor(config: OpenAPIConfig) { + this.request = new FetchHttpRequest(config); + this.api = new ApiService(this.request); + } +} diff --git a/packages/typescript/algod_client/src/core/ApiError.ts b/packages/typescript/algod_client/src/core/ApiError.ts new file mode 100644 index 000000000..17a9213f8 --- /dev/null +++ b/packages/typescript/algod_client/src/core/ApiError.ts @@ -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/packages/typescript/algod_client/src/core/BaseHttpRequest.ts b/packages/typescript/algod_client/src/core/BaseHttpRequest.ts new file mode 100644 index 000000000..85cf8d865 --- /dev/null +++ b/packages/typescript/algod_client/src/core/BaseHttpRequest.ts @@ -0,0 +1,21 @@ +import type { OpenAPIConfig } from "./OpenAPI"; + +export interface RequestOptions { + method: string; + url: string; + path?: Record; + query?: Record; + headers?: Record; + body?: any; + mediaType?: string; + responseHeader?: string; + expectBinary?: boolean; +} + +// Backwards/ergonomic alias used by generated services +export type ApiRequestOptions = RequestOptions; + +export abstract class BaseHttpRequest { + constructor(public readonly config: OpenAPIConfig) {} + abstract request(options: RequestOptions): Promise; +} diff --git a/packages/typescript/algod_client/src/core/CancelablePromise.ts b/packages/typescript/algod_client/src/core/CancelablePromise.ts new file mode 100644 index 000000000..3cb118cb6 --- /dev/null +++ b/packages/typescript/algod_client/src/core/CancelablePromise.ts @@ -0,0 +1,52 @@ +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 _isCancelled = false; + private _cancelHandlers: Array<() => void> = []; + + constructor(executor: (resolve: (value: T | PromiseLike) => void, reject: (reason?: any) => void, onCancel: OnCancel) => void) { + const onCancel: OnCancel = (handler) => { + if (this._isCancelled) { + handler(); + } else { + this._cancelHandlers.push(handler); + } + }; + + this._promise = new Promise((resolve, reject) => executor(resolve, reject, onCancel)); + } + + private _promise: Promise; + + public cancel(): void { + if (!this._isCancelled) { + this._isCancelled = true; + for (const fn of this._cancelHandlers) fn(); + this._cancelHandlers.length = 0; + } + } + + then( + onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, + onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null, + ): Promise { + return this._promise.then(onfulfilled, onrejected); + } + + catch(onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): Promise { + return this._promise.catch(onrejected); + } + + finally(onfinally?: (() => void) | undefined | null): Promise { + return this._promise.finally(onfinally); + } +} diff --git a/packages/typescript/algod_client/src/core/FetchHttpRequest.ts b/packages/typescript/algod_client/src/core/FetchHttpRequest.ts new file mode 100644 index 000000000..b47684434 --- /dev/null +++ b/packages/typescript/algod_client/src/core/FetchHttpRequest.ts @@ -0,0 +1,10 @@ +import { BaseHttpRequest, type RequestOptions } from "./BaseHttpRequest"; +import { OpenAPI } from "./OpenAPI"; +import { request as defaultRequest } from "./request"; + +export class FetchHttpRequest extends BaseHttpRequest { + async request(options: RequestOptions): Promise { + const request = defaultRequest; + return request(this.config, options); + } +} diff --git a/packages/typescript/algod_client/src/core/OpenAPI.ts b/packages/typescript/algod_client/src/core/OpenAPI.ts new file mode 100644 index 000000000..fde885a4d --- /dev/null +++ b/packages/typescript/algod_client/src/core/OpenAPI.ts @@ -0,0 +1,22 @@ +/* + Minimal OpenAPI runtime config holder +*/ +export type BaseURL = string; + +export interface OpenAPIConfig { + BASE: BaseURL; + VERSION?: string; + WITH_CREDENTIALS?: boolean; + CREDENTIALS?: "include" | "omit" | "same-origin"; + TOKEN?: string | (() => string | Promise); + USERNAME?: string; + PASSWORD?: string; + HEADERS?: Record | (() => Record | Promise>); + ENCODE_PATH?: (path: string) => string; + INT_DECODING?: "safe" | "unsafe" | "mixed" | "bigint"; +} + +export const OpenAPI: OpenAPIConfig = { + BASE: "", + INT_DECODING: "mixed", +}; diff --git a/packages/typescript/algod_client/src/core/json.ts b/packages/typescript/algod_client/src/core/json.ts new file mode 100644 index 000000000..3845c5abb --- /dev/null +++ b/packages/typescript/algod_client/src/core/json.ts @@ -0,0 +1,70 @@ +// Use require to avoid ESM/CJS interop issues in consumers +// eslint-disable-next-line @typescript-eslint/no-explicit-any +declare const require: any; +// eslint-disable-next-line @typescript-eslint/no-var-requires +const JSONBigFactory = require("json-bigint"); + +export type IntDecoding = "safe" | "unsafe" | "mixed" | "bigint"; + +// Instances +const JSONBigMixed = JSONBigFactory({ useNativeBigInt: true, alwaysParseAsBig: false }); +const JSONBigAllBig = JSONBigFactory({ useNativeBigInt: true, alwaysParseAsBig: true }); + +function traverseAndThrowOnBigInt(obj: any): void { + // eslint-disable-line @typescript-eslint/no-explicit-any + if (obj === null || obj === undefined) return; + const t = typeof obj; + if (t === "bigint") { + throw new Error('Integer exceeds safe range while INT_DECODING is "safe"'); + } + if (t !== "object") return; + if (Array.isArray(obj)) { + for (const v of obj) traverseAndThrowOnBigInt(v); + } else { + for (const v of Object.values(obj)) traverseAndThrowOnBigInt(v); + } +} + +function convertLargeNumericStrings(obj: any): any { + // eslint-disable-line @typescript-eslint/no-explicit-any + if (obj == null) return obj; + if (typeof obj === "string") { + if (/^\d+$/.test(obj)) { + const asNum = Number(obj); + if (!Number.isSafeInteger(asNum)) return BigInt(obj); + } + return obj; + } + if (Array.isArray(obj)) return obj.map(convertLargeNumericStrings); + if (typeof obj === "object") { + for (const k of Object.keys(obj)) obj[k] = convertLargeNumericStrings(obj[k]); + } + return obj; +} + +export function parseJson(text: string, intDecoding: IntDecoding = "mixed"): any { + // eslint-disable-line @typescript-eslint/no-explicit-any + switch (intDecoding) { + case "unsafe": + return JSON.parse(text); + case "bigint": { + const v = JSONBigAllBig.parse(text); + return convertLargeNumericStrings(v); + } + case "safe": { + const value = JSONBigMixed.parse(text); + traverseAndThrowOnBigInt(value); + return value; + } + case "mixed": + default: { + const v = JSONBigMixed.parse(text); + return convertLargeNumericStrings(v); + } + } +} + +export function stringifyJson(value: any): string { + // eslint-disable-line @typescript-eslint/no-explicit-any + return JSON.stringify(value, (_k, v) => (typeof v === "bigint" ? v.toString() : v)); +} diff --git a/packages/typescript/algod_client/src/core/msgpack.ts b/packages/typescript/algod_client/src/core/msgpack.ts new file mode 100644 index 000000000..1d2a5aa2f --- /dev/null +++ b/packages/typescript/algod_client/src/core/msgpack.ts @@ -0,0 +1,61 @@ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +declare const require: any; +// eslint-disable-next-line @typescript-eslint/no-var-requires +const { decode } = require("algo-msgpack-with-bigint"); + +import type { IntDecoding } from "./json"; + +export function decodeMsgPack(buffer: Uint8Array): any { + // eslint-disable-line @typescript-eslint/no-explicit-any + return decode(buffer); +} + +export function normalizeMsgPackIntegers(value: any, intDecoding: IntDecoding): any { + // eslint-disable-line @typescript-eslint/no-explicit-any + switch (intDecoding) { + case "bigint": + return value; + case "unsafe": + return mapBigInts(value, (bi) => Number(bi)); + case "safe": + // Throw if any bigint is not safely representable + traverse(value, (v) => { + if (typeof v === "bigint" && !Number.isSafeInteger(Number(v))) { + throw new Error('Integer exceeds safe range while INT_DECODING is "safe"'); + } + }); + return mapBigInts(value, (bi) => Number(bi)); + case "mixed": + default: + return mapBigInts(value, (bi) => { + const asNum = Number(bi); + return Number.isSafeInteger(asNum) ? asNum : bi; + }); + } +} + +function traverse(obj: any, fn: (v: any) => void): void { + // eslint-disable-line @typescript-eslint/no-explicit-any + if (obj == null) return; + fn(obj); + if (Array.isArray(obj)) { + for (const v of obj) traverse(v, fn); + } else if (typeof obj === "object") { + for (const v of Object.values(obj)) traverse(v, fn); + } +} + +function mapBigInts(obj: any, mapFn: (bi: bigint) => any): any { + // eslint-disable-line @typescript-eslint/no-explicit-any + if (obj == null) return obj; + if (typeof obj === "bigint") return mapFn(obj); + if (Array.isArray(obj)) return obj.map((v) => mapBigInts(v, mapFn)); + if (typeof obj === "object") { + const out: any = Array.isArray(obj) ? [] : { ...obj }; // eslint-disable-line @typescript-eslint/no-explicit-any + for (const [k, v] of Object.entries(obj)) { + out[k] = mapBigInts(v, mapFn); + } + return out; + } + return obj; +} diff --git a/packages/typescript/algod_client/src/core/request.ts b/packages/typescript/algod_client/src/core/request.ts new file mode 100644 index 000000000..e33d274f1 --- /dev/null +++ b/packages/typescript/algod_client/src/core/request.ts @@ -0,0 +1,90 @@ +import type { OpenAPIConfig } from "./OpenAPI"; +import { ApiError } from "./ApiError"; +import { parseJson, stringifyJson } from "./json"; +import { decodeMsgPack, normalizeMsgPackIntegers } from "./msgpack"; + +const encodeURIPath = (path: string): string => encodeURI(path).replace(/%5B/g, "[").replace(/%5D/g, "]"); + +export async function request( + config: OpenAPIConfig, + options: { + method: string; + url: string; + path?: Record; + query?: Record; + headers?: Record; + body?: any; + mediaType?: string; + responseHeader?: string; + expectBinary?: boolean; + }, +): Promise { + // Replace path params before constructing URL to avoid encoded braces preventing replacement + 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.ENCODE_PATH ? config.ENCODE_PATH(raw) : encodeURIPath(raw); + rawPath = rawPath.replace(`{${key}}`, replace); + } + } + + const url = new URL(rawPath, config.BASE); + + // Query params + if (options.query) { + for (const [key, value] of Object.entries(options.query)) { + if (value === undefined || value === null) continue; + const v = typeof value === "bigint" ? value.toString() : String(value); + url.searchParams.append(key, v); + } + } + + const headers: Record = { + ...(typeof config.HEADERS === "function" ? await config.HEADERS() : (config.HEADERS ?? {})), + ...(options.headers ?? {}), + }; + + // Auth: Bearer or Basic + 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}`)}`; + } + + const response = await fetch(url.toString(), { + method: options.method, + headers, + body: options.body != null ? (options.mediaType?.includes("json") ? stringifyJson(options.body) : options.body) : undefined, + credentials: config.CREDENTIALS, + }); + + if (!response.ok) { + let body: any = undefined; + try { + const ct = response.headers.get("content-type"); + if (ct && ct.includes("application/json")) body = parseJson(await response.text(), config.INT_DECODING); + else body = await response.text(); + } catch {} + throw new ApiError(url.toString(), response.status, body); + } + + if (options.responseHeader) { + const value = response.headers.get(options.responseHeader); + return value as unknown as T; + } + + // Parse by content-type first + const contentType = response.headers.get("content-type") || ""; + if (contentType.includes("application/msgpack") || contentType.includes("application/x-binary")) { + const buf = new Uint8Array(await response.arrayBuffer()); + const decoded = decodeMsgPack(buf); + return normalizeMsgPackIntegers(decoded, config.INT_DECODING ?? "mixed") as T; + } + if (contentType.includes("application/json")) { + const text = await response.text(); + return parseJson(text, config.INT_DECODING) as T; + } + // Fallback to text + return (await response.text()) as unknown as T; +} diff --git a/packages/typescript/algod_client/src/index.ts b/packages/typescript/algod_client/src/index.ts new file mode 100644 index 000000000..e51ca64f4 --- /dev/null +++ b/packages/typescript/algod_client/src/index.ts @@ -0,0 +1,10 @@ +export * from "./core/OpenAPI"; +export * from "./core/BaseHttpRequest"; +export * from "./core/FetchHttpRequest"; +export * from "./core/ApiError"; +export * from "./core/CancelablePromise"; +export * from "./core/json"; + +export * from "./models"; +export * from "./apis"; +export * from "./client"; diff --git a/packages/typescript/algod_client/src/models/abortcatchup.ts b/packages/typescript/algod_client/src/models/abortcatchup.ts new file mode 100644 index 000000000..f186782c8 --- /dev/null +++ b/packages/typescript/algod_client/src/models/abortcatchup.ts @@ -0,0 +1,4 @@ +/** + * An catchpoint abort response. + */ +export type AbortCatchup = { "catchup-message": string }; diff --git a/packages/typescript/algod_client/src/models/account.ts b/packages/typescript/algod_client/src/models/account.ts new file mode 100644 index 000000000..0fd82be6d --- /dev/null +++ b/packages/typescript/algod_client/src/models/account.ts @@ -0,0 +1,37 @@ +import type { AccountParticipation, Application, ApplicationLocalState, ApplicationStateSchema, Asset, AssetHolding } from "./index"; + +/** + * Account information at a given round. + * + * Definition: + * data/basics/userBalance.go : AccountData + */ +export type Account = { + address: string; + amount: bigint; + "min-balance": bigint; + "amount-without-pending-rewards": bigint; + "apps-local-state"?: ApplicationLocalState[]; + "total-apps-opted-in": bigint; + "apps-total-schema"?: ApplicationStateSchema; + "apps-total-extra-pages"?: bigint; + assets?: AssetHolding[]; + "total-assets-opted-in": bigint; + "created-apps"?: Application[]; + "total-created-apps": bigint; + "created-assets"?: Asset[]; + "total-created-assets": bigint; + "total-boxes"?: bigint; + "total-box-bytes"?: bigint; + participation?: AccountParticipation; + "incentive-eligible"?: boolean; + "pending-rewards": bigint; + "reward-base"?: bigint; + rewards: bigint; + round: bigint; + status: string; + "sig-type"?: "sig" | "msig" | "lsig"; + "auth-addr"?: string; + "last-proposed"?: bigint; + "last-heartbeat"?: bigint; +}; diff --git a/packages/typescript/algod_client/src/models/accountapplicationinformation.ts b/packages/typescript/algod_client/src/models/accountapplicationinformation.ts new file mode 100644 index 000000000..50ccf96f7 --- /dev/null +++ b/packages/typescript/algod_client/src/models/accountapplicationinformation.ts @@ -0,0 +1,6 @@ +import type { ApplicationLocalState, ApplicationParams } from "./index"; + +/** + * 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. + */ +export type AccountApplicationInformation = { round: bigint; "app-local-state"?: ApplicationLocalState; "created-app"?: ApplicationParams }; diff --git a/packages/typescript/algod_client/src/models/accountassetholding.ts b/packages/typescript/algod_client/src/models/accountassetholding.ts new file mode 100644 index 000000000..cd3fc67b1 --- /dev/null +++ b/packages/typescript/algod_client/src/models/accountassetholding.ts @@ -0,0 +1,6 @@ +import type { AssetHolding, AssetParams } from "./index"; + +/** + * AccountAssetHolding describes the account's asset holding and asset parameters (if either exist) for a specific asset ID. + */ +export type AccountAssetHolding = { "asset-holding": AssetHolding; "asset-params"?: AssetParams }; diff --git a/packages/typescript/algod_client/src/models/accountassetinformation.ts b/packages/typescript/algod_client/src/models/accountassetinformation.ts new file mode 100644 index 000000000..6f08b23cc --- /dev/null +++ b/packages/typescript/algod_client/src/models/accountassetinformation.ts @@ -0,0 +1,6 @@ +import type { AssetHolding, AssetParams } from "./index"; + +/** + * 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. + */ +export type AccountAssetInformation = { round: bigint; "asset-holding"?: AssetHolding; "created-asset"?: AssetParams }; diff --git a/packages/typescript/algod_client/src/models/accountassetsinformation.ts b/packages/typescript/algod_client/src/models/accountassetsinformation.ts new file mode 100644 index 000000000..32de59c55 --- /dev/null +++ b/packages/typescript/algod_client/src/models/accountassetsinformation.ts @@ -0,0 +1,6 @@ +import type { AccountAssetHolding } from "./index"; + +/** + * AccountAssetsInformationResponse contains a list of assets held by an account. + */ +export type AccountAssetsInformation = { round: bigint; "next-token"?: string; "asset-holdings"?: AccountAssetHolding[] }; diff --git a/packages/typescript/algod_client/src/models/accountparticipation.ts b/packages/typescript/algod_client/src/models/accountparticipation.ts new file mode 100644 index 000000000..2578b7231 --- /dev/null +++ b/packages/typescript/algod_client/src/models/accountparticipation.ts @@ -0,0 +1,11 @@ +/** + * AccountParticipation describes the parameters used by this account in consensus protocol. + */ +export type AccountParticipation = { + "selection-participation-key": string; + "vote-first-valid": bigint; + "vote-key-dilution": bigint; + "vote-last-valid": bigint; + "vote-participation-key": string; + "state-proof-key"?: string; +}; diff --git a/packages/typescript/algod_client/src/models/accountstatedelta.ts b/packages/typescript/algod_client/src/models/accountstatedelta.ts new file mode 100644 index 000000000..b2d101cad --- /dev/null +++ b/packages/typescript/algod_client/src/models/accountstatedelta.ts @@ -0,0 +1,6 @@ +import type { StateDelta } from "./index"; + +/** + * Application state delta. + */ +export type AccountStateDelta = { address: string; delta: StateDelta }; diff --git a/packages/typescript/algod_client/src/models/addparticipationkey.ts b/packages/typescript/algod_client/src/models/addparticipationkey.ts new file mode 100644 index 000000000..77eb9f8b7 --- /dev/null +++ b/packages/typescript/algod_client/src/models/addparticipationkey.ts @@ -0,0 +1,4 @@ +/** + * Participation ID of the submission + */ +export type AddParticipationKey = { partId: string }; diff --git a/packages/typescript/algod_client/src/models/appcalllogs.ts b/packages/typescript/algod_client/src/models/appcalllogs.ts new file mode 100644 index 000000000..84233e1f1 --- /dev/null +++ b/packages/typescript/algod_client/src/models/appcalllogs.ts @@ -0,0 +1,4 @@ +/** + * 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 = { logs: string[]; "application-index": bigint; txId: string }; diff --git a/packages/typescript/algod_client/src/models/application.ts b/packages/typescript/algod_client/src/models/application.ts new file mode 100644 index 000000000..a04d775da --- /dev/null +++ b/packages/typescript/algod_client/src/models/application.ts @@ -0,0 +1,6 @@ +import type { ApplicationParams } from "./index"; + +/** + * Application index and its parameters + */ +export type Application = { id: bigint; params: ApplicationParams }; diff --git a/packages/typescript/algod_client/src/models/applicationinitialstates.ts b/packages/typescript/algod_client/src/models/applicationinitialstates.ts new file mode 100644 index 000000000..ce4cee1b2 --- /dev/null +++ b/packages/typescript/algod_client/src/models/applicationinitialstates.ts @@ -0,0 +1,11 @@ +import type { ApplicationKvstorage } from "./index"; + +/** + * An application's initial global/local/box states that were accessed during simulation. + */ +export type ApplicationInitialStates = { + id: bigint; + "app-locals"?: ApplicationKvstorage[]; + "app-globals"?: ApplicationKvstorage; + "app-boxes"?: ApplicationKvstorage; +}; diff --git a/packages/typescript/algod_client/src/models/applicationkvstorage.ts b/packages/typescript/algod_client/src/models/applicationkvstorage.ts new file mode 100644 index 000000000..d91bdb14f --- /dev/null +++ b/packages/typescript/algod_client/src/models/applicationkvstorage.ts @@ -0,0 +1,6 @@ +import type { AvmKeyValue } from "./index"; + +/** + * An application's global/local/box state. + */ +export type ApplicationKvstorage = { kvs: AvmKeyValue[]; account?: string }; diff --git a/packages/typescript/algod_client/src/models/applicationlocalreference.ts b/packages/typescript/algod_client/src/models/applicationlocalreference.ts new file mode 100644 index 000000000..6236b71ba --- /dev/null +++ b/packages/typescript/algod_client/src/models/applicationlocalreference.ts @@ -0,0 +1,4 @@ +/** + * References an account's local state for an application. + */ +export type ApplicationLocalReference = { account: string; app: bigint }; diff --git a/packages/typescript/algod_client/src/models/applicationlocalstate.ts b/packages/typescript/algod_client/src/models/applicationlocalstate.ts new file mode 100644 index 000000000..66ed306ce --- /dev/null +++ b/packages/typescript/algod_client/src/models/applicationlocalstate.ts @@ -0,0 +1,6 @@ +import type { ApplicationStateSchema, TealKeyValueStore } from "./index"; + +/** + * Stores local state associated with an application. + */ +export type ApplicationLocalState = { id: bigint; schema: ApplicationStateSchema; "key-value"?: TealKeyValueStore }; diff --git a/packages/typescript/algod_client/src/models/applicationparams.ts b/packages/typescript/algod_client/src/models/applicationparams.ts new file mode 100644 index 000000000..bb1386731 --- /dev/null +++ b/packages/typescript/algod_client/src/models/applicationparams.ts @@ -0,0 +1,15 @@ +import type { ApplicationStateSchema, TealKeyValueStore } from "./index"; + +/** + * Stores the global information associated with an application. + */ +export type ApplicationParams = { + creator: string; + "approval-program": string; + "clear-state-program": string; + "extra-program-pages"?: number; + "local-state-schema"?: ApplicationStateSchema; + "global-state-schema"?: ApplicationStateSchema; + "global-state"?: TealKeyValueStore; + version?: bigint; +}; diff --git a/packages/typescript/algod_client/src/models/applicationstateoperation.ts b/packages/typescript/algod_client/src/models/applicationstateoperation.ts new file mode 100644 index 000000000..8a11ce6b6 --- /dev/null +++ b/packages/typescript/algod_client/src/models/applicationstateoperation.ts @@ -0,0 +1,12 @@ +import type { AvmValue } from "./index"; + +/** + * An operation against an application's global/local/box state. + */ +export type ApplicationStateOperation = { + operation: string; + "app-state-type": string; + key: string; + "new-value"?: AvmValue; + account?: string; +}; diff --git a/packages/typescript/algod_client/src/models/applicationstateschema.ts b/packages/typescript/algod_client/src/models/applicationstateschema.ts new file mode 100644 index 000000000..80ddaa431 --- /dev/null +++ b/packages/typescript/algod_client/src/models/applicationstateschema.ts @@ -0,0 +1,4 @@ +/** + * Specifies maximums on the number of each type that may be stored. + */ +export type ApplicationStateSchema = { "num-uint": number; "num-byte-slice": number }; diff --git a/packages/typescript/algod_client/src/models/asset.ts b/packages/typescript/algod_client/src/models/asset.ts new file mode 100644 index 000000000..43f981b8c --- /dev/null +++ b/packages/typescript/algod_client/src/models/asset.ts @@ -0,0 +1,6 @@ +import type { AssetParams } from "./index"; + +/** + * Specifies both the unique identifier and the parameters for an asset + */ +export type Asset = { index: bigint; params: AssetParams }; diff --git a/packages/typescript/algod_client/src/models/assetholding.ts b/packages/typescript/algod_client/src/models/assetholding.ts new file mode 100644 index 000000000..68dcecafc --- /dev/null +++ b/packages/typescript/algod_client/src/models/assetholding.ts @@ -0,0 +1,7 @@ +/** + * Describes an asset held by an account. + * + * Definition: + * data/basics/userBalance.go : AssetHolding + */ +export type AssetHolding = { amount: bigint; "asset-id": bigint; "is-frozen": boolean }; diff --git a/packages/typescript/algod_client/src/models/assetholdingreference.ts b/packages/typescript/algod_client/src/models/assetholdingreference.ts new file mode 100644 index 000000000..c8cf78492 --- /dev/null +++ b/packages/typescript/algod_client/src/models/assetholdingreference.ts @@ -0,0 +1,4 @@ +/** + * References an asset held by an account. + */ +export type AssetHoldingReference = { account: string; asset: bigint }; diff --git a/packages/typescript/algod_client/src/models/assetparams.ts b/packages/typescript/algod_client/src/models/assetparams.ts new file mode 100644 index 000000000..402449209 --- /dev/null +++ b/packages/typescript/algod_client/src/models/assetparams.ts @@ -0,0 +1,25 @@ +/** + * AssetParams specifies the parameters for an asset. + * + * \[apar\] when part of an AssetConfig transaction. + * + * Definition: + * data/transactions/asset.go : AssetParams + */ +export type AssetParams = { + clawback?: string; + creator: string; + decimals: bigint; + "default-frozen"?: boolean; + freeze?: string; + manager?: string; + "metadata-hash"?: string; + name?: string; + "name-b64"?: string; + reserve?: string; + total: bigint; + "unit-name"?: string; + "unit-name-b64"?: string; + url?: string; + "url-b64"?: string; +}; diff --git a/packages/typescript/algod_client/src/models/avmkeyvalue.ts b/packages/typescript/algod_client/src/models/avmkeyvalue.ts new file mode 100644 index 000000000..25d800891 --- /dev/null +++ b/packages/typescript/algod_client/src/models/avmkeyvalue.ts @@ -0,0 +1,6 @@ +import type { AvmValue } from "./index"; + +/** + * Represents an AVM key-value pair in an application store. + */ +export type AvmKeyValue = { key: string; value: AvmValue }; diff --git a/packages/typescript/algod_client/src/models/avmvalue.ts b/packages/typescript/algod_client/src/models/avmvalue.ts new file mode 100644 index 000000000..76857f2e1 --- /dev/null +++ b/packages/typescript/algod_client/src/models/avmvalue.ts @@ -0,0 +1,4 @@ +/** + * Represents an AVM value. + */ +export type AvmValue = { type: bigint; bytes?: string; uint?: bigint }; diff --git a/packages/typescript/algod_client/src/models/box.ts b/packages/typescript/algod_client/src/models/box.ts new file mode 100644 index 000000000..90b5c64e6 --- /dev/null +++ b/packages/typescript/algod_client/src/models/box.ts @@ -0,0 +1,4 @@ +/** + * Box name and its content. + */ +export type Box = { round: bigint; name: string; value: string }; diff --git a/packages/typescript/algod_client/src/models/boxdescriptor.ts b/packages/typescript/algod_client/src/models/boxdescriptor.ts new file mode 100644 index 000000000..adab97fe7 --- /dev/null +++ b/packages/typescript/algod_client/src/models/boxdescriptor.ts @@ -0,0 +1,4 @@ +/** + * Box descriptor describes a Box. + */ +export type BoxDescriptor = { name: string }; diff --git a/packages/typescript/algod_client/src/models/boxreference.ts b/packages/typescript/algod_client/src/models/boxreference.ts new file mode 100644 index 000000000..04885a4de --- /dev/null +++ b/packages/typescript/algod_client/src/models/boxreference.ts @@ -0,0 +1,4 @@ +/** + * References a box of an application. + */ +export type BoxReference = { app: number; name: string }; diff --git a/packages/typescript/algod_client/src/models/buildversion.ts b/packages/typescript/algod_client/src/models/buildversion.ts new file mode 100644 index 000000000..eacf5247b --- /dev/null +++ b/packages/typescript/algod_client/src/models/buildversion.ts @@ -0,0 +1 @@ +export type BuildVersion = { branch: string; build_number: number; channel: string; commit_hash: string; major: number; minor: number }; diff --git a/packages/typescript/algod_client/src/models/debugsettingsprof.ts b/packages/typescript/algod_client/src/models/debugsettingsprof.ts new file mode 100644 index 000000000..51e2cdad5 --- /dev/null +++ b/packages/typescript/algod_client/src/models/debugsettingsprof.ts @@ -0,0 +1,4 @@ +/** + * algod mutex and blocking profiling state. + */ +export type DebugSettingsProf = { "block-rate"?: bigint; "mutex-rate"?: bigint }; diff --git a/packages/typescript/algod_client/src/models/dryrunrequest.ts b/packages/typescript/algod_client/src/models/dryrunrequest.ts new file mode 100644 index 000000000..f79a7135b --- /dev/null +++ b/packages/typescript/algod_client/src/models/dryrunrequest.ts @@ -0,0 +1,14 @@ +import type { Account, Application, DryrunSource } from "./index"; + +/** + * Request data type for dryrun endpoint. Given the Transactions and simulated ledger state upload, run TEAL scripts and return debugging information. + */ +export type DryrunRequest = { + txns: string[]; + accounts: Account[]; + apps: Application[]; + "protocol-version": string; + round: bigint; + "latest-timestamp": number; + sources: DryrunSource[]; +}; diff --git a/packages/typescript/algod_client/src/models/dryrunsource.ts b/packages/typescript/algod_client/src/models/dryrunsource.ts new file mode 100644 index 000000000..11526e724 --- /dev/null +++ b/packages/typescript/algod_client/src/models/dryrunsource.ts @@ -0,0 +1,4 @@ +/** + * DryrunSource is TEAL source text that gets uploaded, compiled, and inserted into transactions or application state. + */ +export type DryrunSource = { "field-name": string; source: string; "txn-index": number; "app-index": bigint }; diff --git a/packages/typescript/algod_client/src/models/dryrunstate.ts b/packages/typescript/algod_client/src/models/dryrunstate.ts new file mode 100644 index 000000000..0ede2e1f5 --- /dev/null +++ b/packages/typescript/algod_client/src/models/dryrunstate.ts @@ -0,0 +1,6 @@ +import type { TealValue } from "./index"; + +/** + * Stores the TEAL eval step data + */ +export type DryrunState = { line: number; pc: number; stack: TealValue[]; scratch?: TealValue[]; error?: string }; diff --git a/packages/typescript/algod_client/src/models/dryruntxnresult.ts b/packages/typescript/algod_client/src/models/dryruntxnresult.ts new file mode 100644 index 000000000..2ce61e4cb --- /dev/null +++ b/packages/typescript/algod_client/src/models/dryruntxnresult.ts @@ -0,0 +1,18 @@ +import type { AccountStateDelta, DryrunState, StateDelta } from "./index"; + +/** + * DryrunTxnResult contains any LogicSig or ApplicationCall program debug information and state updates from a dryrun. + */ +export type DryrunTxnResult = { + disassembly: string[]; + "logic-sig-disassembly"?: string[]; + "logic-sig-trace"?: DryrunState[]; + "logic-sig-messages"?: string[]; + "app-call-trace"?: DryrunState[]; + "app-call-messages"?: string[]; + "global-delta"?: StateDelta; + "local-deltas"?: AccountStateDelta[]; + logs?: string[]; + "budget-added"?: number; + "budget-consumed"?: number; +}; diff --git a/packages/typescript/algod_client/src/models/errorresponse.ts b/packages/typescript/algod_client/src/models/errorresponse.ts new file mode 100644 index 000000000..556c79515 --- /dev/null +++ b/packages/typescript/algod_client/src/models/errorresponse.ts @@ -0,0 +1,4 @@ +/** + * An error response with optional data field. + */ +export type ErrorResponse = { data?: {}; message: string }; diff --git a/packages/typescript/algod_client/src/models/evaldelta.ts b/packages/typescript/algod_client/src/models/evaldelta.ts new file mode 100644 index 000000000..a45620482 --- /dev/null +++ b/packages/typescript/algod_client/src/models/evaldelta.ts @@ -0,0 +1,4 @@ +/** + * Represents a TEAL value delta. + */ +export type EvalDelta = { action: number; bytes?: string; uint?: bigint }; diff --git a/packages/typescript/algod_client/src/models/evaldeltakeyvalue.ts b/packages/typescript/algod_client/src/models/evaldeltakeyvalue.ts new file mode 100644 index 000000000..63d6ea4e1 --- /dev/null +++ b/packages/typescript/algod_client/src/models/evaldeltakeyvalue.ts @@ -0,0 +1,6 @@ +import type { EvalDelta } from "./index"; + +/** + * Key-value pairs for StateDelta. + */ +export type EvalDeltaKeyValue = { key: string; value: EvalDelta }; diff --git a/packages/typescript/algod_client/src/models/genesis.ts b/packages/typescript/algod_client/src/models/genesis.ts new file mode 100644 index 000000000..b1244bda6 --- /dev/null +++ b/packages/typescript/algod_client/src/models/genesis.ts @@ -0,0 +1,13 @@ +import type { GenesisAllocation } from "./index"; + +export type Genesis = { + alloc: GenesisAllocation[]; + comment?: string; + devmode?: boolean; + fees: string; + id: string; + network: string; + proto: string; + rwd: string; + timestamp: number; +}; diff --git a/packages/typescript/algod_client/src/models/genesisallocation.ts b/packages/typescript/algod_client/src/models/genesisallocation.ts new file mode 100644 index 000000000..250d8a0b6 --- /dev/null +++ b/packages/typescript/algod_client/src/models/genesisallocation.ts @@ -0,0 +1,5 @@ +export type GenesisAllocation = { + addr: string; + comment: string; + state: { algo: bigint; onl: number; sel?: string; stprf?: string; vote?: string; voteKD?: bigint; voteFst?: bigint; voteLst?: bigint }; +}; diff --git a/packages/typescript/algod_client/src/models/getapplicationboxes.ts b/packages/typescript/algod_client/src/models/getapplicationboxes.ts new file mode 100644 index 000000000..e731154ce --- /dev/null +++ b/packages/typescript/algod_client/src/models/getapplicationboxes.ts @@ -0,0 +1,6 @@ +import type { BoxDescriptor } from "./index"; + +/** + * Box names of an application + */ +export type GetApplicationBoxes = { boxes: BoxDescriptor[] }; diff --git a/packages/typescript/algod_client/src/models/getblock.ts b/packages/typescript/algod_client/src/models/getblock.ts new file mode 100644 index 000000000..c6f11f9dc --- /dev/null +++ b/packages/typescript/algod_client/src/models/getblock.ts @@ -0,0 +1,4 @@ +/** + * Encoded block object. + */ +export type GetBlock = { block: {}; cert?: {} }; diff --git a/packages/typescript/algod_client/src/models/getblockhash.ts b/packages/typescript/algod_client/src/models/getblockhash.ts new file mode 100644 index 000000000..642e0d0c0 --- /dev/null +++ b/packages/typescript/algod_client/src/models/getblockhash.ts @@ -0,0 +1,4 @@ +/** + * Hash of a block header. + */ +export type GetBlockHash = { blockHash: string }; diff --git a/packages/typescript/algod_client/src/models/getblocklogs.ts b/packages/typescript/algod_client/src/models/getblocklogs.ts new file mode 100644 index 000000000..1ecaa2f17 --- /dev/null +++ b/packages/typescript/algod_client/src/models/getblocklogs.ts @@ -0,0 +1,6 @@ +import type { AppCallLogs } from "./index"; + +/** + * 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) + */ +export type GetBlockLogs = { logs: AppCallLogs[] }; diff --git a/packages/typescript/algod_client/src/models/getblocktimestampoffset.ts b/packages/typescript/algod_client/src/models/getblocktimestampoffset.ts new file mode 100644 index 000000000..b79a134b9 --- /dev/null +++ b/packages/typescript/algod_client/src/models/getblocktimestampoffset.ts @@ -0,0 +1,4 @@ +/** + * Response containing the timestamp offset in seconds + */ +export type GetBlockTimeStampOffset = { offset: bigint }; diff --git a/packages/typescript/algod_client/src/models/getblocktxids.ts b/packages/typescript/algod_client/src/models/getblocktxids.ts new file mode 100644 index 000000000..57e9a2840 --- /dev/null +++ b/packages/typescript/algod_client/src/models/getblocktxids.ts @@ -0,0 +1,4 @@ +/** + * Top level transaction IDs in a block. + */ +export type GetBlockTxids = { blockTxids: string[] }; diff --git a/packages/typescript/algod_client/src/models/getpendingtransactions.ts b/packages/typescript/algod_client/src/models/getpendingtransactions.ts new file mode 100644 index 000000000..8d7955819 --- /dev/null +++ b/packages/typescript/algod_client/src/models/getpendingtransactions.ts @@ -0,0 +1,4 @@ +/** + * PendingTransactions is an array of signed transactions exactly as they were submitted. + */ +export type GetPendingTransactions = { "top-transactions": {}[]; "total-transactions": number }; diff --git a/packages/typescript/algod_client/src/models/getpendingtransactionsbyaddress.ts b/packages/typescript/algod_client/src/models/getpendingtransactionsbyaddress.ts new file mode 100644 index 000000000..63499994d --- /dev/null +++ b/packages/typescript/algod_client/src/models/getpendingtransactionsbyaddress.ts @@ -0,0 +1,4 @@ +/** + * PendingTransactions is an array of signed transactions exactly as they were submitted. + */ +export type GetPendingTransactionsByAddress = { "top-transactions": {}[]; "total-transactions": number }; diff --git a/packages/typescript/algod_client/src/models/getstatus.ts b/packages/typescript/algod_client/src/models/getstatus.ts new file mode 100644 index 000000000..bcf8ffbef --- /dev/null +++ b/packages/typescript/algod_client/src/models/getstatus.ts @@ -0,0 +1,31 @@ +/** + * NodeStatus contains the information about a node status + */ +export type GetStatus = { + "catchup-time": bigint; + "last-round": bigint; + "last-version": string; + "next-version": string; + "next-version-round": number; + "next-version-supported": boolean; + "stopped-at-unsupported-round": boolean; + "time-since-last-round": bigint; + "last-catchpoint"?: string; + catchpoint?: string; + "catchpoint-total-accounts"?: bigint; + "catchpoint-processed-accounts"?: bigint; + "catchpoint-verified-accounts"?: bigint; + "catchpoint-total-kvs"?: bigint; + "catchpoint-processed-kvs"?: bigint; + "catchpoint-verified-kvs"?: bigint; + "catchpoint-total-blocks"?: bigint; + "catchpoint-acquired-blocks"?: bigint; + "upgrade-delay"?: number; + "upgrade-node-vote"?: boolean; + "upgrade-votes-required"?: number; + "upgrade-votes"?: number; + "upgrade-yes-votes"?: number; + "upgrade-no-votes"?: number; + "upgrade-next-protocol-vote-before"?: number; + "upgrade-vote-rounds"?: number; +}; diff --git a/packages/typescript/algod_client/src/models/getsupply.ts b/packages/typescript/algod_client/src/models/getsupply.ts new file mode 100644 index 000000000..fe4daa917 --- /dev/null +++ b/packages/typescript/algod_client/src/models/getsupply.ts @@ -0,0 +1,4 @@ +/** + * Supply represents the current supply of MicroAlgos in the system + */ +export type GetSupply = { current_round: bigint; "online-money": bigint; "total-money": bigint }; diff --git a/packages/typescript/algod_client/src/models/getsyncround.ts b/packages/typescript/algod_client/src/models/getsyncround.ts new file mode 100644 index 000000000..c8ec6cfa3 --- /dev/null +++ b/packages/typescript/algod_client/src/models/getsyncround.ts @@ -0,0 +1,4 @@ +/** + * Response containing the ledger's minimum sync round + */ +export type GetSyncRound = { round: bigint }; diff --git a/packages/typescript/algod_client/src/models/gettransactiongroupledgerstatedeltasforround.ts b/packages/typescript/algod_client/src/models/gettransactiongroupledgerstatedeltasforround.ts new file mode 100644 index 000000000..6fcdcc9d9 --- /dev/null +++ b/packages/typescript/algod_client/src/models/gettransactiongroupledgerstatedeltasforround.ts @@ -0,0 +1,6 @@ +import type { LedgerStateDeltaForTransactionGroup } from "./index"; + +/** + * Response containing all ledger state deltas for transaction groups, with their associated Ids, in a single round. + */ +export type GetTransactionGroupLedgerStateDeltasForRound = { Deltas: LedgerStateDeltaForTransactionGroup[] }; diff --git a/packages/typescript/algod_client/src/models/index.ts b/packages/typescript/algod_client/src/models/index.ts new file mode 100644 index 000000000..2d1767152 --- /dev/null +++ b/packages/typescript/algod_client/src/models/index.ts @@ -0,0 +1,84 @@ +// Barrel file for models +export type { GenesisAllocation } from "./genesisallocation"; +export type { Genesis } from "./genesis"; +export type { LedgerStateDelta } from "./ledgerstatedelta"; +export type { LedgerStateDeltaForTransactionGroup } from "./ledgerstatedeltafortransactiongroup"; +export type { Account } from "./account"; +export type { AccountAssetHolding } from "./accountassetholding"; +export type { AccountParticipation } from "./accountparticipation"; +export type { Asset } from "./asset"; +export type { AssetHolding } from "./assetholding"; +export type { AssetParams } from "./assetparams"; +export type { AssetHoldingReference } from "./assetholdingreference"; +export type { ApplicationLocalReference } from "./applicationlocalreference"; +export type { ApplicationStateSchema } from "./applicationstateschema"; +export type { ApplicationLocalState } from "./applicationlocalstate"; +export type { ParticipationKey } from "./participationkey"; +export type { TealKeyValueStore } from "./tealkeyvaluestore"; +export type { TealKeyValue } from "./tealkeyvalue"; +export type { TealValue } from "./tealvalue"; +export type { AvmValue } from "./avmvalue"; +export type { AvmKeyValue } from "./avmkeyvalue"; +export type { StateDelta } from "./statedelta"; +export type { AccountStateDelta } from "./accountstatedelta"; +export type { EvalDeltaKeyValue } from "./evaldeltakeyvalue"; +export type { EvalDelta } from "./evaldelta"; +export type { Application } from "./application"; +export type { ApplicationParams } from "./applicationparams"; +export type { DryrunState } from "./dryrunstate"; +export type { DryrunTxnResult } from "./dryruntxnresult"; +export type { ErrorResponse } from "./errorresponse"; +export type { DryrunRequest } from "./dryrunrequest"; +export type { DryrunSource } from "./dryrunsource"; +export type { SimulateRequest } from "./simulaterequest"; +export type { SimulateRequestTransactionGroup } from "./simulaterequesttransactiongroup"; +export type { SimulateTraceConfig } from "./simulatetraceconfig"; +export type { Box } from "./box"; +export type { BoxDescriptor } from "./boxdescriptor"; +export type { BoxReference } from "./boxreference"; +export type { Version } from "./version"; +export type { DebugSettingsProf } from "./debugsettingsprof"; +export type { BuildVersion } from "./buildversion"; +export type { PendingTransactionResponse } from "./pendingtransactionresponse"; +export type { SimulateTransactionGroupResult } from "./simulatetransactiongroupresult"; +export type { SimulateTransactionResult } from "./simulatetransactionresult"; +export type { StateProof } from "./stateproof"; +export type { LightBlockHeaderProof } from "./lightblockheaderproof"; +export type { StateProofMessage } from "./stateproofmessage"; +export type { SimulationEvalOverrides } from "./simulationevaloverrides"; +export type { ScratchChange } from "./scratchchange"; +export type { ApplicationStateOperation } from "./applicationstateoperation"; +export type { ApplicationKvstorage } from "./applicationkvstorage"; +export type { ApplicationInitialStates } from "./applicationinitialstates"; +export type { SimulationOpcodeTraceUnit } from "./simulationopcodetraceunit"; +export type { SimulationTransactionExecTrace } from "./simulationtransactionexectrace"; +export type { SimulateUnnamedResourcesAccessed } from "./simulateunnamedresourcesaccessed"; +export type { SimulateInitialStates } from "./simulateinitialstates"; +export type { AppCallLogs } from "./appcalllogs"; +export type { TransactionProof } from "./transactionproof"; +export type { AccountAssetInformation } from "./accountassetinformation"; +export type { AccountAssetsInformation } from "./accountassetsinformation"; +export type { AccountApplicationInformation } from "./accountapplicationinformation"; +export type { GetPendingTransactionsByAddress } from "./getpendingtransactionsbyaddress"; +export type { GetBlock } from "./getblock"; +export type { GetBlockTxids } from "./getblocktxids"; +export type { GetBlockHash } from "./getblockhash"; +export type { GetBlockLogs } from "./getblocklogs"; +export type { GetSupply } from "./getsupply"; +export type { AddParticipationKey } from "./addparticipationkey"; +export type { GetStatus } from "./getstatus"; +export type { WaitForBlock } from "./waitforblock"; +export type { RawTransaction } from "./rawtransaction"; +export type { SimulateTransaction } from "./simulatetransaction"; +export type { TransactionParams } from "./transactionparams"; +export type { GetPendingTransactions } from "./getpendingtransactions"; +export type { GetTransactionGroupLedgerStateDeltasForRound } from "./gettransactiongroupledgerstatedeltasforround"; +export type { GetApplicationBoxes } from "./getapplicationboxes"; +export type { GetSyncRound } from "./getsyncround"; +export type { TealCompile } from "./tealcompile"; +export type { TealDisassemble } from "./tealdisassemble"; +export type { StartCatchup } from "./startcatchup"; +export type { AbortCatchup } from "./abortcatchup"; +export type { TealDryrun } from "./tealdryrun"; +export type { GetBlockTimeStampOffset } from "./getblocktimestampoffset"; +export type { ShutdownNode } from "./shutdownnode"; diff --git a/packages/typescript/algod_client/src/models/ledgerstatedelta.ts b/packages/typescript/algod_client/src/models/ledgerstatedelta.ts new file mode 100644 index 000000000..c2a7b925f --- /dev/null +++ b/packages/typescript/algod_client/src/models/ledgerstatedelta.ts @@ -0,0 +1,4 @@ +/** + * Ledger StateDelta object + */ +export type LedgerStateDelta = {}; diff --git a/packages/typescript/algod_client/src/models/ledgerstatedeltafortransactiongroup.ts b/packages/typescript/algod_client/src/models/ledgerstatedeltafortransactiongroup.ts new file mode 100644 index 000000000..90f19995d --- /dev/null +++ b/packages/typescript/algod_client/src/models/ledgerstatedeltafortransactiongroup.ts @@ -0,0 +1,6 @@ +import type { LedgerStateDelta } from "./index"; + +/** + * Contains a ledger delta for a single transaction group + */ +export type LedgerStateDeltaForTransactionGroup = { Delta: LedgerStateDelta; Ids: string[] }; diff --git a/packages/typescript/algod_client/src/models/lightblockheaderproof.ts b/packages/typescript/algod_client/src/models/lightblockheaderproof.ts new file mode 100644 index 000000000..2ca00a3c7 --- /dev/null +++ b/packages/typescript/algod_client/src/models/lightblockheaderproof.ts @@ -0,0 +1,4 @@ +/** + * Proof of membership and position of a light block header. + */ +export type LightBlockHeaderProof = { index: bigint; treedepth: number; proof: string }; diff --git a/packages/typescript/algod_client/src/models/participationkey.ts b/packages/typescript/algod_client/src/models/participationkey.ts new file mode 100644 index 000000000..68e902ddb --- /dev/null +++ b/packages/typescript/algod_client/src/models/participationkey.ts @@ -0,0 +1,15 @@ +import type { AccountParticipation } from "./index"; + +/** + * Represents a participation key used by the node. + */ +export type ParticipationKey = { + id: string; + address: string; + "effective-first-valid"?: bigint; + "effective-last-valid"?: bigint; + "last-vote"?: number; + "last-block-proposal"?: number; + "last-state-proof"?: number; + key: AccountParticipation; +}; diff --git a/packages/typescript/algod_client/src/models/pendingtransactionresponse.ts b/packages/typescript/algod_client/src/models/pendingtransactionresponse.ts new file mode 100644 index 000000000..36a1aaefc --- /dev/null +++ b/packages/typescript/algod_client/src/models/pendingtransactionresponse.ts @@ -0,0 +1,21 @@ +import type { AccountStateDelta, StateDelta } from "./index"; + +/** + * Details about a pending transaction. If the transaction was recently confirmed, includes confirmation details like the round and reward details. + */ +export type PendingTransactionResponse = { + "asset-index"?: bigint; + "application-index"?: bigint; + "close-rewards"?: number; + "closing-amount"?: bigint; + "asset-closing-amount"?: bigint; + "confirmed-round"?: bigint; + "pool-error": string; + "receiver-rewards"?: bigint; + "sender-rewards"?: bigint; + "local-state-delta"?: AccountStateDelta[]; + "global-state-delta"?: StateDelta; + logs?: string[]; + "inner-txns"?: PendingTransactionResponse[]; + txn: {}; +}; diff --git a/packages/typescript/algod_client/src/models/rawtransaction.ts b/packages/typescript/algod_client/src/models/rawtransaction.ts new file mode 100644 index 000000000..c0333feb1 --- /dev/null +++ b/packages/typescript/algod_client/src/models/rawtransaction.ts @@ -0,0 +1,4 @@ +/** + * Transaction ID of the submission. + */ +export type RawTransaction = { txId: string }; diff --git a/packages/typescript/algod_client/src/models/scratchchange.ts b/packages/typescript/algod_client/src/models/scratchchange.ts new file mode 100644 index 000000000..a33c54599 --- /dev/null +++ b/packages/typescript/algod_client/src/models/scratchchange.ts @@ -0,0 +1,6 @@ +import type { AvmValue } from "./index"; + +/** + * A write operation into a scratch slot. + */ +export type ScratchChange = { slot: number; "new-value": AvmValue }; diff --git a/packages/typescript/algod_client/src/models/shutdownnode.ts b/packages/typescript/algod_client/src/models/shutdownnode.ts new file mode 100644 index 000000000..f14d02ec8 --- /dev/null +++ b/packages/typescript/algod_client/src/models/shutdownnode.ts @@ -0,0 +1 @@ +export type ShutdownNode = {}; diff --git a/packages/typescript/algod_client/src/models/simulateinitialstates.ts b/packages/typescript/algod_client/src/models/simulateinitialstates.ts new file mode 100644 index 000000000..e00a0f185 --- /dev/null +++ b/packages/typescript/algod_client/src/models/simulateinitialstates.ts @@ -0,0 +1,6 @@ +import type { ApplicationInitialStates } from "./index"; + +/** + * Initial states of resources that were accessed during simulation. + */ +export type SimulateInitialStates = { "app-initial-states"?: ApplicationInitialStates[] }; diff --git a/packages/typescript/algod_client/src/models/simulaterequest.ts b/packages/typescript/algod_client/src/models/simulaterequest.ts new file mode 100644 index 000000000..5d2271d4a --- /dev/null +++ b/packages/typescript/algod_client/src/models/simulaterequest.ts @@ -0,0 +1,15 @@ +import type { SimulateRequestTransactionGroup, SimulateTraceConfig } from "./index"; + +/** + * Request type for simulation endpoint. + */ +export type SimulateRequest = { + "txn-groups": SimulateRequestTransactionGroup[]; + round?: bigint; + "allow-empty-signatures"?: boolean; + "allow-more-logging"?: boolean; + "allow-unnamed-resources"?: boolean; + "extra-opcode-budget"?: number; + "exec-trace-config"?: SimulateTraceConfig; + "fix-signers"?: boolean; +}; diff --git a/packages/typescript/algod_client/src/models/simulaterequesttransactiongroup.ts b/packages/typescript/algod_client/src/models/simulaterequesttransactiongroup.ts new file mode 100644 index 000000000..908390abe --- /dev/null +++ b/packages/typescript/algod_client/src/models/simulaterequesttransactiongroup.ts @@ -0,0 +1,4 @@ +/** + * A transaction group to simulate. + */ +export type SimulateRequestTransactionGroup = { txns: string[] }; diff --git a/packages/typescript/algod_client/src/models/simulatetraceconfig.ts b/packages/typescript/algod_client/src/models/simulatetraceconfig.ts new file mode 100644 index 000000000..1ab5559d4 --- /dev/null +++ b/packages/typescript/algod_client/src/models/simulatetraceconfig.ts @@ -0,0 +1,4 @@ +/** + * An object that configures simulation execution trace. + */ +export type SimulateTraceConfig = { enable?: boolean; "stack-change"?: boolean; "scratch-change"?: boolean; "state-change"?: boolean }; diff --git a/packages/typescript/algod_client/src/models/simulatetransaction.ts b/packages/typescript/algod_client/src/models/simulatetransaction.ts new file mode 100644 index 000000000..6bcef49a8 --- /dev/null +++ b/packages/typescript/algod_client/src/models/simulatetransaction.ts @@ -0,0 +1,13 @@ +import type { SimulateInitialStates, SimulateTraceConfig, SimulateTransactionGroupResult, SimulationEvalOverrides } from "./index"; + +/** + * Result of a transaction group simulation. + */ +export type SimulateTransaction = { + version: bigint; + "last-round": bigint; + "txn-groups": SimulateTransactionGroupResult[]; + "eval-overrides"?: SimulationEvalOverrides; + "exec-trace-config"?: SimulateTraceConfig; + "initial-states"?: SimulateInitialStates; +}; diff --git a/packages/typescript/algod_client/src/models/simulatetransactiongroupresult.ts b/packages/typescript/algod_client/src/models/simulatetransactiongroupresult.ts new file mode 100644 index 000000000..d11087154 --- /dev/null +++ b/packages/typescript/algod_client/src/models/simulatetransactiongroupresult.ts @@ -0,0 +1,13 @@ +import type { SimulateTransactionResult, SimulateUnnamedResourcesAccessed } from "./index"; + +/** + * Simulation result for an atomic transaction group + */ +export type SimulateTransactionGroupResult = { + "txn-results": SimulateTransactionResult[]; + "failure-message"?: string; + "failed-at"?: number[]; + "app-budget-added"?: number; + "app-budget-consumed"?: number; + "unnamed-resources-accessed"?: SimulateUnnamedResourcesAccessed; +}; diff --git a/packages/typescript/algod_client/src/models/simulatetransactionresult.ts b/packages/typescript/algod_client/src/models/simulatetransactionresult.ts new file mode 100644 index 000000000..dace14b62 --- /dev/null +++ b/packages/typescript/algod_client/src/models/simulatetransactionresult.ts @@ -0,0 +1,13 @@ +import type { PendingTransactionResponse, SimulateUnnamedResourcesAccessed, SimulationTransactionExecTrace } from "./index"; + +/** + * Simulation result for an individual transaction + */ +export type SimulateTransactionResult = { + "txn-result": PendingTransactionResponse; + "app-budget-consumed"?: number; + "logic-sig-budget-consumed"?: number; + "exec-trace"?: SimulationTransactionExecTrace; + "unnamed-resources-accessed"?: SimulateUnnamedResourcesAccessed; + "fixed-signer"?: string; +}; diff --git a/packages/typescript/algod_client/src/models/simulateunnamedresourcesaccessed.ts b/packages/typescript/algod_client/src/models/simulateunnamedresourcesaccessed.ts new file mode 100644 index 000000000..af1aaa3b6 --- /dev/null +++ b/packages/typescript/algod_client/src/models/simulateunnamedresourcesaccessed.ts @@ -0,0 +1,14 @@ +import type { ApplicationLocalReference, AssetHoldingReference, BoxReference } from "./index"; + +/** + * 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. + */ +export type SimulateUnnamedResourcesAccessed = { + accounts?: string[]; + assets?: bigint[]; + apps?: bigint[]; + boxes?: BoxReference[]; + "extra-box-refs"?: number; + "asset-holdings"?: AssetHoldingReference[]; + "app-locals"?: ApplicationLocalReference[]; +}; diff --git a/packages/typescript/algod_client/src/models/simulationevaloverrides.ts b/packages/typescript/algod_client/src/models/simulationevaloverrides.ts new file mode 100644 index 000000000..176e80311 --- /dev/null +++ b/packages/typescript/algod_client/src/models/simulationevaloverrides.ts @@ -0,0 +1,11 @@ +/** + * 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. + */ +export type SimulationEvalOverrides = { + "allow-empty-signatures"?: boolean; + "allow-unnamed-resources"?: boolean; + "max-log-calls"?: number; + "max-log-size"?: number; + "extra-opcode-budget"?: number; + "fix-signers"?: boolean; +}; diff --git a/packages/typescript/algod_client/src/models/simulationopcodetraceunit.ts b/packages/typescript/algod_client/src/models/simulationopcodetraceunit.ts new file mode 100644 index 000000000..13ca37112 --- /dev/null +++ b/packages/typescript/algod_client/src/models/simulationopcodetraceunit.ts @@ -0,0 +1,13 @@ +import type { ApplicationStateOperation, AvmValue, ScratchChange } from "./index"; + +/** + * The set of trace information and effect from evaluating a single opcode. + */ +export type SimulationOpcodeTraceUnit = { + pc: number; + "scratch-changes"?: ScratchChange[]; + "state-changes"?: ApplicationStateOperation[]; + "spawned-inners"?: number[]; + "stack-pop-count"?: number; + "stack-additions"?: AvmValue[]; +}; diff --git a/packages/typescript/algod_client/src/models/simulationtransactionexectrace.ts b/packages/typescript/algod_client/src/models/simulationtransactionexectrace.ts new file mode 100644 index 000000000..220050550 --- /dev/null +++ b/packages/typescript/algod_client/src/models/simulationtransactionexectrace.ts @@ -0,0 +1,16 @@ +import type { SimulationOpcodeTraceUnit } from "./index"; + +/** + * The execution trace of calling an app or a logic sig, containing the inner app call trace in a recursive way. + */ +export type SimulationTransactionExecTrace = { + "approval-program-trace"?: SimulationOpcodeTraceUnit[]; + "approval-program-hash"?: string; + "clear-state-program-trace"?: SimulationOpcodeTraceUnit[]; + "clear-state-program-hash"?: string; + "clear-state-rollback"?: boolean; + "clear-state-rollback-error"?: string; + "logic-sig-trace"?: SimulationOpcodeTraceUnit[]; + "logic-sig-hash"?: string; + "inner-trace"?: SimulationTransactionExecTrace[]; +}; diff --git a/packages/typescript/algod_client/src/models/startcatchup.ts b/packages/typescript/algod_client/src/models/startcatchup.ts new file mode 100644 index 000000000..5ab7452e5 --- /dev/null +++ b/packages/typescript/algod_client/src/models/startcatchup.ts @@ -0,0 +1,4 @@ +/** + * An catchpoint start response. + */ +export type StartCatchup = { "catchup-message": string }; diff --git a/packages/typescript/algod_client/src/models/statedelta.ts b/packages/typescript/algod_client/src/models/statedelta.ts new file mode 100644 index 000000000..2f09ff92a --- /dev/null +++ b/packages/typescript/algod_client/src/models/statedelta.ts @@ -0,0 +1,6 @@ +import type { EvalDeltaKeyValue } from "./index"; + +/** + * Application state delta. + */ +export type StateDelta = EvalDeltaKeyValue[]; diff --git a/packages/typescript/algod_client/src/models/stateproof.ts b/packages/typescript/algod_client/src/models/stateproof.ts new file mode 100644 index 000000000..446be6298 --- /dev/null +++ b/packages/typescript/algod_client/src/models/stateproof.ts @@ -0,0 +1,6 @@ +import type { StateProofMessage } from "./index"; + +/** + * Represents a state proof and its corresponding message + */ +export type StateProof = { Message: StateProofMessage; StateProof: string }; diff --git a/packages/typescript/algod_client/src/models/stateproofmessage.ts b/packages/typescript/algod_client/src/models/stateproofmessage.ts new file mode 100644 index 000000000..b0db2fed3 --- /dev/null +++ b/packages/typescript/algod_client/src/models/stateproofmessage.ts @@ -0,0 +1,10 @@ +/** + * Represents the message that the state proofs are attesting to. + */ +export type StateProofMessage = { + BlockHeadersCommitment: string; + VotersCommitment: string; + LnProvenWeight: bigint; + FirstAttestedRound: bigint; + LastAttestedRound: bigint; +}; diff --git a/packages/typescript/algod_client/src/models/tealcompile.ts b/packages/typescript/algod_client/src/models/tealcompile.ts new file mode 100644 index 000000000..e83ba6919 --- /dev/null +++ b/packages/typescript/algod_client/src/models/tealcompile.ts @@ -0,0 +1,4 @@ +/** + * Teal compile Result + */ +export type TealCompile = { hash: string; result: string; sourcemap?: {} }; diff --git a/packages/typescript/algod_client/src/models/tealdisassemble.ts b/packages/typescript/algod_client/src/models/tealdisassemble.ts new file mode 100644 index 000000000..9ce7813e5 --- /dev/null +++ b/packages/typescript/algod_client/src/models/tealdisassemble.ts @@ -0,0 +1,4 @@ +/** + * Teal disassembly Result + */ +export type TealDisassemble = { result: string }; diff --git a/packages/typescript/algod_client/src/models/tealdryrun.ts b/packages/typescript/algod_client/src/models/tealdryrun.ts new file mode 100644 index 000000000..eb289e136 --- /dev/null +++ b/packages/typescript/algod_client/src/models/tealdryrun.ts @@ -0,0 +1,6 @@ +import type { DryrunTxnResult } from "./index"; + +/** + * DryrunResponse contains per-txn debug information from a dryrun. + */ +export type TealDryrun = { txns: DryrunTxnResult[]; error: string; "protocol-version": string }; diff --git a/packages/typescript/algod_client/src/models/tealkeyvalue.ts b/packages/typescript/algod_client/src/models/tealkeyvalue.ts new file mode 100644 index 000000000..aeeee7399 --- /dev/null +++ b/packages/typescript/algod_client/src/models/tealkeyvalue.ts @@ -0,0 +1,6 @@ +import type { TealValue } from "./index"; + +/** + * Represents a key-value pair in an application store. + */ +export type TealKeyValue = { key: string; value: TealValue }; diff --git a/packages/typescript/algod_client/src/models/tealkeyvaluestore.ts b/packages/typescript/algod_client/src/models/tealkeyvaluestore.ts new file mode 100644 index 000000000..6dbc2b693 --- /dev/null +++ b/packages/typescript/algod_client/src/models/tealkeyvaluestore.ts @@ -0,0 +1,6 @@ +import type { TealKeyValue } from "./index"; + +/** + * Represents a key-value store for use in an application. + */ +export type TealKeyValueStore = TealKeyValue[]; diff --git a/packages/typescript/algod_client/src/models/tealvalue.ts b/packages/typescript/algod_client/src/models/tealvalue.ts new file mode 100644 index 000000000..84e3993af --- /dev/null +++ b/packages/typescript/algod_client/src/models/tealvalue.ts @@ -0,0 +1,4 @@ +/** + * Represents a TEAL value. + */ +export type TealValue = { type: bigint; bytes: string; uint: bigint }; diff --git a/packages/typescript/algod_client/src/models/transactionparams.ts b/packages/typescript/algod_client/src/models/transactionparams.ts new file mode 100644 index 000000000..c26f1c965 --- /dev/null +++ b/packages/typescript/algod_client/src/models/transactionparams.ts @@ -0,0 +1,12 @@ +/** + * TransactionParams contains the parameters that help a client construct + * a new transaction. + */ +export type TransactionParams = { + "consensus-version": string; + fee: bigint; + "genesis-hash": string; + "genesis-id": string; + "last-round": bigint; + "min-fee": bigint; +}; diff --git a/packages/typescript/algod_client/src/models/transactionproof.ts b/packages/typescript/algod_client/src/models/transactionproof.ts new file mode 100644 index 000000000..583d9208b --- /dev/null +++ b/packages/typescript/algod_client/src/models/transactionproof.ts @@ -0,0 +1,4 @@ +/** + * Proof of transaction in a block. + */ +export type TransactionProof = { proof: string; stibhash: string; treedepth: bigint; idx: bigint; hashtype: "sha512_256" | "sha256" }; diff --git a/packages/typescript/algod_client/src/models/version.ts b/packages/typescript/algod_client/src/models/version.ts new file mode 100644 index 000000000..5bd5e15b3 --- /dev/null +++ b/packages/typescript/algod_client/src/models/version.ts @@ -0,0 +1,6 @@ +import type { BuildVersion } from "./index"; + +/** + * algod version information. + */ +export type Version = { build: BuildVersion; genesis_hash_b64: string; genesis_id: string; versions: string[] }; diff --git a/packages/typescript/algod_client/src/models/waitforblock.ts b/packages/typescript/algod_client/src/models/waitforblock.ts new file mode 100644 index 000000000..64212ae59 --- /dev/null +++ b/packages/typescript/algod_client/src/models/waitforblock.ts @@ -0,0 +1,31 @@ +/** + * NodeStatus contains the information about a node status + */ +export type WaitForBlock = { + "catchup-time": bigint; + "last-round": bigint; + "last-version": string; + "next-version": string; + "next-version-round": number; + "next-version-supported": boolean; + "stopped-at-unsupported-round": boolean; + "time-since-last-round": bigint; + "last-catchpoint"?: string; + catchpoint?: string; + "catchpoint-total-accounts"?: bigint; + "catchpoint-processed-accounts"?: bigint; + "catchpoint-verified-accounts"?: bigint; + "catchpoint-total-kvs"?: bigint; + "catchpoint-processed-kvs"?: bigint; + "catchpoint-verified-kvs"?: bigint; + "catchpoint-total-blocks"?: bigint; + "catchpoint-acquired-blocks"?: bigint; + "upgrade-delay"?: number; + "upgrade-node-vote"?: boolean; + "upgrade-votes-required"?: number; + "upgrade-votes"?: number; + "upgrade-yes-votes"?: number; + "upgrade-no-votes"?: number; + "upgrade-next-protocol-vote-before"?: number; + "upgrade-vote-rounds"?: number; +}; diff --git a/packages/typescript/algod_client/tests/generated/smoke.generated.spec.ts b/packages/typescript/algod_client/tests/generated/smoke.generated.spec.ts new file mode 100644 index 000000000..d2a0f9e98 --- /dev/null +++ b/packages/typescript/algod_client/tests/generated/smoke.generated.spec.ts @@ -0,0 +1,49 @@ +/* AUTO-GENERATED FILE - DO NOT EDIT DIRECTLY. + * This smoke test is generated by ts_oas_generator. + * Location: tests/generated/smoke.generated.spec.ts + */ +import { describe, expect, it } from "vitest"; +import { Client } from "../src/client"; + +const BASE = "http://localhost/"; + +declare global { + // eslint-disable-next-line no-var, vars-on-top + var fetch: any; +} + +describe("JSON BigInt parsing", () => { + it("parses bigint values using json-bigint", async () => { + const big = "18446744073709551615"; // > Number.MAX_SAFE_INTEGER + global.fetch = async () => ({ + ok: true, + headers: new Map([["content-type", "application/json"]]), + text: async () => JSON.stringify({ value: big }), + arrayBuffer: async () => new ArrayBuffer(0), + }); + + const client = new Client({ BASE }); + // Directly use request core to keep template-agnostic + const res = await client.request.request<{ value: bigint }>({ method: "GET", url: "/foo" }); + expect(typeof res.value).toBe("bigint"); + }); +}); + +describe("Msgpack binary response", () => { + it("decodes msgpack into structured data", async () => { + // eslint-disable-next-line @typescript-eslint/no-var-requires + const { encode } = require("algo-msgpack-with-bigint"); + const msg = { ok: 1n, small: 2 }; + const bytes: Uint8Array = encode(msg); + global.fetch = async () => ({ + ok: true, + headers: new Map([["content-type", "application/msgpack"]]), + text: async () => "", + arrayBuffer: async () => bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength), + }); + + const client = new Client({ BASE }); + const res = await client.request.request<{ ok: bigint | number; small: number }>({ method: "GET", url: "/foo", expectBinary: true }); + expect(res).toHaveProperty("ok"); + }); +}); diff --git a/packages/typescript/algod_client/tests/helpers/env.ts b/packages/typescript/algod_client/tests/helpers/env.ts new file mode 100644 index 000000000..3fcf7260f --- /dev/null +++ b/packages/typescript/algod_client/tests/helpers/env.ts @@ -0,0 +1,49 @@ +import { describe } from "vitest"; +import algosdk from "algosdk"; + +export interface AlgodEnvConfig { + algodBaseUrl: string; + algodApiToken?: string; + senderMnemonic?: string; +} + +export function getAlgodEnv(): AlgodEnvConfig { + return { + algodBaseUrl: process.env.ALGOD_BASE_URL ?? "http://localhost:4001", + // Default token for localnet (Algorand sandbox / Algokit LocalNet) + algodApiToken: process.env.ALGOD_API_TOKEN ?? "a".repeat(64), + senderMnemonic: process.env.SENDER_MNEMONIC, + }; +} + +export async function getSenderMnemonic(): Promise { + if (process.env.SENDER_MNEMONIC) return process.env.SENDER_MNEMONIC; + // Try to derive from local KMD defaults + const kmdBase = process.env.KMD_BASE_URL ?? "http://localhost:4002"; + const kmdToken = process.env.KMD_API_TOKEN ?? "a".repeat(64); + const url = new URL(kmdBase); + const server = `${url.protocol}//${url.hostname}`; + const port = Number(url.port || 4002); + const kmd = new algosdk.Kmd(kmdToken, server, port); + const wallets = await kmd.listWallets(); + const wallet = wallets.wallets.find((w: any) => w.name === "unencrypted-default-wallet") ?? wallets.wallets[0]; + if (!wallet) throw new Error("No KMD wallet found on localnet"); + const handle = await kmd.initWalletHandle(wallet.id, ""); + try { + const keys = await kmd.listKeys(handle.wallet_handle_token); + let address: string | undefined = keys.addresses[0]; + if (!address) { + const gen = await kmd.generateKey(handle.wallet_handle_token); + address = gen.address; + } + const exported = await kmd.exportKey(handle.wallet_handle_token, "", address!); + const sk = new Uint8Array(exported.private_key); + return algosdk.secretKeyToMnemonic(sk); + } finally { + await kmd.releaseWalletHandle(handle.wallet_handle_token); + } +} + +export function maybeDescribe(name: string, fn: (env: AlgodEnvConfig) => void) { + describe(name, () => fn(getAlgodEnv())); +} diff --git a/packages/typescript/algod_client/tests/helpers/wait.ts b/packages/typescript/algod_client/tests/helpers/wait.ts new file mode 100644 index 000000000..2939c9659 --- /dev/null +++ b/packages/typescript/algod_client/tests/helpers/wait.ts @@ -0,0 +1,16 @@ +export async function waitFor( + fn: () => Promise, + predicate: (v: T) => boolean, + opts?: { timeoutMs?: number; intervalMs?: number }, +): Promise { + const timeoutMs = opts?.timeoutMs ?? 30_000; + const intervalMs = opts?.intervalMs ?? 1_000; + const start = Date.now(); + // eslint-disable-next-line no-constant-condition + while (true) { + const v = await fn(); + if (predicate(v)) return v; + if (Date.now() - start > timeoutMs) throw new Error("waitFor: timeout"); + await new Promise((r) => setTimeout(r, intervalMs)); + } +} diff --git a/packages/typescript/algod_client/tests/pendingTransaction.spec.ts b/packages/typescript/algod_client/tests/pendingTransaction.spec.ts new file mode 100644 index 000000000..357642ace --- /dev/null +++ b/packages/typescript/algod_client/tests/pendingTransaction.spec.ts @@ -0,0 +1,46 @@ +import { expect, it } from "vitest"; +import algosdk from "algosdk"; +import { Client } from "../src/client"; +import { getSenderMnemonic, maybeDescribe } from "./helpers/env"; +import { waitFor } from "./helpers/wait"; + +maybeDescribe("Algod pendingTransaction", (env) => { + it("submits a payment tx and queries pending info", async () => { + const client = new Client({ + BASE: env.algodBaseUrl, + HEADERS: env.algodApiToken ? { "X-Algo-API-Token": env.algodApiToken } : undefined, + }); + + const mnemonic = env.senderMnemonic ?? (await getSenderMnemonic()); + const acct = algosdk.mnemonicToSecretKey(mnemonic); + const sp = await client.api.transactionParams(); + + // Build simple self-payment of 0 microalgos (allowed) as a noop + const txn = algosdk.makePaymentTxnWithSuggestedParamsFromObject({ + from: acct.addr, + to: acct.addr, + amount: 0, + suggestedParams: { + fee: Number(sp["min-fee"]), + firstRound: Number(sp["last-round"]), + flatFee: true, + lastRound: Number(sp["last-round"]) + 1000, + genesisHash: sp["genesis-hash"] as string, + genesisID: sp["genesis-id"] as string, + }, + }); + + const signed = txn.signTxn(acct.sk); + const sendResult = await client.api.rawTransaction({ body: signed }); + const txId = sendResult.txId as string; + + const pending = await waitFor( + async () => client.api.pendingTransactionInformation(txId, { format: "json" }), + (r) => !!(r as any)["confirmed-round"] || !!(r as any)["pool-error"], + { timeoutMs: 45_000, intervalMs: 1_000 }, + ); + + // Some nodes may omit 'txid' in pending response; require txn presence + expect(pending).toHaveProperty("txn"); + }, 30_000); +}); diff --git a/packages/typescript/algod_client/tests/smoke.spec.ts b/packages/typescript/algod_client/tests/smoke.spec.ts new file mode 100644 index 000000000..c19a27e89 --- /dev/null +++ b/packages/typescript/algod_client/tests/smoke.spec.ts @@ -0,0 +1,46 @@ +import { describe, expect, it } from "vitest"; +import { Client } from "../src/client"; + +const BASE = "http://localhost/"; + +declare global { + // eslint-disable-next-line no-var, vars-on-top + var fetch: any; +} + +describe("JSON BigInt parsing", () => { + it("parses bigint values using json-bigint", async () => { + const big = "18446744073709551615"; // > Number.MAX_SAFE_INTEGER + global.fetch = async () => ({ + ok: true, + headers: new Map([["content-type", "application/json"]]), + text: async () => JSON.stringify({ value: big }), + arrayBuffer: async () => new ArrayBuffer(0), + }); + + const client = new Client({ BASE, INT_DECODING: "bigint" }); + // Directly use request core to keep template-agnostic + const res = await client.request.request<{ value: bigint }>({ method: "GET", url: "/foo" }); + expect(typeof res.value).toBe("bigint"); + }); +}); + +describe("Msgpack binary response", () => { + it("decodes msgpack into structured data", async () => { + // eslint-disable-next-line @typescript-eslint/no-var-requires + const { encode } = require("algo-msgpack-with-bigint"); + const payload = { ok: 1n, text: "hi" }; + const bytes: Uint8Array = encode(payload); + global.fetch = async () => ({ + ok: true, + headers: new Map([["content-type", "application/msgpack"]]), + text: async () => "", + arrayBuffer: async () => bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength), + }); + + const client = new Client({ BASE }); + const res = await client.request.request<{ ok: bigint | number; text: string }>({ method: "GET", url: "/foo", expectBinary: true }); + expect(res).toHaveProperty("ok"); + expect(res).toHaveProperty("text", "hi"); + }); +}); diff --git a/packages/typescript/algod_client/tests/src/client.ts b/packages/typescript/algod_client/tests/src/client.ts new file mode 100644 index 000000000..7c7bd3cdc --- /dev/null +++ b/packages/typescript/algod_client/tests/src/client.ts @@ -0,0 +1,12 @@ +import type { OpenAPIConfig } from "../../src/core/OpenAPI"; +import { Client as BaseClient } from "../../src/client"; + +// Re-export everything first +export * from "../../src/client"; + +// Override Client to default INT_DECODING to 'bigint' for generated smoke tests +export class Client extends BaseClient { + constructor(config: OpenAPIConfig) { + super({ INT_DECODING: config.INT_DECODING ?? "bigint", ...config }); + } +} diff --git a/packages/typescript/algod_client/tests/transactionParams.spec.ts b/packages/typescript/algod_client/tests/transactionParams.spec.ts new file mode 100644 index 000000000..c31770c39 --- /dev/null +++ b/packages/typescript/algod_client/tests/transactionParams.spec.ts @@ -0,0 +1,18 @@ +import { expect, it, describe } from "vitest"; +import { Client } from "../src/client"; +import { maybeDescribe } from "./helpers/env"; + +maybeDescribe("Algod transactionParams", (env) => { + it("fetches suggested params", async () => { + const client = new Client({ + BASE: env.algodBaseUrl, + INT_DECODING: "bigint", + HEADERS: env.algodApiToken ? { "X-Algo-API-Token": env.algodApiToken } : undefined, + }); + const params = await client.api.transactionParams(); + // Basic shape checks + expect(params).toHaveProperty("genesis-id"); + expect(typeof params["last-round"]).toBe("bigint"); + expect(typeof params["min-fee"]).toBe("bigint"); + }); +}); diff --git a/packages/typescript/algod_client/tsconfig.json b/packages/typescript/algod_client/tsconfig.json new file mode 100644 index 000000000..7a538edc0 --- /dev/null +++ b/packages/typescript/algod_client/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "ES2020", + "moduleResolution": "node", + "declaration": true, + "outDir": "dist", + "rootDir": "src", + "strict": true, + "skipLibCheck": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/typescript/indexer_client/.prettierignore b/packages/typescript/indexer_client/.prettierignore new file mode 100644 index 000000000..454dee356 --- /dev/null +++ b/packages/typescript/indexer_client/.prettierignore @@ -0,0 +1,3 @@ +# Ignore compiled output + +dist/ \ No newline at end of file diff --git a/packages/typescript/indexer_client/README.md b/packages/typescript/indexer_client/README.md new file mode 100644 index 000000000..73c6d70c5 --- /dev/null +++ b/packages/typescript/indexer_client/README.md @@ -0,0 +1,24 @@ +# indexer_client + +TypeScript client for indexer interaction. + +## Usage + +Install dependencies and build: + +- bun install (or pnpm/yarn) +- bun run build + +### Configure base URL and issue requests + +```ts +import { OpenAPI, FetchHttpRequest } from "./dist/index.js"; + +OpenAPI.BASE = "http://localhost:4001"; + +const client = new FetchHttpRequest(OpenAPI); +// Example call once APIs are available in Phase 2: +// await client.request({ method: 'GET', url: '/health' }); +``` + +To inject a custom client, implement your own HttpRequest class extending `BaseHttpRequest` and use it where needed. diff --git a/packages/typescript/indexer_client/package.json b/packages/typescript/indexer_client/package.json new file mode 100644 index 000000000..3d2e478f1 --- /dev/null +++ b/packages/typescript/indexer_client/package.json @@ -0,0 +1,24 @@ +{ + "name": "indexer_client", + "version": "0.1.0", + "private": true, + "type": "module", + "description": "TypeScript client for indexer interaction.", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "build": "tsc -p tsconfig.json", + "test": "vitest run" + }, + "dependencies": { + "json-bigint": "^1.0.0", + "algo-msgpack-with-bigint": "^2.1.1" + }, + "devDependencies": { + "typescript": "^5.5.0", + "@types/json-bigint": "^1.0.0", + "vitest": "^2.0.0", + "@types/node": "^20.0.0", + "algosdk": "^2.7.0" + } +} diff --git a/packages/typescript/indexer_client/src/apis/api.service.ts b/packages/typescript/indexer_client/src/apis/api.service.ts new file mode 100644 index 000000000..f5cdfba9d --- /dev/null +++ b/packages/typescript/indexer_client/src/apis/api.service.ts @@ -0,0 +1,671 @@ +import type { BaseHttpRequest, ApiRequestOptions } from "../core/BaseHttpRequest"; +import type { + Block, + Box, + HealthCheck, + LookupAccountAppLocalStates, + LookupAccountAssets, + LookupAccountById, + LookupAccountCreatedApplications, + LookupAccountCreatedAssets, + LookupAccountTransactions, + LookupApplicationById, + LookupApplicationLogsById, + LookupAssetBalances, + LookupAssetById, + LookupAssetTransactions, + LookupTransaction, + SearchForAccounts, + SearchForApplicationBoxes, + SearchForApplications, + SearchForAssets, + SearchForBlockHeaders, + SearchForTransactions, +} from "../models/index"; + +export class ApiService { + constructor(public readonly httpRequest: BaseHttpRequest) {} + + lookupAccountAppLocalStates( + accountId: string, + params?: { applicationId?: number; includeAll?: boolean; limit?: number; next?: string }, + requestOptions?: ApiRequestOptions, + ): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/accounts/{account-id}/apps-local-state", + path: { "account-id": accountId }, + query: { "application-id": params?.applicationId, "include-all": params?.includeAll, limit: params?.limit, next: params?.next }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + lookupAccountAssets( + accountId: string, + params?: { assetId?: number; includeAll?: boolean; limit?: number; next?: string }, + requestOptions?: ApiRequestOptions, + ): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/accounts/{account-id}/assets", + path: { "account-id": accountId }, + query: { "asset-id": params?.assetId, "include-all": params?.includeAll, limit: params?.limit, next: params?.next }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + lookupAccountById( + accountId: string, + params?: { + round?: number; + includeAll?: boolean; + exclude?: "all" | "assets" | "created-assets" | "apps-local-state" | "created-apps" | "none"[]; + }, + requestOptions?: ApiRequestOptions, + ): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/accounts/{account-id}", + path: { "account-id": accountId }, + query: { round: params?.round, "include-all": params?.includeAll, exclude: params?.exclude }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + lookupAccountCreatedApplications( + accountId: string, + params?: { applicationId?: number; includeAll?: boolean; limit?: number; next?: string }, + requestOptions?: ApiRequestOptions, + ): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/accounts/{account-id}/created-applications", + path: { "account-id": accountId }, + query: { "application-id": params?.applicationId, "include-all": params?.includeAll, limit: params?.limit, next: params?.next }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + lookupAccountCreatedAssets( + accountId: string, + params?: { assetId?: number; includeAll?: boolean; limit?: number; next?: string }, + requestOptions?: ApiRequestOptions, + ): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/accounts/{account-id}/created-assets", + path: { "account-id": accountId }, + query: { "asset-id": params?.assetId, "include-all": params?.includeAll, limit: params?.limit, next: params?.next }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + lookupAccountTransactions( + accountId: string, + params?: { + limit?: number; + next?: string; + notePrefix?: string; + txType?: "pay" | "keyreg" | "acfg" | "axfer" | "afrz" | "appl" | "stpf" | "hb"; + sigType?: "sig" | "msig" | "lsig"; + txid?: string; + round?: number; + minRound?: number; + maxRound?: number; + assetId?: number; + beforeTime?: string; + afterTime?: string; + currencyGreaterThan?: number; + currencyLessThan?: number; + rekeyTo?: boolean; + }, + requestOptions?: ApiRequestOptions, + ): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/accounts/{account-id}/transactions", + path: { "account-id": accountId }, + query: { + limit: params?.limit, + next: params?.next, + "note-prefix": params?.notePrefix, + "tx-type": params?.txType, + "sig-type": params?.sigType, + txid: params?.txid, + round: params?.round, + "min-round": params?.minRound, + "max-round": params?.maxRound, + "asset-id": params?.assetId, + "before-time": params?.beforeTime, + "after-time": params?.afterTime, + "currency-greater-than": params?.currencyGreaterThan, + "currency-less-than": params?.currencyLessThan, + "rekey-to": params?.rekeyTo, + }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + lookupApplicationBoxByIdandName(applicationId: number, params?: { name: string }, requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/applications/{application-id}/box", + path: { "application-id": applicationId }, + query: { name: params?.name }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + lookupApplicationById( + applicationId: number, + params?: { includeAll?: boolean }, + requestOptions?: ApiRequestOptions, + ): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/applications/{application-id}", + path: { "application-id": applicationId }, + query: { "include-all": params?.includeAll }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + lookupApplicationLogsById( + applicationId: number, + params?: { limit?: number; next?: string; txid?: string; minRound?: number; maxRound?: number; senderAddress?: string }, + requestOptions?: ApiRequestOptions, + ): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/applications/{application-id}/logs", + path: { "application-id": applicationId }, + query: { + limit: params?.limit, + next: params?.next, + txid: params?.txid, + "min-round": params?.minRound, + "max-round": params?.maxRound, + "sender-address": params?.senderAddress, + }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + lookupAssetBalances( + assetId: number, + params?: { includeAll?: boolean; limit?: number; next?: string; currencyGreaterThan?: number; currencyLessThan?: number }, + requestOptions?: ApiRequestOptions, + ): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/assets/{asset-id}/balances", + path: { "asset-id": assetId }, + query: { + "include-all": params?.includeAll, + limit: params?.limit, + next: params?.next, + "currency-greater-than": params?.currencyGreaterThan, + "currency-less-than": params?.currencyLessThan, + }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + lookupAssetById(assetId: number, params?: { includeAll?: boolean }, requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/assets/{asset-id}", + path: { "asset-id": assetId }, + query: { "include-all": params?.includeAll }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + lookupAssetTransactions( + assetId: number, + params?: { + limit?: number; + next?: string; + notePrefix?: string; + txType?: "pay" | "keyreg" | "acfg" | "axfer" | "afrz" | "appl" | "stpf" | "hb"; + sigType?: "sig" | "msig" | "lsig"; + txid?: string; + round?: number; + minRound?: number; + maxRound?: number; + beforeTime?: string; + afterTime?: string; + currencyGreaterThan?: number; + currencyLessThan?: number; + address?: string; + addressRole?: "sender" | "receiver" | "freeze-target"; + excludeCloseTo?: boolean; + rekeyTo?: boolean; + }, + requestOptions?: ApiRequestOptions, + ): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/assets/{asset-id}/transactions", + path: { "asset-id": assetId }, + query: { + limit: params?.limit, + next: params?.next, + "note-prefix": params?.notePrefix, + "tx-type": params?.txType, + "sig-type": params?.sigType, + txid: params?.txid, + round: params?.round, + "min-round": params?.minRound, + "max-round": params?.maxRound, + "before-time": params?.beforeTime, + "after-time": params?.afterTime, + "currency-greater-than": params?.currencyGreaterThan, + "currency-less-than": params?.currencyLessThan, + address: params?.address, + "address-role": params?.addressRole, + "exclude-close-to": params?.excludeCloseTo, + "rekey-to": params?.rekeyTo, + }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + lookupBlock(roundNumber: number, params?: { headerOnly?: boolean }, requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/blocks/{round-number}", + path: { "round-number": roundNumber }, + query: { "header-only": params?.headerOnly }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + lookupTransaction(txid: string, requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/transactions/{txid}", + path: { txid: txid }, + query: {}, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + makeHealthCheck(requestOptions?: ApiRequestOptions): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/health", + path: {}, + query: {}, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + searchForAccounts( + params?: { + assetId?: number; + limit?: number; + next?: string; + currencyGreaterThan?: number; + includeAll?: boolean; + exclude?: "all" | "assets" | "created-assets" | "apps-local-state" | "created-apps" | "none"[]; + currencyLessThan?: number; + authAddr?: string; + round?: number; + applicationId?: number; + onlineOnly?: boolean; + }, + requestOptions?: ApiRequestOptions, + ): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/accounts", + path: {}, + query: { + "asset-id": params?.assetId, + limit: params?.limit, + next: params?.next, + "currency-greater-than": params?.currencyGreaterThan, + "include-all": params?.includeAll, + exclude: params?.exclude, + "currency-less-than": params?.currencyLessThan, + "auth-addr": params?.authAddr, + round: params?.round, + "application-id": params?.applicationId, + "online-only": params?.onlineOnly, + }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + searchForApplicationBoxes( + applicationId: number, + params?: { limit?: number; next?: string }, + requestOptions?: ApiRequestOptions, + ): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/applications/{application-id}/boxes", + path: { "application-id": applicationId }, + query: { limit: params?.limit, next: params?.next }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + searchForApplications( + params?: { applicationId?: number; creator?: string; includeAll?: boolean; limit?: number; next?: string }, + requestOptions?: ApiRequestOptions, + ): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/applications", + path: {}, + query: { + "application-id": params?.applicationId, + creator: params?.creator, + "include-all": params?.includeAll, + limit: params?.limit, + next: params?.next, + }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + searchForAssets( + params?: { includeAll?: boolean; limit?: number; next?: string; creator?: string; name?: string; unit?: string; assetId?: number }, + requestOptions?: ApiRequestOptions, + ): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/assets", + path: {}, + query: { + "include-all": params?.includeAll, + limit: params?.limit, + next: params?.next, + creator: params?.creator, + name: params?.name, + unit: params?.unit, + "asset-id": params?.assetId, + }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + searchForBlockHeaders( + params?: { + limit?: number; + next?: string; + minRound?: number; + maxRound?: number; + beforeTime?: string; + afterTime?: string; + proposers?: string[]; + expired?: string[]; + absent?: string[]; + }, + requestOptions?: ApiRequestOptions, + ): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/block-headers", + path: {}, + query: { + limit: params?.limit, + next: params?.next, + "min-round": params?.minRound, + "max-round": params?.maxRound, + "before-time": params?.beforeTime, + "after-time": params?.afterTime, + proposers: params?.proposers, + expired: params?.expired, + absent: params?.absent, + }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } + + searchForTransactions( + params?: { + limit?: number; + next?: string; + notePrefix?: string; + txType?: "pay" | "keyreg" | "acfg" | "axfer" | "afrz" | "appl" | "stpf" | "hb"; + sigType?: "sig" | "msig" | "lsig"; + groupId?: string; + txid?: string; + round?: number; + minRound?: number; + maxRound?: number; + assetId?: number; + beforeTime?: string; + afterTime?: string; + currencyGreaterThan?: number; + currencyLessThan?: number; + address?: string; + addressRole?: "sender" | "receiver" | "freeze-target"; + excludeCloseTo?: boolean; + rekeyTo?: boolean; + applicationId?: number; + }, + requestOptions?: ApiRequestOptions, + ): Promise { + const headers: Record = {}; + headers["Accept"] = "application/json"; + + // Header parameters + + return this.httpRequest.request({ + method: "GET", + url: "/v2/transactions", + path: {}, + query: { + limit: params?.limit, + next: params?.next, + "note-prefix": params?.notePrefix, + "tx-type": params?.txType, + "sig-type": params?.sigType, + "group-id": params?.groupId, + txid: params?.txid, + round: params?.round, + "min-round": params?.minRound, + "max-round": params?.maxRound, + "asset-id": params?.assetId, + "before-time": params?.beforeTime, + "after-time": params?.afterTime, + "currency-greater-than": params?.currencyGreaterThan, + "currency-less-than": params?.currencyLessThan, + address: params?.address, + "address-role": params?.addressRole, + "exclude-close-to": params?.excludeCloseTo, + "rekey-to": params?.rekeyTo, + "application-id": params?.applicationId, + }, + headers, + body: undefined, + mediaType: undefined, + expectBinary: false, + ...(requestOptions ?? {}), + }); + } +} diff --git a/packages/typescript/indexer_client/src/apis/index.ts b/packages/typescript/indexer_client/src/apis/index.ts new file mode 100644 index 000000000..c8244b99b --- /dev/null +++ b/packages/typescript/indexer_client/src/apis/index.ts @@ -0,0 +1,2 @@ +// Barrel file for services +export { ApiService } from "./api.service"; diff --git a/packages/typescript/indexer_client/src/client.ts b/packages/typescript/indexer_client/src/client.ts new file mode 100644 index 000000000..310bdaba7 --- /dev/null +++ b/packages/typescript/indexer_client/src/client.ts @@ -0,0 +1,13 @@ +import type { OpenAPIConfig } from "./core/OpenAPI"; +import { FetchHttpRequest } from "./core/FetchHttpRequest"; +import { ApiService } from "./apis/api.service"; + +export class Client { + public readonly request: FetchHttpRequest; + public readonly api: ApiService; + + constructor(config: OpenAPIConfig) { + this.request = new FetchHttpRequest(config); + this.api = new ApiService(this.request); + } +} diff --git a/packages/typescript/indexer_client/src/core/ApiError.ts b/packages/typescript/indexer_client/src/core/ApiError.ts new file mode 100644 index 000000000..17a9213f8 --- /dev/null +++ b/packages/typescript/indexer_client/src/core/ApiError.ts @@ -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/packages/typescript/indexer_client/src/core/BaseHttpRequest.ts b/packages/typescript/indexer_client/src/core/BaseHttpRequest.ts new file mode 100644 index 000000000..85cf8d865 --- /dev/null +++ b/packages/typescript/indexer_client/src/core/BaseHttpRequest.ts @@ -0,0 +1,21 @@ +import type { OpenAPIConfig } from "./OpenAPI"; + +export interface RequestOptions { + method: string; + url: string; + path?: Record; + query?: Record; + headers?: Record; + body?: any; + mediaType?: string; + responseHeader?: string; + expectBinary?: boolean; +} + +// Backwards/ergonomic alias used by generated services +export type ApiRequestOptions = RequestOptions; + +export abstract class BaseHttpRequest { + constructor(public readonly config: OpenAPIConfig) {} + abstract request(options: RequestOptions): Promise; +} diff --git a/packages/typescript/indexer_client/src/core/CancelablePromise.ts b/packages/typescript/indexer_client/src/core/CancelablePromise.ts new file mode 100644 index 000000000..3cb118cb6 --- /dev/null +++ b/packages/typescript/indexer_client/src/core/CancelablePromise.ts @@ -0,0 +1,52 @@ +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 _isCancelled = false; + private _cancelHandlers: Array<() => void> = []; + + constructor(executor: (resolve: (value: T | PromiseLike) => void, reject: (reason?: any) => void, onCancel: OnCancel) => void) { + const onCancel: OnCancel = (handler) => { + if (this._isCancelled) { + handler(); + } else { + this._cancelHandlers.push(handler); + } + }; + + this._promise = new Promise((resolve, reject) => executor(resolve, reject, onCancel)); + } + + private _promise: Promise; + + public cancel(): void { + if (!this._isCancelled) { + this._isCancelled = true; + for (const fn of this._cancelHandlers) fn(); + this._cancelHandlers.length = 0; + } + } + + then( + onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, + onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null, + ): Promise { + return this._promise.then(onfulfilled, onrejected); + } + + catch(onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): Promise { + return this._promise.catch(onrejected); + } + + finally(onfinally?: (() => void) | undefined | null): Promise { + return this._promise.finally(onfinally); + } +} diff --git a/packages/typescript/indexer_client/src/core/FetchHttpRequest.ts b/packages/typescript/indexer_client/src/core/FetchHttpRequest.ts new file mode 100644 index 000000000..b47684434 --- /dev/null +++ b/packages/typescript/indexer_client/src/core/FetchHttpRequest.ts @@ -0,0 +1,10 @@ +import { BaseHttpRequest, type RequestOptions } from "./BaseHttpRequest"; +import { OpenAPI } from "./OpenAPI"; +import { request as defaultRequest } from "./request"; + +export class FetchHttpRequest extends BaseHttpRequest { + async request(options: RequestOptions): Promise { + const request = defaultRequest; + return request(this.config, options); + } +} diff --git a/packages/typescript/indexer_client/src/core/OpenAPI.ts b/packages/typescript/indexer_client/src/core/OpenAPI.ts new file mode 100644 index 000000000..fde885a4d --- /dev/null +++ b/packages/typescript/indexer_client/src/core/OpenAPI.ts @@ -0,0 +1,22 @@ +/* + Minimal OpenAPI runtime config holder +*/ +export type BaseURL = string; + +export interface OpenAPIConfig { + BASE: BaseURL; + VERSION?: string; + WITH_CREDENTIALS?: boolean; + CREDENTIALS?: "include" | "omit" | "same-origin"; + TOKEN?: string | (() => string | Promise); + USERNAME?: string; + PASSWORD?: string; + HEADERS?: Record | (() => Record | Promise>); + ENCODE_PATH?: (path: string) => string; + INT_DECODING?: "safe" | "unsafe" | "mixed" | "bigint"; +} + +export const OpenAPI: OpenAPIConfig = { + BASE: "", + INT_DECODING: "mixed", +}; diff --git a/packages/typescript/indexer_client/src/core/json.ts b/packages/typescript/indexer_client/src/core/json.ts new file mode 100644 index 000000000..3845c5abb --- /dev/null +++ b/packages/typescript/indexer_client/src/core/json.ts @@ -0,0 +1,70 @@ +// Use require to avoid ESM/CJS interop issues in consumers +// eslint-disable-next-line @typescript-eslint/no-explicit-any +declare const require: any; +// eslint-disable-next-line @typescript-eslint/no-var-requires +const JSONBigFactory = require("json-bigint"); + +export type IntDecoding = "safe" | "unsafe" | "mixed" | "bigint"; + +// Instances +const JSONBigMixed = JSONBigFactory({ useNativeBigInt: true, alwaysParseAsBig: false }); +const JSONBigAllBig = JSONBigFactory({ useNativeBigInt: true, alwaysParseAsBig: true }); + +function traverseAndThrowOnBigInt(obj: any): void { + // eslint-disable-line @typescript-eslint/no-explicit-any + if (obj === null || obj === undefined) return; + const t = typeof obj; + if (t === "bigint") { + throw new Error('Integer exceeds safe range while INT_DECODING is "safe"'); + } + if (t !== "object") return; + if (Array.isArray(obj)) { + for (const v of obj) traverseAndThrowOnBigInt(v); + } else { + for (const v of Object.values(obj)) traverseAndThrowOnBigInt(v); + } +} + +function convertLargeNumericStrings(obj: any): any { + // eslint-disable-line @typescript-eslint/no-explicit-any + if (obj == null) return obj; + if (typeof obj === "string") { + if (/^\d+$/.test(obj)) { + const asNum = Number(obj); + if (!Number.isSafeInteger(asNum)) return BigInt(obj); + } + return obj; + } + if (Array.isArray(obj)) return obj.map(convertLargeNumericStrings); + if (typeof obj === "object") { + for (const k of Object.keys(obj)) obj[k] = convertLargeNumericStrings(obj[k]); + } + return obj; +} + +export function parseJson(text: string, intDecoding: IntDecoding = "mixed"): any { + // eslint-disable-line @typescript-eslint/no-explicit-any + switch (intDecoding) { + case "unsafe": + return JSON.parse(text); + case "bigint": { + const v = JSONBigAllBig.parse(text); + return convertLargeNumericStrings(v); + } + case "safe": { + const value = JSONBigMixed.parse(text); + traverseAndThrowOnBigInt(value); + return value; + } + case "mixed": + default: { + const v = JSONBigMixed.parse(text); + return convertLargeNumericStrings(v); + } + } +} + +export function stringifyJson(value: any): string { + // eslint-disable-line @typescript-eslint/no-explicit-any + return JSON.stringify(value, (_k, v) => (typeof v === "bigint" ? v.toString() : v)); +} diff --git a/packages/typescript/indexer_client/src/core/msgpack.ts b/packages/typescript/indexer_client/src/core/msgpack.ts new file mode 100644 index 000000000..1d2a5aa2f --- /dev/null +++ b/packages/typescript/indexer_client/src/core/msgpack.ts @@ -0,0 +1,61 @@ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +declare const require: any; +// eslint-disable-next-line @typescript-eslint/no-var-requires +const { decode } = require("algo-msgpack-with-bigint"); + +import type { IntDecoding } from "./json"; + +export function decodeMsgPack(buffer: Uint8Array): any { + // eslint-disable-line @typescript-eslint/no-explicit-any + return decode(buffer); +} + +export function normalizeMsgPackIntegers(value: any, intDecoding: IntDecoding): any { + // eslint-disable-line @typescript-eslint/no-explicit-any + switch (intDecoding) { + case "bigint": + return value; + case "unsafe": + return mapBigInts(value, (bi) => Number(bi)); + case "safe": + // Throw if any bigint is not safely representable + traverse(value, (v) => { + if (typeof v === "bigint" && !Number.isSafeInteger(Number(v))) { + throw new Error('Integer exceeds safe range while INT_DECODING is "safe"'); + } + }); + return mapBigInts(value, (bi) => Number(bi)); + case "mixed": + default: + return mapBigInts(value, (bi) => { + const asNum = Number(bi); + return Number.isSafeInteger(asNum) ? asNum : bi; + }); + } +} + +function traverse(obj: any, fn: (v: any) => void): void { + // eslint-disable-line @typescript-eslint/no-explicit-any + if (obj == null) return; + fn(obj); + if (Array.isArray(obj)) { + for (const v of obj) traverse(v, fn); + } else if (typeof obj === "object") { + for (const v of Object.values(obj)) traverse(v, fn); + } +} + +function mapBigInts(obj: any, mapFn: (bi: bigint) => any): any { + // eslint-disable-line @typescript-eslint/no-explicit-any + if (obj == null) return obj; + if (typeof obj === "bigint") return mapFn(obj); + if (Array.isArray(obj)) return obj.map((v) => mapBigInts(v, mapFn)); + if (typeof obj === "object") { + const out: any = Array.isArray(obj) ? [] : { ...obj }; // eslint-disable-line @typescript-eslint/no-explicit-any + for (const [k, v] of Object.entries(obj)) { + out[k] = mapBigInts(v, mapFn); + } + return out; + } + return obj; +} diff --git a/packages/typescript/indexer_client/src/core/request.ts b/packages/typescript/indexer_client/src/core/request.ts new file mode 100644 index 000000000..e33d274f1 --- /dev/null +++ b/packages/typescript/indexer_client/src/core/request.ts @@ -0,0 +1,90 @@ +import type { OpenAPIConfig } from "./OpenAPI"; +import { ApiError } from "./ApiError"; +import { parseJson, stringifyJson } from "./json"; +import { decodeMsgPack, normalizeMsgPackIntegers } from "./msgpack"; + +const encodeURIPath = (path: string): string => encodeURI(path).replace(/%5B/g, "[").replace(/%5D/g, "]"); + +export async function request( + config: OpenAPIConfig, + options: { + method: string; + url: string; + path?: Record; + query?: Record; + headers?: Record; + body?: any; + mediaType?: string; + responseHeader?: string; + expectBinary?: boolean; + }, +): Promise { + // Replace path params before constructing URL to avoid encoded braces preventing replacement + 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.ENCODE_PATH ? config.ENCODE_PATH(raw) : encodeURIPath(raw); + rawPath = rawPath.replace(`{${key}}`, replace); + } + } + + const url = new URL(rawPath, config.BASE); + + // Query params + if (options.query) { + for (const [key, value] of Object.entries(options.query)) { + if (value === undefined || value === null) continue; + const v = typeof value === "bigint" ? value.toString() : String(value); + url.searchParams.append(key, v); + } + } + + const headers: Record = { + ...(typeof config.HEADERS === "function" ? await config.HEADERS() : (config.HEADERS ?? {})), + ...(options.headers ?? {}), + }; + + // Auth: Bearer or Basic + 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}`)}`; + } + + const response = await fetch(url.toString(), { + method: options.method, + headers, + body: options.body != null ? (options.mediaType?.includes("json") ? stringifyJson(options.body) : options.body) : undefined, + credentials: config.CREDENTIALS, + }); + + if (!response.ok) { + let body: any = undefined; + try { + const ct = response.headers.get("content-type"); + if (ct && ct.includes("application/json")) body = parseJson(await response.text(), config.INT_DECODING); + else body = await response.text(); + } catch {} + throw new ApiError(url.toString(), response.status, body); + } + + if (options.responseHeader) { + const value = response.headers.get(options.responseHeader); + return value as unknown as T; + } + + // Parse by content-type first + const contentType = response.headers.get("content-type") || ""; + if (contentType.includes("application/msgpack") || contentType.includes("application/x-binary")) { + const buf = new Uint8Array(await response.arrayBuffer()); + const decoded = decodeMsgPack(buf); + return normalizeMsgPackIntegers(decoded, config.INT_DECODING ?? "mixed") as T; + } + if (contentType.includes("application/json")) { + const text = await response.text(); + return parseJson(text, config.INT_DECODING) as T; + } + // Fallback to text + return (await response.text()) as unknown as T; +} diff --git a/packages/typescript/indexer_client/src/index.ts b/packages/typescript/indexer_client/src/index.ts new file mode 100644 index 000000000..e51ca64f4 --- /dev/null +++ b/packages/typescript/indexer_client/src/index.ts @@ -0,0 +1,10 @@ +export * from "./core/OpenAPI"; +export * from "./core/BaseHttpRequest"; +export * from "./core/FetchHttpRequest"; +export * from "./core/ApiError"; +export * from "./core/CancelablePromise"; +export * from "./core/json"; + +export * from "./models"; +export * from "./apis"; +export * from "./client"; diff --git a/packages/typescript/indexer_client/src/models/account.ts b/packages/typescript/indexer_client/src/models/account.ts new file mode 100644 index 000000000..98e5803ec --- /dev/null +++ b/packages/typescript/indexer_client/src/models/account.ts @@ -0,0 +1,40 @@ +import type { AccountParticipation, Application, ApplicationLocalState, ApplicationStateSchema, Asset, AssetHolding } from "./index"; + +/** + * Account information at a given round. + * + * Definition: + * data/basics/userBalance.go : AccountData + */ +export type Account = { + address: string; + amount: bigint; + "min-balance": bigint; + "amount-without-pending-rewards": bigint; + "apps-local-state"?: ApplicationLocalState[]; + "apps-total-schema"?: ApplicationStateSchema; + "apps-total-extra-pages"?: number; + assets?: AssetHolding[]; + "created-apps"?: Application[]; + "created-assets"?: Asset[]; + participation?: AccountParticipation; + "incentive-eligible"?: boolean; + "pending-rewards": bigint; + "reward-base"?: bigint; + rewards: bigint; + round: bigint; + status: string; + "sig-type"?: "sig" | "msig" | "lsig"; + "total-apps-opted-in": number; + "total-assets-opted-in": number; + "total-box-bytes": number; + "total-boxes": number; + "total-created-apps": number; + "total-created-assets": number; + "auth-addr"?: string; + "last-proposed"?: bigint; + "last-heartbeat"?: bigint; + deleted?: boolean; + "created-at-round"?: bigint; + "closed-at-round"?: bigint; +}; diff --git a/packages/typescript/indexer_client/src/models/accountparticipation.ts b/packages/typescript/indexer_client/src/models/accountparticipation.ts new file mode 100644 index 000000000..2578b7231 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/accountparticipation.ts @@ -0,0 +1,11 @@ +/** + * AccountParticipation describes the parameters used by this account in consensus protocol. + */ +export type AccountParticipation = { + "selection-participation-key": string; + "vote-first-valid": bigint; + "vote-key-dilution": bigint; + "vote-last-valid": bigint; + "vote-participation-key": string; + "state-proof-key"?: string; +}; diff --git a/packages/typescript/indexer_client/src/models/accountstatedelta.ts b/packages/typescript/indexer_client/src/models/accountstatedelta.ts new file mode 100644 index 000000000..b2d101cad --- /dev/null +++ b/packages/typescript/indexer_client/src/models/accountstatedelta.ts @@ -0,0 +1,6 @@ +import type { StateDelta } from "./index"; + +/** + * Application state delta. + */ +export type AccountStateDelta = { address: string; delta: StateDelta }; diff --git a/packages/typescript/indexer_client/src/models/application.ts b/packages/typescript/indexer_client/src/models/application.ts new file mode 100644 index 000000000..adc30f460 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/application.ts @@ -0,0 +1,12 @@ +import type { ApplicationParams } from "./index"; + +/** + * Application index and its parameters + */ +export type Application = { + id: bigint; + deleted?: boolean; + "created-at-round"?: bigint; + "deleted-at-round"?: bigint; + params: ApplicationParams; +}; diff --git a/packages/typescript/indexer_client/src/models/applicationlocalstate.ts b/packages/typescript/indexer_client/src/models/applicationlocalstate.ts new file mode 100644 index 000000000..cdf81c8e6 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/applicationlocalstate.ts @@ -0,0 +1,13 @@ +import type { ApplicationStateSchema, TealKeyValueStore } from "./index"; + +/** + * Stores local state associated with an application. + */ +export type ApplicationLocalState = { + id: bigint; + deleted?: boolean; + "opted-in-at-round"?: bigint; + "closed-out-at-round"?: bigint; + schema: ApplicationStateSchema; + "key-value"?: TealKeyValueStore; +}; diff --git a/packages/typescript/indexer_client/src/models/applicationlogdata.ts b/packages/typescript/indexer_client/src/models/applicationlogdata.ts new file mode 100644 index 000000000..91b880ceb --- /dev/null +++ b/packages/typescript/indexer_client/src/models/applicationlogdata.ts @@ -0,0 +1,4 @@ +/** + * Stores the global information associated with an application. + */ +export type ApplicationLogData = { txid: string; logs: string[] }; diff --git a/packages/typescript/indexer_client/src/models/applicationparams.ts b/packages/typescript/indexer_client/src/models/applicationparams.ts new file mode 100644 index 000000000..03582b67b --- /dev/null +++ b/packages/typescript/indexer_client/src/models/applicationparams.ts @@ -0,0 +1,15 @@ +import type { ApplicationStateSchema, TealKeyValueStore } from "./index"; + +/** + * Stores the global information associated with an application. + */ +export type ApplicationParams = { + creator?: string; + "approval-program"?: string; + "clear-state-program"?: string; + "extra-program-pages"?: number; + "local-state-schema"?: ApplicationStateSchema; + "global-state-schema"?: ApplicationStateSchema; + "global-state"?: TealKeyValueStore; + version?: number; +}; diff --git a/packages/typescript/indexer_client/src/models/applicationstateschema.ts b/packages/typescript/indexer_client/src/models/applicationstateschema.ts new file mode 100644 index 000000000..80ddaa431 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/applicationstateschema.ts @@ -0,0 +1,4 @@ +/** + * Specifies maximums on the number of each type that may be stored. + */ +export type ApplicationStateSchema = { "num-uint": number; "num-byte-slice": number }; diff --git a/packages/typescript/indexer_client/src/models/asset.ts b/packages/typescript/indexer_client/src/models/asset.ts new file mode 100644 index 000000000..dde90439b --- /dev/null +++ b/packages/typescript/indexer_client/src/models/asset.ts @@ -0,0 +1,6 @@ +import type { AssetParams } from "./index"; + +/** + * Specifies both the unique identifier and the parameters for an asset + */ +export type Asset = { index: bigint; deleted?: boolean; "created-at-round"?: bigint; "destroyed-at-round"?: bigint; params: AssetParams }; diff --git a/packages/typescript/indexer_client/src/models/assetholding.ts b/packages/typescript/indexer_client/src/models/assetholding.ts new file mode 100644 index 000000000..ec5599a27 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/assetholding.ts @@ -0,0 +1,14 @@ +/** + * Describes an asset held by an account. + * + * Definition: + * data/basics/userBalance.go : AssetHolding + */ +export type AssetHolding = { + amount: bigint; + "asset-id": bigint; + "is-frozen": boolean; + deleted?: boolean; + "opted-in-at-round"?: bigint; + "opted-out-at-round"?: bigint; +}; diff --git a/packages/typescript/indexer_client/src/models/assetparams.ts b/packages/typescript/indexer_client/src/models/assetparams.ts new file mode 100644 index 000000000..a7a2e4e25 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/assetparams.ts @@ -0,0 +1,25 @@ +/** + * AssetParams specifies the parameters for an asset. + * + * \[apar\] when part of an AssetConfig transaction. + * + * Definition: + * data/transactions/asset.go : AssetParams + */ +export type AssetParams = { + clawback?: string; + creator: string; + decimals: number; + "default-frozen"?: boolean; + freeze?: string; + manager?: string; + "metadata-hash"?: string; + name?: string; + "name-b64"?: string; + reserve?: string; + total: bigint; + "unit-name"?: string; + "unit-name-b64"?: string; + url?: string; + "url-b64"?: string; +}; diff --git a/packages/typescript/indexer_client/src/models/block.ts b/packages/typescript/indexer_client/src/models/block.ts new file mode 100644 index 000000000..28a9d93dd --- /dev/null +++ b/packages/typescript/indexer_client/src/models/block.ts @@ -0,0 +1,29 @@ +import type { BlockRewards, BlockUpgradeState, BlockUpgradeVote, ParticipationUpdates, StateProofTracking, Transaction } from "./index"; + +/** + * Block information. + * + * Definition: + * data/bookkeeping/block.go : Block + */ +export type Block = { + proposer?: string; + "fees-collected"?: number; + bonus?: number; + "proposer-payout"?: number; + "genesis-hash": string; + "genesis-id": string; + "previous-block-hash": string; + rewards?: BlockRewards; + round: bigint; + seed: string; + "state-proof-tracking"?: StateProofTracking[]; + timestamp: number; + transactions?: Transaction[]; + "transactions-root": string; + "transactions-root-sha256": string; + "txn-counter"?: number; + "upgrade-state"?: BlockUpgradeState; + "upgrade-vote"?: BlockUpgradeVote; + "participation-updates"?: ParticipationUpdates; +}; diff --git a/packages/typescript/indexer_client/src/models/blockrewards.ts b/packages/typescript/indexer_client/src/models/blockrewards.ts new file mode 100644 index 000000000..e460c2776 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/blockrewards.ts @@ -0,0 +1,11 @@ +/** + * Fields relating to rewards, + */ +export type BlockRewards = { + "fee-sink": string; + "rewards-calculation-round": number; + "rewards-level": number; + "rewards-pool": string; + "rewards-rate": number; + "rewards-residue": number; +}; diff --git a/packages/typescript/indexer_client/src/models/blockupgradestate.ts b/packages/typescript/indexer_client/src/models/blockupgradestate.ts new file mode 100644 index 000000000..c0eee4425 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/blockupgradestate.ts @@ -0,0 +1,10 @@ +/** + * Fields relating to a protocol upgrade. + */ +export type BlockUpgradeState = { + "current-protocol": string; + "next-protocol"?: string; + "next-protocol-approvals"?: number; + "next-protocol-switch-on"?: number; + "next-protocol-vote-before"?: number; +}; diff --git a/packages/typescript/indexer_client/src/models/blockupgradevote.ts b/packages/typescript/indexer_client/src/models/blockupgradevote.ts new file mode 100644 index 000000000..402675a6f --- /dev/null +++ b/packages/typescript/indexer_client/src/models/blockupgradevote.ts @@ -0,0 +1,4 @@ +/** + * Fields relating to voting for a protocol upgrade. + */ +export type BlockUpgradeVote = { "upgrade-approve"?: boolean; "upgrade-delay"?: number; "upgrade-propose"?: string }; diff --git a/packages/typescript/indexer_client/src/models/box.ts b/packages/typescript/indexer_client/src/models/box.ts new file mode 100644 index 000000000..90b5c64e6 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/box.ts @@ -0,0 +1,4 @@ +/** + * Box name and its content. + */ +export type Box = { round: bigint; name: string; value: string }; diff --git a/packages/typescript/indexer_client/src/models/boxdescriptor.ts b/packages/typescript/indexer_client/src/models/boxdescriptor.ts new file mode 100644 index 000000000..076918a2e --- /dev/null +++ b/packages/typescript/indexer_client/src/models/boxdescriptor.ts @@ -0,0 +1,4 @@ +/** + * Box descriptor describes an app box without a value. + */ +export type BoxDescriptor = { name: string }; diff --git a/packages/typescript/indexer_client/src/models/boxreference.ts b/packages/typescript/indexer_client/src/models/boxreference.ts new file mode 100644 index 000000000..fce3cf41d --- /dev/null +++ b/packages/typescript/indexer_client/src/models/boxreference.ts @@ -0,0 +1,4 @@ +/** + * BoxReference names a box by its name and the application ID it belongs to. + */ +export type BoxReference = { app: number; name: string }; diff --git a/packages/typescript/indexer_client/src/models/evaldelta.ts b/packages/typescript/indexer_client/src/models/evaldelta.ts new file mode 100644 index 000000000..a45620482 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/evaldelta.ts @@ -0,0 +1,4 @@ +/** + * Represents a TEAL value delta. + */ +export type EvalDelta = { action: number; bytes?: string; uint?: bigint }; diff --git a/packages/typescript/indexer_client/src/models/evaldeltakeyvalue.ts b/packages/typescript/indexer_client/src/models/evaldeltakeyvalue.ts new file mode 100644 index 000000000..63d6ea4e1 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/evaldeltakeyvalue.ts @@ -0,0 +1,6 @@ +import type { EvalDelta } from "./index"; + +/** + * Key-value pairs for StateDelta. + */ +export type EvalDeltaKeyValue = { key: string; value: EvalDelta }; diff --git a/packages/typescript/indexer_client/src/models/hashfactory.ts b/packages/typescript/indexer_client/src/models/hashfactory.ts new file mode 100644 index 000000000..19d640d10 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/hashfactory.ts @@ -0,0 +1 @@ +export type HashFactory = { "hash-type"?: number }; diff --git a/packages/typescript/indexer_client/src/models/hashtype.ts b/packages/typescript/indexer_client/src/models/hashtype.ts new file mode 100644 index 000000000..acf353f5d --- /dev/null +++ b/packages/typescript/indexer_client/src/models/hashtype.ts @@ -0,0 +1,6 @@ +/** + * The type of hash function used to create the proof, must be one of: + * * sha512_256 + * * sha256 + */ +export type Hashtype = "sha512_256" | "sha256"; diff --git a/packages/typescript/indexer_client/src/models/hbprooffields.ts b/packages/typescript/indexer_client/src/models/hbprooffields.ts new file mode 100644 index 000000000..f39f0c3da --- /dev/null +++ b/packages/typescript/indexer_client/src/models/hbprooffields.ts @@ -0,0 +1,4 @@ +/** + * \[hbprf\] HbProof is a signature using HeartbeatAddress's partkey, thereby showing it is online. + */ +export type HbProofFields = { "hb-sig"?: string; "hb-pk"?: string; "hb-pk2"?: string; "hb-pk1sig"?: string; "hb-pk2sig"?: string }; diff --git a/packages/typescript/indexer_client/src/models/healthcheck.ts b/packages/typescript/indexer_client/src/models/healthcheck.ts new file mode 100644 index 000000000..6f164901b --- /dev/null +++ b/packages/typescript/indexer_client/src/models/healthcheck.ts @@ -0,0 +1,12 @@ +/** + * A health check response. + */ +export type HealthCheck = { + version: string; + data?: {}; + round: bigint; + "is-migrating": boolean; + "db-available": boolean; + message: string; + errors?: string[]; +}; diff --git a/packages/typescript/indexer_client/src/models/index.ts b/packages/typescript/indexer_client/src/models/index.ts new file mode 100644 index 000000000..f5e8f0d60 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/index.ts @@ -0,0 +1,73 @@ +// Barrel file for models +export type { Hashtype } from "./hashtype"; +export type { Account } from "./account"; +export type { AccountParticipation } from "./accountparticipation"; +export type { ApplicationStateSchema } from "./applicationstateschema"; +export type { ApplicationLocalState } from "./applicationlocalstate"; +export type { TealKeyValueStore } from "./tealkeyvaluestore"; +export type { TealKeyValue } from "./tealkeyvalue"; +export type { TealValue } from "./tealvalue"; +export type { Application } from "./application"; +export type { ApplicationParams } from "./applicationparams"; +export type { ApplicationLogData } from "./applicationlogdata"; +export type { Asset } from "./asset"; +export type { AssetHolding } from "./assetholding"; +export type { AssetParams } from "./assetparams"; +export type { Block } from "./block"; +export type { BlockRewards } from "./blockrewards"; +export type { BlockUpgradeState } from "./blockupgradestate"; +export type { BlockUpgradeVote } from "./blockupgradevote"; +export type { Box } from "./box"; +export type { BoxDescriptor } from "./boxdescriptor"; +export type { BoxReference } from "./boxreference"; +export type { HealthCheck } from "./healthcheck"; +export type { MiniAssetHolding } from "./miniassetholding"; +export type { OnCompletion } from "./oncompletion"; +export type { ParticipationUpdates } from "./participationupdates"; +export type { StateDelta } from "./statedelta"; +export type { AccountStateDelta } from "./accountstatedelta"; +export type { EvalDeltaKeyValue } from "./evaldeltakeyvalue"; +export type { EvalDelta } from "./evaldelta"; +export type { StateSchema } from "./stateschema"; +export type { Transaction } from "./transaction"; +export type { TransactionApplication } from "./transactionapplication"; +export type { TransactionAssetConfig } from "./transactionassetconfig"; +export type { TransactionAssetFreeze } from "./transactionassetfreeze"; +export type { TransactionStateProof } from "./transactionstateproof"; +export type { TransactionHeartbeat } from "./transactionheartbeat"; +export type { TransactionAssetTransfer } from "./transactionassettransfer"; +export type { TransactionKeyreg } from "./transactionkeyreg"; +export type { TransactionPayment } from "./transactionpayment"; +export type { TransactionSignature } from "./transactionsignature"; +export type { TransactionSignatureLogicsig } from "./transactionsignaturelogicsig"; +export type { TransactionSignatureMultisig } from "./transactionsignaturemultisig"; +export type { TransactionSignatureMultisigSubsignature } from "./transactionsignaturemultisigsubsignature"; +export type { StateProofFields } from "./stateprooffields"; +export type { HbProofFields } from "./hbprooffields"; +export type { IndexerStateProofMessage } from "./indexerstateproofmessage"; +export type { StateProofReveal } from "./stateproofreveal"; +export type { StateProofSigSlot } from "./stateproofsigslot"; +export type { StateProofSignature } from "./stateproofsignature"; +export type { StateProofParticipant } from "./stateproofparticipant"; +export type { StateProofVerifier } from "./stateproofverifier"; +export type { StateProofTracking } from "./stateprooftracking"; +export type { MerkleArrayProof } from "./merklearrayproof"; +export type { HashFactory } from "./hashfactory"; +export type { SearchForAccounts } from "./searchforaccounts"; +export type { LookupAccountById } from "./lookupaccountbyid"; +export type { LookupAccountAssets } from "./lookupaccountassets"; +export type { LookupAccountCreatedAssets } from "./lookupaccountcreatedassets"; +export type { LookupAccountAppLocalStates } from "./lookupaccountapplocalstates"; +export type { LookupAccountCreatedApplications } from "./lookupaccountcreatedapplications"; +export type { LookupAccountTransactions } from "./lookupaccounttransactions"; +export type { SearchForApplications } from "./searchforapplications"; +export type { LookupApplicationById } from "./lookupapplicationbyid"; +export type { SearchForApplicationBoxes } from "./searchforapplicationboxes"; +export type { LookupApplicationLogsById } from "./lookupapplicationlogsbyid"; +export type { SearchForAssets } from "./searchforassets"; +export type { LookupAssetById } from "./lookupassetbyid"; +export type { LookupAssetBalances } from "./lookupassetbalances"; +export type { LookupAssetTransactions } from "./lookupassettransactions"; +export type { SearchForBlockHeaders } from "./searchforblockheaders"; +export type { LookupTransaction } from "./lookuptransaction"; +export type { SearchForTransactions } from "./searchfortransactions"; diff --git a/packages/typescript/indexer_client/src/models/indexerstateproofmessage.ts b/packages/typescript/indexer_client/src/models/indexerstateproofmessage.ts new file mode 100644 index 000000000..a78976c4c --- /dev/null +++ b/packages/typescript/indexer_client/src/models/indexerstateproofmessage.ts @@ -0,0 +1,7 @@ +export type IndexerStateProofMessage = { + "block-headers-commitment"?: string; + "voters-commitment"?: string; + "ln-proven-weight"?: bigint; + "first-attested-round"?: bigint; + "latest-attested-round"?: bigint; +}; diff --git a/packages/typescript/indexer_client/src/models/lookupaccountapplocalstates.ts b/packages/typescript/indexer_client/src/models/lookupaccountapplocalstates.ts new file mode 100644 index 000000000..4bb6e6edc --- /dev/null +++ b/packages/typescript/indexer_client/src/models/lookupaccountapplocalstates.ts @@ -0,0 +1,6 @@ +import type { ApplicationLocalState } from "./index"; + +/** + * (empty) + */ +export type LookupAccountAppLocalStates = { "apps-local-states": ApplicationLocalState[]; "current-round": number; "next-token"?: string }; diff --git a/packages/typescript/indexer_client/src/models/lookupaccountassets.ts b/packages/typescript/indexer_client/src/models/lookupaccountassets.ts new file mode 100644 index 000000000..ee28d1c31 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/lookupaccountassets.ts @@ -0,0 +1,6 @@ +import type { AssetHolding } from "./index"; + +/** + * (empty) + */ +export type LookupAccountAssets = { "current-round": number; "next-token"?: string; assets: AssetHolding[] }; diff --git a/packages/typescript/indexer_client/src/models/lookupaccountbyid.ts b/packages/typescript/indexer_client/src/models/lookupaccountbyid.ts new file mode 100644 index 000000000..3b2305c9a --- /dev/null +++ b/packages/typescript/indexer_client/src/models/lookupaccountbyid.ts @@ -0,0 +1,6 @@ +import type { Account } from "./index"; + +/** + * (empty) + */ +export type LookupAccountById = { account: Account; "current-round": number }; diff --git a/packages/typescript/indexer_client/src/models/lookupaccountcreatedapplications.ts b/packages/typescript/indexer_client/src/models/lookupaccountcreatedapplications.ts new file mode 100644 index 000000000..02cc0fc2a --- /dev/null +++ b/packages/typescript/indexer_client/src/models/lookupaccountcreatedapplications.ts @@ -0,0 +1,6 @@ +import type { Application } from "./index"; + +/** + * (empty) + */ +export type LookupAccountCreatedApplications = { applications: Application[]; "current-round": number; "next-token"?: string }; diff --git a/packages/typescript/indexer_client/src/models/lookupaccountcreatedassets.ts b/packages/typescript/indexer_client/src/models/lookupaccountcreatedassets.ts new file mode 100644 index 000000000..771875fc4 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/lookupaccountcreatedassets.ts @@ -0,0 +1,6 @@ +import type { Asset } from "./index"; + +/** + * (empty) + */ +export type LookupAccountCreatedAssets = { assets: Asset[]; "current-round": number; "next-token"?: string }; diff --git a/packages/typescript/indexer_client/src/models/lookupaccounttransactions.ts b/packages/typescript/indexer_client/src/models/lookupaccounttransactions.ts new file mode 100644 index 000000000..a7c6ddcf5 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/lookupaccounttransactions.ts @@ -0,0 +1,6 @@ +import type { Transaction } from "./index"; + +/** + * (empty) + */ +export type LookupAccountTransactions = { "current-round": number; "next-token"?: string; transactions: Transaction[] }; diff --git a/packages/typescript/indexer_client/src/models/lookupapplicationbyid.ts b/packages/typescript/indexer_client/src/models/lookupapplicationbyid.ts new file mode 100644 index 000000000..729d684b1 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/lookupapplicationbyid.ts @@ -0,0 +1,6 @@ +import type { Application } from "./index"; + +/** + * (empty) + */ +export type LookupApplicationById = { application?: Application; "current-round": number }; diff --git a/packages/typescript/indexer_client/src/models/lookupapplicationlogsbyid.ts b/packages/typescript/indexer_client/src/models/lookupapplicationlogsbyid.ts new file mode 100644 index 000000000..1e6024f24 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/lookupapplicationlogsbyid.ts @@ -0,0 +1,11 @@ +import type { ApplicationLogData } from "./index"; + +/** + * (empty) + */ +export type LookupApplicationLogsById = { + "application-id": number; + "current-round": number; + "next-token"?: string; + "log-data"?: ApplicationLogData[]; +}; diff --git a/packages/typescript/indexer_client/src/models/lookupassetbalances.ts b/packages/typescript/indexer_client/src/models/lookupassetbalances.ts new file mode 100644 index 000000000..6ebe8375a --- /dev/null +++ b/packages/typescript/indexer_client/src/models/lookupassetbalances.ts @@ -0,0 +1,6 @@ +import type { MiniAssetHolding } from "./index"; + +/** + * (empty) + */ +export type LookupAssetBalances = { balances: MiniAssetHolding[]; "current-round": number; "next-token"?: string }; diff --git a/packages/typescript/indexer_client/src/models/lookupassetbyid.ts b/packages/typescript/indexer_client/src/models/lookupassetbyid.ts new file mode 100644 index 000000000..df3432ba3 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/lookupassetbyid.ts @@ -0,0 +1,6 @@ +import type { Asset } from "./index"; + +/** + * (empty) + */ +export type LookupAssetById = { asset: Asset; "current-round": number }; diff --git a/packages/typescript/indexer_client/src/models/lookupassettransactions.ts b/packages/typescript/indexer_client/src/models/lookupassettransactions.ts new file mode 100644 index 000000000..26cdcbd25 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/lookupassettransactions.ts @@ -0,0 +1,6 @@ +import type { Transaction } from "./index"; + +/** + * (empty) + */ +export type LookupAssetTransactions = { "current-round": number; "next-token"?: string; transactions: Transaction[] }; diff --git a/packages/typescript/indexer_client/src/models/lookuptransaction.ts b/packages/typescript/indexer_client/src/models/lookuptransaction.ts new file mode 100644 index 000000000..7412f95bc --- /dev/null +++ b/packages/typescript/indexer_client/src/models/lookuptransaction.ts @@ -0,0 +1,6 @@ +import type { Transaction } from "./index"; + +/** + * (empty) + */ +export type LookupTransaction = { transaction: Transaction; "current-round": number }; diff --git a/packages/typescript/indexer_client/src/models/merklearrayproof.ts b/packages/typescript/indexer_client/src/models/merklearrayproof.ts new file mode 100644 index 000000000..2440c2e17 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/merklearrayproof.ts @@ -0,0 +1,3 @@ +import type { HashFactory } from "./index"; + +export type MerkleArrayProof = { path?: string[]; "hash-factory"?: HashFactory; "tree-depth"?: number }; diff --git a/packages/typescript/indexer_client/src/models/miniassetholding.ts b/packages/typescript/indexer_client/src/models/miniassetholding.ts new file mode 100644 index 000000000..6bb3543b7 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/miniassetholding.ts @@ -0,0 +1,11 @@ +/** + * A simplified version of AssetHolding + */ +export type MiniAssetHolding = { + address: string; + amount: bigint; + "is-frozen": boolean; + deleted?: boolean; + "opted-in-at-round"?: bigint; + "opted-out-at-round"?: bigint; +}; diff --git a/packages/typescript/indexer_client/src/models/oncompletion.ts b/packages/typescript/indexer_client/src/models/oncompletion.ts new file mode 100644 index 000000000..2d5336344 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/oncompletion.ts @@ -0,0 +1,12 @@ +/** + * \[apan\] defines the what additional actions occur with the transaction. + * + * Valid types: + * * noop + * * optin + * * closeout + * * clear + * * update + * * delete + */ +export type OnCompletion = "noop" | "optin" | "closeout" | "clear" | "update" | "delete"; diff --git a/packages/typescript/indexer_client/src/models/participationupdates.ts b/packages/typescript/indexer_client/src/models/participationupdates.ts new file mode 100644 index 000000000..614c1407c --- /dev/null +++ b/packages/typescript/indexer_client/src/models/participationupdates.ts @@ -0,0 +1,4 @@ +/** + * Participation account data that needs to be checked/acted on by the network. + */ +export type ParticipationUpdates = { "expired-participation-accounts"?: string[]; "absent-participation-accounts"?: string[] }; diff --git a/packages/typescript/indexer_client/src/models/searchforaccounts.ts b/packages/typescript/indexer_client/src/models/searchforaccounts.ts new file mode 100644 index 000000000..a5dcf8acd --- /dev/null +++ b/packages/typescript/indexer_client/src/models/searchforaccounts.ts @@ -0,0 +1,6 @@ +import type { Account } from "./index"; + +/** + * (empty) + */ +export type SearchForAccounts = { accounts: Account[]; "current-round": number; "next-token"?: string }; diff --git a/packages/typescript/indexer_client/src/models/searchforapplicationboxes.ts b/packages/typescript/indexer_client/src/models/searchforapplicationboxes.ts new file mode 100644 index 000000000..f17138753 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/searchforapplicationboxes.ts @@ -0,0 +1,6 @@ +import type { BoxDescriptor } from "./index"; + +/** + * Box names of an application + */ +export type SearchForApplicationBoxes = { "application-id": number; boxes: BoxDescriptor[]; "next-token"?: string }; diff --git a/packages/typescript/indexer_client/src/models/searchforapplications.ts b/packages/typescript/indexer_client/src/models/searchforapplications.ts new file mode 100644 index 000000000..5f2f5e43c --- /dev/null +++ b/packages/typescript/indexer_client/src/models/searchforapplications.ts @@ -0,0 +1,6 @@ +import type { Application } from "./index"; + +/** + * (empty) + */ +export type SearchForApplications = { applications: Application[]; "current-round": number; "next-token"?: string }; diff --git a/packages/typescript/indexer_client/src/models/searchforassets.ts b/packages/typescript/indexer_client/src/models/searchforassets.ts new file mode 100644 index 000000000..3d237c06c --- /dev/null +++ b/packages/typescript/indexer_client/src/models/searchforassets.ts @@ -0,0 +1,6 @@ +import type { Asset } from "./index"; + +/** + * (empty) + */ +export type SearchForAssets = { assets: Asset[]; "current-round": number; "next-token"?: string }; diff --git a/packages/typescript/indexer_client/src/models/searchforblockheaders.ts b/packages/typescript/indexer_client/src/models/searchforblockheaders.ts new file mode 100644 index 000000000..ae1763229 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/searchforblockheaders.ts @@ -0,0 +1,6 @@ +import type { Block } from "./index"; + +/** + * (empty) + */ +export type SearchForBlockHeaders = { "current-round": number; "next-token"?: string; blocks: Block[] }; diff --git a/packages/typescript/indexer_client/src/models/searchfortransactions.ts b/packages/typescript/indexer_client/src/models/searchfortransactions.ts new file mode 100644 index 000000000..65640be82 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/searchfortransactions.ts @@ -0,0 +1,6 @@ +import type { Transaction } from "./index"; + +/** + * (empty) + */ +export type SearchForTransactions = { "current-round": number; "next-token"?: string; transactions: Transaction[] }; diff --git a/packages/typescript/indexer_client/src/models/statedelta.ts b/packages/typescript/indexer_client/src/models/statedelta.ts new file mode 100644 index 000000000..2f09ff92a --- /dev/null +++ b/packages/typescript/indexer_client/src/models/statedelta.ts @@ -0,0 +1,6 @@ +import type { EvalDeltaKeyValue } from "./index"; + +/** + * Application state delta. + */ +export type StateDelta = EvalDeltaKeyValue[]; diff --git a/packages/typescript/indexer_client/src/models/stateprooffields.ts b/packages/typescript/indexer_client/src/models/stateprooffields.ts new file mode 100644 index 000000000..c583170d8 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/stateprooffields.ts @@ -0,0 +1,17 @@ +import type { MerkleArrayProof, StateProofReveal } from "./index"; + +/** + * \[sp\] represents a state proof. + * + * Definition: + * crypto/stateproof/structs.go : StateProof + */ +export type StateProofFields = { + "sig-commit"?: string; + "signed-weight"?: bigint; + "sig-proofs"?: MerkleArrayProof; + "part-proofs"?: MerkleArrayProof; + "salt-version"?: number; + reveals?: StateProofReveal[]; + "positions-to-reveal"?: bigint[]; +}; diff --git a/packages/typescript/indexer_client/src/models/stateproofparticipant.ts b/packages/typescript/indexer_client/src/models/stateproofparticipant.ts new file mode 100644 index 000000000..fe4097183 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/stateproofparticipant.ts @@ -0,0 +1,3 @@ +import type { StateProofVerifier } from "./index"; + +export type StateProofParticipant = { verifier?: StateProofVerifier; weight?: bigint }; diff --git a/packages/typescript/indexer_client/src/models/stateproofreveal.ts b/packages/typescript/indexer_client/src/models/stateproofreveal.ts new file mode 100644 index 000000000..ee36a8fab --- /dev/null +++ b/packages/typescript/indexer_client/src/models/stateproofreveal.ts @@ -0,0 +1,3 @@ +import type { StateProofParticipant, StateProofSigSlot } from "./index"; + +export type StateProofReveal = { position?: bigint; "sig-slot"?: StateProofSigSlot; participant?: StateProofParticipant }; diff --git a/packages/typescript/indexer_client/src/models/stateproofsignature.ts b/packages/typescript/indexer_client/src/models/stateproofsignature.ts new file mode 100644 index 000000000..6eff2a95c --- /dev/null +++ b/packages/typescript/indexer_client/src/models/stateproofsignature.ts @@ -0,0 +1,8 @@ +import type { MerkleArrayProof } from "./index"; + +export type StateProofSignature = { + "falcon-signature"?: string; + "merkle-array-index"?: number; + proof?: MerkleArrayProof; + "verifying-key"?: string; +}; diff --git a/packages/typescript/indexer_client/src/models/stateproofsigslot.ts b/packages/typescript/indexer_client/src/models/stateproofsigslot.ts new file mode 100644 index 000000000..7c4de01b3 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/stateproofsigslot.ts @@ -0,0 +1,3 @@ +import type { StateProofSignature } from "./index"; + +export type StateProofSigSlot = { signature?: StateProofSignature; "lower-sig-weight"?: bigint }; diff --git a/packages/typescript/indexer_client/src/models/stateprooftracking.ts b/packages/typescript/indexer_client/src/models/stateprooftracking.ts new file mode 100644 index 000000000..86ea41947 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/stateprooftracking.ts @@ -0,0 +1 @@ +export type StateProofTracking = { type?: bigint; "voters-commitment"?: string; "online-total-weight"?: number; "next-round"?: number }; diff --git a/packages/typescript/indexer_client/src/models/stateproofverifier.ts b/packages/typescript/indexer_client/src/models/stateproofverifier.ts new file mode 100644 index 000000000..e8a56c534 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/stateproofverifier.ts @@ -0,0 +1 @@ +export type StateProofVerifier = { commitment?: string; "key-lifetime"?: bigint }; diff --git a/packages/typescript/indexer_client/src/models/stateschema.ts b/packages/typescript/indexer_client/src/models/stateschema.ts new file mode 100644 index 000000000..30effa44f --- /dev/null +++ b/packages/typescript/indexer_client/src/models/stateschema.ts @@ -0,0 +1,4 @@ +/** + * 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. + */ +export type StateSchema = { "num-uint": number; "num-byte-slice": number }; diff --git a/packages/typescript/indexer_client/src/models/tealkeyvalue.ts b/packages/typescript/indexer_client/src/models/tealkeyvalue.ts new file mode 100644 index 000000000..aeeee7399 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/tealkeyvalue.ts @@ -0,0 +1,6 @@ +import type { TealValue } from "./index"; + +/** + * Represents a key-value pair in an application store. + */ +export type TealKeyValue = { key: string; value: TealValue }; diff --git a/packages/typescript/indexer_client/src/models/tealkeyvaluestore.ts b/packages/typescript/indexer_client/src/models/tealkeyvaluestore.ts new file mode 100644 index 000000000..6dbc2b693 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/tealkeyvaluestore.ts @@ -0,0 +1,6 @@ +import type { TealKeyValue } from "./index"; + +/** + * Represents a key-value store for use in an application. + */ +export type TealKeyValueStore = TealKeyValue[]; diff --git a/packages/typescript/indexer_client/src/models/tealvalue.ts b/packages/typescript/indexer_client/src/models/tealvalue.ts new file mode 100644 index 000000000..c98f15d78 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/tealvalue.ts @@ -0,0 +1,4 @@ +/** + * Represents a TEAL value. + */ +export type TealValue = { type: number; bytes: string; uint: bigint }; diff --git a/packages/typescript/indexer_client/src/models/transaction.ts b/packages/typescript/indexer_client/src/models/transaction.ts new file mode 100644 index 000000000..c84ef92a7 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/transaction.ts @@ -0,0 +1,58 @@ +import type { + AccountStateDelta, + StateDelta, + TransactionApplication, + TransactionAssetConfig, + TransactionAssetFreeze, + TransactionAssetTransfer, + TransactionHeartbeat, + TransactionKeyreg, + TransactionPayment, + TransactionSignature, + TransactionStateProof, +} from "./index"; + +/** + * Contains all fields common to all transactions and serves as an envelope to all transactions type. Represents both regular and inner transactions. + * + * Definition: + * data/transactions/signedtxn.go : SignedTxn + * data/transactions/transaction.go : Transaction + */ +export type Transaction = { + "application-transaction"?: TransactionApplication; + "asset-config-transaction"?: TransactionAssetConfig; + "asset-freeze-transaction"?: TransactionAssetFreeze; + "asset-transfer-transaction"?: TransactionAssetTransfer; + "state-proof-transaction"?: TransactionStateProof; + "heartbeat-transaction"?: TransactionHeartbeat; + "auth-addr"?: string; + "close-rewards"?: number; + "closing-amount"?: bigint; + "confirmed-round"?: bigint; + "created-application-index"?: number; + "created-asset-index"?: number; + fee: bigint; + "first-valid": number; + "genesis-hash"?: string; + "genesis-id"?: string; + group?: string; + id?: string; + "intra-round-offset"?: number; + "keyreg-transaction"?: TransactionKeyreg; + "last-valid": number; + lease?: string; + note?: string; + "payment-transaction"?: TransactionPayment; + "receiver-rewards"?: number; + "rekey-to"?: string; + "round-time"?: number; + sender: string; + "sender-rewards"?: number; + signature?: TransactionSignature; + "tx-type": "pay" | "keyreg" | "acfg" | "axfer" | "afrz" | "appl" | "stpf" | "hb"; + "local-state-delta"?: AccountStateDelta[]; + "global-state-delta"?: StateDelta; + logs?: string[]; + "inner-txns"?: Transaction[]; +}; diff --git a/packages/typescript/indexer_client/src/models/transactionapplication.ts b/packages/typescript/indexer_client/src/models/transactionapplication.ts new file mode 100644 index 000000000..a97b8e24c --- /dev/null +++ b/packages/typescript/indexer_client/src/models/transactionapplication.ts @@ -0,0 +1,23 @@ +import type { BoxReference, OnCompletion, StateSchema } from "./index"; + +/** + * Fields for application transactions. + * + * Definition: + * data/transactions/application.go : ApplicationCallTxnFields + */ +export type TransactionApplication = { + "application-id": number; + "on-completion": OnCompletion; + "application-args"?: string[]; + accounts?: string[]; + "box-references"?: BoxReference[]; + "foreign-apps"?: number[]; + "foreign-assets"?: number[]; + "local-state-schema"?: StateSchema; + "global-state-schema"?: StateSchema; + "approval-program"?: string; + "clear-state-program"?: string; + "extra-program-pages"?: number; + "reject-version"?: number; +}; diff --git a/packages/typescript/indexer_client/src/models/transactionassetconfig.ts b/packages/typescript/indexer_client/src/models/transactionassetconfig.ts new file mode 100644 index 000000000..92916045b --- /dev/null +++ b/packages/typescript/indexer_client/src/models/transactionassetconfig.ts @@ -0,0 +1,13 @@ +import type { AssetParams } from "./index"; + +/** + * Fields for asset allocation, re-configuration, and destruction. + * + * + * A zero value for asset-id indicates asset creation. + * A zero value for the params indicates asset destruction. + * + * Definition: + * data/transactions/asset.go : AssetConfigTxnFields + */ +export type TransactionAssetConfig = { "asset-id"?: bigint; params?: AssetParams }; diff --git a/packages/typescript/indexer_client/src/models/transactionassetfreeze.ts b/packages/typescript/indexer_client/src/models/transactionassetfreeze.ts new file mode 100644 index 000000000..0628282bf --- /dev/null +++ b/packages/typescript/indexer_client/src/models/transactionassetfreeze.ts @@ -0,0 +1,7 @@ +/** + * Fields for an asset freeze transaction. + * + * Definition: + * data/transactions/asset.go : AssetFreezeTxnFields + */ +export type TransactionAssetFreeze = { address: string; "asset-id": bigint; "new-freeze-status": boolean }; diff --git a/packages/typescript/indexer_client/src/models/transactionassettransfer.ts b/packages/typescript/indexer_client/src/models/transactionassettransfer.ts new file mode 100644 index 000000000..eb5afffbe --- /dev/null +++ b/packages/typescript/indexer_client/src/models/transactionassettransfer.ts @@ -0,0 +1,14 @@ +/** + * Fields for an asset transfer transaction. + * + * Definition: + * data/transactions/asset.go : AssetTransferTxnFields + */ +export type TransactionAssetTransfer = { + amount: bigint; + "asset-id": bigint; + "close-amount"?: bigint; + "close-to"?: string; + receiver: string; + sender?: string; +}; diff --git a/packages/typescript/indexer_client/src/models/transactionheartbeat.ts b/packages/typescript/indexer_client/src/models/transactionheartbeat.ts new file mode 100644 index 000000000..4d1037cb6 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/transactionheartbeat.ts @@ -0,0 +1,15 @@ +import type { HbProofFields } from "./index"; + +/** + * Fields for a heartbeat transaction. + * + * Definition: + * data/transactions/heartbeat.go : HeartbeatTxnFields + */ +export type TransactionHeartbeat = { + "hb-address": string; + "hb-proof": HbProofFields; + "hb-seed": string; + "hb-vote-id": string; + "hb-key-dilution": bigint; +}; diff --git a/packages/typescript/indexer_client/src/models/transactionkeyreg.ts b/packages/typescript/indexer_client/src/models/transactionkeyreg.ts new file mode 100644 index 000000000..fd69a8ca4 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/transactionkeyreg.ts @@ -0,0 +1,15 @@ +/** + * Fields for a keyreg transaction. + * + * Definition: + * data/transactions/keyreg.go : KeyregTxnFields + */ +export type TransactionKeyreg = { + "non-participation"?: boolean; + "selection-participation-key"?: string; + "vote-first-valid"?: bigint; + "vote-key-dilution"?: bigint; + "vote-last-valid"?: bigint; + "vote-participation-key"?: string; + "state-proof-key"?: string; +}; diff --git a/packages/typescript/indexer_client/src/models/transactionpayment.ts b/packages/typescript/indexer_client/src/models/transactionpayment.ts new file mode 100644 index 000000000..69370a25f --- /dev/null +++ b/packages/typescript/indexer_client/src/models/transactionpayment.ts @@ -0,0 +1,7 @@ +/** + * Fields for a payment transaction. + * + * Definition: + * data/transactions/payment.go : PaymentTxnFields + */ +export type TransactionPayment = { amount: bigint; "close-amount"?: number; "close-remainder-to"?: string; receiver: string }; diff --git a/packages/typescript/indexer_client/src/models/transactionsignature.ts b/packages/typescript/indexer_client/src/models/transactionsignature.ts new file mode 100644 index 000000000..48f303a62 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/transactionsignature.ts @@ -0,0 +1,6 @@ +import type { TransactionSignatureLogicsig, TransactionSignatureMultisig } from "./index"; + +/** + * Validation signature associated with some data. Only one of the signatures should be provided. + */ +export type TransactionSignature = { logicsig?: TransactionSignatureLogicsig; multisig?: TransactionSignatureMultisig; sig?: string }; diff --git a/packages/typescript/indexer_client/src/models/transactionsignaturelogicsig.ts b/packages/typescript/indexer_client/src/models/transactionsignaturelogicsig.ts new file mode 100644 index 000000000..d708af8e5 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/transactionsignaturelogicsig.ts @@ -0,0 +1,14 @@ +import type { TransactionSignatureMultisig } from "./index"; + +/** + * \[lsig\] Programatic transaction signature. + * + * Definition: + * data/transactions/logicsig.go + */ +export type TransactionSignatureLogicsig = { + args?: string[]; + logic: string; + "multisig-signature"?: TransactionSignatureMultisig; + signature?: string; +}; diff --git a/packages/typescript/indexer_client/src/models/transactionsignaturemultisig.ts b/packages/typescript/indexer_client/src/models/transactionsignaturemultisig.ts new file mode 100644 index 000000000..7bf1aca48 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/transactionsignaturemultisig.ts @@ -0,0 +1,13 @@ +import type { TransactionSignatureMultisigSubsignature } from "./index"; + +/** + * \[msig\] structure holding multiple subsignatures. + * + * Definition: + * crypto/multisig.go : MultisigSig + */ +export type TransactionSignatureMultisig = { + subsignature?: TransactionSignatureMultisigSubsignature[]; + threshold?: number; + version?: number; +}; diff --git a/packages/typescript/indexer_client/src/models/transactionsignaturemultisigsubsignature.ts b/packages/typescript/indexer_client/src/models/transactionsignaturemultisigsubsignature.ts new file mode 100644 index 000000000..75d8df5f6 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/transactionsignaturemultisigsubsignature.ts @@ -0,0 +1 @@ +export type TransactionSignatureMultisigSubsignature = { "public-key"?: string; signature?: string }; diff --git a/packages/typescript/indexer_client/src/models/transactionstateproof.ts b/packages/typescript/indexer_client/src/models/transactionstateproof.ts new file mode 100644 index 000000000..dbf6e0235 --- /dev/null +++ b/packages/typescript/indexer_client/src/models/transactionstateproof.ts @@ -0,0 +1,9 @@ +import type { IndexerStateProofMessage, StateProofFields } from "./index"; + +/** + * Fields for a state proof transaction. + * + * Definition: + * data/transactions/stateproof.go : StateProofTxnFields + */ +export type TransactionStateProof = { "state-proof-type"?: bigint; "state-proof"?: StateProofFields; message?: IndexerStateProofMessage }; diff --git a/packages/typescript/indexer_client/tests/generated/smoke.generated.spec.ts b/packages/typescript/indexer_client/tests/generated/smoke.generated.spec.ts new file mode 100644 index 000000000..d2a0f9e98 --- /dev/null +++ b/packages/typescript/indexer_client/tests/generated/smoke.generated.spec.ts @@ -0,0 +1,49 @@ +/* AUTO-GENERATED FILE - DO NOT EDIT DIRECTLY. + * This smoke test is generated by ts_oas_generator. + * Location: tests/generated/smoke.generated.spec.ts + */ +import { describe, expect, it } from "vitest"; +import { Client } from "../src/client"; + +const BASE = "http://localhost/"; + +declare global { + // eslint-disable-next-line no-var, vars-on-top + var fetch: any; +} + +describe("JSON BigInt parsing", () => { + it("parses bigint values using json-bigint", async () => { + const big = "18446744073709551615"; // > Number.MAX_SAFE_INTEGER + global.fetch = async () => ({ + ok: true, + headers: new Map([["content-type", "application/json"]]), + text: async () => JSON.stringify({ value: big }), + arrayBuffer: async () => new ArrayBuffer(0), + }); + + const client = new Client({ BASE }); + // Directly use request core to keep template-agnostic + const res = await client.request.request<{ value: bigint }>({ method: "GET", url: "/foo" }); + expect(typeof res.value).toBe("bigint"); + }); +}); + +describe("Msgpack binary response", () => { + it("decodes msgpack into structured data", async () => { + // eslint-disable-next-line @typescript-eslint/no-var-requires + const { encode } = require("algo-msgpack-with-bigint"); + const msg = { ok: 1n, small: 2 }; + const bytes: Uint8Array = encode(msg); + global.fetch = async () => ({ + ok: true, + headers: new Map([["content-type", "application/msgpack"]]), + text: async () => "", + arrayBuffer: async () => bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength), + }); + + const client = new Client({ BASE }); + const res = await client.request.request<{ ok: bigint | number; small: number }>({ method: "GET", url: "/foo", expectBinary: true }); + expect(res).toHaveProperty("ok"); + }); +}); diff --git a/packages/typescript/indexer_client/tests/helpers/env.ts b/packages/typescript/indexer_client/tests/helpers/env.ts new file mode 100644 index 000000000..0723ae150 --- /dev/null +++ b/packages/typescript/indexer_client/tests/helpers/env.ts @@ -0,0 +1,18 @@ +import { describe } from "vitest"; + +export interface IndexerEnvConfig { + indexerBaseUrl: string; + indexerApiToken?: string; +} + +export function getIndexerEnv(): IndexerEnvConfig { + return { + indexerBaseUrl: process.env.INDEXER_BASE_URL ?? "http://localhost:8980", + // Default token for localnet (if required by reverse proxy) + indexerApiToken: process.env.INDEXER_API_TOKEN ?? "a".repeat(64), + }; +} + +export function maybeDescribe(name: string, fn: (env: IndexerEnvConfig) => void) { + describe(name, () => fn(getIndexerEnv())); +} diff --git a/packages/typescript/indexer_client/tests/helpers/wait.ts b/packages/typescript/indexer_client/tests/helpers/wait.ts new file mode 100644 index 000000000..cfffdd399 --- /dev/null +++ b/packages/typescript/indexer_client/tests/helpers/wait.ts @@ -0,0 +1,16 @@ +export async function waitFor( + fn: () => Promise, + predicate: (v: T) => boolean, + opts?: { timeoutMs?: number; intervalMs?: number }, +): Promise { + const timeoutMs = opts?.timeoutMs ?? 10_000; + const intervalMs = opts?.intervalMs ?? 500; + const start = Date.now(); + // eslint-disable-next-line no-constant-condition + while (true) { + const v = await fn(); + if (predicate(v)) return v; + if (Date.now() - start > timeoutMs) throw new Error("waitFor: timeout"); + await new Promise((r) => setTimeout(r, intervalMs)); + } +} diff --git a/packages/typescript/indexer_client/tests/searchTransactions.spec.ts b/packages/typescript/indexer_client/tests/searchTransactions.spec.ts new file mode 100644 index 000000000..4bc418884 --- /dev/null +++ b/packages/typescript/indexer_client/tests/searchTransactions.spec.ts @@ -0,0 +1,15 @@ +import { expect, it } from "vitest"; +import { Client } from "../src/client"; +import { maybeDescribe } from "./helpers/env"; + +maybeDescribe("Indexer searchTransactions", (env) => { + it("searches for recent transactions", async () => { + const client = new Client({ + BASE: env.indexerBaseUrl, + HEADERS: env.indexerApiToken ? { "X-Algo-API-Token": env.indexerApiToken } : undefined, + }); + const res = await client.api.searchForTransactions({ limit: 5 }); + expect(res).toHaveProperty("transactions"); + expect(Array.isArray(res.transactions)).toBe(true); + }); +}); diff --git a/packages/typescript/indexer_client/tests/smoke.spec.ts b/packages/typescript/indexer_client/tests/smoke.spec.ts new file mode 100644 index 000000000..c19a27e89 --- /dev/null +++ b/packages/typescript/indexer_client/tests/smoke.spec.ts @@ -0,0 +1,46 @@ +import { describe, expect, it } from "vitest"; +import { Client } from "../src/client"; + +const BASE = "http://localhost/"; + +declare global { + // eslint-disable-next-line no-var, vars-on-top + var fetch: any; +} + +describe("JSON BigInt parsing", () => { + it("parses bigint values using json-bigint", async () => { + const big = "18446744073709551615"; // > Number.MAX_SAFE_INTEGER + global.fetch = async () => ({ + ok: true, + headers: new Map([["content-type", "application/json"]]), + text: async () => JSON.stringify({ value: big }), + arrayBuffer: async () => new ArrayBuffer(0), + }); + + const client = new Client({ BASE, INT_DECODING: "bigint" }); + // Directly use request core to keep template-agnostic + const res = await client.request.request<{ value: bigint }>({ method: "GET", url: "/foo" }); + expect(typeof res.value).toBe("bigint"); + }); +}); + +describe("Msgpack binary response", () => { + it("decodes msgpack into structured data", async () => { + // eslint-disable-next-line @typescript-eslint/no-var-requires + const { encode } = require("algo-msgpack-with-bigint"); + const payload = { ok: 1n, text: "hi" }; + const bytes: Uint8Array = encode(payload); + global.fetch = async () => ({ + ok: true, + headers: new Map([["content-type", "application/msgpack"]]), + text: async () => "", + arrayBuffer: async () => bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength), + }); + + const client = new Client({ BASE }); + const res = await client.request.request<{ ok: bigint | number; text: string }>({ method: "GET", url: "/foo", expectBinary: true }); + expect(res).toHaveProperty("ok"); + expect(res).toHaveProperty("text", "hi"); + }); +}); diff --git a/packages/typescript/indexer_client/tests/src/client.ts b/packages/typescript/indexer_client/tests/src/client.ts new file mode 100644 index 000000000..4b25d837e --- /dev/null +++ b/packages/typescript/indexer_client/tests/src/client.ts @@ -0,0 +1,10 @@ +import type { OpenAPIConfig } from "../../src/core/OpenAPI"; +import { Client as BaseClient } from "../../src/client"; + +export * from "../../src/client"; + +export class Client extends BaseClient { + constructor(config: OpenAPIConfig) { + super({ INT_DECODING: config.INT_DECODING ?? "bigint", ...config }); + } +} diff --git a/packages/typescript/indexer_client/tsconfig.json b/packages/typescript/indexer_client/tsconfig.json new file mode 100644 index 000000000..7a538edc0 --- /dev/null +++ b/packages/typescript/indexer_client/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "ES2020", + "moduleResolution": "node", + "declaration": true, + "outDir": "dist", + "rootDir": "src", + "strict": true, + "skipLibCheck": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/tools/api_tools/src/main.rs b/tools/api_tools/src/main.rs index e3ed64e6e..2e34206cf 100644 --- a/tools/api_tools/src/main.rs +++ b/tools/api_tools/src/main.rs @@ -6,6 +6,7 @@ use std::process::Output; use clap::{Parser, Subcommand}; use color_eyre::eyre::Result; use duct::cmd; +use std::fs; #[derive(Parser, Debug)] #[command(author, version, about = "API development tools", long_about = None)] @@ -41,6 +42,15 @@ enum Commands { /// Generate both algod and indexer API clients #[command(name = "generate-all")] GenerateAll, + /// Generate TypeScript algod client + #[command(name = "generate-ts-algod")] + GenerateTsAlgod, + /// Generate TypeScript indexer client + #[command(name = "generate-ts-indexer")] + GenerateTsIndexer, + /// Generate both TypeScript clients (algod and indexer) + #[command(name = "generate-ts-all")] + GenerateTsAll, /// Convert OpenAPI specifications (both algod and indexer) #[command(name = "convert-openapi")] ConvertOpenapi, @@ -85,6 +95,32 @@ fn run( } fn execute_command(command: &Commands) -> Result<()> { + fn clean_ts_package(rel_dir: &str) -> Result<()> { + let root = get_repo_root(); + let pkg_dir = root.join(rel_dir); + if !pkg_dir.exists() { + return Ok(()); + } + + let preserve: Vec<&str> = vec!["tests", "node_modules"]; + for entry in fs::read_dir(&pkg_dir)? { + let entry = entry?; + let name = entry.file_name(); + let name_str = name.to_string_lossy(); + if preserve.iter().any(|p| *p == name_str) { + continue; + } + let path = entry.path(); + if path.is_dir() { + // Remove entire directory tree + fs::remove_dir_all(&path)?; + } else { + // Remove file + fs::remove_file(&path)?; + } + } + Ok(()) + } match command { Commands::TestOas => { run("uv run pytest", Some(Path::new("api/oas_generator")), None)?; @@ -175,6 +211,88 @@ fn execute_command(command: &Commands) -> Result<()> { None, )?; } + Commands::GenerateTsAlgod => { + // Clean package directory but preserve manual tests and node_modules + clean_ts_package("packages/typescript/algod_client")?; + // Generate the TypeScript client (algod) + run( + "uv run python -m ts_oas_generator.cli ../specs/algod.oas3.json --output ../../packages/typescript/algod_client/ --package-name algod_client --description \"TypeScript client for algod interaction.\" --verbose", + Some(Path::new("api/oas_generator")), + None, + )?; + // Format generated code + run( + "npx --yes prettier --write .", + Some(Path::new("packages/typescript/algod_client")), + None, + )?; + // Build the generated package + run( + "bun run build", + Some(Path::new("packages/typescript/algod_client")), + None, + )?; + } + Commands::GenerateTsIndexer => { + // Clean package directory but preserve manual tests and node_modules + clean_ts_package("packages/typescript/indexer_client")?; + // Generate the TypeScript client (indexer) + run( + "uv run python -m ts_oas_generator.cli ../specs/indexer.oas3.json --output ../../packages/typescript/indexer_client/ --package-name indexer_client --description \"TypeScript client for indexer interaction.\" --verbose", + Some(Path::new("api/oas_generator")), + None, + )?; + // Format generated code + run( + "npx --yes prettier --write .", + Some(Path::new("packages/typescript/indexer_client")), + None, + )?; + // Build the generated package + run( + "bun run build", + Some(Path::new("packages/typescript/indexer_client")), + None, + )?; + } + Commands::GenerateTsAll => { + // Clean package directories while preserving manual tests and node_modules + clean_ts_package("packages/typescript/algod_client")?; + clean_ts_package("packages/typescript/indexer_client")?; + // Generate both TypeScript clients + run( + "uv run python -m ts_oas_generator.cli ../specs/algod.oas3.json --output ../../packages/typescript/algod_client/ --package-name algod_client --description \"TypeScript client for algod interaction.\"", + Some(Path::new("api/oas_generator")), + None, + )?; + run( + "uv run python -m ts_oas_generator.cli ../specs/indexer.oas3.json --output ../../packages/typescript/indexer_client/ --package-name indexer_client --description \"TypeScript client for indexer interaction.\"", + Some(Path::new("api/oas_generator")), + None, + )?; + // Format both generated packages + run( + "npx --yes prettier --write .", + Some(Path::new("packages/typescript/algod_client")), + None, + )?; + run( + "npx --yes prettier --write .", + Some(Path::new("packages/typescript/indexer_client")), + None, + )?; + // Build both packages + run( + "bun run build", + Some(Path::new("packages/typescript/algod_client")), + None, + )?; + run( + "bun run build", + Some(Path::new("packages/typescript/indexer_client")), + None, + )?; + } Commands::ConvertOpenapi => { run( "bun scripts/convert-openapi.ts", From 4906fad3e1011870b2e9e23051d082334bf7c8b9 Mon Sep 17 00:00:00 2001 From: Altynbek Orumbayev Date: Mon, 8 Sep 2025 18:08:26 +0200 Subject: [PATCH 2/4] refactor: addressing pr comments --- .github/actions/setup-api-tools/action.yml | 18 +- .github/workflows/api_ci.yml | 6 + api/oas_generator/ts_oas_generator/cli.py | 31 +- .../ts_oas_generator/generator/filters.py | 13 +- .../generator/template_engine.py | 74 ++++- .../templates/apis/index.ts.j2 | 2 +- .../templates/apis/service.ts.j2 | 48 ++- .../templates/base/README.md.j2 | 15 +- .../templates/base/package.json.j2 | 10 +- .../base/src/core/BaseHttpRequest.ts.j2 | 4 +- .../{OpenAPI.ts.j2 => ClientConfig.ts.j2} | 9 +- .../base/src/core/FetchHttpRequest.ts.j2 | 1 - .../templates/base/src/core/casing.ts.j2 | 52 ++++ .../templates/base/src/core/msgpack.ts.j2 | 129 +++++++- .../templates/base/src/core/request.ts.j2 | 55 +++- .../templates/base/src/index.ts.j2 | 4 +- .../ts_oas_generator/templates/client.ts.j2 | 12 +- .../templates/full/src/index.ts.j2 | 2 +- .../templates/full/tests/smoke.spec.ts.j2 | 7 +- .../templates/models/model.ts.j2 | 3 +- packages/typescript/algod_client/README.md | 15 +- packages/typescript/algod_client/bun.lock | 222 ++++++++++++++ packages/typescript/algod_client/package.json | 10 +- .../algod_client/src/apis/api.service.ts | 248 ++++++++-------- .../typescript/algod_client/src/apis/index.ts | 2 +- .../typescript/algod_client/src/client.ts | 12 +- .../algod_client/src/core/BaseHttpRequest.ts | 4 +- .../src/core/{OpenAPI.ts => ClientConfig.ts} | 9 +- .../algod_client/src/core/FetchHttpRequest.ts | 1 - .../algod_client/src/core/casing.ts | 52 ++++ .../algod_client/src/core/msgpack.ts | 131 +++++++- .../algod_client/src/core/request.ts | 55 +++- packages/typescript/algod_client/src/index.ts | 2 +- .../algod_client/src/models/abortcatchup.ts | 2 +- .../algod_client/src/models/account.ts | 40 +-- .../models/accountapplicationinformation.ts | 2 +- .../src/models/accountassetholding.ts | 2 +- .../src/models/accountassetinformation.ts | 2 +- .../src/models/accountassetsinformation.ts | 2 +- .../src/models/accountparticipation.ts | 12 +- .../algod_client/src/models/appcalllogs.ts | 2 +- .../src/models/applicationinitialstates.ts | 6 +- .../src/models/applicationlocalstate.ts | 2 +- .../src/models/applicationparams.ts | 12 +- .../src/models/applicationstateoperation.ts | 8 +- .../src/models/applicationstateschema.ts | 2 +- .../algod_client/src/models/assetholding.ts | 2 +- .../algod_client/src/models/assetparams.ts | 12 +- .../algod_client/src/models/boxreference.ts | 2 +- .../algod_client/src/models/buildversion.ts | 2 +- .../src/models/debugsettingsprof.ts | 2 +- .../algod_client/src/models/dryrunrequest.ts | 4 +- .../algod_client/src/models/dryrunsource.ts | 2 +- .../algod_client/src/models/dryrunstate.ts | 2 +- .../src/models/dryruntxnresult.ts | 18 +- .../algod_client/src/models/evaldelta.ts | 2 +- .../algod_client/src/models/genesis.ts | 2 +- .../src/models/genesisallocation.ts | 2 +- .../src/models/getpendingtransactions.ts | 2 +- .../models/getpendingtransactionsbyaddress.ts | 2 +- .../algod_client/src/models/getstatus.ts | 50 ++-- .../algod_client/src/models/getsupply.ts | 2 +- ...ansactiongroupledgerstatedeltasforround.ts | 2 +- .../ledgerstatedeltafortransactiongroup.ts | 2 +- .../src/models/lightblockheaderproof.ts | 2 +- .../src/models/participationkey.ts | 10 +- .../src/models/pendingtransactionresponse.ts | 24 +- .../algod_client/src/models/scratchchange.ts | 2 +- .../src/models/simulateinitialstates.ts | 2 +- .../src/models/simulaterequest.ts | 14 +- .../src/models/simulatetraceconfig.ts | 2 +- .../src/models/simulatetransaction.ts | 10 +- .../models/simulatetransactiongroupresult.ts | 12 +- .../src/models/simulatetransactionresult.ts | 12 +- .../simulateunnamedresourcesaccessed.ts | 6 +- .../src/models/simulationevaloverrides.ts | 12 +- .../src/models/simulationopcodetraceunit.ts | 12 +- .../models/simulationtransactionexectrace.ts | 18 +- .../algod_client/src/models/startcatchup.ts | 2 +- .../algod_client/src/models/stateproof.ts | 2 +- .../src/models/stateproofmessage.ts | 10 +- .../algod_client/src/models/tealdryrun.ts | 2 +- .../src/models/transactionparams.ts | 10 +- .../algod_client/src/models/version.ts | 2 +- .../algod_client/src/models/waitforblock.ts | 50 ++-- .../tests/{helpers/env.ts => config.ts} | 8 +- .../tests/generated/smoke.generated.spec.ts | 49 --- .../algod_client/tests/helpers/wait.ts | 16 - .../tests/pendingTransaction.spec.ts | 43 +-- .../algod_client/tests/smoke.spec.ts | 46 --- .../algod_client/tests/src/client.ts | 12 - .../tests/transactionParams.spec.ts | 15 +- packages/typescript/indexer_client/README.md | 15 +- packages/typescript/indexer_client/bun.lock | 222 ++++++++++++++ .../typescript/indexer_client/package.json | 10 +- .../indexer_client/src/apis/api.service.ts | 279 +++++++++++------- .../indexer_client/src/apis/index.ts | 2 +- .../typescript/indexer_client/src/client.ts | 12 +- .../src/core/BaseHttpRequest.ts | 4 +- .../src/core/{OpenAPI.ts => ClientConfig.ts} | 9 +- .../src/core/FetchHttpRequest.ts | 1 - .../indexer_client/src/core/casing.ts | 52 ++++ .../indexer_client/src/core/msgpack.ts | 131 +++++++- .../indexer_client/src/core/request.ts | 55 +++- .../typescript/indexer_client/src/index.ts | 2 +- .../indexer_client/src/models/account.ts | 44 +-- .../src/models/accountparticipation.ts | 12 +- .../indexer_client/src/models/application.ts | 8 +- .../src/models/applicationlocalstate.ts | 6 +- .../src/models/applicationparams.ts | 14 +- .../src/models/applicationstateschema.ts | 2 +- .../indexer_client/src/models/asset.ts | 2 +- .../indexer_client/src/models/assetholding.ts | 8 +- .../indexer_client/src/models/assetparams.ts | 14 +- .../indexer_client/src/models/block.ts | 28 +- .../indexer_client/src/models/blockrewards.ts | 12 +- .../src/models/blockupgradestate.ts | 10 +- .../src/models/blockupgradevote.ts | 2 +- .../indexer_client/src/models/boxreference.ts | 2 +- .../indexer_client/src/models/evaldelta.ts | 2 +- .../indexer_client/src/models/hashfactory.ts | 2 +- .../src/models/hbprooffields.ts | 2 +- .../indexer_client/src/models/healthcheck.ts | 4 +- .../src/models/indexerstateproofmessage.ts | 10 +- .../src/models/lookupaccountapplocalstates.ts | 2 +- .../src/models/lookupaccountassets.ts | 2 +- .../src/models/lookupaccountbyid.ts | 2 +- .../lookupaccountcreatedapplications.ts | 2 +- .../src/models/lookupaccountcreatedassets.ts | 2 +- .../src/models/lookupaccounttransactions.ts | 2 +- .../src/models/lookupapplicationbyid.ts | 2 +- .../src/models/lookupapplicationlogsbyid.ts | 7 +- .../src/models/lookupassetbalances.ts | 2 +- .../src/models/lookupassetbyid.ts | 2 +- .../src/models/lookupassettransactions.ts | 2 +- .../src/models/lookuptransaction.ts | 2 +- .../src/models/merklearrayproof.ts | 2 +- .../src/models/miniassetholding.ts | 6 +- .../src/models/participationupdates.ts | 2 +- .../src/models/searchforaccounts.ts | 2 +- .../src/models/searchforapplicationboxes.ts | 2 +- .../src/models/searchforapplications.ts | 2 +- .../src/models/searchforassets.ts | 2 +- .../src/models/searchforblockheaders.ts | 2 +- .../src/models/searchfortransactions.ts | 2 +- .../src/models/stateprooffields.ts | 12 +- .../src/models/stateproofreveal.ts | 2 +- .../src/models/stateproofsignature.ts | 7 +- .../src/models/stateproofsigslot.ts | 2 +- .../src/models/stateprooftracking.ts | 2 +- .../src/models/stateproofverifier.ts | 2 +- .../indexer_client/src/models/stateschema.ts | 2 +- .../indexer_client/src/models/tealvalue.ts | 2 +- .../indexer_client/src/models/transaction.ts | 54 ++-- .../src/models/transactionapplication.ts | 24 +- .../src/models/transactionassetconfig.ts | 2 +- .../src/models/transactionassetfreeze.ts | 2 +- .../src/models/transactionassettransfer.ts | 6 +- .../src/models/transactionheartbeat.ts | 8 +- .../src/models/transactionkeyreg.ts | 14 +- .../src/models/transactionpayment.ts | 2 +- .../models/transactionsignaturelogicsig.ts | 2 +- .../models/transactionsignaturemultisig.ts | 4 +- ...ransactionsignaturemultisigsubsignature.ts | 2 +- .../src/models/transactionstateproof.ts | 2 +- .../typescript/indexer_client/tests/config.ts | 131 ++++++++ .../tests/generated/smoke.generated.spec.ts | 49 --- .../indexer_client/tests/helpers/env.ts | 18 -- .../indexer_client/tests/helpers/wait.ts | 16 - .../tests/searchApplications.spec.ts | 79 +++++ .../tests/searchTransactions.spec.ts | 9 +- .../indexer_client/tests/smoke.spec.ts | 46 --- .../indexer_client/tests/src/client.ts | 10 - tools/api_tools/src/main.rs | 30 +- 174 files changed, 2283 insertions(+), 1156 deletions(-) rename api/oas_generator/ts_oas_generator/templates/base/src/core/{OpenAPI.ts.j2 => ClientConfig.ts.j2} (74%) create mode 100644 api/oas_generator/ts_oas_generator/templates/base/src/core/casing.ts.j2 create mode 100644 packages/typescript/algod_client/bun.lock rename packages/typescript/algod_client/src/core/{OpenAPI.ts => ClientConfig.ts} (74%) create mode 100644 packages/typescript/algod_client/src/core/casing.ts rename packages/typescript/algod_client/tests/{helpers/env.ts => config.ts} (89%) delete mode 100644 packages/typescript/algod_client/tests/generated/smoke.generated.spec.ts delete mode 100644 packages/typescript/algod_client/tests/helpers/wait.ts delete mode 100644 packages/typescript/algod_client/tests/smoke.spec.ts delete mode 100644 packages/typescript/algod_client/tests/src/client.ts create mode 100644 packages/typescript/indexer_client/bun.lock rename packages/typescript/indexer_client/src/core/{OpenAPI.ts => ClientConfig.ts} (74%) create mode 100644 packages/typescript/indexer_client/src/core/casing.ts create mode 100644 packages/typescript/indexer_client/tests/config.ts delete mode 100644 packages/typescript/indexer_client/tests/generated/smoke.generated.spec.ts delete mode 100644 packages/typescript/indexer_client/tests/helpers/env.ts delete mode 100644 packages/typescript/indexer_client/tests/helpers/wait.ts create mode 100644 packages/typescript/indexer_client/tests/searchApplications.spec.ts delete mode 100644 packages/typescript/indexer_client/tests/smoke.spec.ts delete mode 100644 packages/typescript/indexer_client/tests/src/client.ts diff --git a/.github/actions/setup-api-tools/action.yml b/.github/actions/setup-api-tools/action.yml index 5d5cedc6b..ab20f56e3 100644 --- a/.github/actions/setup-api-tools/action.yml +++ b/.github/actions/setup-api-tools/action.yml @@ -1,6 +1,12 @@ name: 'Setup API Tools' description: 'Setup Rust, Bun, and Python dependencies for API tools' +inputs: + setup_algokit: + description: 'Whether to install and start algokit localnet' + required: false + default: 'false' + runs: using: 'composite' steps: @@ -24,4 +30,14 @@ runs: - name: Install uv dependencies working-directory: api/oas_generator shell: bash - run: uv sync --extra dev \ No newline at end of file + run: uv sync --extra dev + + - name: Optionally install algokit + if: ${{ inputs.setup_algokit == 'true' }} + shell: bash + run: uv tool install algokit + + - name: Optionally start localnet + if: ${{ inputs.setup_algokit == 'true' }} + shell: bash + run: algokit localnet start \ No newline at end of file diff --git a/.github/workflows/api_ci.yml b/.github/workflows/api_ci.yml index fb45ade6b..868ab341c 100644 --- a/.github/workflows/api_ci.yml +++ b/.github/workflows/api_ci.yml @@ -81,6 +81,8 @@ jobs: steps: - uses: actions/checkout@v4 - uses: ./.github/actions/setup-api-tools + with: + setup_algokit: 'true' - uses: actions/setup-node@v4 with: node-version: "20" @@ -108,3 +110,7 @@ jobs: - name: Build (tsc) ${{ matrix.pkg }} working-directory: packages/typescript/${{ matrix.pkg }} run: bun run build + + - name: Test (${{ matrix.pkg }}) + working-directory: packages/typescript/${{ matrix.pkg }} + run: bun test diff --git a/api/oas_generator/ts_oas_generator/cli.py b/api/oas_generator/ts_oas_generator/cli.py index 63933a095..2bb604508 100644 --- a/api/oas_generator/ts_oas_generator/cli.py +++ b/api/oas_generator/ts_oas_generator/cli.py @@ -30,7 +30,6 @@ def parse_command_line_args(args: list[str] | None = None) -> argparse.Namespace formatter_class=argparse.RawDescriptionHelpFormatter, epilog=""" Examples: - %(prog)s --runtime-only --output ./packages/algod_client --package-name algod_client %(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 """, @@ -38,16 +37,10 @@ def parse_command_line_args(args: list[str] | None = None) -> argparse.Namespace parser.add_argument( "spec_file", - nargs="?", type=Path, help="Path to OpenAPI specification file (JSON or YAML)", metavar="SPEC_FILE", ) - parser.add_argument( - "--runtime-only", - action="store_true", - help="Generate only the base runtime files (no models/APIs); does not require a spec file", - ) parser.add_argument( "--output", "-o", @@ -86,10 +79,7 @@ def parse_command_line_args(args: list[str] | None = None) -> argparse.Namespace parsed_args = parser.parse_args(args) # Validate inputs - if not parsed_args.runtime_only and parsed_args.spec_file is None: - parser.error("SPEC_FILE is required unless --runtime-only is provided") - - if parsed_args.spec_file is not None and not parsed_args.spec_file.exists(): + if not parsed_args.spec_file.exists(): parser.error(f"Specification file not found: {parsed_args.spec_file}") return parsed_args @@ -141,19 +131,12 @@ def main(args: list[str] | None = None) -> int: with backup_and_prepare_output_dir(parsed_args.output_dir): generator = TsCodeGenerator(template_dir=parsed_args.template_dir) - if parsed_args.runtime_only: - generated_files = generator.generate_runtime( - parsed_args.output_dir, - parsed_args.package_name, - custom_description=parsed_args.custom_description, - ) - else: - generated_files = generator.generate_full( - parsed_args.spec_file, - parsed_args.output_dir, - parsed_args.package_name, - custom_description=parsed_args.custom_description, - ) + generated_files = generator.generate_full( + 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) diff --git a/api/oas_generator/ts_oas_generator/generator/filters.py b/api/oas_generator/ts_oas_generator/generator/filters.py index c1d02e30c..18e14079f 100644 --- a/api/oas_generator/ts_oas_generator/generator/filters.py +++ b/api/oas_generator/ts_oas_generator/generator/filters.py @@ -105,7 +105,8 @@ def _inline_object(schema: dict[str, Any], schemas: dict[str, Any] | None) -> st parts: list[str] = [] for prop_name, prop_schema in properties.items(): - ts_name = ts_property_name(prop_name) + # Generate camelCase TS property names for better DX + ts_name = ts_camel_case(prop_name) ts_t = ts_type(prop_schema, schemas) opt = "" if prop_name in required else "?" parts.append(f"{ts_name}{opt}: {ts_t};") @@ -121,12 +122,12 @@ def _inline_object(schema: dict[str, Any], schemas: dict[str, Any] | None) -> st return "{" + (" ".join(parts)) + "}" -def _map_primitive(schema_type: str, _schema_format: str | None, schema: dict[str, Any]) -> str: - if schema.get("x-algokit-bigint") is True and schema_type == "integer": - return "bigint" - +def _map_primitive(schema_type: str, _schema_format: str | None, _schema: dict[str, Any]) -> str: if schema_type == "integer": - return "number" + # Default to bigint for blockchain-sized integers; keep int32 as number + if _schema_format == "int32": + return "number" + return "bigint" if schema_type in ("number",): return "number" diff --git a/api/oas_generator/ts_oas_generator/generator/template_engine.py b/api/oas_generator/ts_oas_generator/generator/template_engine.py index 7e6359045..9247d7ee5 100644 --- a/api/oas_generator/ts_oas_generator/generator/template_engine.py +++ b/api/oas_generator/ts_oas_generator/generator/template_engine.py @@ -71,14 +71,23 @@ def generate_runtime( """Generate runtime files under the provided output directory.""" output_dir = Path(output_dir) src_core = output_dir / "src" / "core" + base_name = ts_pascal_case(package_name) + base_core = base_name[:-6] if base_name.lower().endswith("client") else base_name + client_class_name = f"{base_core}Client" + service_class_name = f"{base_core}Api" + context = { "package_name": package_name, "custom_description": custom_description, + "client_class_name": client_class_name, + "service_class_name": service_class_name, } files: dict[Path, str] = {} # Core runtime files - files[src_core / "OpenAPI.ts"] = self.template_engine.render_template("base/src/core/OpenAPI.ts.j2", context) + files[src_core / "ClientConfig.ts"] = self.template_engine.render_template( + "base/src/core/ClientConfig.ts.j2", context + ) files[src_core / "BaseHttpRequest.ts"] = self.template_engine.render_template( "base/src/core/BaseHttpRequest.ts.j2", context ) @@ -92,6 +101,7 @@ def generate_runtime( ) files[src_core / "json.ts"] = self.template_engine.render_template("base/src/core/json.ts.j2", context) files[src_core / "msgpack.ts"] = self.template_engine.render_template("base/src/core/msgpack.ts.j2", context) + files[src_core / "casing.ts"] = self.template_engine.render_template("base/src/core/casing.ts.j2", context) # Index barrel (runtime-only) files[output_dir / "src" / "index.ts"] = self.template_engine.render_template("base/src/index.ts.j2", context) @@ -222,8 +232,8 @@ def collect_model_types(type_str: str) -> set[str]: param = node schema = param.get("schema", {}) or {} t = ts_type(schema, schemas) - # BigInt params accept number | bigint - if schema.get("x-algokit-bigint") is True and t == "bigint": + # When a parameter resolves to bigint, accept number | bigint for ergonomics + if t == "bigint": t_sig = "number | bigint" stringify_bigint = True else: @@ -256,23 +266,44 @@ def collect_model_types(type_str: str) -> set[str]: } ) - # Request body (pick json if present, else msgpack/text) + # Request body handling request_body_ctx: dict[str, Any] | None = None + request_body_supports_msgpack = False + request_body_supports_json = False rb = op.get("requestBody") if isinstance(rb, dict): content = rb.get("content", {}) + + # Check what content types are supported + if "application/msgpack" in content: + request_body_supports_msgpack = True + if "application/json" in content: + request_body_supports_json = True + + # Determine the type to use for TypeScript typing + # Prefer JSON schema for typing even when msgpack is used at runtime if "application/json" in content: sch = (content["application/json"] or {}).get("schema", {}) request_body_ctx = { - "mediaType": "application/json", + "mediaType": ( + "application/msgpack" + if request_body_supports_msgpack and not request_body_supports_json + else "application/json" + ), "tsType": ts_type(sch, schemas), "required": rb.get("required", False), + "supportsMsgpack": request_body_supports_msgpack, + "supportsJson": request_body_supports_json, } elif "application/msgpack" in content: + # msgpack-only endpoint - infer type from msgpack schema if available + sch = (content["application/msgpack"] or {}).get("schema", {}) request_body_ctx = { "mediaType": "application/msgpack", - "tsType": "Uint8Array", + "tsType": ts_type(sch, schemas) if sch else "any", "required": rb.get("required", False), + "supportsMsgpack": True, + "supportsJson": False, } elif "application/x-binary" in content or "application/octet-stream" in content: # Raw binary transaction submission etc. @@ -281,6 +312,8 @@ def collect_model_types(type_str: str) -> set[str]: "mediaType": mt, "tsType": "Uint8Array", "required": rb.get("required", False), + "supportsMsgpack": False, + "supportsJson": False, } elif "text/plain" in content: sch = (content["text/plain"] or {}).get("schema", {}) @@ -288,6 +321,8 @@ def collect_model_types(type_str: str) -> set[str]: "mediaType": "text/plain", "tsType": ts_type(sch, schemas), "required": rb.get("required", False), + "supportsMsgpack": False, + "supportsJson": False, } # Responses @@ -387,6 +422,8 @@ def collect_model_types(type_str: str) -> set[str]: "acceptsMsgpack": returns_msgpack, "returnsMsgpack": returns_msgpack, "supportsJson": supports_json, + "requestBodySupportsMsgpack": request_body_supports_msgpack, + "requestBodySupportsJson": request_body_supports_json, "hasFormatParam": has_format_param, "formatVarName": format_var_name, "signature": ", ".join(sig_parts), @@ -465,21 +502,32 @@ def generate_full( for t in op.get("importTypes", []): import_types.add(t) + # Determine class names from package name (e.g., algod_client -> AlgodClient, AlgodApi) + base_name = ts_pascal_case(package_name) + base_core = base_name[:-6] if base_name.lower().endswith("client") else base_name + client_class_name = f"{base_core}Client" + service_class_name = f"{base_core}Api" + svc_content = self.template_engine.render_template( "apis/service.ts.j2", - {"tag_name": "api", "operations": all_ops, "import_types": sorted(import_types)}, + { + "tag_name": "api", + "operations": all_ops, + "import_types": sorted(import_types), + "service_class_name": service_class_name, + }, ) files[apis_dir / "api.service.ts"] = svc_content files[apis_dir / "index.ts"] = self.template_engine.render_template( "apis/index.ts.j2", - {}, + {"service_class_name": service_class_name}, ) # Client (single service) files[Path(output_dir) / "src" / "client.ts"] = self.template_engine.render_template( "client.ts.j2", - {}, + {"service_class_name": service_class_name, "client_class_name": client_class_name}, ) # Replace index with full barrel @@ -488,12 +536,6 @@ def generate_full( {}, ) - # Smoke tests (generated) - files[Path(output_dir) / "tests" / "generated" / "smoke.generated.spec.ts"] = ( - self.template_engine.render_template( - "full/tests/smoke.spec.ts.j2", - {}, - ) - ) + # Note: Generated smoke tests removed; prefer manual integration tests maintained by developers return files diff --git a/api/oas_generator/ts_oas_generator/templates/apis/index.ts.j2 b/api/oas_generator/ts_oas_generator/templates/apis/index.ts.j2 index 0a3830c78..59555ee46 100644 --- a/api/oas_generator/ts_oas_generator/templates/apis/index.ts.j2 +++ b/api/oas_generator/ts_oas_generator/templates/apis/index.ts.j2 @@ -1,2 +1,2 @@ // Barrel file for services -export { ApiService } from './api.service'; +export { {{ service_class_name }} } from './api.service'; diff --git a/api/oas_generator/ts_oas_generator/templates/apis/service.ts.j2 b/api/oas_generator/ts_oas_generator/templates/apis/service.ts.j2 index adef08ed7..eeac13eea 100644 --- a/api/oas_generator/ts_oas_generator/templates/apis/service.ts.j2 +++ b/api/oas_generator/ts_oas_generator/templates/apis/service.ts.j2 @@ -3,7 +3,7 @@ import type { BaseHttpRequest, ApiRequestOptions } from '../core/BaseHttpRequest import type { {{ import_types | sort | join(', ') }} } from '../models/index'; {% endif %} -export class ApiService { +export class {{ service_class_name }} { constructor(public readonly httpRequest: BaseHttpRequest) {} {% for op in operations %} @@ -25,22 +25,29 @@ export class ApiService { ): Promise<{{ op.responseTsType }}> { const headers: Record = {}; {% if op.acceptsMsgpack %} - // Content negotiation: - // - If explicit format=json, prefer JSON - // - Else if server supports JSON, prefer JSON by default - // - Else fall back to msgpack + // Content negotiation (aligned with Rust behavior): + // - Default to msgpack when available (better performance, smaller payload) + // - Only use JSON if explicitly requested via format=json {% if op.hasFormatParam and op.formatVarName %} - const hasExplicitJson = params?.{{ op.formatVarName }} === 'json'; - const prefersJson = hasExplicitJson || {{ 'true' if op.supportsJson else 'false' }}; - headers['Accept'] = prefersJson ? 'application/json' : 'application/msgpack'; + const useJson = params?.{{ op.formatVarName }} === 'json'; + headers['Accept'] = useJson ? 'application/json' : 'application/msgpack'; {% else %} - headers['Accept'] = {{ "'application/json'" if op.supportsJson else "'application/msgpack'" }}; + // Prefer msgpack when available, fallback to JSON + headers['Accept'] = 'application/msgpack'; {% endif %} {% else %} headers['Accept'] = 'application/json'; {% endif %} -{% if op.requestBody and op.requestBody.get('mediaType') %} +{% if op.requestBody %} +{% if op.requestBodySupportsMsgpack and op.requestBodySupportsJson and op.hasFormatParam and op.formatVarName %} + headers['Content-Type'] = params?.{{ op.formatVarName }} === 'json' ? 'application/json' : 'application/msgpack'; +{% elif op.requestBodySupportsMsgpack and not op.requestBodySupportsJson %} + headers['Content-Type'] = 'application/msgpack'; +{% elif op.requestBodySupportsMsgpack and op.requestBodySupportsJson %} + headers['Content-Type'] = 'application/msgpack'; +{% elif op.requestBody.get('mediaType') %} headers['Content-Type'] = '{{ op.requestBody['mediaType'] }}'; +{% endif %} {% endif %} // Header parameters @@ -65,12 +72,27 @@ export class ApiService { }, headers, body: {% if op.requestBody %}params?.body{% else %}undefined{% endif %}, - mediaType: {% if op.requestBody %}'{{ op.requestBody['mediaType'] }}'{% else %}undefined{% endif %}, +{% if op.requestBody %} +{% if op.requestBodySupportsMsgpack and op.requestBodySupportsJson and op.hasFormatParam and op.formatVarName %} + // Dynamic mediaType based on format parameter (prefer msgpack by default) + mediaType: params?.{{ op.formatVarName }} === 'json' ? 'application/json' : 'application/msgpack', +{% elif op.requestBodySupportsMsgpack and not op.requestBodySupportsJson %} + // Only msgpack supported for request body + mediaType: 'application/msgpack', +{% elif op.requestBodySupportsMsgpack and op.requestBodySupportsJson %} + // Both supported, prefer msgpack for better performance + mediaType: 'application/msgpack', +{% else %} + mediaType: '{{ op.requestBody['mediaType'] }}', +{% endif %} +{% else %} + mediaType: undefined, +{% endif %} {% if op.returnsMsgpack %} {% if op.hasFormatParam and op.formatVarName %} - expectBinary: params?.{{ op.formatVarName }} === 'json' ? false : {{ 'false' if op.supportsJson else 'true' }}, + expectBinary: params?.{{ op.formatVarName }} === 'json' ? false : true, {% else %} - expectBinary: {{ 'false' if op.supportsJson else 'true' }}, + expectBinary: true, {% endif %} {% else %} expectBinary: false, diff --git a/api/oas_generator/ts_oas_generator/templates/base/README.md.j2 b/api/oas_generator/ts_oas_generator/templates/base/README.md.j2 index e9278b203..5c5937507 100644 --- a/api/oas_generator/ts_oas_generator/templates/base/README.md.j2 +++ b/api/oas_generator/ts_oas_generator/templates/base/README.md.j2 @@ -9,16 +9,17 @@ Install dependencies and build: - bun install (or pnpm/yarn) - bun run build -### Configure base URL and issue requests +### Configure base URL and create a client ```ts -import { OpenAPI, FetchHttpRequest } from './dist/index.js'; +import { FetchHttpRequest, type ClientConfig, {{ client_class_name }}, {{ service_class_name }} } from './dist/index.js'; -OpenAPI.BASE = 'http://localhost:4001'; +const client = new AlgodClient({ + BASE: env.algodBaseUrl, + HEADERS: env.algodApiToken ? { "X-Algo-API-Token": env.algodApiToken } : undefined, +}); -const client = new FetchHttpRequest(OpenAPI); -// Example call once APIs are available in Phase 2: -// await client.request({ method: 'GET', url: '/health' }); +// client is now ready to use ``` -To inject a custom client, implement your own HttpRequest class extending `BaseHttpRequest` and use it where needed. +To inject a custom HTTP implementation, implement your own request class extending `BaseHttpRequest` and pass it into your own wrapper if needed. diff --git a/api/oas_generator/ts_oas_generator/templates/base/package.json.j2 b/api/oas_generator/ts_oas_generator/templates/base/package.json.j2 index 9c6aedb1b..d202e007d 100644 --- a/api/oas_generator/ts_oas_generator/templates/base/package.json.j2 +++ b/api/oas_generator/ts_oas_generator/templates/base/package.json.j2 @@ -11,14 +11,14 @@ "test": "vitest run" }, "dependencies": { - "json-bigint": "^1.0.0", - "algo-msgpack-with-bigint": "^2.1.1" + "@msgpack/msgpack": "^3.1.2", + "json-bigint": "^1.0.0" }, "devDependencies": { - "typescript": "^5.5.0", "@types/json-bigint": "^1.0.0", - "vitest": "^2.0.0", "@types/node": "^20.0.0", - "algosdk": "^2.7.0" + "algosdk": "^3.0.0", + "typescript": "^5.5.0", + "vitest": "^2.0.0" } } diff --git a/api/oas_generator/ts_oas_generator/templates/base/src/core/BaseHttpRequest.ts.j2 b/api/oas_generator/ts_oas_generator/templates/base/src/core/BaseHttpRequest.ts.j2 index 33781c051..5ca88bff5 100644 --- a/api/oas_generator/ts_oas_generator/templates/base/src/core/BaseHttpRequest.ts.j2 +++ b/api/oas_generator/ts_oas_generator/templates/base/src/core/BaseHttpRequest.ts.j2 @@ -1,4 +1,4 @@ -import type { OpenAPIConfig } from './OpenAPI'; +import type { ClientConfig } from './ClientConfig'; export interface RequestOptions { method: string; @@ -16,6 +16,6 @@ export interface RequestOptions { export type ApiRequestOptions = RequestOptions; export abstract class BaseHttpRequest { - constructor(public readonly config: OpenAPIConfig) {} + constructor(public readonly config: ClientConfig) {} abstract request(options: RequestOptions): Promise; } diff --git a/api/oas_generator/ts_oas_generator/templates/base/src/core/OpenAPI.ts.j2 b/api/oas_generator/ts_oas_generator/templates/base/src/core/ClientConfig.ts.j2 similarity index 74% rename from api/oas_generator/ts_oas_generator/templates/base/src/core/OpenAPI.ts.j2 rename to api/oas_generator/ts_oas_generator/templates/base/src/core/ClientConfig.ts.j2 index 97d63df9d..531e4b52b 100644 --- a/api/oas_generator/ts_oas_generator/templates/base/src/core/OpenAPI.ts.j2 +++ b/api/oas_generator/ts_oas_generator/templates/base/src/core/ClientConfig.ts.j2 @@ -1,9 +1,9 @@ /* - Minimal OpenAPI runtime config holder + Minimal client runtime config holder */ export type BaseURL = string; -export interface OpenAPIConfig { +export interface ClientConfig { BASE: BaseURL; VERSION?: string; WITH_CREDENTIALS?: boolean; @@ -16,7 +16,4 @@ export interface OpenAPIConfig { INT_DECODING?: 'safe' | 'unsafe' | 'mixed' | 'bigint'; } -export const OpenAPI: OpenAPIConfig = { - BASE: '', - INT_DECODING: 'mixed', -}; + diff --git a/api/oas_generator/ts_oas_generator/templates/base/src/core/FetchHttpRequest.ts.j2 b/api/oas_generator/ts_oas_generator/templates/base/src/core/FetchHttpRequest.ts.j2 index d2b463ba3..45218043b 100644 --- a/api/oas_generator/ts_oas_generator/templates/base/src/core/FetchHttpRequest.ts.j2 +++ b/api/oas_generator/ts_oas_generator/templates/base/src/core/FetchHttpRequest.ts.j2 @@ -1,5 +1,4 @@ import { BaseHttpRequest, type RequestOptions } from './BaseHttpRequest'; -import { OpenAPI } from './OpenAPI'; import { request as defaultRequest } from './request'; export class FetchHttpRequest extends BaseHttpRequest { diff --git a/api/oas_generator/ts_oas_generator/templates/base/src/core/casing.ts.j2 b/api/oas_generator/ts_oas_generator/templates/base/src/core/casing.ts.j2 new file mode 100644 index 000000000..a1642dbb4 --- /dev/null +++ b/api/oas_generator/ts_oas_generator/templates/base/src/core/casing.ts.j2 @@ -0,0 +1,52 @@ +function toCamel(segmented: string): string { + if (!segmented) return segmented; + // Fast path: if no hyphen, return as-is but ensure typical camel conversion for underscores + if (!segmented.includes('-')) return segmented.replace(/_([a-z0-9])/g, (_, c) => c.toUpperCase()); + return segmented + .split('-') + .map((part, index) => (index === 0 ? part : part.charAt(0).toUpperCase() + part.slice(1))) + .join(''); +} + +function toKebab(camel: string): string { + if (!camel) return camel; + // Convert camelCase or mixedCase to kebab-case; leave existing hyphens and numbers intact + return camel + .replace(/([a-z0-9])([A-Z])/g, '$1-$2') + .replace(/_/g, '-') + .toLowerCase(); +} + +function isPlainObject(value: unknown): value is Record { + if (value === null || typeof value !== 'object') return false; + const proto = Object.getPrototypeOf(value); + return proto === Object.prototype || proto === null; +} + +export function toCamelCaseKeysDeep(value: T): T { // eslint-disable-line @typescript-eslint/no-explicit-any + if (Array.isArray(value)) return value.map((v) => toCamelCaseKeysDeep(v)) as unknown as T; + if (value instanceof Uint8Array) return value; + if (!isPlainObject(value)) return value; + + const out: Record = {}; + for (const [k, v] of Object.entries(value)) { + const newKey = toCamel(k); + out[newKey] = toCamelCaseKeysDeep(v as unknown); + } + return out as unknown as T; +} + +export function toKebabCaseKeysDeep(value: T): T { // eslint-disable-line @typescript-eslint/no-explicit-any + if (Array.isArray(value)) return value.map((v) => toKebabCaseKeysDeep(v)) as unknown as T; + if (value instanceof Uint8Array) return value; + if (!isPlainObject(value)) return value; + + const out: Record = {}; + for (const [k, v] of Object.entries(value)) { + const newKey = toKebab(k); + out[newKey] = toKebabCaseKeysDeep(v as unknown); + } + return out as unknown as T; +} + + diff --git a/api/oas_generator/ts_oas_generator/templates/base/src/core/msgpack.ts.j2 b/api/oas_generator/ts_oas_generator/templates/base/src/core/msgpack.ts.j2 index 92cd41b8c..1d0213abf 100644 --- a/api/oas_generator/ts_oas_generator/templates/base/src/core/msgpack.ts.j2 +++ b/api/oas_generator/ts_oas_generator/templates/base/src/core/msgpack.ts.j2 @@ -1,12 +1,128 @@ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -declare const require: any; -// eslint-disable-next-line @typescript-eslint/no-var-requires -const { decode } = require('algo-msgpack-with-bigint'); - +import { encode as msgpackEncode, decode as msgpackDecode } from "@msgpack/msgpack"; import type { IntDecoding } from './json'; +/** + * Prepare value for Algorand-compliant msgpack encoding. + * Implements strict Algorand msgpack rules (matching go-algorand behavior): + * 1. Omit zero values, empty strings, and empty arrays (RecursiveEmptyCheck) + * 2. Convert bigints to smallest safe integer type (PositiveIntUnsigned) + * 3. Sorted keys and canonical encoding are handled by msgpackEncode options + * + * These rules apply universally for both API communication and transaction encoding, + * as go-algorand uses the same codec settings for all msgpack operations. + */ +function prepareForEncoding(value: any): any { // eslint-disable-line @typescript-eslint/no-explicit-any + if (value === null || value === undefined) { + return undefined; + } + + // Handle numbers - omit zeros + if (typeof value === 'number') { + if (value === 0) return undefined; + return value; + } + + // Handle bigints - omit zeros and convert to number when safe (for smaller encoding) + if (typeof value === 'bigint') { + if (value === 0n) return undefined; + // Convert to number if it fits safely (implements PositiveIntUnsigned behavior) + if (value <= BigInt(Number.MAX_SAFE_INTEGER) && value >= BigInt(Number.MIN_SAFE_INTEGER)) { + return Number(value); + } + return value; + } + + // Handle strings - omit empty strings + if (typeof value === 'string') { + if (value === '') return undefined; + return value; + } + + // Handle Uint8Array - omit empty arrays + if (value instanceof Uint8Array) { + if (value.length === 0) return undefined; + return value; + } + + // Handle arrays - omit empty arrays and filter undefined values + if (Array.isArray(value)) { + if (value.length === 0) return undefined; + const processed = value.map(prepareForEncoding).filter(v => v !== undefined); + return processed.length > 0 ? processed : undefined; + } + + // Handle objects - omit empty objects and filter undefined values (RecursiveEmptyCheck) + if (value && typeof value === 'object') { + const result: any = {}; // eslint-disable-line @typescript-eslint/no-explicit-any + for (const [k, v] of Object.entries(value)) { + const prepared = prepareForEncoding(v); + if (prepared !== undefined) { + result[k] = prepared; + } + } + // Return undefined if object is empty after filtering + return Object.keys(result).length > 0 ? result : undefined; + } + + return value; +} + +function convertIntegersToBigInt(value: any): any { // eslint-disable-line @typescript-eslint/no-explicit-any + if (value === null || value === undefined) { + return value; + } + if (typeof value === 'number' && Number.isInteger(value)) { + return BigInt(value); + } + if (typeof value === 'bigint') { + return value; + } + if (value instanceof Uint8Array) { + return value; + } + if (Array.isArray(value)) { + return value.map(convertIntegersToBigInt); + } + if (value && typeof value === 'object') { + const result: any = {}; // eslint-disable-line @typescript-eslint/no-explicit-any + for (const [k, v] of Object.entries(value)) { + result[k] = convertIntegersToBigInt(v); + } + return result; + } + return value; +} + +/** + * Encode a value as msgpack using Algorand's strict encoding rules. + * This matches go-algorand's protocol.CodecHandle settings: + * - Canonical = true (sorted keys, deterministic encoding) + * - RecursiveEmptyCheck = true (omit empty/zero values recursively) + * - PositiveIntUnsigned = true (use smallest unsigned integer types) + * + * @param value - The value to encode + * @returns Encoded msgpack bytes + */ +export function encodeMsgPack(value: any): Uint8Array { // eslint-disable-line @typescript-eslint/no-explicit-any + const prepared = prepareForEncoding(value); + + // Ensure we return valid msgpack even if everything was omitted + const toEncode = prepared === undefined ? {} : prepared; + + return msgpackEncode(toEncode, { + sortKeys: true, // Canonical = true in go-algorand + forceIntegerToFloat: false, + ignoreUndefined: true, // Handle undefined values from prepareForEncoding + initialBufferSize: 2048, + useBigInt64: true, // Support for large integers + }); +} + export function decodeMsgPack(buffer: Uint8Array): any { // eslint-disable-line @typescript-eslint/no-explicit-any - return decode(buffer); + const decoded = msgpackDecode(buffer, { + useBigInt64: true, + }); + return convertIntegersToBigInt(decoded); } export function normalizeMsgPackIntegers(value: any, intDecoding: IntDecoding): any { // eslint-disable-line @typescript-eslint/no-explicit-any @@ -56,4 +172,3 @@ function mapBigInts(obj: any, mapFn: (bi: bigint) => any): any { // eslint-disab return obj; } - diff --git a/api/oas_generator/ts_oas_generator/templates/base/src/core/request.ts.j2 b/api/oas_generator/ts_oas_generator/templates/base/src/core/request.ts.j2 index 85b18aa98..a8813f867 100644 --- a/api/oas_generator/ts_oas_generator/templates/base/src/core/request.ts.j2 +++ b/api/oas_generator/ts_oas_generator/templates/base/src/core/request.ts.j2 @@ -1,11 +1,13 @@ -import type { OpenAPIConfig } from './OpenAPI'; +import type { ClientConfig } from './ClientConfig'; import { ApiError } from './ApiError'; import { parseJson, stringifyJson } from './json'; -import { decodeMsgPack, normalizeMsgPackIntegers } from './msgpack'; +import { decodeMsgPack, encodeMsgPack, normalizeMsgPackIntegers } from './msgpack'; + import { toCamelCaseKeysDeep } from './casing'; +import { toKebabCaseKeysDeep } from './casing'; const encodeURIPath = (path: string): string => encodeURI(path).replace(/%5B/g, '[').replace(/%5D/g, ']'); -export async function request(config: OpenAPIConfig, options: { +export async function request(config: ClientConfig, options: { method: string; url: string; path?: Record; @@ -49,10 +51,24 @@ export async function request(config: OpenAPIConfig, options: { headers['Authorization'] = `Basic ${btoa(`${config.USERNAME}:${config.PASSWORD}`)}`; } + // Prepare body based on media type + let body: any = undefined; + if (options.body != null) { + if (options.mediaType?.includes('json')) { + body = stringifyJson(toKebabCaseKeysDeep(options.body)); + } else if (options.mediaType?.includes('msgpack')) { + // Encode typed models to msgpack for requests + body = encodeMsgPack(toKebabCaseKeysDeep(options.body)); + } else { + // For binary/text, pass through as-is + body = options.body; + } + } + const response = await fetch(url.toString(), { method: options.method, headers, - body: options.body != null ? (options.mediaType?.includes('json') ? stringifyJson(options.body) : options.body) : undefined, + body, credentials: config.CREDENTIALS, }); @@ -60,7 +76,7 @@ export async function request(config: OpenAPIConfig, options: { let body: any = undefined; try { const ct = response.headers.get('content-type'); - if (ct && ct.includes('application/json')) body = parseJson(await response.text(), config.INT_DECODING); + if (ct && ct.includes('application/json')) body = parseJson(await response.text(), config.INT_DECODING ?? 'mixed'); else body = await response.text(); } catch {} throw new ApiError(url.toString(), response.status, body); @@ -71,17 +87,36 @@ export async function request(config: OpenAPIConfig, options: { return value as unknown as T; } - // Parse by content-type first + // Parse response by content-type const contentType = response.headers.get('content-type') || ''; - if (contentType.includes('application/msgpack') || contentType.includes('application/x-binary')) { + + // Handle msgpack responses - decode to typed models + if (contentType.includes('application/msgpack')) { const buf = new Uint8Array(await response.arrayBuffer()); const decoded = decodeMsgPack(buf); - return normalizeMsgPackIntegers(decoded, config.INT_DECODING ?? 'mixed') as T; + const normalized = normalizeMsgPackIntegers(decoded, config.INT_DECODING ?? 'bigint'); + return toCamelCaseKeysDeep(normalized) as T; } + + // Handle raw binary responses (e.g., application/x-binary for raw transactions) + if (contentType.includes('application/x-binary') || contentType.includes('application/octet-stream')) { + // For raw binary, return as Uint8Array without decoding + return new Uint8Array(await response.arrayBuffer()) as unknown as T; + } + + // Handle JSON responses if (contentType.includes('application/json')) { const text = await response.text(); - return parseJson(text, config.INT_DECODING) as T; + const parsed = parseJson(text, config.INT_DECODING ?? 'mixed'); + return toCamelCaseKeysDeep(parsed) as T; } + // Fallback to text - return (await response.text()) as unknown as T; + const text = await response.text(); + try { + const parsed = JSON.parse(text); + return toCamelCaseKeysDeep(parsed) as T; + } catch { + return text as unknown as T; + } } diff --git a/api/oas_generator/ts_oas_generator/templates/base/src/index.ts.j2 b/api/oas_generator/ts_oas_generator/templates/base/src/index.ts.j2 index 78b47df1d..07fe9d426 100644 --- a/api/oas_generator/ts_oas_generator/templates/base/src/index.ts.j2 +++ b/api/oas_generator/ts_oas_generator/templates/base/src/index.ts.j2 @@ -1,9 +1,11 @@ -export * from './core/OpenAPI'; +export * from './core/ClientConfig'; export * from './core/BaseHttpRequest'; export * from './core/FetchHttpRequest'; export * from './core/ApiError'; export * from './core/CancelablePromise'; export * from './core/json'; +export * from './core/casing'; +export { encodeMsgPack, decodeMsgPack } from './core/msgpack'; // Generated export * from './models'; diff --git a/api/oas_generator/ts_oas_generator/templates/client.ts.j2 b/api/oas_generator/ts_oas_generator/templates/client.ts.j2 index c8efb1749..47946159e 100644 --- a/api/oas_generator/ts_oas_generator/templates/client.ts.j2 +++ b/api/oas_generator/ts_oas_generator/templates/client.ts.j2 @@ -1,13 +1,13 @@ -import type { OpenAPIConfig } from './core/OpenAPI'; +import type { ClientConfig } from './core/ClientConfig'; import { FetchHttpRequest } from './core/FetchHttpRequest'; -import { ApiService } from './apis/api.service'; +import { {{ service_class_name }} } from './apis/api.service'; -export class Client { +export class {{ client_class_name }} { public readonly request: FetchHttpRequest; - public readonly api: ApiService; + public readonly api: {{ service_class_name }}; - constructor(config: OpenAPIConfig) { + constructor(config: ClientConfig) { this.request = new FetchHttpRequest(config); - this.api = new ApiService(this.request); + this.api = new {{ service_class_name }}(this.request); } } diff --git a/api/oas_generator/ts_oas_generator/templates/full/src/index.ts.j2 b/api/oas_generator/ts_oas_generator/templates/full/src/index.ts.j2 index 2803e335f..244dc30c8 100644 --- a/api/oas_generator/ts_oas_generator/templates/full/src/index.ts.j2 +++ b/api/oas_generator/ts_oas_generator/templates/full/src/index.ts.j2 @@ -1,4 +1,4 @@ -export * from './core/OpenAPI'; +export * from './core/ClientConfig'; export * from './core/BaseHttpRequest'; export * from './core/FetchHttpRequest'; export * from './core/ApiError'; diff --git a/api/oas_generator/ts_oas_generator/templates/full/tests/smoke.spec.ts.j2 b/api/oas_generator/ts_oas_generator/templates/full/tests/smoke.spec.ts.j2 index 751751a8a..047dc1c5a 100644 --- a/api/oas_generator/ts_oas_generator/templates/full/tests/smoke.spec.ts.j2 +++ b/api/oas_generator/ts_oas_generator/templates/full/tests/smoke.spec.ts.j2 @@ -2,7 +2,7 @@ * This smoke test is generated by ts_oas_generator. * Location: tests/generated/smoke.generated.spec.ts */ -import { describe, expect, it } from 'vitest'; +import { describe, expect, it } from 'bun:test'; import { Client } from '../src/client'; const BASE = 'http://localhost/'; @@ -31,10 +31,9 @@ describe('JSON BigInt parsing', () => { describe('Msgpack binary response', () => { it('decodes msgpack into structured data', async () => { - // eslint-disable-next-line @typescript-eslint/no-var-requires - const { encode } = require('algo-msgpack-with-bigint'); + const { encode } = await import('@msgpack/msgpack'); const msg = { ok: 1n, small: 2 }; - const bytes: Uint8Array = encode(msg); + const bytes: Uint8Array = encode(msg, { useBigInt64: true }); global.fetch = async () => ({ ok: true, headers: new Map([['content-type', 'application/msgpack']]), diff --git a/api/oas_generator/ts_oas_generator/templates/models/model.ts.j2 b/api/oas_generator/ts_oas_generator/templates/models/model.ts.j2 index 1881449af..77a3749a6 100644 --- a/api/oas_generator/ts_oas_generator/templates/models/model.ts.j2 +++ b/api/oas_generator/ts_oas_generator/templates/models/model.ts.j2 @@ -9,7 +9,8 @@ import type { {{ refTypes | join(', ') }} } from './index'; {% 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 prop_name, prop_schema in (schema.get('properties') or {}).items() %} - {{ prop_name | ts_property_name }}{{ '' if (schema.get('required') or []) | list | select('equalto', prop_name) | list | length > 0 else '?' }}: {{ prop_schema | ts_type(schemas) }}; + {{ prop_schema.description | ts_doc_comment }} + {{ prop_name | ts_camel_case }}{{ '' if (schema.get('required') or []) | list | select('equalto', prop_name) | list | length > 0 else '?' }}: {{ prop_schema | ts_type(schemas) }}; {% endfor %} {% if schema.get('additionalProperties') is sameas true %} [key: string]: any; diff --git a/packages/typescript/algod_client/README.md b/packages/typescript/algod_client/README.md index 990b6a9da..37eb10225 100644 --- a/packages/typescript/algod_client/README.md +++ b/packages/typescript/algod_client/README.md @@ -9,16 +9,17 @@ Install dependencies and build: - bun install (or pnpm/yarn) - bun run build -### Configure base URL and issue requests +### Configure base URL and create a client ```ts -import { OpenAPI, FetchHttpRequest } from "./dist/index.js"; +import { FetchHttpRequest, type ClientConfig, AlgodClient, AlgodApi } from "./dist/index.js"; -OpenAPI.BASE = "http://localhost:4001"; +const client = new AlgodClient({ + BASE: env.algodBaseUrl, + HEADERS: env.algodApiToken ? { "X-Algo-API-Token": env.algodApiToken } : undefined, +}); -const client = new FetchHttpRequest(OpenAPI); -// Example call once APIs are available in Phase 2: -// await client.request({ method: 'GET', url: '/health' }); +// client is now ready to use ``` -To inject a custom client, implement your own HttpRequest class extending `BaseHttpRequest` and use it where needed. +To inject a custom HTTP implementation, implement your own request class extending `BaseHttpRequest` and pass it into your own wrapper if needed. diff --git a/packages/typescript/algod_client/bun.lock b/packages/typescript/algod_client/bun.lock new file mode 100644 index 000000000..33ffe1813 --- /dev/null +++ b/packages/typescript/algod_client/bun.lock @@ -0,0 +1,222 @@ +{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "algod_client", + "dependencies": { + "@msgpack/msgpack": "^3.1.2", + "json-bigint": "^1.0.0", + }, + "devDependencies": { + "@types/json-bigint": "^1.0.0", + "@types/node": "^20.0.0", + "algosdk": "^3.0.0", + "typescript": "^5.5.0", + "vitest": "^2.0.0", + }, + }, + }, + "packages": { + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="], + + "@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os": "android", "cpu": "arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="], + + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.21.5", "", { "os": "android", "cpu": "arm64" }, "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A=="], + + "@esbuild/android-x64": ["@esbuild/android-x64@0.21.5", "", { "os": "android", "cpu": "x64" }, "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA=="], + + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.21.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ=="], + + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.21.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw=="], + + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.21.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g=="], + + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.21.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ=="], + + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.21.5", "", { "os": "linux", "cpu": "arm" }, "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA=="], + + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.21.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q=="], + + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.21.5", "", { "os": "linux", "cpu": "ia32" }, "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg=="], + + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg=="], + + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg=="], + + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.21.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w=="], + + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA=="], + + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.21.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A=="], + + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.21.5", "", { "os": "linux", "cpu": "x64" }, "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ=="], + + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.21.5", "", { "os": "none", "cpu": "x64" }, "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg=="], + + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.21.5", "", { "os": "openbsd", "cpu": "x64" }, "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow=="], + + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.21.5", "", { "os": "sunos", "cpu": "x64" }, "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg=="], + + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.21.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A=="], + + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.21.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA=="], + + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.21.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw=="], + + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], + + "@msgpack/msgpack": ["@msgpack/msgpack@3.1.2", "", {}, "sha512-JEW4DEtBzfe8HvUYecLU9e6+XJnKDlUAIve8FvPzF3Kzs6Xo/KuZkZJsDH0wJXl/qEZbeeE7edxDNY3kMs39hQ=="], + + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.50.1", "", { "os": "android", "cpu": "arm" }, "sha512-HJXwzoZN4eYTdD8bVV22DN8gsPCAj3V20NHKOs8ezfXanGpmVPR7kalUHd+Y31IJp9stdB87VKPFbsGY3H/2ag=="], + + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.50.1", "", { "os": "android", "cpu": "arm64" }, "sha512-PZlsJVcjHfcH53mOImyt3bc97Ep3FJDXRpk9sMdGX0qgLmY0EIWxCag6EigerGhLVuL8lDVYNnSo8qnTElO4xw=="], + + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.50.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-xc6i2AuWh++oGi4ylOFPmzJOEeAa2lJeGUGb4MudOtgfyyjr4UPNK+eEWTPLvmPJIY/pgw6ssFIox23SyrkkJw=="], + + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.50.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-2ofU89lEpDYhdLAbRdeyz/kX3Y2lpYc6ShRnDjY35bZhd2ipuDMDi6ZTQ9NIag94K28nFMofdnKeHR7BT0CATw=="], + + "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.50.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-wOsE6H2u6PxsHY/BeFHA4VGQN3KUJFZp7QJBmDYI983fgxq5Th8FDkVuERb2l9vDMs1D5XhOrhBrnqcEY6l8ZA=="], + + "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.50.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-A/xeqaHTlKbQggxCqispFAcNjycpUEHP52mwMQZUNqDUJFFYtPHCXS1VAG29uMlDzIVr+i00tSFWFLivMcoIBQ=="], + + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.50.1", "", { "os": "linux", "cpu": "arm" }, "sha512-54v4okehwl5TaSIkpp97rAHGp7t3ghinRd/vyC1iXqXMfjYUTm7TfYmCzXDoHUPTTf36L8pr0E7YsD3CfB3ZDg=="], + + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.50.1", "", { "os": "linux", "cpu": "arm" }, "sha512-p/LaFyajPN/0PUHjv8TNyxLiA7RwmDoVY3flXHPSzqrGcIp/c2FjwPPP5++u87DGHtw+5kSH5bCJz0mvXngYxw=="], + + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.50.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-2AbMhFFkTo6Ptna1zO7kAXXDLi7H9fGTbVaIq2AAYO7yzcAsuTNWPHhb2aTA6GPiP+JXh85Y8CiS54iZoj4opw=="], + + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.50.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-Cgef+5aZwuvesQNw9eX7g19FfKX5/pQRIyhoXLCiBOrWopjo7ycfB292TX9MDcDijiuIJlx1IzJz3IoCPfqs9w=="], + + "@rollup/rollup-linux-loongarch64-gnu": ["@rollup/rollup-linux-loongarch64-gnu@4.50.1", "", { "os": "linux", "cpu": "none" }, "sha512-RPhTwWMzpYYrHrJAS7CmpdtHNKtt2Ueo+BlLBjfZEhYBhK00OsEqM08/7f+eohiF6poe0YRDDd8nAvwtE/Y62Q=="], + + "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.50.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-eSGMVQw9iekut62O7eBdbiccRguuDgiPMsw++BVUg+1K7WjZXHOg/YOT9SWMzPZA+w98G+Fa1VqJgHZOHHnY0Q=="], + + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.50.1", "", { "os": "linux", "cpu": "none" }, "sha512-S208ojx8a4ciIPrLgazF6AgdcNJzQE4+S9rsmOmDJkusvctii+ZvEuIC4v/xFqzbuP8yDjn73oBlNDgF6YGSXQ=="], + + "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.50.1", "", { "os": "linux", "cpu": "none" }, "sha512-3Ag8Ls1ggqkGUvSZWYcdgFwriy2lWo+0QlYgEFra/5JGtAd6C5Hw59oojx1DeqcA2Wds2ayRgvJ4qxVTzCHgzg=="], + + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.50.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-t9YrKfaxCYe7l7ldFERE1BRg/4TATxIg+YieHQ966jwvo7ddHJxPj9cNFWLAzhkVsbBvNA4qTbPVNsZKBO4NSg=="], + + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.50.1", "", { "os": "linux", "cpu": "x64" }, "sha512-MCgtFB2+SVNuQmmjHf+wfI4CMxy3Tk8XjA5Z//A0AKD7QXUYFMQcns91K6dEHBvZPCnhJSyDWLApk40Iq/H3tA=="], + + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.50.1", "", { "os": "linux", "cpu": "x64" }, "sha512-nEvqG+0jeRmqaUMuwzlfMKwcIVffy/9KGbAGyoa26iu6eSngAYQ512bMXuqqPrlTyfqdlB9FVINs93j534UJrg=="], + + "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.50.1", "", { "os": "none", "cpu": "arm64" }, "sha512-RDsLm+phmT3MJd9SNxA9MNuEAO/J2fhW8GXk62G/B4G7sLVumNFbRwDL6v5NrESb48k+QMqdGbHgEtfU0LCpbA=="], + + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.50.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-hpZB/TImk2FlAFAIsoElM3tLzq57uxnGYwplg6WDyAxbYczSi8O2eQ+H2Lx74504rwKtZ3N2g4bCUkiamzS6TQ=="], + + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.50.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-SXjv8JlbzKM0fTJidX4eVsH+Wmnp0/WcD8gJxIZyR6Gay5Qcsmdbi9zVtnbkGPG8v2vMR1AD06lGWy5FLMcG7A=="], + + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.50.1", "", { "os": "win32", "cpu": "x64" }, "sha512-StxAO/8ts62KZVRAm4JZYq9+NqNsV7RvimNK+YM7ry//zebEH6meuugqW/P5OFUCjyQgui+9fUxT6d5NShvMvA=="], + + "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], + + "@types/json-bigint": ["@types/json-bigint@1.0.4", "", {}, "sha512-ydHooXLbOmxBbubnA7Eh+RpBzuaIiQjh8WGJYQB50JFGFrdxW7JzVlyEV7fAXw0T2sqJ1ysTneJbiyNLqZRAag=="], + + "@types/node": ["@types/node@20.19.13", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-yCAeZl7a0DxgNVteXFHt9+uyFbqXGy/ShC4BlcHkoE0AfGXYv/BUiplV72DjMYXHDBXFjhvr6DD1NiRVfB4j8g=="], + + "@vitest/expect": ["@vitest/expect@2.1.9", "", { "dependencies": { "@vitest/spy": "2.1.9", "@vitest/utils": "2.1.9", "chai": "^5.1.2", "tinyrainbow": "^1.2.0" } }, "sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw=="], + + "@vitest/mocker": ["@vitest/mocker@2.1.9", "", { "dependencies": { "@vitest/spy": "2.1.9", "estree-walker": "^3.0.3", "magic-string": "^0.30.12" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^5.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg=="], + + "@vitest/pretty-format": ["@vitest/pretty-format@2.1.9", "", { "dependencies": { "tinyrainbow": "^1.2.0" } }, "sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ=="], + + "@vitest/runner": ["@vitest/runner@2.1.9", "", { "dependencies": { "@vitest/utils": "2.1.9", "pathe": "^1.1.2" } }, "sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g=="], + + "@vitest/snapshot": ["@vitest/snapshot@2.1.9", "", { "dependencies": { "@vitest/pretty-format": "2.1.9", "magic-string": "^0.30.12", "pathe": "^1.1.2" } }, "sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ=="], + + "@vitest/spy": ["@vitest/spy@2.1.9", "", { "dependencies": { "tinyspy": "^3.0.2" } }, "sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ=="], + + "@vitest/utils": ["@vitest/utils@2.1.9", "", { "dependencies": { "@vitest/pretty-format": "2.1.9", "loupe": "^3.1.2", "tinyrainbow": "^1.2.0" } }, "sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ=="], + + "algorand-msgpack": ["algorand-msgpack@1.1.0", "", {}, "sha512-08k7pBQnkaUB5p+jL7f1TRaUIlTSDE0cesFu1mD7llLao+1cAhtvvZmGE3OnisTd0xOn118QMw74SRqddqaYvw=="], + + "algosdk": ["algosdk@3.4.0", "", { "dependencies": { "algorand-msgpack": "^1.1.0", "hi-base32": "^0.5.1", "js-sha256": "^0.9.0", "js-sha3": "^0.8.0", "js-sha512": "^0.8.0", "json-bigint": "^1.0.0", "tweetnacl": "^1.0.3", "vlq": "^2.0.4" } }, "sha512-95NYlVxMsHKs9gV8/hUvNTRAqmRC55wtesGR53j37fjP/sHUWd1gxNGTNBy0d1+o4jDKxVaasVgUHh78IqgtCw=="], + + "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="], + + "bignumber.js": ["bignumber.js@9.3.1", "", {}, "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ=="], + + "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="], + + "chai": ["chai@5.3.3", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw=="], + + "check-error": ["check-error@2.1.1", "", {}, "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw=="], + + "debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], + + "deep-eql": ["deep-eql@5.0.2", "", {}, "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q=="], + + "es-module-lexer": ["es-module-lexer@1.7.0", "", {}, "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA=="], + + "esbuild": ["esbuild@0.21.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.21.5", "@esbuild/android-arm": "0.21.5", "@esbuild/android-arm64": "0.21.5", "@esbuild/android-x64": "0.21.5", "@esbuild/darwin-arm64": "0.21.5", "@esbuild/darwin-x64": "0.21.5", "@esbuild/freebsd-arm64": "0.21.5", "@esbuild/freebsd-x64": "0.21.5", "@esbuild/linux-arm": "0.21.5", "@esbuild/linux-arm64": "0.21.5", "@esbuild/linux-ia32": "0.21.5", "@esbuild/linux-loong64": "0.21.5", "@esbuild/linux-mips64el": "0.21.5", "@esbuild/linux-ppc64": "0.21.5", "@esbuild/linux-riscv64": "0.21.5", "@esbuild/linux-s390x": "0.21.5", "@esbuild/linux-x64": "0.21.5", "@esbuild/netbsd-x64": "0.21.5", "@esbuild/openbsd-x64": "0.21.5", "@esbuild/sunos-x64": "0.21.5", "@esbuild/win32-arm64": "0.21.5", "@esbuild/win32-ia32": "0.21.5", "@esbuild/win32-x64": "0.21.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw=="], + + "estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], + + "expect-type": ["expect-type@1.2.2", "", {}, "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA=="], + + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + + "hi-base32": ["hi-base32@0.5.1", "", {}, "sha512-EmBBpvdYh/4XxsnUybsPag6VikPYnN30td+vQk+GI3qpahVEG9+gTkG0aXVxTjBqQ5T6ijbWIu77O+C5WFWsnA=="], + + "js-sha256": ["js-sha256@0.9.0", "", {}, "sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA=="], + + "js-sha3": ["js-sha3@0.8.0", "", {}, "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q=="], + + "js-sha512": ["js-sha512@0.8.0", "", {}, "sha512-PWsmefG6Jkodqt+ePTvBZCSMFgN7Clckjd0O7su3I0+BW2QWUTJNzjktHsztGLhncP2h8mcF9V9Y2Ha59pAViQ=="], + + "json-bigint": ["json-bigint@1.0.0", "", { "dependencies": { "bignumber.js": "^9.0.0" } }, "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ=="], + + "loupe": ["loupe@3.2.1", "", {}, "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ=="], + + "magic-string": ["magic-string@0.30.19", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw=="], + + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], + + "pathe": ["pathe@1.1.2", "", {}, "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="], + + "pathval": ["pathval@2.0.1", "", {}, "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ=="], + + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + + "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], + + "rollup": ["rollup@4.50.1", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.50.1", "@rollup/rollup-android-arm64": "4.50.1", "@rollup/rollup-darwin-arm64": "4.50.1", "@rollup/rollup-darwin-x64": "4.50.1", "@rollup/rollup-freebsd-arm64": "4.50.1", "@rollup/rollup-freebsd-x64": "4.50.1", "@rollup/rollup-linux-arm-gnueabihf": "4.50.1", "@rollup/rollup-linux-arm-musleabihf": "4.50.1", "@rollup/rollup-linux-arm64-gnu": "4.50.1", "@rollup/rollup-linux-arm64-musl": "4.50.1", "@rollup/rollup-linux-loongarch64-gnu": "4.50.1", "@rollup/rollup-linux-ppc64-gnu": "4.50.1", "@rollup/rollup-linux-riscv64-gnu": "4.50.1", "@rollup/rollup-linux-riscv64-musl": "4.50.1", "@rollup/rollup-linux-s390x-gnu": "4.50.1", "@rollup/rollup-linux-x64-gnu": "4.50.1", "@rollup/rollup-linux-x64-musl": "4.50.1", "@rollup/rollup-openharmony-arm64": "4.50.1", "@rollup/rollup-win32-arm64-msvc": "4.50.1", "@rollup/rollup-win32-ia32-msvc": "4.50.1", "@rollup/rollup-win32-x64-msvc": "4.50.1", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-78E9voJHwnXQMiQdiqswVLZwJIzdBKJ1GdI5Zx6XwoFKUIk09/sSrr+05QFzvYb8q6Y9pPV45zzDuYa3907TZA=="], + + "siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="], + + "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], + + "stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="], + + "std-env": ["std-env@3.9.0", "", {}, "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw=="], + + "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="], + + "tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="], + + "tinypool": ["tinypool@1.1.1", "", {}, "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg=="], + + "tinyrainbow": ["tinyrainbow@1.2.0", "", {}, "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ=="], + + "tinyspy": ["tinyspy@3.0.2", "", {}, "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q=="], + + "tweetnacl": ["tweetnacl@1.0.3", "", {}, "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw=="], + + "typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="], + + "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], + + "vite": ["vite@5.4.20", "", { "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", "rollup": "^4.20.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["@types/node", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-j3lYzGC3P+B5Yfy/pfKNgVEg4+UtcIJcVRt2cDjIOmhLourAqPqf8P7acgxeiSgUB7E3p2P8/3gNIgDLpwzs4g=="], + + "vite-node": ["vite-node@2.1.9", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.3.7", "es-module-lexer": "^1.5.4", "pathe": "^1.1.2", "vite": "^5.0.0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA=="], + + "vitest": ["vitest@2.1.9", "", { "dependencies": { "@vitest/expect": "2.1.9", "@vitest/mocker": "2.1.9", "@vitest/pretty-format": "^2.1.9", "@vitest/runner": "2.1.9", "@vitest/snapshot": "2.1.9", "@vitest/spy": "2.1.9", "@vitest/utils": "2.1.9", "chai": "^5.1.2", "debug": "^4.3.7", "expect-type": "^1.1.0", "magic-string": "^0.30.12", "pathe": "^1.1.2", "std-env": "^3.8.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.1", "tinypool": "^1.0.1", "tinyrainbow": "^1.2.0", "vite": "^5.0.0", "vite-node": "2.1.9", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/node": "^18.0.0 || >=20.0.0", "@vitest/browser": "2.1.9", "@vitest/ui": "2.1.9", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q=="], + + "vlq": ["vlq@2.0.4", "", {}, "sha512-aodjPa2wPQFkra1G8CzJBTHXhgk3EVSwxSWXNPr1fgdFLUb8kvLV1iEb6rFgasIsjP82HWI6dsb5Io26DDnasA=="], + + "why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="], + } +} diff --git a/packages/typescript/algod_client/package.json b/packages/typescript/algod_client/package.json index d239f4357..ec23cfbea 100644 --- a/packages/typescript/algod_client/package.json +++ b/packages/typescript/algod_client/package.json @@ -11,14 +11,14 @@ "test": "vitest run" }, "dependencies": { - "json-bigint": "^1.0.0", - "algo-msgpack-with-bigint": "^2.1.1" + "@msgpack/msgpack": "^3.1.2", + "json-bigint": "^1.0.0" }, "devDependencies": { - "typescript": "^5.5.0", "@types/json-bigint": "^1.0.0", - "vitest": "^2.0.0", "@types/node": "^20.0.0", - "algosdk": "^2.7.0" + "algosdk": "^3.0.0", + "typescript": "^5.5.0", + "vitest": "^2.0.0" } } diff --git a/packages/typescript/algod_client/src/apis/api.service.ts b/packages/typescript/algod_client/src/apis/api.service.ts index 0d43b44f4..62d0cbab6 100644 --- a/packages/typescript/algod_client/src/apis/api.service.ts +++ b/packages/typescript/algod_client/src/apis/api.service.ts @@ -43,7 +43,7 @@ import type { WaitForBlock, } from "../models/index"; -export class ApiService { +export class AlgodApi { constructor(public readonly httpRequest: BaseHttpRequest) {} abortCatchup(catchpoint: string, requestOptions?: ApiRequestOptions): Promise { @@ -67,60 +67,56 @@ export class ApiService { accountApplicationInformation( address: string, - applicationId: number, + applicationId: number | bigint, params?: { format?: "json" | "msgpack" }, requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {}; - // Content negotiation: - // - If explicit format=json, prefer JSON - // - Else if server supports JSON, prefer JSON by default - // - Else fall back to msgpack - const hasExplicitJson = params?.format === "json"; - const prefersJson = hasExplicitJson || true; - headers["Accept"] = prefersJson ? "application/json" : "application/msgpack"; + // Content negotiation (aligned with Rust behavior): + // - Default to msgpack when available (better performance, smaller payload) + // - Only use JSON if explicitly requested via format=json + const useJson = params?.format === "json"; + headers["Accept"] = useJson ? "application/json" : "application/msgpack"; // Header parameters return this.httpRequest.request({ method: "GET", url: "/v2/accounts/{address}/applications/{application-id}", - path: { address: address, "application-id": applicationId }, + path: { address: address, "application-id": typeof applicationId === "bigint" ? applicationId.toString() : applicationId }, query: { format: params?.format }, headers, body: undefined, mediaType: undefined, - expectBinary: params?.format === "json" ? false : false, + expectBinary: params?.format === "json" ? false : true, ...(requestOptions ?? {}), }); } accountAssetInformation( address: string, - assetId: number, + assetId: number | bigint, params?: { format?: "json" | "msgpack" }, requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {}; - // Content negotiation: - // - If explicit format=json, prefer JSON - // - Else if server supports JSON, prefer JSON by default - // - Else fall back to msgpack - const hasExplicitJson = params?.format === "json"; - const prefersJson = hasExplicitJson || true; - headers["Accept"] = prefersJson ? "application/json" : "application/msgpack"; + // Content negotiation (aligned with Rust behavior): + // - Default to msgpack when available (better performance, smaller payload) + // - Only use JSON if explicitly requested via format=json + const useJson = params?.format === "json"; + headers["Accept"] = useJson ? "application/json" : "application/msgpack"; // Header parameters return this.httpRequest.request({ method: "GET", url: "/v2/accounts/{address}/assets/{asset-id}", - path: { address: address, "asset-id": assetId }, + path: { address: address, "asset-id": typeof assetId === "bigint" ? assetId.toString() : assetId }, query: { format: params?.format }, headers, body: undefined, mediaType: undefined, - expectBinary: params?.format === "json" ? false : false, + expectBinary: params?.format === "json" ? false : true, ...(requestOptions ?? {}), }); } @@ -154,13 +150,11 @@ export class ApiService { requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {}; - // Content negotiation: - // - If explicit format=json, prefer JSON - // - Else if server supports JSON, prefer JSON by default - // - Else fall back to msgpack - const hasExplicitJson = params?.format === "json"; - const prefersJson = hasExplicitJson || true; - headers["Accept"] = prefersJson ? "application/json" : "application/msgpack"; + // Content negotiation (aligned with Rust behavior): + // - Default to msgpack when available (better performance, smaller payload) + // - Only use JSON if explicitly requested via format=json + const useJson = params?.format === "json"; + headers["Accept"] = useJson ? "application/json" : "application/msgpack"; // Header parameters @@ -172,12 +166,12 @@ export class ApiService { headers, body: undefined, mediaType: undefined, - expectBinary: params?.format === "json" ? false : false, + expectBinary: params?.format === "json" ? false : true, ...(requestOptions ?? {}), }); } - addParticipationKey(params?: { body: Uint8Array }, requestOptions?: ApiRequestOptions): Promise { + addParticipationKey(params?: { body: string }, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; headers["Content-Type"] = "application/msgpack"; @@ -191,13 +185,14 @@ export class ApiService { query: {}, headers, body: params?.body, + // Only msgpack supported for request body mediaType: "application/msgpack", expectBinary: false, ...(requestOptions ?? {}), }); } - appendKeys(participationId: string, params?: { body: Uint8Array }, requestOptions?: ApiRequestOptions): Promise { + appendKeys(participationId: string, params?: { body: string }, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; headers["Content-Type"] = "application/msgpack"; @@ -211,6 +206,7 @@ export class ApiService { query: {}, headers, body: params?.body, + // Only msgpack supported for request body mediaType: "application/msgpack", expectBinary: false, ...(requestOptions ?? {}), @@ -282,7 +278,7 @@ export class ApiService { }); } - getApplicationBoxByName(applicationId: number, params?: { name: string }, requestOptions?: ApiRequestOptions): Promise { + getApplicationBoxByName(applicationId: number | bigint, params?: { name: string }, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -291,7 +287,7 @@ export class ApiService { return this.httpRequest.request({ method: "GET", url: "/v2/applications/{application-id}/box", - path: { "application-id": applicationId }, + path: { "application-id": typeof applicationId === "bigint" ? applicationId.toString() : applicationId }, query: { name: params?.name }, headers, body: undefined, @@ -302,7 +298,7 @@ export class ApiService { } getApplicationBoxes( - applicationId: number, + applicationId: number | bigint, params?: { max?: number | bigint }, requestOptions?: ApiRequestOptions, ): Promise { @@ -314,7 +310,7 @@ export class ApiService { return this.httpRequest.request({ method: "GET", url: "/v2/applications/{application-id}/boxes", - path: { "application-id": applicationId }, + path: { "application-id": typeof applicationId === "bigint" ? applicationId.toString() : applicationId }, query: { max: typeof params?.max === "bigint" ? (params!.max as bigint).toString() : params?.max }, headers, body: undefined, @@ -324,7 +320,7 @@ export class ApiService { }); } - getApplicationById(applicationId: number, requestOptions?: ApiRequestOptions): Promise { + getApplicationById(applicationId: number | bigint, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -333,7 +329,7 @@ export class ApiService { return this.httpRequest.request({ method: "GET", url: "/v2/applications/{application-id}", - path: { "application-id": applicationId }, + path: { "application-id": typeof applicationId === "bigint" ? applicationId.toString() : applicationId }, query: {}, headers, body: undefined, @@ -343,7 +339,7 @@ export class ApiService { }); } - getAssetById(assetId: number, requestOptions?: ApiRequestOptions): Promise { + getAssetById(assetId: number | bigint, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -352,7 +348,7 @@ export class ApiService { return this.httpRequest.request({ method: "GET", url: "/v2/assets/{asset-id}", - path: { "asset-id": assetId }, + path: { "asset-id": typeof assetId === "bigint" ? assetId.toString() : assetId }, query: {}, headers, body: undefined, @@ -363,35 +359,33 @@ export class ApiService { } getBlock( - round: number, + round: number | bigint, params?: { headerOnly?: boolean; format?: "json" | "msgpack" }, requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {}; - // Content negotiation: - // - If explicit format=json, prefer JSON - // - Else if server supports JSON, prefer JSON by default - // - Else fall back to msgpack - const hasExplicitJson = params?.format === "json"; - const prefersJson = hasExplicitJson || true; - headers["Accept"] = prefersJson ? "application/json" : "application/msgpack"; + // Content negotiation (aligned with Rust behavior): + // - Default to msgpack when available (better performance, smaller payload) + // - Only use JSON if explicitly requested via format=json + const useJson = params?.format === "json"; + headers["Accept"] = useJson ? "application/json" : "application/msgpack"; // Header parameters return this.httpRequest.request({ method: "GET", url: "/v2/blocks/{round}", - path: { round: round }, + path: { round: typeof round === "bigint" ? round.toString() : round }, query: { "header-only": params?.headerOnly, format: params?.format }, headers, body: undefined, mediaType: undefined, - expectBinary: params?.format === "json" ? false : false, + expectBinary: params?.format === "json" ? false : true, ...(requestOptions ?? {}), }); } - getBlockHash(round: number, requestOptions?: ApiRequestOptions): Promise { + getBlockHash(round: number | bigint, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -400,7 +394,7 @@ export class ApiService { return this.httpRequest.request({ method: "GET", url: "/v2/blocks/{round}/hash", - path: { round: round }, + path: { round: typeof round === "bigint" ? round.toString() : round }, query: {}, headers, body: undefined, @@ -410,7 +404,7 @@ export class ApiService { }); } - getBlockLogs(round: number, requestOptions?: ApiRequestOptions): Promise { + getBlockLogs(round: number | bigint, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -419,7 +413,7 @@ export class ApiService { return this.httpRequest.request({ method: "GET", url: "/v2/blocks/{round}/logs", - path: { round: round }, + path: { round: typeof round === "bigint" ? round.toString() : round }, query: {}, headers, body: undefined, @@ -448,7 +442,7 @@ export class ApiService { }); } - getBlockTxids(round: number, requestOptions?: ApiRequestOptions): Promise { + getBlockTxids(round: number | bigint, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -457,7 +451,7 @@ export class ApiService { return this.httpRequest.request({ method: "GET", url: "/v2/blocks/{round}/txids", - path: { round: round }, + path: { round: typeof round === "bigint" ? round.toString() : round }, query: {}, headers, body: undefined, @@ -525,30 +519,28 @@ export class ApiService { } getLedgerStateDelta( - round: number, + round: number | bigint, params?: { format?: "json" | "msgpack" }, requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {}; - // Content negotiation: - // - If explicit format=json, prefer JSON - // - Else if server supports JSON, prefer JSON by default - // - Else fall back to msgpack - const hasExplicitJson = params?.format === "json"; - const prefersJson = hasExplicitJson || true; - headers["Accept"] = prefersJson ? "application/json" : "application/msgpack"; + // Content negotiation (aligned with Rust behavior): + // - Default to msgpack when available (better performance, smaller payload) + // - Only use JSON if explicitly requested via format=json + const useJson = params?.format === "json"; + headers["Accept"] = useJson ? "application/json" : "application/msgpack"; // Header parameters return this.httpRequest.request({ method: "GET", url: "/v2/deltas/{round}", - path: { round: round }, + path: { round: typeof round === "bigint" ? round.toString() : round }, query: { format: params?.format }, headers, body: undefined, mediaType: undefined, - expectBinary: params?.format === "json" ? false : false, + expectBinary: params?.format === "json" ? false : true, ...(requestOptions ?? {}), }); } @@ -559,13 +551,11 @@ export class ApiService { requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {}; - // Content negotiation: - // - If explicit format=json, prefer JSON - // - Else if server supports JSON, prefer JSON by default - // - Else fall back to msgpack - const hasExplicitJson = params?.format === "json"; - const prefersJson = hasExplicitJson || true; - headers["Accept"] = prefersJson ? "application/json" : "application/msgpack"; + // Content negotiation (aligned with Rust behavior): + // - Default to msgpack when available (better performance, smaller payload) + // - Only use JSON if explicitly requested via format=json + const useJson = params?.format === "json"; + headers["Accept"] = useJson ? "application/json" : "application/msgpack"; // Header parameters @@ -577,12 +567,12 @@ export class ApiService { headers, body: undefined, mediaType: undefined, - expectBinary: params?.format === "json" ? false : false, + expectBinary: params?.format === "json" ? false : true, ...(requestOptions ?? {}), }); } - getLightBlockHeaderProof(round: number, requestOptions?: ApiRequestOptions): Promise { + getLightBlockHeaderProof(round: number | bigint, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -591,7 +581,7 @@ export class ApiService { return this.httpRequest.request({ method: "GET", url: "/v2/blocks/{round}/lightheader/proof", - path: { round: round }, + path: { round: typeof round === "bigint" ? round.toString() : round }, query: {}, headers, body: undefined, @@ -644,13 +634,11 @@ export class ApiService { requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {}; - // Content negotiation: - // - If explicit format=json, prefer JSON - // - Else if server supports JSON, prefer JSON by default - // - Else fall back to msgpack - const hasExplicitJson = params?.format === "json"; - const prefersJson = hasExplicitJson || true; - headers["Accept"] = prefersJson ? "application/json" : "application/msgpack"; + // Content negotiation (aligned with Rust behavior): + // - Default to msgpack when available (better performance, smaller payload) + // - Only use JSON if explicitly requested via format=json + const useJson = params?.format === "json"; + headers["Accept"] = useJson ? "application/json" : "application/msgpack"; // Header parameters @@ -662,7 +650,7 @@ export class ApiService { headers, body: undefined, mediaType: undefined, - expectBinary: params?.format === "json" ? false : false, + expectBinary: params?.format === "json" ? false : true, ...(requestOptions ?? {}), }); } @@ -673,13 +661,11 @@ export class ApiService { requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {}; - // Content negotiation: - // - If explicit format=json, prefer JSON - // - Else if server supports JSON, prefer JSON by default - // - Else fall back to msgpack - const hasExplicitJson = params?.format === "json"; - const prefersJson = hasExplicitJson || true; - headers["Accept"] = prefersJson ? "application/json" : "application/msgpack"; + // Content negotiation (aligned with Rust behavior): + // - Default to msgpack when available (better performance, smaller payload) + // - Only use JSON if explicitly requested via format=json + const useJson = params?.format === "json"; + headers["Accept"] = useJson ? "application/json" : "application/msgpack"; // Header parameters @@ -691,7 +677,7 @@ export class ApiService { headers, body: undefined, mediaType: undefined, - expectBinary: params?.format === "json" ? false : false, + expectBinary: params?.format === "json" ? false : true, ...(requestOptions ?? {}), }); } @@ -715,7 +701,7 @@ export class ApiService { }); } - getStateProof(round: number, requestOptions?: ApiRequestOptions): Promise { + getStateProof(round: number | bigint, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -724,7 +710,7 @@ export class ApiService { return this.httpRequest.request({ method: "GET", url: "/v2/stateproofs/{round}", - path: { round: round }, + path: { round: typeof round === "bigint" ? round.toString() : round }, query: {}, headers, body: undefined, @@ -792,36 +778,34 @@ export class ApiService { } getTransactionGroupLedgerStateDeltasForRound( - round: number, + round: number | bigint, params?: { format?: "json" | "msgpack" }, requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {}; - // Content negotiation: - // - If explicit format=json, prefer JSON - // - Else if server supports JSON, prefer JSON by default - // - Else fall back to msgpack - const hasExplicitJson = params?.format === "json"; - const prefersJson = hasExplicitJson || true; - headers["Accept"] = prefersJson ? "application/json" : "application/msgpack"; + // Content negotiation (aligned with Rust behavior): + // - Default to msgpack when available (better performance, smaller payload) + // - Only use JSON if explicitly requested via format=json + const useJson = params?.format === "json"; + headers["Accept"] = useJson ? "application/json" : "application/msgpack"; // Header parameters return this.httpRequest.request({ method: "GET", url: "/v2/deltas/{round}/txn/group", - path: { round: round }, + path: { round: typeof round === "bigint" ? round.toString() : round }, query: { format: params?.format }, headers, body: undefined, mediaType: undefined, - expectBinary: params?.format === "json" ? false : false, + expectBinary: params?.format === "json" ? false : true, ...(requestOptions ?? {}), }); } getTransactionProof( - round: number, + round: number | bigint, txid: string, params?: { hashtype?: "sha512_256" | "sha256"; format?: "json" | "msgpack" }, requestOptions?: ApiRequestOptions, @@ -834,7 +818,7 @@ export class ApiService { return this.httpRequest.request({ method: "GET", url: "/v2/blocks/{round}/transactions/{txid}/proof", - path: { round: round, txid: txid }, + path: { round: typeof round === "bigint" ? round.toString() : round, txid: txid }, query: { hashtype: params?.hashtype, format: params?.format }, headers, body: undefined, @@ -907,13 +891,11 @@ export class ApiService { requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {}; - // Content negotiation: - // - If explicit format=json, prefer JSON - // - Else if server supports JSON, prefer JSON by default - // - Else fall back to msgpack - const hasExplicitJson = params?.format === "json"; - const prefersJson = hasExplicitJson || true; - headers["Accept"] = prefersJson ? "application/json" : "application/msgpack"; + // Content negotiation (aligned with Rust behavior): + // - Default to msgpack when available (better performance, smaller payload) + // - Only use JSON if explicitly requested via format=json + const useJson = params?.format === "json"; + headers["Accept"] = useJson ? "application/json" : "application/msgpack"; // Header parameters @@ -925,7 +907,7 @@ export class ApiService { headers, body: undefined, mediaType: undefined, - expectBinary: params?.format === "json" ? false : false, + expectBinary: params?.format === "json" ? false : true, ...(requestOptions ?? {}), }); } @@ -1008,7 +990,7 @@ export class ApiService { }); } - setSyncRound(round: number, requestOptions?: ApiRequestOptions): Promise { + setSyncRound(round: number | bigint, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -1017,7 +999,7 @@ export class ApiService { return this.httpRequest.request({ method: "POST", url: "/v2/ledger/sync/{round}", - path: { round: round }, + path: { round: typeof round === "bigint" ? round.toString() : round }, query: {}, headers, body: undefined, @@ -1027,7 +1009,7 @@ export class ApiService { }); } - shutdownNode(params?: { timeout?: number }, requestOptions?: ApiRequestOptions): Promise { + shutdownNode(params?: { timeout?: number | bigint }, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -1037,7 +1019,7 @@ export class ApiService { method: "POST", url: "/v2/shutdown", path: {}, - query: { timeout: params?.timeout }, + query: { timeout: typeof params?.timeout === "bigint" ? (params!.timeout as bigint).toString() : params?.timeout }, headers, body: undefined, mediaType: undefined, @@ -1051,14 +1033,12 @@ export class ApiService { requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {}; - // Content negotiation: - // - If explicit format=json, prefer JSON - // - Else if server supports JSON, prefer JSON by default - // - Else fall back to msgpack - const hasExplicitJson = params?.format === "json"; - const prefersJson = hasExplicitJson || true; - headers["Accept"] = prefersJson ? "application/json" : "application/msgpack"; - headers["Content-Type"] = "application/json"; + // Content negotiation (aligned with Rust behavior): + // - Default to msgpack when available (better performance, smaller payload) + // - Only use JSON if explicitly requested via format=json + const useJson = params?.format === "json"; + headers["Accept"] = useJson ? "application/json" : "application/msgpack"; + headers["Content-Type"] = params?.format === "json" ? "application/json" : "application/msgpack"; // Header parameters @@ -1069,13 +1049,14 @@ export class ApiService { query: { format: params?.format }, headers, body: params?.body, - mediaType: "application/json", - expectBinary: params?.format === "json" ? false : false, + // Dynamic mediaType based on format parameter (prefer msgpack by default) + mediaType: params?.format === "json" ? "application/json" : "application/msgpack", + expectBinary: params?.format === "json" ? false : true, ...(requestOptions ?? {}), }); } - startCatchup(catchpoint: string, params?: { min?: number }, requestOptions?: ApiRequestOptions): Promise { + startCatchup(catchpoint: string, params?: { min?: number | bigint }, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -1085,7 +1066,7 @@ export class ApiService { method: "POST", url: "/v2/catchup/{catchpoint}", path: { catchpoint: catchpoint }, - query: { min: params?.min }, + query: { min: typeof params?.min === "bigint" ? (params!.min as bigint).toString() : params?.min }, headers, body: undefined, mediaType: undefined, @@ -1156,7 +1137,7 @@ export class ApiService { tealDryrun(params?: { body?: DryrunRequest }, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; - headers["Content-Type"] = "application/json"; + headers["Content-Type"] = "application/msgpack"; // Header parameters @@ -1167,7 +1148,8 @@ export class ApiService { query: {}, headers, body: params?.body, - mediaType: "application/json", + // Both supported, prefer msgpack for better performance + mediaType: "application/msgpack", expectBinary: false, ...(requestOptions ?? {}), }); @@ -1211,7 +1193,7 @@ export class ApiService { }); } - waitForBlock(round: number, requestOptions?: ApiRequestOptions): Promise { + waitForBlock(round: number | bigint, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -1220,7 +1202,7 @@ export class ApiService { return this.httpRequest.request({ method: "GET", url: "/v2/status/wait-for-block-after/{round}", - path: { round: round }, + path: { round: typeof round === "bigint" ? round.toString() : round }, query: {}, headers, body: undefined, diff --git a/packages/typescript/algod_client/src/apis/index.ts b/packages/typescript/algod_client/src/apis/index.ts index c8244b99b..f1d4c2337 100644 --- a/packages/typescript/algod_client/src/apis/index.ts +++ b/packages/typescript/algod_client/src/apis/index.ts @@ -1,2 +1,2 @@ // Barrel file for services -export { ApiService } from "./api.service"; +export { AlgodApi } from "./api.service"; diff --git a/packages/typescript/algod_client/src/client.ts b/packages/typescript/algod_client/src/client.ts index 310bdaba7..2c8f50e71 100644 --- a/packages/typescript/algod_client/src/client.ts +++ b/packages/typescript/algod_client/src/client.ts @@ -1,13 +1,13 @@ -import type { OpenAPIConfig } from "./core/OpenAPI"; +import type { ClientConfig } from "./core/ClientConfig"; import { FetchHttpRequest } from "./core/FetchHttpRequest"; -import { ApiService } from "./apis/api.service"; +import { AlgodApi } from "./apis/api.service"; -export class Client { +export class AlgodClient { public readonly request: FetchHttpRequest; - public readonly api: ApiService; + public readonly api: AlgodApi; - constructor(config: OpenAPIConfig) { + constructor(config: ClientConfig) { this.request = new FetchHttpRequest(config); - this.api = new ApiService(this.request); + this.api = new AlgodApi(this.request); } } diff --git a/packages/typescript/algod_client/src/core/BaseHttpRequest.ts b/packages/typescript/algod_client/src/core/BaseHttpRequest.ts index 85cf8d865..45f2f0666 100644 --- a/packages/typescript/algod_client/src/core/BaseHttpRequest.ts +++ b/packages/typescript/algod_client/src/core/BaseHttpRequest.ts @@ -1,4 +1,4 @@ -import type { OpenAPIConfig } from "./OpenAPI"; +import type { ClientConfig } from "./ClientConfig"; export interface RequestOptions { method: string; @@ -16,6 +16,6 @@ export interface RequestOptions { export type ApiRequestOptions = RequestOptions; export abstract class BaseHttpRequest { - constructor(public readonly config: OpenAPIConfig) {} + constructor(public readonly config: ClientConfig) {} abstract request(options: RequestOptions): Promise; } diff --git a/packages/typescript/algod_client/src/core/OpenAPI.ts b/packages/typescript/algod_client/src/core/ClientConfig.ts similarity index 74% rename from packages/typescript/algod_client/src/core/OpenAPI.ts rename to packages/typescript/algod_client/src/core/ClientConfig.ts index fde885a4d..45cd2cf9f 100644 --- a/packages/typescript/algod_client/src/core/OpenAPI.ts +++ b/packages/typescript/algod_client/src/core/ClientConfig.ts @@ -1,9 +1,9 @@ /* - Minimal OpenAPI runtime config holder + Minimal client runtime config holder */ export type BaseURL = string; -export interface OpenAPIConfig { +export interface ClientConfig { BASE: BaseURL; VERSION?: string; WITH_CREDENTIALS?: boolean; @@ -15,8 +15,3 @@ export interface OpenAPIConfig { ENCODE_PATH?: (path: string) => string; INT_DECODING?: "safe" | "unsafe" | "mixed" | "bigint"; } - -export const OpenAPI: OpenAPIConfig = { - BASE: "", - INT_DECODING: "mixed", -}; diff --git a/packages/typescript/algod_client/src/core/FetchHttpRequest.ts b/packages/typescript/algod_client/src/core/FetchHttpRequest.ts index b47684434..bc0c4cb9a 100644 --- a/packages/typescript/algod_client/src/core/FetchHttpRequest.ts +++ b/packages/typescript/algod_client/src/core/FetchHttpRequest.ts @@ -1,5 +1,4 @@ import { BaseHttpRequest, type RequestOptions } from "./BaseHttpRequest"; -import { OpenAPI } from "./OpenAPI"; import { request as defaultRequest } from "./request"; export class FetchHttpRequest extends BaseHttpRequest { diff --git a/packages/typescript/algod_client/src/core/casing.ts b/packages/typescript/algod_client/src/core/casing.ts new file mode 100644 index 000000000..7ad409bd5 --- /dev/null +++ b/packages/typescript/algod_client/src/core/casing.ts @@ -0,0 +1,52 @@ +function toCamel(segmented: string): string { + if (!segmented) return segmented; + // Fast path: if no hyphen, return as-is but ensure typical camel conversion for underscores + if (!segmented.includes("-")) return segmented.replace(/_([a-z0-9])/g, (_, c) => c.toUpperCase()); + return segmented + .split("-") + .map((part, index) => (index === 0 ? part : part.charAt(0).toUpperCase() + part.slice(1))) + .join(""); +} + +function toKebab(camel: string): string { + if (!camel) return camel; + // Convert camelCase or mixedCase to kebab-case; leave existing hyphens and numbers intact + return camel + .replace(/([a-z0-9])([A-Z])/g, "$1-$2") + .replace(/_/g, "-") + .toLowerCase(); +} + +function isPlainObject(value: unknown): value is Record { + if (value === null || typeof value !== "object") return false; + const proto = Object.getPrototypeOf(value); + return proto === Object.prototype || proto === null; +} + +export function toCamelCaseKeysDeep(value: T): T { + // eslint-disable-line @typescript-eslint/no-explicit-any + if (Array.isArray(value)) return value.map((v) => toCamelCaseKeysDeep(v)) as unknown as T; + if (value instanceof Uint8Array) return value; + if (!isPlainObject(value)) return value; + + const out: Record = {}; + for (const [k, v] of Object.entries(value)) { + const newKey = toCamel(k); + out[newKey] = toCamelCaseKeysDeep(v as unknown); + } + return out as unknown as T; +} + +export function toKebabCaseKeysDeep(value: T): T { + // eslint-disable-line @typescript-eslint/no-explicit-any + if (Array.isArray(value)) return value.map((v) => toKebabCaseKeysDeep(v)) as unknown as T; + if (value instanceof Uint8Array) return value; + if (!isPlainObject(value)) return value; + + const out: Record = {}; + for (const [k, v] of Object.entries(value)) { + const newKey = toKebab(k); + out[newKey] = toKebabCaseKeysDeep(v as unknown); + } + return out as unknown as T; +} diff --git a/packages/typescript/algod_client/src/core/msgpack.ts b/packages/typescript/algod_client/src/core/msgpack.ts index 1d2a5aa2f..a30aa9314 100644 --- a/packages/typescript/algod_client/src/core/msgpack.ts +++ b/packages/typescript/algod_client/src/core/msgpack.ts @@ -1,13 +1,132 @@ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -declare const require: any; -// eslint-disable-next-line @typescript-eslint/no-var-requires -const { decode } = require("algo-msgpack-with-bigint"); - +import { encode as msgpackEncode, decode as msgpackDecode } from "@msgpack/msgpack"; import type { IntDecoding } from "./json"; +/** + * Prepare value for Algorand-compliant msgpack encoding. + * Implements strict Algorand msgpack rules (matching go-algorand behavior): + * 1. Omit zero values, empty strings, and empty arrays (RecursiveEmptyCheck) + * 2. Convert bigints to smallest safe integer type (PositiveIntUnsigned) + * 3. Sorted keys and canonical encoding are handled by msgpackEncode options + * + * These rules apply universally for both API communication and transaction encoding, + * as go-algorand uses the same codec settings for all msgpack operations. + */ +function prepareForEncoding(value: any): any { + // eslint-disable-line @typescript-eslint/no-explicit-any + if (value === null || value === undefined) { + return undefined; + } + + // Handle numbers - omit zeros + if (typeof value === "number") { + if (value === 0) return undefined; + return value; + } + + // Handle bigints - omit zeros and convert to number when safe (for smaller encoding) + if (typeof value === "bigint") { + if (value === 0n) return undefined; + // Convert to number if it fits safely (implements PositiveIntUnsigned behavior) + if (value <= BigInt(Number.MAX_SAFE_INTEGER) && value >= BigInt(Number.MIN_SAFE_INTEGER)) { + return Number(value); + } + return value; + } + + // Handle strings - omit empty strings + if (typeof value === "string") { + if (value === "") return undefined; + return value; + } + + // Handle Uint8Array - omit empty arrays + if (value instanceof Uint8Array) { + if (value.length === 0) return undefined; + return value; + } + + // Handle arrays - omit empty arrays and filter undefined values + if (Array.isArray(value)) { + if (value.length === 0) return undefined; + const processed = value.map(prepareForEncoding).filter((v) => v !== undefined); + return processed.length > 0 ? processed : undefined; + } + + // Handle objects - omit empty objects and filter undefined values (RecursiveEmptyCheck) + if (value && typeof value === "object") { + const result: any = {}; // eslint-disable-line @typescript-eslint/no-explicit-any + for (const [k, v] of Object.entries(value)) { + const prepared = prepareForEncoding(v); + if (prepared !== undefined) { + result[k] = prepared; + } + } + // Return undefined if object is empty after filtering + return Object.keys(result).length > 0 ? result : undefined; + } + + return value; +} + +function convertIntegersToBigInt(value: any): any { + // eslint-disable-line @typescript-eslint/no-explicit-any + if (value === null || value === undefined) { + return value; + } + if (typeof value === "number" && Number.isInteger(value)) { + return BigInt(value); + } + if (typeof value === "bigint") { + return value; + } + if (value instanceof Uint8Array) { + return value; + } + if (Array.isArray(value)) { + return value.map(convertIntegersToBigInt); + } + if (value && typeof value === "object") { + const result: any = {}; // eslint-disable-line @typescript-eslint/no-explicit-any + for (const [k, v] of Object.entries(value)) { + result[k] = convertIntegersToBigInt(v); + } + return result; + } + return value; +} + +/** + * Encode a value as msgpack using Algorand's strict encoding rules. + * This matches go-algorand's protocol.CodecHandle settings: + * - Canonical = true (sorted keys, deterministic encoding) + * - RecursiveEmptyCheck = true (omit empty/zero values recursively) + * - PositiveIntUnsigned = true (use smallest unsigned integer types) + * + * @param value - The value to encode + * @returns Encoded msgpack bytes + */ +export function encodeMsgPack(value: any): Uint8Array { + // eslint-disable-line @typescript-eslint/no-explicit-any + const prepared = prepareForEncoding(value); + + // Ensure we return valid msgpack even if everything was omitted + const toEncode = prepared === undefined ? {} : prepared; + + return msgpackEncode(toEncode, { + sortKeys: true, // Canonical = true in go-algorand + forceIntegerToFloat: false, + ignoreUndefined: true, // Handle undefined values from prepareForEncoding + initialBufferSize: 2048, + useBigInt64: true, // Support for large integers + }); +} + export function decodeMsgPack(buffer: Uint8Array): any { // eslint-disable-line @typescript-eslint/no-explicit-any - return decode(buffer); + const decoded = msgpackDecode(buffer, { + useBigInt64: true, + }); + return convertIntegersToBigInt(decoded); } export function normalizeMsgPackIntegers(value: any, intDecoding: IntDecoding): any { diff --git a/packages/typescript/algod_client/src/core/request.ts b/packages/typescript/algod_client/src/core/request.ts index e33d274f1..38eb3d463 100644 --- a/packages/typescript/algod_client/src/core/request.ts +++ b/packages/typescript/algod_client/src/core/request.ts @@ -1,12 +1,14 @@ -import type { OpenAPIConfig } from "./OpenAPI"; +import type { ClientConfig } from "./ClientConfig"; import { ApiError } from "./ApiError"; import { parseJson, stringifyJson } from "./json"; -import { decodeMsgPack, normalizeMsgPackIntegers } from "./msgpack"; +import { decodeMsgPack, encodeMsgPack, normalizeMsgPackIntegers } from "./msgpack"; +import { toCamelCaseKeysDeep } from "./casing"; +import { toKebabCaseKeysDeep } from "./casing"; const encodeURIPath = (path: string): string => encodeURI(path).replace(/%5B/g, "[").replace(/%5D/g, "]"); export async function request( - config: OpenAPIConfig, + config: ClientConfig, options: { method: string; url: string; @@ -52,10 +54,24 @@ export async function request( headers["Authorization"] = `Basic ${btoa(`${config.USERNAME}:${config.PASSWORD}`)}`; } + // Prepare body based on media type + let body: any = undefined; + if (options.body != null) { + if (options.mediaType?.includes("json")) { + body = stringifyJson(toKebabCaseKeysDeep(options.body)); + } else if (options.mediaType?.includes("msgpack")) { + // Encode typed models to msgpack for requests + body = encodeMsgPack(toKebabCaseKeysDeep(options.body)); + } else { + // For binary/text, pass through as-is + body = options.body; + } + } + const response = await fetch(url.toString(), { method: options.method, headers, - body: options.body != null ? (options.mediaType?.includes("json") ? stringifyJson(options.body) : options.body) : undefined, + body, credentials: config.CREDENTIALS, }); @@ -63,7 +79,7 @@ export async function request( let body: any = undefined; try { const ct = response.headers.get("content-type"); - if (ct && ct.includes("application/json")) body = parseJson(await response.text(), config.INT_DECODING); + if (ct && ct.includes("application/json")) body = parseJson(await response.text(), config.INT_DECODING ?? "mixed"); else body = await response.text(); } catch {} throw new ApiError(url.toString(), response.status, body); @@ -74,17 +90,36 @@ export async function request( return value as unknown as T; } - // Parse by content-type first + // Parse response by content-type const contentType = response.headers.get("content-type") || ""; - if (contentType.includes("application/msgpack") || contentType.includes("application/x-binary")) { + + // Handle msgpack responses - decode to typed models + if (contentType.includes("application/msgpack")) { const buf = new Uint8Array(await response.arrayBuffer()); const decoded = decodeMsgPack(buf); - return normalizeMsgPackIntegers(decoded, config.INT_DECODING ?? "mixed") as T; + const normalized = normalizeMsgPackIntegers(decoded, config.INT_DECODING ?? "bigint"); + return toCamelCaseKeysDeep(normalized) as T; } + + // Handle raw binary responses (e.g., application/x-binary for raw transactions) + if (contentType.includes("application/x-binary") || contentType.includes("application/octet-stream")) { + // For raw binary, return as Uint8Array without decoding + return new Uint8Array(await response.arrayBuffer()) as unknown as T; + } + + // Handle JSON responses if (contentType.includes("application/json")) { const text = await response.text(); - return parseJson(text, config.INT_DECODING) as T; + const parsed = parseJson(text, config.INT_DECODING ?? "mixed"); + return toCamelCaseKeysDeep(parsed) as T; } + // Fallback to text - return (await response.text()) as unknown as T; + const text = await response.text(); + try { + const parsed = JSON.parse(text); + return toCamelCaseKeysDeep(parsed) as T; + } catch { + return text as unknown as T; + } } diff --git a/packages/typescript/algod_client/src/index.ts b/packages/typescript/algod_client/src/index.ts index e51ca64f4..9912e902e 100644 --- a/packages/typescript/algod_client/src/index.ts +++ b/packages/typescript/algod_client/src/index.ts @@ -1,4 +1,4 @@ -export * from "./core/OpenAPI"; +export * from "./core/ClientConfig"; export * from "./core/BaseHttpRequest"; export * from "./core/FetchHttpRequest"; export * from "./core/ApiError"; diff --git a/packages/typescript/algod_client/src/models/abortcatchup.ts b/packages/typescript/algod_client/src/models/abortcatchup.ts index f186782c8..7bc622991 100644 --- a/packages/typescript/algod_client/src/models/abortcatchup.ts +++ b/packages/typescript/algod_client/src/models/abortcatchup.ts @@ -1,4 +1,4 @@ /** * An catchpoint abort response. */ -export type AbortCatchup = { "catchup-message": string }; +export type AbortCatchup = { catchupMessage: string }; diff --git a/packages/typescript/algod_client/src/models/account.ts b/packages/typescript/algod_client/src/models/account.ts index 0fd82be6d..183c7871f 100644 --- a/packages/typescript/algod_client/src/models/account.ts +++ b/packages/typescript/algod_client/src/models/account.ts @@ -9,29 +9,29 @@ import type { AccountParticipation, Application, ApplicationLocalState, Applicat export type Account = { address: string; amount: bigint; - "min-balance": bigint; - "amount-without-pending-rewards": bigint; - "apps-local-state"?: ApplicationLocalState[]; - "total-apps-opted-in": bigint; - "apps-total-schema"?: ApplicationStateSchema; - "apps-total-extra-pages"?: bigint; + minBalance: bigint; + amountWithoutPendingRewards: bigint; + appsLocalState?: ApplicationLocalState[]; + totalAppsOptedIn: bigint; + appsTotalSchema?: ApplicationStateSchema; + appsTotalExtraPages?: bigint; assets?: AssetHolding[]; - "total-assets-opted-in": bigint; - "created-apps"?: Application[]; - "total-created-apps": bigint; - "created-assets"?: Asset[]; - "total-created-assets": bigint; - "total-boxes"?: bigint; - "total-box-bytes"?: bigint; + totalAssetsOptedIn: bigint; + createdApps?: Application[]; + totalCreatedApps: bigint; + createdAssets?: Asset[]; + totalCreatedAssets: bigint; + totalBoxes?: bigint; + totalBoxBytes?: bigint; participation?: AccountParticipation; - "incentive-eligible"?: boolean; - "pending-rewards": bigint; - "reward-base"?: bigint; + incentiveEligible?: boolean; + pendingRewards: bigint; + rewardBase?: bigint; rewards: bigint; round: bigint; status: string; - "sig-type"?: "sig" | "msig" | "lsig"; - "auth-addr"?: string; - "last-proposed"?: bigint; - "last-heartbeat"?: bigint; + sigType?: "sig" | "msig" | "lsig"; + authAddr?: string; + lastProposed?: bigint; + lastHeartbeat?: bigint; }; diff --git a/packages/typescript/algod_client/src/models/accountapplicationinformation.ts b/packages/typescript/algod_client/src/models/accountapplicationinformation.ts index 50ccf96f7..c80c9c212 100644 --- a/packages/typescript/algod_client/src/models/accountapplicationinformation.ts +++ b/packages/typescript/algod_client/src/models/accountapplicationinformation.ts @@ -3,4 +3,4 @@ import type { ApplicationLocalState, ApplicationParams } from "./index"; /** * 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. */ -export type AccountApplicationInformation = { round: bigint; "app-local-state"?: ApplicationLocalState; "created-app"?: ApplicationParams }; +export type AccountApplicationInformation = { round: bigint; appLocalState?: ApplicationLocalState; createdApp?: ApplicationParams }; diff --git a/packages/typescript/algod_client/src/models/accountassetholding.ts b/packages/typescript/algod_client/src/models/accountassetholding.ts index cd3fc67b1..5fbf11c31 100644 --- a/packages/typescript/algod_client/src/models/accountassetholding.ts +++ b/packages/typescript/algod_client/src/models/accountassetholding.ts @@ -3,4 +3,4 @@ import type { AssetHolding, AssetParams } from "./index"; /** * AccountAssetHolding describes the account's asset holding and asset parameters (if either exist) for a specific asset ID. */ -export type AccountAssetHolding = { "asset-holding": AssetHolding; "asset-params"?: AssetParams }; +export type AccountAssetHolding = { assetHolding: AssetHolding; assetParams?: AssetParams }; diff --git a/packages/typescript/algod_client/src/models/accountassetinformation.ts b/packages/typescript/algod_client/src/models/accountassetinformation.ts index 6f08b23cc..b0cfdb675 100644 --- a/packages/typescript/algod_client/src/models/accountassetinformation.ts +++ b/packages/typescript/algod_client/src/models/accountassetinformation.ts @@ -3,4 +3,4 @@ import type { AssetHolding, AssetParams } from "./index"; /** * 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. */ -export type AccountAssetInformation = { round: bigint; "asset-holding"?: AssetHolding; "created-asset"?: AssetParams }; +export type AccountAssetInformation = { round: bigint; assetHolding?: AssetHolding; createdAsset?: AssetParams }; diff --git a/packages/typescript/algod_client/src/models/accountassetsinformation.ts b/packages/typescript/algod_client/src/models/accountassetsinformation.ts index 32de59c55..3e82d65e9 100644 --- a/packages/typescript/algod_client/src/models/accountassetsinformation.ts +++ b/packages/typescript/algod_client/src/models/accountassetsinformation.ts @@ -3,4 +3,4 @@ import type { AccountAssetHolding } from "./index"; /** * AccountAssetsInformationResponse contains a list of assets held by an account. */ -export type AccountAssetsInformation = { round: bigint; "next-token"?: string; "asset-holdings"?: AccountAssetHolding[] }; +export type AccountAssetsInformation = { round: bigint; nextToken?: string; assetHoldings?: AccountAssetHolding[] }; diff --git a/packages/typescript/algod_client/src/models/accountparticipation.ts b/packages/typescript/algod_client/src/models/accountparticipation.ts index 2578b7231..b77cf3b00 100644 --- a/packages/typescript/algod_client/src/models/accountparticipation.ts +++ b/packages/typescript/algod_client/src/models/accountparticipation.ts @@ -2,10 +2,10 @@ * AccountParticipation describes the parameters used by this account in consensus protocol. */ export type AccountParticipation = { - "selection-participation-key": string; - "vote-first-valid": bigint; - "vote-key-dilution": bigint; - "vote-last-valid": bigint; - "vote-participation-key": string; - "state-proof-key"?: string; + selectionParticipationKey: string; + voteFirstValid: bigint; + voteKeyDilution: bigint; + voteLastValid: bigint; + voteParticipationKey: string; + stateProofKey?: string; }; diff --git a/packages/typescript/algod_client/src/models/appcalllogs.ts b/packages/typescript/algod_client/src/models/appcalllogs.ts index 84233e1f1..04e727db5 100644 --- a/packages/typescript/algod_client/src/models/appcalllogs.ts +++ b/packages/typescript/algod_client/src/models/appcalllogs.ts @@ -1,4 +1,4 @@ /** * 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 = { logs: string[]; "application-index": bigint; txId: string }; +export type AppCallLogs = { logs: string[]; applicationIndex: bigint; txId: string }; diff --git a/packages/typescript/algod_client/src/models/applicationinitialstates.ts b/packages/typescript/algod_client/src/models/applicationinitialstates.ts index ce4cee1b2..a75123b82 100644 --- a/packages/typescript/algod_client/src/models/applicationinitialstates.ts +++ b/packages/typescript/algod_client/src/models/applicationinitialstates.ts @@ -5,7 +5,7 @@ import type { ApplicationKvstorage } from "./index"; */ export type ApplicationInitialStates = { id: bigint; - "app-locals"?: ApplicationKvstorage[]; - "app-globals"?: ApplicationKvstorage; - "app-boxes"?: ApplicationKvstorage; + appLocals?: ApplicationKvstorage[]; + appGlobals?: ApplicationKvstorage; + appBoxes?: ApplicationKvstorage; }; diff --git a/packages/typescript/algod_client/src/models/applicationlocalstate.ts b/packages/typescript/algod_client/src/models/applicationlocalstate.ts index 66ed306ce..59ebece87 100644 --- a/packages/typescript/algod_client/src/models/applicationlocalstate.ts +++ b/packages/typescript/algod_client/src/models/applicationlocalstate.ts @@ -3,4 +3,4 @@ import type { ApplicationStateSchema, TealKeyValueStore } from "./index"; /** * Stores local state associated with an application. */ -export type ApplicationLocalState = { id: bigint; schema: ApplicationStateSchema; "key-value"?: TealKeyValueStore }; +export type ApplicationLocalState = { id: bigint; schema: ApplicationStateSchema; keyValue?: TealKeyValueStore }; diff --git a/packages/typescript/algod_client/src/models/applicationparams.ts b/packages/typescript/algod_client/src/models/applicationparams.ts index bb1386731..0ad5c10f3 100644 --- a/packages/typescript/algod_client/src/models/applicationparams.ts +++ b/packages/typescript/algod_client/src/models/applicationparams.ts @@ -5,11 +5,11 @@ import type { ApplicationStateSchema, TealKeyValueStore } from "./index"; */ export type ApplicationParams = { creator: string; - "approval-program": string; - "clear-state-program": string; - "extra-program-pages"?: number; - "local-state-schema"?: ApplicationStateSchema; - "global-state-schema"?: ApplicationStateSchema; - "global-state"?: TealKeyValueStore; + approvalProgram: string; + clearStateProgram: string; + extraProgramPages?: bigint; + localStateSchema?: ApplicationStateSchema; + globalStateSchema?: ApplicationStateSchema; + globalState?: TealKeyValueStore; version?: bigint; }; diff --git a/packages/typescript/algod_client/src/models/applicationstateoperation.ts b/packages/typescript/algod_client/src/models/applicationstateoperation.ts index 8a11ce6b6..5e7eba254 100644 --- a/packages/typescript/algod_client/src/models/applicationstateoperation.ts +++ b/packages/typescript/algod_client/src/models/applicationstateoperation.ts @@ -3,10 +3,4 @@ import type { AvmValue } from "./index"; /** * An operation against an application's global/local/box state. */ -export type ApplicationStateOperation = { - operation: string; - "app-state-type": string; - key: string; - "new-value"?: AvmValue; - account?: string; -}; +export type ApplicationStateOperation = { operation: string; appStateType: string; key: string; newValue?: AvmValue; account?: string }; diff --git a/packages/typescript/algod_client/src/models/applicationstateschema.ts b/packages/typescript/algod_client/src/models/applicationstateschema.ts index 80ddaa431..d40cb1f25 100644 --- a/packages/typescript/algod_client/src/models/applicationstateschema.ts +++ b/packages/typescript/algod_client/src/models/applicationstateschema.ts @@ -1,4 +1,4 @@ /** * Specifies maximums on the number of each type that may be stored. */ -export type ApplicationStateSchema = { "num-uint": number; "num-byte-slice": number }; +export type ApplicationStateSchema = { numUint: bigint; numByteSlice: bigint }; diff --git a/packages/typescript/algod_client/src/models/assetholding.ts b/packages/typescript/algod_client/src/models/assetholding.ts index 68dcecafc..710ebb107 100644 --- a/packages/typescript/algod_client/src/models/assetholding.ts +++ b/packages/typescript/algod_client/src/models/assetholding.ts @@ -4,4 +4,4 @@ * Definition: * data/basics/userBalance.go : AssetHolding */ -export type AssetHolding = { amount: bigint; "asset-id": bigint; "is-frozen": boolean }; +export type AssetHolding = { amount: bigint; assetId: bigint; isFrozen: boolean }; diff --git a/packages/typescript/algod_client/src/models/assetparams.ts b/packages/typescript/algod_client/src/models/assetparams.ts index 402449209..3ff1492fc 100644 --- a/packages/typescript/algod_client/src/models/assetparams.ts +++ b/packages/typescript/algod_client/src/models/assetparams.ts @@ -10,16 +10,16 @@ export type AssetParams = { clawback?: string; creator: string; decimals: bigint; - "default-frozen"?: boolean; + defaultFrozen?: boolean; freeze?: string; manager?: string; - "metadata-hash"?: string; + metadataHash?: string; name?: string; - "name-b64"?: string; + nameB64?: string; reserve?: string; total: bigint; - "unit-name"?: string; - "unit-name-b64"?: string; + unitName?: string; + unitNameB64?: string; url?: string; - "url-b64"?: string; + urlB64?: string; }; diff --git a/packages/typescript/algod_client/src/models/boxreference.ts b/packages/typescript/algod_client/src/models/boxreference.ts index 04885a4de..6a0a75026 100644 --- a/packages/typescript/algod_client/src/models/boxreference.ts +++ b/packages/typescript/algod_client/src/models/boxreference.ts @@ -1,4 +1,4 @@ /** * References a box of an application. */ -export type BoxReference = { app: number; name: string }; +export type BoxReference = { app: bigint; name: string }; diff --git a/packages/typescript/algod_client/src/models/buildversion.ts b/packages/typescript/algod_client/src/models/buildversion.ts index eacf5247b..33006a33f 100644 --- a/packages/typescript/algod_client/src/models/buildversion.ts +++ b/packages/typescript/algod_client/src/models/buildversion.ts @@ -1 +1 @@ -export type BuildVersion = { branch: string; build_number: number; channel: string; commit_hash: string; major: number; minor: number }; +export type BuildVersion = { branch: string; buildNumber: bigint; channel: string; commitHash: string; major: bigint; minor: bigint }; diff --git a/packages/typescript/algod_client/src/models/debugsettingsprof.ts b/packages/typescript/algod_client/src/models/debugsettingsprof.ts index 51e2cdad5..369d6d9a8 100644 --- a/packages/typescript/algod_client/src/models/debugsettingsprof.ts +++ b/packages/typescript/algod_client/src/models/debugsettingsprof.ts @@ -1,4 +1,4 @@ /** * algod mutex and blocking profiling state. */ -export type DebugSettingsProf = { "block-rate"?: bigint; "mutex-rate"?: bigint }; +export type DebugSettingsProf = { blockRate?: bigint; mutexRate?: bigint }; diff --git a/packages/typescript/algod_client/src/models/dryrunrequest.ts b/packages/typescript/algod_client/src/models/dryrunrequest.ts index f79a7135b..f59b78b07 100644 --- a/packages/typescript/algod_client/src/models/dryrunrequest.ts +++ b/packages/typescript/algod_client/src/models/dryrunrequest.ts @@ -7,8 +7,8 @@ export type DryrunRequest = { txns: string[]; accounts: Account[]; apps: Application[]; - "protocol-version": string; + protocolVersion: string; round: bigint; - "latest-timestamp": number; + latestTimestamp: bigint; sources: DryrunSource[]; }; diff --git a/packages/typescript/algod_client/src/models/dryrunsource.ts b/packages/typescript/algod_client/src/models/dryrunsource.ts index 11526e724..d5f4621ce 100644 --- a/packages/typescript/algod_client/src/models/dryrunsource.ts +++ b/packages/typescript/algod_client/src/models/dryrunsource.ts @@ -1,4 +1,4 @@ /** * DryrunSource is TEAL source text that gets uploaded, compiled, and inserted into transactions or application state. */ -export type DryrunSource = { "field-name": string; source: string; "txn-index": number; "app-index": bigint }; +export type DryrunSource = { fieldName: string; source: string; txnIndex: bigint; appIndex: bigint }; diff --git a/packages/typescript/algod_client/src/models/dryrunstate.ts b/packages/typescript/algod_client/src/models/dryrunstate.ts index 0ede2e1f5..ebeafd9d9 100644 --- a/packages/typescript/algod_client/src/models/dryrunstate.ts +++ b/packages/typescript/algod_client/src/models/dryrunstate.ts @@ -3,4 +3,4 @@ import type { TealValue } from "./index"; /** * Stores the TEAL eval step data */ -export type DryrunState = { line: number; pc: number; stack: TealValue[]; scratch?: TealValue[]; error?: string }; +export type DryrunState = { line: bigint; pc: bigint; stack: TealValue[]; scratch?: TealValue[]; error?: string }; diff --git a/packages/typescript/algod_client/src/models/dryruntxnresult.ts b/packages/typescript/algod_client/src/models/dryruntxnresult.ts index 2ce61e4cb..0a7e4adec 100644 --- a/packages/typescript/algod_client/src/models/dryruntxnresult.ts +++ b/packages/typescript/algod_client/src/models/dryruntxnresult.ts @@ -5,14 +5,14 @@ import type { AccountStateDelta, DryrunState, StateDelta } from "./index"; */ export type DryrunTxnResult = { disassembly: string[]; - "logic-sig-disassembly"?: string[]; - "logic-sig-trace"?: DryrunState[]; - "logic-sig-messages"?: string[]; - "app-call-trace"?: DryrunState[]; - "app-call-messages"?: string[]; - "global-delta"?: StateDelta; - "local-deltas"?: AccountStateDelta[]; + logicSigDisassembly?: string[]; + logicSigTrace?: DryrunState[]; + logicSigMessages?: string[]; + appCallTrace?: DryrunState[]; + appCallMessages?: string[]; + globalDelta?: StateDelta; + localDeltas?: AccountStateDelta[]; logs?: string[]; - "budget-added"?: number; - "budget-consumed"?: number; + budgetAdded?: bigint; + budgetConsumed?: bigint; }; diff --git a/packages/typescript/algod_client/src/models/evaldelta.ts b/packages/typescript/algod_client/src/models/evaldelta.ts index a45620482..2d9fe7313 100644 --- a/packages/typescript/algod_client/src/models/evaldelta.ts +++ b/packages/typescript/algod_client/src/models/evaldelta.ts @@ -1,4 +1,4 @@ /** * Represents a TEAL value delta. */ -export type EvalDelta = { action: number; bytes?: string; uint?: bigint }; +export type EvalDelta = { action: bigint; bytes?: string; uint?: bigint }; diff --git a/packages/typescript/algod_client/src/models/genesis.ts b/packages/typescript/algod_client/src/models/genesis.ts index b1244bda6..888421e64 100644 --- a/packages/typescript/algod_client/src/models/genesis.ts +++ b/packages/typescript/algod_client/src/models/genesis.ts @@ -9,5 +9,5 @@ export type Genesis = { network: string; proto: string; rwd: string; - timestamp: number; + timestamp: bigint; }; diff --git a/packages/typescript/algod_client/src/models/genesisallocation.ts b/packages/typescript/algod_client/src/models/genesisallocation.ts index 250d8a0b6..2548faf65 100644 --- a/packages/typescript/algod_client/src/models/genesisallocation.ts +++ b/packages/typescript/algod_client/src/models/genesisallocation.ts @@ -1,5 +1,5 @@ export type GenesisAllocation = { addr: string; comment: string; - state: { algo: bigint; onl: number; sel?: string; stprf?: string; vote?: string; voteKD?: bigint; voteFst?: bigint; voteLst?: bigint }; + state: { algo: bigint; onl: bigint; sel?: string; stprf?: string; vote?: string; voteKd?: bigint; voteFst?: bigint; voteLst?: bigint }; }; diff --git a/packages/typescript/algod_client/src/models/getpendingtransactions.ts b/packages/typescript/algod_client/src/models/getpendingtransactions.ts index 8d7955819..6d30718d0 100644 --- a/packages/typescript/algod_client/src/models/getpendingtransactions.ts +++ b/packages/typescript/algod_client/src/models/getpendingtransactions.ts @@ -1,4 +1,4 @@ /** * PendingTransactions is an array of signed transactions exactly as they were submitted. */ -export type GetPendingTransactions = { "top-transactions": {}[]; "total-transactions": number }; +export type GetPendingTransactions = { topTransactions: {}[]; totalTransactions: bigint }; diff --git a/packages/typescript/algod_client/src/models/getpendingtransactionsbyaddress.ts b/packages/typescript/algod_client/src/models/getpendingtransactionsbyaddress.ts index 63499994d..4a3897b17 100644 --- a/packages/typescript/algod_client/src/models/getpendingtransactionsbyaddress.ts +++ b/packages/typescript/algod_client/src/models/getpendingtransactionsbyaddress.ts @@ -1,4 +1,4 @@ /** * PendingTransactions is an array of signed transactions exactly as they were submitted. */ -export type GetPendingTransactionsByAddress = { "top-transactions": {}[]; "total-transactions": number }; +export type GetPendingTransactionsByAddress = { topTransactions: {}[]; totalTransactions: bigint }; diff --git a/packages/typescript/algod_client/src/models/getstatus.ts b/packages/typescript/algod_client/src/models/getstatus.ts index bcf8ffbef..996bbdcbd 100644 --- a/packages/typescript/algod_client/src/models/getstatus.ts +++ b/packages/typescript/algod_client/src/models/getstatus.ts @@ -2,30 +2,30 @@ * NodeStatus contains the information about a node status */ export type GetStatus = { - "catchup-time": bigint; - "last-round": bigint; - "last-version": string; - "next-version": string; - "next-version-round": number; - "next-version-supported": boolean; - "stopped-at-unsupported-round": boolean; - "time-since-last-round": bigint; - "last-catchpoint"?: string; + catchupTime: bigint; + lastRound: bigint; + lastVersion: string; + nextVersion: string; + nextVersionRound: bigint; + nextVersionSupported: boolean; + stoppedAtUnsupportedRound: boolean; + timeSinceLastRound: bigint; + lastCatchpoint?: string; catchpoint?: string; - "catchpoint-total-accounts"?: bigint; - "catchpoint-processed-accounts"?: bigint; - "catchpoint-verified-accounts"?: bigint; - "catchpoint-total-kvs"?: bigint; - "catchpoint-processed-kvs"?: bigint; - "catchpoint-verified-kvs"?: bigint; - "catchpoint-total-blocks"?: bigint; - "catchpoint-acquired-blocks"?: bigint; - "upgrade-delay"?: number; - "upgrade-node-vote"?: boolean; - "upgrade-votes-required"?: number; - "upgrade-votes"?: number; - "upgrade-yes-votes"?: number; - "upgrade-no-votes"?: number; - "upgrade-next-protocol-vote-before"?: number; - "upgrade-vote-rounds"?: number; + catchpointTotalAccounts?: bigint; + catchpointProcessedAccounts?: bigint; + catchpointVerifiedAccounts?: bigint; + catchpointTotalKvs?: bigint; + catchpointProcessedKvs?: bigint; + catchpointVerifiedKvs?: bigint; + catchpointTotalBlocks?: bigint; + catchpointAcquiredBlocks?: bigint; + upgradeDelay?: bigint; + upgradeNodeVote?: boolean; + upgradeVotesRequired?: bigint; + upgradeVotes?: bigint; + upgradeYesVotes?: bigint; + upgradeNoVotes?: bigint; + upgradeNextProtocolVoteBefore?: bigint; + upgradeVoteRounds?: bigint; }; diff --git a/packages/typescript/algod_client/src/models/getsupply.ts b/packages/typescript/algod_client/src/models/getsupply.ts index fe4daa917..81160e60a 100644 --- a/packages/typescript/algod_client/src/models/getsupply.ts +++ b/packages/typescript/algod_client/src/models/getsupply.ts @@ -1,4 +1,4 @@ /** * Supply represents the current supply of MicroAlgos in the system */ -export type GetSupply = { current_round: bigint; "online-money": bigint; "total-money": bigint }; +export type GetSupply = { currentRound: bigint; onlineMoney: bigint; totalMoney: bigint }; diff --git a/packages/typescript/algod_client/src/models/gettransactiongroupledgerstatedeltasforround.ts b/packages/typescript/algod_client/src/models/gettransactiongroupledgerstatedeltasforround.ts index 6fcdcc9d9..6b47af74e 100644 --- a/packages/typescript/algod_client/src/models/gettransactiongroupledgerstatedeltasforround.ts +++ b/packages/typescript/algod_client/src/models/gettransactiongroupledgerstatedeltasforround.ts @@ -3,4 +3,4 @@ import type { LedgerStateDeltaForTransactionGroup } from "./index"; /** * Response containing all ledger state deltas for transaction groups, with their associated Ids, in a single round. */ -export type GetTransactionGroupLedgerStateDeltasForRound = { Deltas: LedgerStateDeltaForTransactionGroup[] }; +export type GetTransactionGroupLedgerStateDeltasForRound = { deltas: LedgerStateDeltaForTransactionGroup[] }; diff --git a/packages/typescript/algod_client/src/models/ledgerstatedeltafortransactiongroup.ts b/packages/typescript/algod_client/src/models/ledgerstatedeltafortransactiongroup.ts index 90f19995d..db48e7d25 100644 --- a/packages/typescript/algod_client/src/models/ledgerstatedeltafortransactiongroup.ts +++ b/packages/typescript/algod_client/src/models/ledgerstatedeltafortransactiongroup.ts @@ -3,4 +3,4 @@ import type { LedgerStateDelta } from "./index"; /** * Contains a ledger delta for a single transaction group */ -export type LedgerStateDeltaForTransactionGroup = { Delta: LedgerStateDelta; Ids: string[] }; +export type LedgerStateDeltaForTransactionGroup = { delta: LedgerStateDelta; ids: string[] }; diff --git a/packages/typescript/algod_client/src/models/lightblockheaderproof.ts b/packages/typescript/algod_client/src/models/lightblockheaderproof.ts index 2ca00a3c7..485a8ba75 100644 --- a/packages/typescript/algod_client/src/models/lightblockheaderproof.ts +++ b/packages/typescript/algod_client/src/models/lightblockheaderproof.ts @@ -1,4 +1,4 @@ /** * Proof of membership and position of a light block header. */ -export type LightBlockHeaderProof = { index: bigint; treedepth: number; proof: string }; +export type LightBlockHeaderProof = { index: bigint; treedepth: bigint; proof: string }; diff --git a/packages/typescript/algod_client/src/models/participationkey.ts b/packages/typescript/algod_client/src/models/participationkey.ts index 68e902ddb..a4cdfbd5a 100644 --- a/packages/typescript/algod_client/src/models/participationkey.ts +++ b/packages/typescript/algod_client/src/models/participationkey.ts @@ -6,10 +6,10 @@ import type { AccountParticipation } from "./index"; export type ParticipationKey = { id: string; address: string; - "effective-first-valid"?: bigint; - "effective-last-valid"?: bigint; - "last-vote"?: number; - "last-block-proposal"?: number; - "last-state-proof"?: number; + effectiveFirstValid?: bigint; + effectiveLastValid?: bigint; + lastVote?: bigint; + lastBlockProposal?: bigint; + lastStateProof?: bigint; key: AccountParticipation; }; diff --git a/packages/typescript/algod_client/src/models/pendingtransactionresponse.ts b/packages/typescript/algod_client/src/models/pendingtransactionresponse.ts index 36a1aaefc..f5413314d 100644 --- a/packages/typescript/algod_client/src/models/pendingtransactionresponse.ts +++ b/packages/typescript/algod_client/src/models/pendingtransactionresponse.ts @@ -4,18 +4,18 @@ import type { AccountStateDelta, StateDelta } from "./index"; * Details about a pending transaction. If the transaction was recently confirmed, includes confirmation details like the round and reward details. */ export type PendingTransactionResponse = { - "asset-index"?: bigint; - "application-index"?: bigint; - "close-rewards"?: number; - "closing-amount"?: bigint; - "asset-closing-amount"?: bigint; - "confirmed-round"?: bigint; - "pool-error": string; - "receiver-rewards"?: bigint; - "sender-rewards"?: bigint; - "local-state-delta"?: AccountStateDelta[]; - "global-state-delta"?: StateDelta; + assetIndex?: bigint; + applicationIndex?: bigint; + closeRewards?: bigint; + closingAmount?: bigint; + assetClosingAmount?: bigint; + confirmedRound?: bigint; + poolError: string; + receiverRewards?: bigint; + senderRewards?: bigint; + localStateDelta?: AccountStateDelta[]; + globalStateDelta?: StateDelta; logs?: string[]; - "inner-txns"?: PendingTransactionResponse[]; + innerTxns?: PendingTransactionResponse[]; txn: {}; }; diff --git a/packages/typescript/algod_client/src/models/scratchchange.ts b/packages/typescript/algod_client/src/models/scratchchange.ts index a33c54599..9764d99f9 100644 --- a/packages/typescript/algod_client/src/models/scratchchange.ts +++ b/packages/typescript/algod_client/src/models/scratchchange.ts @@ -3,4 +3,4 @@ import type { AvmValue } from "./index"; /** * A write operation into a scratch slot. */ -export type ScratchChange = { slot: number; "new-value": AvmValue }; +export type ScratchChange = { slot: bigint; newValue: AvmValue }; diff --git a/packages/typescript/algod_client/src/models/simulateinitialstates.ts b/packages/typescript/algod_client/src/models/simulateinitialstates.ts index e00a0f185..b3d2b5890 100644 --- a/packages/typescript/algod_client/src/models/simulateinitialstates.ts +++ b/packages/typescript/algod_client/src/models/simulateinitialstates.ts @@ -3,4 +3,4 @@ import type { ApplicationInitialStates } from "./index"; /** * Initial states of resources that were accessed during simulation. */ -export type SimulateInitialStates = { "app-initial-states"?: ApplicationInitialStates[] }; +export type SimulateInitialStates = { appInitialStates?: ApplicationInitialStates[] }; diff --git a/packages/typescript/algod_client/src/models/simulaterequest.ts b/packages/typescript/algod_client/src/models/simulaterequest.ts index 5d2271d4a..d84776a7c 100644 --- a/packages/typescript/algod_client/src/models/simulaterequest.ts +++ b/packages/typescript/algod_client/src/models/simulaterequest.ts @@ -4,12 +4,12 @@ import type { SimulateRequestTransactionGroup, SimulateTraceConfig } from "./ind * Request type for simulation endpoint. */ export type SimulateRequest = { - "txn-groups": SimulateRequestTransactionGroup[]; + txnGroups: SimulateRequestTransactionGroup[]; round?: bigint; - "allow-empty-signatures"?: boolean; - "allow-more-logging"?: boolean; - "allow-unnamed-resources"?: boolean; - "extra-opcode-budget"?: number; - "exec-trace-config"?: SimulateTraceConfig; - "fix-signers"?: boolean; + allowEmptySignatures?: boolean; + allowMoreLogging?: boolean; + allowUnnamedResources?: boolean; + extraOpcodeBudget?: bigint; + execTraceConfig?: SimulateTraceConfig; + fixSigners?: boolean; }; diff --git a/packages/typescript/algod_client/src/models/simulatetraceconfig.ts b/packages/typescript/algod_client/src/models/simulatetraceconfig.ts index 1ab5559d4..d1aafec43 100644 --- a/packages/typescript/algod_client/src/models/simulatetraceconfig.ts +++ b/packages/typescript/algod_client/src/models/simulatetraceconfig.ts @@ -1,4 +1,4 @@ /** * An object that configures simulation execution trace. */ -export type SimulateTraceConfig = { enable?: boolean; "stack-change"?: boolean; "scratch-change"?: boolean; "state-change"?: boolean }; +export type SimulateTraceConfig = { enable?: boolean; stackChange?: boolean; scratchChange?: boolean; stateChange?: boolean }; diff --git a/packages/typescript/algod_client/src/models/simulatetransaction.ts b/packages/typescript/algod_client/src/models/simulatetransaction.ts index 6bcef49a8..7377acab7 100644 --- a/packages/typescript/algod_client/src/models/simulatetransaction.ts +++ b/packages/typescript/algod_client/src/models/simulatetransaction.ts @@ -5,9 +5,9 @@ import type { SimulateInitialStates, SimulateTraceConfig, SimulateTransactionGro */ export type SimulateTransaction = { version: bigint; - "last-round": bigint; - "txn-groups": SimulateTransactionGroupResult[]; - "eval-overrides"?: SimulationEvalOverrides; - "exec-trace-config"?: SimulateTraceConfig; - "initial-states"?: SimulateInitialStates; + lastRound: bigint; + txnGroups: SimulateTransactionGroupResult[]; + evalOverrides?: SimulationEvalOverrides; + execTraceConfig?: SimulateTraceConfig; + initialStates?: SimulateInitialStates; }; diff --git a/packages/typescript/algod_client/src/models/simulatetransactiongroupresult.ts b/packages/typescript/algod_client/src/models/simulatetransactiongroupresult.ts index d11087154..f6efbf98b 100644 --- a/packages/typescript/algod_client/src/models/simulatetransactiongroupresult.ts +++ b/packages/typescript/algod_client/src/models/simulatetransactiongroupresult.ts @@ -4,10 +4,10 @@ import type { SimulateTransactionResult, SimulateUnnamedResourcesAccessed } from * Simulation result for an atomic transaction group */ export type SimulateTransactionGroupResult = { - "txn-results": SimulateTransactionResult[]; - "failure-message"?: string; - "failed-at"?: number[]; - "app-budget-added"?: number; - "app-budget-consumed"?: number; - "unnamed-resources-accessed"?: SimulateUnnamedResourcesAccessed; + txnResults: SimulateTransactionResult[]; + failureMessage?: string; + failedAt?: bigint[]; + appBudgetAdded?: bigint; + appBudgetConsumed?: bigint; + unnamedResourcesAccessed?: SimulateUnnamedResourcesAccessed; }; diff --git a/packages/typescript/algod_client/src/models/simulatetransactionresult.ts b/packages/typescript/algod_client/src/models/simulatetransactionresult.ts index dace14b62..a75a1dc8e 100644 --- a/packages/typescript/algod_client/src/models/simulatetransactionresult.ts +++ b/packages/typescript/algod_client/src/models/simulatetransactionresult.ts @@ -4,10 +4,10 @@ import type { PendingTransactionResponse, SimulateUnnamedResourcesAccessed, Simu * Simulation result for an individual transaction */ export type SimulateTransactionResult = { - "txn-result": PendingTransactionResponse; - "app-budget-consumed"?: number; - "logic-sig-budget-consumed"?: number; - "exec-trace"?: SimulationTransactionExecTrace; - "unnamed-resources-accessed"?: SimulateUnnamedResourcesAccessed; - "fixed-signer"?: string; + txnResult: PendingTransactionResponse; + appBudgetConsumed?: bigint; + logicSigBudgetConsumed?: bigint; + execTrace?: SimulationTransactionExecTrace; + unnamedResourcesAccessed?: SimulateUnnamedResourcesAccessed; + fixedSigner?: string; }; diff --git a/packages/typescript/algod_client/src/models/simulateunnamedresourcesaccessed.ts b/packages/typescript/algod_client/src/models/simulateunnamedresourcesaccessed.ts index af1aaa3b6..8b2872702 100644 --- a/packages/typescript/algod_client/src/models/simulateunnamedresourcesaccessed.ts +++ b/packages/typescript/algod_client/src/models/simulateunnamedresourcesaccessed.ts @@ -8,7 +8,7 @@ export type SimulateUnnamedResourcesAccessed = { assets?: bigint[]; apps?: bigint[]; boxes?: BoxReference[]; - "extra-box-refs"?: number; - "asset-holdings"?: AssetHoldingReference[]; - "app-locals"?: ApplicationLocalReference[]; + extraBoxRefs?: bigint; + assetHoldings?: AssetHoldingReference[]; + appLocals?: ApplicationLocalReference[]; }; diff --git a/packages/typescript/algod_client/src/models/simulationevaloverrides.ts b/packages/typescript/algod_client/src/models/simulationevaloverrides.ts index 176e80311..1bcd0a8a9 100644 --- a/packages/typescript/algod_client/src/models/simulationevaloverrides.ts +++ b/packages/typescript/algod_client/src/models/simulationevaloverrides.ts @@ -2,10 +2,10 @@ * 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. */ export type SimulationEvalOverrides = { - "allow-empty-signatures"?: boolean; - "allow-unnamed-resources"?: boolean; - "max-log-calls"?: number; - "max-log-size"?: number; - "extra-opcode-budget"?: number; - "fix-signers"?: boolean; + allowEmptySignatures?: boolean; + allowUnnamedResources?: boolean; + maxLogCalls?: bigint; + maxLogSize?: bigint; + extraOpcodeBudget?: bigint; + fixSigners?: boolean; }; diff --git a/packages/typescript/algod_client/src/models/simulationopcodetraceunit.ts b/packages/typescript/algod_client/src/models/simulationopcodetraceunit.ts index 13ca37112..25f9507fd 100644 --- a/packages/typescript/algod_client/src/models/simulationopcodetraceunit.ts +++ b/packages/typescript/algod_client/src/models/simulationopcodetraceunit.ts @@ -4,10 +4,10 @@ import type { ApplicationStateOperation, AvmValue, ScratchChange } from "./index * The set of trace information and effect from evaluating a single opcode. */ export type SimulationOpcodeTraceUnit = { - pc: number; - "scratch-changes"?: ScratchChange[]; - "state-changes"?: ApplicationStateOperation[]; - "spawned-inners"?: number[]; - "stack-pop-count"?: number; - "stack-additions"?: AvmValue[]; + pc: bigint; + scratchChanges?: ScratchChange[]; + stateChanges?: ApplicationStateOperation[]; + spawnedInners?: bigint[]; + stackPopCount?: bigint; + stackAdditions?: AvmValue[]; }; diff --git a/packages/typescript/algod_client/src/models/simulationtransactionexectrace.ts b/packages/typescript/algod_client/src/models/simulationtransactionexectrace.ts index 220050550..f5b5f7c73 100644 --- a/packages/typescript/algod_client/src/models/simulationtransactionexectrace.ts +++ b/packages/typescript/algod_client/src/models/simulationtransactionexectrace.ts @@ -4,13 +4,13 @@ import type { SimulationOpcodeTraceUnit } from "./index"; * The execution trace of calling an app or a logic sig, containing the inner app call trace in a recursive way. */ export type SimulationTransactionExecTrace = { - "approval-program-trace"?: SimulationOpcodeTraceUnit[]; - "approval-program-hash"?: string; - "clear-state-program-trace"?: SimulationOpcodeTraceUnit[]; - "clear-state-program-hash"?: string; - "clear-state-rollback"?: boolean; - "clear-state-rollback-error"?: string; - "logic-sig-trace"?: SimulationOpcodeTraceUnit[]; - "logic-sig-hash"?: string; - "inner-trace"?: SimulationTransactionExecTrace[]; + approvalProgramTrace?: SimulationOpcodeTraceUnit[]; + approvalProgramHash?: string; + clearStateProgramTrace?: SimulationOpcodeTraceUnit[]; + clearStateProgramHash?: string; + clearStateRollback?: boolean; + clearStateRollbackError?: string; + logicSigTrace?: SimulationOpcodeTraceUnit[]; + logicSigHash?: string; + innerTrace?: SimulationTransactionExecTrace[]; }; diff --git a/packages/typescript/algod_client/src/models/startcatchup.ts b/packages/typescript/algod_client/src/models/startcatchup.ts index 5ab7452e5..2f7bfa331 100644 --- a/packages/typescript/algod_client/src/models/startcatchup.ts +++ b/packages/typescript/algod_client/src/models/startcatchup.ts @@ -1,4 +1,4 @@ /** * An catchpoint start response. */ -export type StartCatchup = { "catchup-message": string }; +export type StartCatchup = { catchupMessage: string }; diff --git a/packages/typescript/algod_client/src/models/stateproof.ts b/packages/typescript/algod_client/src/models/stateproof.ts index 446be6298..4a84b36c6 100644 --- a/packages/typescript/algod_client/src/models/stateproof.ts +++ b/packages/typescript/algod_client/src/models/stateproof.ts @@ -3,4 +3,4 @@ import type { StateProofMessage } from "./index"; /** * Represents a state proof and its corresponding message */ -export type StateProof = { Message: StateProofMessage; StateProof: string }; +export type StateProof = { message: StateProofMessage; stateProof: string }; diff --git a/packages/typescript/algod_client/src/models/stateproofmessage.ts b/packages/typescript/algod_client/src/models/stateproofmessage.ts index b0db2fed3..655081702 100644 --- a/packages/typescript/algod_client/src/models/stateproofmessage.ts +++ b/packages/typescript/algod_client/src/models/stateproofmessage.ts @@ -2,9 +2,9 @@ * Represents the message that the state proofs are attesting to. */ export type StateProofMessage = { - BlockHeadersCommitment: string; - VotersCommitment: string; - LnProvenWeight: bigint; - FirstAttestedRound: bigint; - LastAttestedRound: bigint; + blockHeadersCommitment: string; + votersCommitment: string; + lnProvenWeight: bigint; + firstAttestedRound: bigint; + lastAttestedRound: bigint; }; diff --git a/packages/typescript/algod_client/src/models/tealdryrun.ts b/packages/typescript/algod_client/src/models/tealdryrun.ts index eb289e136..329a98664 100644 --- a/packages/typescript/algod_client/src/models/tealdryrun.ts +++ b/packages/typescript/algod_client/src/models/tealdryrun.ts @@ -3,4 +3,4 @@ import type { DryrunTxnResult } from "./index"; /** * DryrunResponse contains per-txn debug information from a dryrun. */ -export type TealDryrun = { txns: DryrunTxnResult[]; error: string; "protocol-version": string }; +export type TealDryrun = { txns: DryrunTxnResult[]; error: string; protocolVersion: string }; diff --git a/packages/typescript/algod_client/src/models/transactionparams.ts b/packages/typescript/algod_client/src/models/transactionparams.ts index c26f1c965..e19dbd33b 100644 --- a/packages/typescript/algod_client/src/models/transactionparams.ts +++ b/packages/typescript/algod_client/src/models/transactionparams.ts @@ -3,10 +3,10 @@ * a new transaction. */ export type TransactionParams = { - "consensus-version": string; + consensusVersion: string; fee: bigint; - "genesis-hash": string; - "genesis-id": string; - "last-round": bigint; - "min-fee": bigint; + genesisHash: string; + genesisId: string; + lastRound: bigint; + minFee: bigint; }; diff --git a/packages/typescript/algod_client/src/models/version.ts b/packages/typescript/algod_client/src/models/version.ts index 5bd5e15b3..060cea5a6 100644 --- a/packages/typescript/algod_client/src/models/version.ts +++ b/packages/typescript/algod_client/src/models/version.ts @@ -3,4 +3,4 @@ import type { BuildVersion } from "./index"; /** * algod version information. */ -export type Version = { build: BuildVersion; genesis_hash_b64: string; genesis_id: string; versions: string[] }; +export type Version = { build: BuildVersion; genesisHashB64: string; genesisId: string; versions: string[] }; diff --git a/packages/typescript/algod_client/src/models/waitforblock.ts b/packages/typescript/algod_client/src/models/waitforblock.ts index 64212ae59..3c8378223 100644 --- a/packages/typescript/algod_client/src/models/waitforblock.ts +++ b/packages/typescript/algod_client/src/models/waitforblock.ts @@ -2,30 +2,30 @@ * NodeStatus contains the information about a node status */ export type WaitForBlock = { - "catchup-time": bigint; - "last-round": bigint; - "last-version": string; - "next-version": string; - "next-version-round": number; - "next-version-supported": boolean; - "stopped-at-unsupported-round": boolean; - "time-since-last-round": bigint; - "last-catchpoint"?: string; + catchupTime: bigint; + lastRound: bigint; + lastVersion: string; + nextVersion: string; + nextVersionRound: bigint; + nextVersionSupported: boolean; + stoppedAtUnsupportedRound: boolean; + timeSinceLastRound: bigint; + lastCatchpoint?: string; catchpoint?: string; - "catchpoint-total-accounts"?: bigint; - "catchpoint-processed-accounts"?: bigint; - "catchpoint-verified-accounts"?: bigint; - "catchpoint-total-kvs"?: bigint; - "catchpoint-processed-kvs"?: bigint; - "catchpoint-verified-kvs"?: bigint; - "catchpoint-total-blocks"?: bigint; - "catchpoint-acquired-blocks"?: bigint; - "upgrade-delay"?: number; - "upgrade-node-vote"?: boolean; - "upgrade-votes-required"?: number; - "upgrade-votes"?: number; - "upgrade-yes-votes"?: number; - "upgrade-no-votes"?: number; - "upgrade-next-protocol-vote-before"?: number; - "upgrade-vote-rounds"?: number; + catchpointTotalAccounts?: bigint; + catchpointProcessedAccounts?: bigint; + catchpointVerifiedAccounts?: bigint; + catchpointTotalKvs?: bigint; + catchpointProcessedKvs?: bigint; + catchpointVerifiedKvs?: bigint; + catchpointTotalBlocks?: bigint; + catchpointAcquiredBlocks?: bigint; + upgradeDelay?: bigint; + upgradeNodeVote?: boolean; + upgradeVotesRequired?: bigint; + upgradeVotes?: bigint; + upgradeYesVotes?: bigint; + upgradeNoVotes?: bigint; + upgradeNextProtocolVoteBefore?: bigint; + upgradeVoteRounds?: bigint; }; diff --git a/packages/typescript/algod_client/tests/helpers/env.ts b/packages/typescript/algod_client/tests/config.ts similarity index 89% rename from packages/typescript/algod_client/tests/helpers/env.ts rename to packages/typescript/algod_client/tests/config.ts index 3fcf7260f..44624cb7c 100644 --- a/packages/typescript/algod_client/tests/helpers/env.ts +++ b/packages/typescript/algod_client/tests/config.ts @@ -1,13 +1,13 @@ -import { describe } from "vitest"; +import { describe } from "bun:test"; import algosdk from "algosdk"; -export interface AlgodEnvConfig { +export interface AlgodTestConfig { algodBaseUrl: string; algodApiToken?: string; senderMnemonic?: string; } -export function getAlgodEnv(): AlgodEnvConfig { +export function getAlgodEnv(): AlgodTestConfig { return { algodBaseUrl: process.env.ALGOD_BASE_URL ?? "http://localhost:4001", // Default token for localnet (Algorand sandbox / Algokit LocalNet) @@ -44,6 +44,6 @@ export async function getSenderMnemonic(): Promise { } } -export function maybeDescribe(name: string, fn: (env: AlgodEnvConfig) => void) { +export function maybeDescribe(name: string, fn: (env: AlgodTestConfig) => void) { describe(name, () => fn(getAlgodEnv())); } diff --git a/packages/typescript/algod_client/tests/generated/smoke.generated.spec.ts b/packages/typescript/algod_client/tests/generated/smoke.generated.spec.ts deleted file mode 100644 index d2a0f9e98..000000000 --- a/packages/typescript/algod_client/tests/generated/smoke.generated.spec.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* AUTO-GENERATED FILE - DO NOT EDIT DIRECTLY. - * This smoke test is generated by ts_oas_generator. - * Location: tests/generated/smoke.generated.spec.ts - */ -import { describe, expect, it } from "vitest"; -import { Client } from "../src/client"; - -const BASE = "http://localhost/"; - -declare global { - // eslint-disable-next-line no-var, vars-on-top - var fetch: any; -} - -describe("JSON BigInt parsing", () => { - it("parses bigint values using json-bigint", async () => { - const big = "18446744073709551615"; // > Number.MAX_SAFE_INTEGER - global.fetch = async () => ({ - ok: true, - headers: new Map([["content-type", "application/json"]]), - text: async () => JSON.stringify({ value: big }), - arrayBuffer: async () => new ArrayBuffer(0), - }); - - const client = new Client({ BASE }); - // Directly use request core to keep template-agnostic - const res = await client.request.request<{ value: bigint }>({ method: "GET", url: "/foo" }); - expect(typeof res.value).toBe("bigint"); - }); -}); - -describe("Msgpack binary response", () => { - it("decodes msgpack into structured data", async () => { - // eslint-disable-next-line @typescript-eslint/no-var-requires - const { encode } = require("algo-msgpack-with-bigint"); - const msg = { ok: 1n, small: 2 }; - const bytes: Uint8Array = encode(msg); - global.fetch = async () => ({ - ok: true, - headers: new Map([["content-type", "application/msgpack"]]), - text: async () => "", - arrayBuffer: async () => bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength), - }); - - const client = new Client({ BASE }); - const res = await client.request.request<{ ok: bigint | number; small: number }>({ method: "GET", url: "/foo", expectBinary: true }); - expect(res).toHaveProperty("ok"); - }); -}); diff --git a/packages/typescript/algod_client/tests/helpers/wait.ts b/packages/typescript/algod_client/tests/helpers/wait.ts deleted file mode 100644 index 2939c9659..000000000 --- a/packages/typescript/algod_client/tests/helpers/wait.ts +++ /dev/null @@ -1,16 +0,0 @@ -export async function waitFor( - fn: () => Promise, - predicate: (v: T) => boolean, - opts?: { timeoutMs?: number; intervalMs?: number }, -): Promise { - const timeoutMs = opts?.timeoutMs ?? 30_000; - const intervalMs = opts?.intervalMs ?? 1_000; - const start = Date.now(); - // eslint-disable-next-line no-constant-condition - while (true) { - const v = await fn(); - if (predicate(v)) return v; - if (Date.now() - start > timeoutMs) throw new Error("waitFor: timeout"); - await new Promise((r) => setTimeout(r, intervalMs)); - } -} diff --git a/packages/typescript/algod_client/tests/pendingTransaction.spec.ts b/packages/typescript/algod_client/tests/pendingTransaction.spec.ts index 357642ace..5e1114c9f 100644 --- a/packages/typescript/algod_client/tests/pendingTransaction.spec.ts +++ b/packages/typescript/algod_client/tests/pendingTransaction.spec.ts @@ -1,13 +1,14 @@ -import { expect, it } from "vitest"; +import { expect, it } from "bun:test"; import algosdk from "algosdk"; -import { Client } from "../src/client"; -import { getSenderMnemonic, maybeDescribe } from "./helpers/env"; -import { waitFor } from "./helpers/wait"; +import { AlgodClient } from "../src/client"; +import { getSenderMnemonic, maybeDescribe } from "./config"; +import { PendingTransactionResponse } from "../src/models"; maybeDescribe("Algod pendingTransaction", (env) => { it("submits a payment tx and queries pending info", async () => { - const client = new Client({ + const client = new AlgodClient({ BASE: env.algodBaseUrl, + INT_DECODING: "bigint", HEADERS: env.algodApiToken ? { "X-Algo-API-Token": env.algodApiToken } : undefined, }); @@ -17,16 +18,17 @@ maybeDescribe("Algod pendingTransaction", (env) => { // Build simple self-payment of 0 microalgos (allowed) as a noop const txn = algosdk.makePaymentTxnWithSuggestedParamsFromObject({ - from: acct.addr, - to: acct.addr, + sender: acct.addr, + receiver: acct.addr, amount: 0, suggestedParams: { - fee: Number(sp["min-fee"]), - firstRound: Number(sp["last-round"]), + minFee: Number(sp["minFee"]), + fee: Number(sp["minFee"]), + firstValid: Number(sp["lastRound"]), flatFee: true, - lastRound: Number(sp["last-round"]) + 1000, - genesisHash: sp["genesis-hash"] as string, - genesisID: sp["genesis-id"] as string, + lastValid: Number(sp["lastRound"]) + 1000, + genesisHash: algosdk.base64ToBytes(sp["genesisHash"]), + genesisID: sp["genesisId"] as string, }, }); @@ -34,11 +36,18 @@ maybeDescribe("Algod pendingTransaction", (env) => { const sendResult = await client.api.rawTransaction({ body: signed }); const txId = sendResult.txId as string; - const pending = await waitFor( - async () => client.api.pendingTransactionInformation(txId, { format: "json" }), - (r) => !!(r as any)["confirmed-round"] || !!(r as any)["pool-error"], - { timeoutMs: 45_000, intervalMs: 1_000 }, - ); + let pending: PendingTransactionResponse | undefined; + const maxAttempts = 10; + for (let i = 0; i < maxAttempts; i++) { + pending = await client.api.pendingTransactionInformation(txId, { format: "msgpack" }); + if (pending?.confirmedRound || pending?.poolError) { + break; + } + await new Promise((resolve) => setTimeout(resolve, 1000)); + } + if (!pending) { + throw new Error("Transaction confirmation timeout"); + } // Some nodes may omit 'txid' in pending response; require txn presence expect(pending).toHaveProperty("txn"); diff --git a/packages/typescript/algod_client/tests/smoke.spec.ts b/packages/typescript/algod_client/tests/smoke.spec.ts deleted file mode 100644 index c19a27e89..000000000 --- a/packages/typescript/algod_client/tests/smoke.spec.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { describe, expect, it } from "vitest"; -import { Client } from "../src/client"; - -const BASE = "http://localhost/"; - -declare global { - // eslint-disable-next-line no-var, vars-on-top - var fetch: any; -} - -describe("JSON BigInt parsing", () => { - it("parses bigint values using json-bigint", async () => { - const big = "18446744073709551615"; // > Number.MAX_SAFE_INTEGER - global.fetch = async () => ({ - ok: true, - headers: new Map([["content-type", "application/json"]]), - text: async () => JSON.stringify({ value: big }), - arrayBuffer: async () => new ArrayBuffer(0), - }); - - const client = new Client({ BASE, INT_DECODING: "bigint" }); - // Directly use request core to keep template-agnostic - const res = await client.request.request<{ value: bigint }>({ method: "GET", url: "/foo" }); - expect(typeof res.value).toBe("bigint"); - }); -}); - -describe("Msgpack binary response", () => { - it("decodes msgpack into structured data", async () => { - // eslint-disable-next-line @typescript-eslint/no-var-requires - const { encode } = require("algo-msgpack-with-bigint"); - const payload = { ok: 1n, text: "hi" }; - const bytes: Uint8Array = encode(payload); - global.fetch = async () => ({ - ok: true, - headers: new Map([["content-type", "application/msgpack"]]), - text: async () => "", - arrayBuffer: async () => bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength), - }); - - const client = new Client({ BASE }); - const res = await client.request.request<{ ok: bigint | number; text: string }>({ method: "GET", url: "/foo", expectBinary: true }); - expect(res).toHaveProperty("ok"); - expect(res).toHaveProperty("text", "hi"); - }); -}); diff --git a/packages/typescript/algod_client/tests/src/client.ts b/packages/typescript/algod_client/tests/src/client.ts deleted file mode 100644 index 7c7bd3cdc..000000000 --- a/packages/typescript/algod_client/tests/src/client.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { OpenAPIConfig } from "../../src/core/OpenAPI"; -import { Client as BaseClient } from "../../src/client"; - -// Re-export everything first -export * from "../../src/client"; - -// Override Client to default INT_DECODING to 'bigint' for generated smoke tests -export class Client extends BaseClient { - constructor(config: OpenAPIConfig) { - super({ INT_DECODING: config.INT_DECODING ?? "bigint", ...config }); - } -} diff --git a/packages/typescript/algod_client/tests/transactionParams.spec.ts b/packages/typescript/algod_client/tests/transactionParams.spec.ts index c31770c39..22b0f1ad6 100644 --- a/packages/typescript/algod_client/tests/transactionParams.spec.ts +++ b/packages/typescript/algod_client/tests/transactionParams.spec.ts @@ -1,18 +1,17 @@ -import { expect, it, describe } from "vitest"; -import { Client } from "../src/client"; -import { maybeDescribe } from "./helpers/env"; +import { expect, it } from "bun:test"; +import { AlgodClient } from "../src/client"; +import { maybeDescribe } from "./config"; maybeDescribe("Algod transactionParams", (env) => { it("fetches suggested params", async () => { - const client = new Client({ + const client = new AlgodClient({ BASE: env.algodBaseUrl, INT_DECODING: "bigint", HEADERS: env.algodApiToken ? { "X-Algo-API-Token": env.algodApiToken } : undefined, }); const params = await client.api.transactionParams(); - // Basic shape checks - expect(params).toHaveProperty("genesis-id"); - expect(typeof params["last-round"]).toBe("bigint"); - expect(typeof params["min-fee"]).toBe("bigint"); + expect(params).toHaveProperty("genesisId"); + expect(typeof params["lastRound"]).toBe("bigint"); + expect(typeof params["minFee"]).toBe("bigint"); }); }); diff --git a/packages/typescript/indexer_client/README.md b/packages/typescript/indexer_client/README.md index 73c6d70c5..b37a9aed2 100644 --- a/packages/typescript/indexer_client/README.md +++ b/packages/typescript/indexer_client/README.md @@ -9,16 +9,17 @@ Install dependencies and build: - bun install (or pnpm/yarn) - bun run build -### Configure base URL and issue requests +### Configure base URL and create a client ```ts -import { OpenAPI, FetchHttpRequest } from "./dist/index.js"; +import { FetchHttpRequest, type ClientConfig, IndexerClient, IndexerApi } from "./dist/index.js"; -OpenAPI.BASE = "http://localhost:4001"; +const client = new AlgodClient({ + BASE: env.algodBaseUrl, + HEADERS: env.algodApiToken ? { "X-Algo-API-Token": env.algodApiToken } : undefined, +}); -const client = new FetchHttpRequest(OpenAPI); -// Example call once APIs are available in Phase 2: -// await client.request({ method: 'GET', url: '/health' }); +// client is now ready to use ``` -To inject a custom client, implement your own HttpRequest class extending `BaseHttpRequest` and use it where needed. +To inject a custom HTTP implementation, implement your own request class extending `BaseHttpRequest` and pass it into your own wrapper if needed. diff --git a/packages/typescript/indexer_client/bun.lock b/packages/typescript/indexer_client/bun.lock new file mode 100644 index 000000000..84f470649 --- /dev/null +++ b/packages/typescript/indexer_client/bun.lock @@ -0,0 +1,222 @@ +{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "indexer_client", + "dependencies": { + "@msgpack/msgpack": "^3.1.2", + "json-bigint": "^1.0.0", + }, + "devDependencies": { + "@types/json-bigint": "^1.0.0", + "@types/node": "^20.0.0", + "algosdk": "^3.0.0", + "typescript": "^5.5.0", + "vitest": "^2.0.0", + }, + }, + }, + "packages": { + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="], + + "@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os": "android", "cpu": "arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="], + + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.21.5", "", { "os": "android", "cpu": "arm64" }, "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A=="], + + "@esbuild/android-x64": ["@esbuild/android-x64@0.21.5", "", { "os": "android", "cpu": "x64" }, "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA=="], + + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.21.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ=="], + + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.21.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw=="], + + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.21.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g=="], + + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.21.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ=="], + + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.21.5", "", { "os": "linux", "cpu": "arm" }, "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA=="], + + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.21.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q=="], + + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.21.5", "", { "os": "linux", "cpu": "ia32" }, "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg=="], + + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg=="], + + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg=="], + + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.21.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w=="], + + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA=="], + + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.21.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A=="], + + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.21.5", "", { "os": "linux", "cpu": "x64" }, "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ=="], + + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.21.5", "", { "os": "none", "cpu": "x64" }, "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg=="], + + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.21.5", "", { "os": "openbsd", "cpu": "x64" }, "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow=="], + + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.21.5", "", { "os": "sunos", "cpu": "x64" }, "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg=="], + + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.21.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A=="], + + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.21.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA=="], + + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.21.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw=="], + + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], + + "@msgpack/msgpack": ["@msgpack/msgpack@3.1.2", "", {}, "sha512-JEW4DEtBzfe8HvUYecLU9e6+XJnKDlUAIve8FvPzF3Kzs6Xo/KuZkZJsDH0wJXl/qEZbeeE7edxDNY3kMs39hQ=="], + + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.50.1", "", { "os": "android", "cpu": "arm" }, "sha512-HJXwzoZN4eYTdD8bVV22DN8gsPCAj3V20NHKOs8ezfXanGpmVPR7kalUHd+Y31IJp9stdB87VKPFbsGY3H/2ag=="], + + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.50.1", "", { "os": "android", "cpu": "arm64" }, "sha512-PZlsJVcjHfcH53mOImyt3bc97Ep3FJDXRpk9sMdGX0qgLmY0EIWxCag6EigerGhLVuL8lDVYNnSo8qnTElO4xw=="], + + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.50.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-xc6i2AuWh++oGi4ylOFPmzJOEeAa2lJeGUGb4MudOtgfyyjr4UPNK+eEWTPLvmPJIY/pgw6ssFIox23SyrkkJw=="], + + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.50.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-2ofU89lEpDYhdLAbRdeyz/kX3Y2lpYc6ShRnDjY35bZhd2ipuDMDi6ZTQ9NIag94K28nFMofdnKeHR7BT0CATw=="], + + "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.50.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-wOsE6H2u6PxsHY/BeFHA4VGQN3KUJFZp7QJBmDYI983fgxq5Th8FDkVuERb2l9vDMs1D5XhOrhBrnqcEY6l8ZA=="], + + "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.50.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-A/xeqaHTlKbQggxCqispFAcNjycpUEHP52mwMQZUNqDUJFFYtPHCXS1VAG29uMlDzIVr+i00tSFWFLivMcoIBQ=="], + + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.50.1", "", { "os": "linux", "cpu": "arm" }, "sha512-54v4okehwl5TaSIkpp97rAHGp7t3ghinRd/vyC1iXqXMfjYUTm7TfYmCzXDoHUPTTf36L8pr0E7YsD3CfB3ZDg=="], + + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.50.1", "", { "os": "linux", "cpu": "arm" }, "sha512-p/LaFyajPN/0PUHjv8TNyxLiA7RwmDoVY3flXHPSzqrGcIp/c2FjwPPP5++u87DGHtw+5kSH5bCJz0mvXngYxw=="], + + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.50.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-2AbMhFFkTo6Ptna1zO7kAXXDLi7H9fGTbVaIq2AAYO7yzcAsuTNWPHhb2aTA6GPiP+JXh85Y8CiS54iZoj4opw=="], + + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.50.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-Cgef+5aZwuvesQNw9eX7g19FfKX5/pQRIyhoXLCiBOrWopjo7ycfB292TX9MDcDijiuIJlx1IzJz3IoCPfqs9w=="], + + "@rollup/rollup-linux-loongarch64-gnu": ["@rollup/rollup-linux-loongarch64-gnu@4.50.1", "", { "os": "linux", "cpu": "none" }, "sha512-RPhTwWMzpYYrHrJAS7CmpdtHNKtt2Ueo+BlLBjfZEhYBhK00OsEqM08/7f+eohiF6poe0YRDDd8nAvwtE/Y62Q=="], + + "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.50.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-eSGMVQw9iekut62O7eBdbiccRguuDgiPMsw++BVUg+1K7WjZXHOg/YOT9SWMzPZA+w98G+Fa1VqJgHZOHHnY0Q=="], + + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.50.1", "", { "os": "linux", "cpu": "none" }, "sha512-S208ojx8a4ciIPrLgazF6AgdcNJzQE4+S9rsmOmDJkusvctii+ZvEuIC4v/xFqzbuP8yDjn73oBlNDgF6YGSXQ=="], + + "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.50.1", "", { "os": "linux", "cpu": "none" }, "sha512-3Ag8Ls1ggqkGUvSZWYcdgFwriy2lWo+0QlYgEFra/5JGtAd6C5Hw59oojx1DeqcA2Wds2ayRgvJ4qxVTzCHgzg=="], + + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.50.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-t9YrKfaxCYe7l7ldFERE1BRg/4TATxIg+YieHQ966jwvo7ddHJxPj9cNFWLAzhkVsbBvNA4qTbPVNsZKBO4NSg=="], + + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.50.1", "", { "os": "linux", "cpu": "x64" }, "sha512-MCgtFB2+SVNuQmmjHf+wfI4CMxy3Tk8XjA5Z//A0AKD7QXUYFMQcns91K6dEHBvZPCnhJSyDWLApk40Iq/H3tA=="], + + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.50.1", "", { "os": "linux", "cpu": "x64" }, "sha512-nEvqG+0jeRmqaUMuwzlfMKwcIVffy/9KGbAGyoa26iu6eSngAYQ512bMXuqqPrlTyfqdlB9FVINs93j534UJrg=="], + + "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.50.1", "", { "os": "none", "cpu": "arm64" }, "sha512-RDsLm+phmT3MJd9SNxA9MNuEAO/J2fhW8GXk62G/B4G7sLVumNFbRwDL6v5NrESb48k+QMqdGbHgEtfU0LCpbA=="], + + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.50.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-hpZB/TImk2FlAFAIsoElM3tLzq57uxnGYwplg6WDyAxbYczSi8O2eQ+H2Lx74504rwKtZ3N2g4bCUkiamzS6TQ=="], + + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.50.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-SXjv8JlbzKM0fTJidX4eVsH+Wmnp0/WcD8gJxIZyR6Gay5Qcsmdbi9zVtnbkGPG8v2vMR1AD06lGWy5FLMcG7A=="], + + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.50.1", "", { "os": "win32", "cpu": "x64" }, "sha512-StxAO/8ts62KZVRAm4JZYq9+NqNsV7RvimNK+YM7ry//zebEH6meuugqW/P5OFUCjyQgui+9fUxT6d5NShvMvA=="], + + "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], + + "@types/json-bigint": ["@types/json-bigint@1.0.4", "", {}, "sha512-ydHooXLbOmxBbubnA7Eh+RpBzuaIiQjh8WGJYQB50JFGFrdxW7JzVlyEV7fAXw0T2sqJ1ysTneJbiyNLqZRAag=="], + + "@types/node": ["@types/node@20.19.13", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-yCAeZl7a0DxgNVteXFHt9+uyFbqXGy/ShC4BlcHkoE0AfGXYv/BUiplV72DjMYXHDBXFjhvr6DD1NiRVfB4j8g=="], + + "@vitest/expect": ["@vitest/expect@2.1.9", "", { "dependencies": { "@vitest/spy": "2.1.9", "@vitest/utils": "2.1.9", "chai": "^5.1.2", "tinyrainbow": "^1.2.0" } }, "sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw=="], + + "@vitest/mocker": ["@vitest/mocker@2.1.9", "", { "dependencies": { "@vitest/spy": "2.1.9", "estree-walker": "^3.0.3", "magic-string": "^0.30.12" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^5.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg=="], + + "@vitest/pretty-format": ["@vitest/pretty-format@2.1.9", "", { "dependencies": { "tinyrainbow": "^1.2.0" } }, "sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ=="], + + "@vitest/runner": ["@vitest/runner@2.1.9", "", { "dependencies": { "@vitest/utils": "2.1.9", "pathe": "^1.1.2" } }, "sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g=="], + + "@vitest/snapshot": ["@vitest/snapshot@2.1.9", "", { "dependencies": { "@vitest/pretty-format": "2.1.9", "magic-string": "^0.30.12", "pathe": "^1.1.2" } }, "sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ=="], + + "@vitest/spy": ["@vitest/spy@2.1.9", "", { "dependencies": { "tinyspy": "^3.0.2" } }, "sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ=="], + + "@vitest/utils": ["@vitest/utils@2.1.9", "", { "dependencies": { "@vitest/pretty-format": "2.1.9", "loupe": "^3.1.2", "tinyrainbow": "^1.2.0" } }, "sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ=="], + + "algorand-msgpack": ["algorand-msgpack@1.1.0", "", {}, "sha512-08k7pBQnkaUB5p+jL7f1TRaUIlTSDE0cesFu1mD7llLao+1cAhtvvZmGE3OnisTd0xOn118QMw74SRqddqaYvw=="], + + "algosdk": ["algosdk@3.4.0", "", { "dependencies": { "algorand-msgpack": "^1.1.0", "hi-base32": "^0.5.1", "js-sha256": "^0.9.0", "js-sha3": "^0.8.0", "js-sha512": "^0.8.0", "json-bigint": "^1.0.0", "tweetnacl": "^1.0.3", "vlq": "^2.0.4" } }, "sha512-95NYlVxMsHKs9gV8/hUvNTRAqmRC55wtesGR53j37fjP/sHUWd1gxNGTNBy0d1+o4jDKxVaasVgUHh78IqgtCw=="], + + "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="], + + "bignumber.js": ["bignumber.js@9.3.1", "", {}, "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ=="], + + "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="], + + "chai": ["chai@5.3.3", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw=="], + + "check-error": ["check-error@2.1.1", "", {}, "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw=="], + + "debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], + + "deep-eql": ["deep-eql@5.0.2", "", {}, "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q=="], + + "es-module-lexer": ["es-module-lexer@1.7.0", "", {}, "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA=="], + + "esbuild": ["esbuild@0.21.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.21.5", "@esbuild/android-arm": "0.21.5", "@esbuild/android-arm64": "0.21.5", "@esbuild/android-x64": "0.21.5", "@esbuild/darwin-arm64": "0.21.5", "@esbuild/darwin-x64": "0.21.5", "@esbuild/freebsd-arm64": "0.21.5", "@esbuild/freebsd-x64": "0.21.5", "@esbuild/linux-arm": "0.21.5", "@esbuild/linux-arm64": "0.21.5", "@esbuild/linux-ia32": "0.21.5", "@esbuild/linux-loong64": "0.21.5", "@esbuild/linux-mips64el": "0.21.5", "@esbuild/linux-ppc64": "0.21.5", "@esbuild/linux-riscv64": "0.21.5", "@esbuild/linux-s390x": "0.21.5", "@esbuild/linux-x64": "0.21.5", "@esbuild/netbsd-x64": "0.21.5", "@esbuild/openbsd-x64": "0.21.5", "@esbuild/sunos-x64": "0.21.5", "@esbuild/win32-arm64": "0.21.5", "@esbuild/win32-ia32": "0.21.5", "@esbuild/win32-x64": "0.21.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw=="], + + "estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], + + "expect-type": ["expect-type@1.2.2", "", {}, "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA=="], + + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + + "hi-base32": ["hi-base32@0.5.1", "", {}, "sha512-EmBBpvdYh/4XxsnUybsPag6VikPYnN30td+vQk+GI3qpahVEG9+gTkG0aXVxTjBqQ5T6ijbWIu77O+C5WFWsnA=="], + + "js-sha256": ["js-sha256@0.9.0", "", {}, "sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA=="], + + "js-sha3": ["js-sha3@0.8.0", "", {}, "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q=="], + + "js-sha512": ["js-sha512@0.8.0", "", {}, "sha512-PWsmefG6Jkodqt+ePTvBZCSMFgN7Clckjd0O7su3I0+BW2QWUTJNzjktHsztGLhncP2h8mcF9V9Y2Ha59pAViQ=="], + + "json-bigint": ["json-bigint@1.0.0", "", { "dependencies": { "bignumber.js": "^9.0.0" } }, "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ=="], + + "loupe": ["loupe@3.2.1", "", {}, "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ=="], + + "magic-string": ["magic-string@0.30.19", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw=="], + + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], + + "pathe": ["pathe@1.1.2", "", {}, "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="], + + "pathval": ["pathval@2.0.1", "", {}, "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ=="], + + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + + "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], + + "rollup": ["rollup@4.50.1", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.50.1", "@rollup/rollup-android-arm64": "4.50.1", "@rollup/rollup-darwin-arm64": "4.50.1", "@rollup/rollup-darwin-x64": "4.50.1", "@rollup/rollup-freebsd-arm64": "4.50.1", "@rollup/rollup-freebsd-x64": "4.50.1", "@rollup/rollup-linux-arm-gnueabihf": "4.50.1", "@rollup/rollup-linux-arm-musleabihf": "4.50.1", "@rollup/rollup-linux-arm64-gnu": "4.50.1", "@rollup/rollup-linux-arm64-musl": "4.50.1", "@rollup/rollup-linux-loongarch64-gnu": "4.50.1", "@rollup/rollup-linux-ppc64-gnu": "4.50.1", "@rollup/rollup-linux-riscv64-gnu": "4.50.1", "@rollup/rollup-linux-riscv64-musl": "4.50.1", "@rollup/rollup-linux-s390x-gnu": "4.50.1", "@rollup/rollup-linux-x64-gnu": "4.50.1", "@rollup/rollup-linux-x64-musl": "4.50.1", "@rollup/rollup-openharmony-arm64": "4.50.1", "@rollup/rollup-win32-arm64-msvc": "4.50.1", "@rollup/rollup-win32-ia32-msvc": "4.50.1", "@rollup/rollup-win32-x64-msvc": "4.50.1", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-78E9voJHwnXQMiQdiqswVLZwJIzdBKJ1GdI5Zx6XwoFKUIk09/sSrr+05QFzvYb8q6Y9pPV45zzDuYa3907TZA=="], + + "siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="], + + "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], + + "stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="], + + "std-env": ["std-env@3.9.0", "", {}, "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw=="], + + "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="], + + "tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="], + + "tinypool": ["tinypool@1.1.1", "", {}, "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg=="], + + "tinyrainbow": ["tinyrainbow@1.2.0", "", {}, "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ=="], + + "tinyspy": ["tinyspy@3.0.2", "", {}, "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q=="], + + "tweetnacl": ["tweetnacl@1.0.3", "", {}, "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw=="], + + "typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="], + + "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], + + "vite": ["vite@5.4.20", "", { "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", "rollup": "^4.20.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["@types/node", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-j3lYzGC3P+B5Yfy/pfKNgVEg4+UtcIJcVRt2cDjIOmhLourAqPqf8P7acgxeiSgUB7E3p2P8/3gNIgDLpwzs4g=="], + + "vite-node": ["vite-node@2.1.9", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.3.7", "es-module-lexer": "^1.5.4", "pathe": "^1.1.2", "vite": "^5.0.0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA=="], + + "vitest": ["vitest@2.1.9", "", { "dependencies": { "@vitest/expect": "2.1.9", "@vitest/mocker": "2.1.9", "@vitest/pretty-format": "^2.1.9", "@vitest/runner": "2.1.9", "@vitest/snapshot": "2.1.9", "@vitest/spy": "2.1.9", "@vitest/utils": "2.1.9", "chai": "^5.1.2", "debug": "^4.3.7", "expect-type": "^1.1.0", "magic-string": "^0.30.12", "pathe": "^1.1.2", "std-env": "^3.8.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.1", "tinypool": "^1.0.1", "tinyrainbow": "^1.2.0", "vite": "^5.0.0", "vite-node": "2.1.9", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/node": "^18.0.0 || >=20.0.0", "@vitest/browser": "2.1.9", "@vitest/ui": "2.1.9", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q=="], + + "vlq": ["vlq@2.0.4", "", {}, "sha512-aodjPa2wPQFkra1G8CzJBTHXhgk3EVSwxSWXNPr1fgdFLUb8kvLV1iEb6rFgasIsjP82HWI6dsb5Io26DDnasA=="], + + "why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="], + } +} diff --git a/packages/typescript/indexer_client/package.json b/packages/typescript/indexer_client/package.json index 3d2e478f1..2f939d500 100644 --- a/packages/typescript/indexer_client/package.json +++ b/packages/typescript/indexer_client/package.json @@ -11,14 +11,14 @@ "test": "vitest run" }, "dependencies": { - "json-bigint": "^1.0.0", - "algo-msgpack-with-bigint": "^2.1.1" + "@msgpack/msgpack": "^3.1.2", + "json-bigint": "^1.0.0" }, "devDependencies": { - "typescript": "^5.5.0", "@types/json-bigint": "^1.0.0", - "vitest": "^2.0.0", "@types/node": "^20.0.0", - "algosdk": "^2.7.0" + "algosdk": "^3.0.0", + "typescript": "^5.5.0", + "vitest": "^2.0.0" } } diff --git a/packages/typescript/indexer_client/src/apis/api.service.ts b/packages/typescript/indexer_client/src/apis/api.service.ts index f5cdfba9d..feb1396c1 100644 --- a/packages/typescript/indexer_client/src/apis/api.service.ts +++ b/packages/typescript/indexer_client/src/apis/api.service.ts @@ -23,12 +23,12 @@ import type { SearchForTransactions, } from "../models/index"; -export class ApiService { +export class IndexerApi { constructor(public readonly httpRequest: BaseHttpRequest) {} lookupAccountAppLocalStates( accountId: string, - params?: { applicationId?: number; includeAll?: boolean; limit?: number; next?: string }, + params?: { applicationId?: number | bigint; includeAll?: boolean; limit?: number | bigint; next?: string }, requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {}; @@ -40,7 +40,12 @@ export class ApiService { method: "GET", url: "/v2/accounts/{account-id}/apps-local-state", path: { "account-id": accountId }, - query: { "application-id": params?.applicationId, "include-all": params?.includeAll, limit: params?.limit, next: params?.next }, + 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, + next: params?.next, + }, headers, body: undefined, mediaType: undefined, @@ -51,7 +56,7 @@ export class ApiService { lookupAccountAssets( accountId: string, - params?: { assetId?: number; includeAll?: boolean; limit?: number; next?: string }, + params?: { assetId?: number | bigint; includeAll?: boolean; limit?: number | bigint; next?: string }, requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {}; @@ -63,7 +68,12 @@ export class ApiService { method: "GET", url: "/v2/accounts/{account-id}/assets", path: { "account-id": accountId }, - query: { "asset-id": params?.assetId, "include-all": params?.includeAll, limit: params?.limit, next: params?.next }, + 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, + next: params?.next, + }, headers, body: undefined, mediaType: undefined, @@ -75,7 +85,7 @@ export class ApiService { lookupAccountById( accountId: string, params?: { - round?: number; + round?: number | bigint; includeAll?: boolean; exclude?: "all" | "assets" | "created-assets" | "apps-local-state" | "created-apps" | "none"[]; }, @@ -90,7 +100,11 @@ export class ApiService { method: "GET", url: "/v2/accounts/{account-id}", path: { "account-id": accountId }, - query: { round: params?.round, "include-all": params?.includeAll, exclude: params?.exclude }, + query: { + round: typeof params?.round === "bigint" ? (params!.round as bigint).toString() : params?.round, + "include-all": params?.includeAll, + exclude: params?.exclude, + }, headers, body: undefined, mediaType: undefined, @@ -101,7 +115,7 @@ export class ApiService { lookupAccountCreatedApplications( accountId: string, - params?: { applicationId?: number; includeAll?: boolean; limit?: number; next?: string }, + params?: { applicationId?: number | bigint; includeAll?: boolean; limit?: number | bigint; next?: string }, requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {}; @@ -113,7 +127,12 @@ export class ApiService { method: "GET", url: "/v2/accounts/{account-id}/created-applications", path: { "account-id": accountId }, - query: { "application-id": params?.applicationId, "include-all": params?.includeAll, limit: params?.limit, next: params?.next }, + 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, + next: params?.next, + }, headers, body: undefined, mediaType: undefined, @@ -124,7 +143,7 @@ export class ApiService { lookupAccountCreatedAssets( accountId: string, - params?: { assetId?: number; includeAll?: boolean; limit?: number; next?: string }, + params?: { assetId?: number | bigint; includeAll?: boolean; limit?: number | bigint; next?: string }, requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {}; @@ -136,7 +155,12 @@ export class ApiService { method: "GET", url: "/v2/accounts/{account-id}/created-assets", path: { "account-id": accountId }, - query: { "asset-id": params?.assetId, "include-all": params?.includeAll, limit: params?.limit, next: params?.next }, + 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, + next: params?.next, + }, headers, body: undefined, mediaType: undefined, @@ -148,20 +172,20 @@ export class ApiService { lookupAccountTransactions( accountId: string, params?: { - limit?: number; + limit?: number | bigint; next?: string; notePrefix?: string; txType?: "pay" | "keyreg" | "acfg" | "axfer" | "afrz" | "appl" | "stpf" | "hb"; sigType?: "sig" | "msig" | "lsig"; txid?: string; - round?: number; - minRound?: number; - maxRound?: number; - assetId?: number; + round?: number | bigint; + minRound?: number | bigint; + maxRound?: number | bigint; + assetId?: number | bigint; beforeTime?: string; afterTime?: string; - currencyGreaterThan?: number; - currencyLessThan?: number; + currencyGreaterThan?: number | bigint; + currencyLessThan?: number | bigint; rekeyTo?: boolean; }, requestOptions?: ApiRequestOptions, @@ -176,20 +200,24 @@ export class ApiService { url: "/v2/accounts/{account-id}/transactions", path: { "account-id": accountId }, query: { - limit: params?.limit, + limit: typeof params?.limit === "bigint" ? (params!.limit as bigint).toString() : params?.limit, next: params?.next, "note-prefix": params?.notePrefix, "tx-type": params?.txType, "sig-type": params?.sigType, txid: params?.txid, - round: params?.round, - "min-round": params?.minRound, - "max-round": params?.maxRound, - "asset-id": params?.assetId, + round: typeof params?.round === "bigint" ? (params!.round as bigint).toString() : params?.round, + "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, + "asset-id": typeof params?.assetId === "bigint" ? (params!.assetId as bigint).toString() : params?.assetId, "before-time": params?.beforeTime, "after-time": params?.afterTime, - "currency-greater-than": params?.currencyGreaterThan, - "currency-less-than": params?.currencyLessThan, + "currency-greater-than": + typeof params?.currencyGreaterThan === "bigint" + ? (params!.currencyGreaterThan as bigint).toString() + : params?.currencyGreaterThan, + "currency-less-than": + typeof params?.currencyLessThan === "bigint" ? (params!.currencyLessThan as bigint).toString() : params?.currencyLessThan, "rekey-to": params?.rekeyTo, }, headers, @@ -200,7 +228,11 @@ export class ApiService { }); } - lookupApplicationBoxByIdandName(applicationId: number, params?: { name: string }, requestOptions?: ApiRequestOptions): Promise { + lookupApplicationBoxByIdandName( + applicationId: number | bigint, + params?: { name: string }, + requestOptions?: ApiRequestOptions, + ): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -209,7 +241,7 @@ export class ApiService { return this.httpRequest.request({ method: "GET", url: "/v2/applications/{application-id}/box", - path: { "application-id": applicationId }, + path: { "application-id": typeof applicationId === "bigint" ? applicationId.toString() : applicationId }, query: { name: params?.name }, headers, body: undefined, @@ -220,7 +252,7 @@ export class ApiService { } lookupApplicationById( - applicationId: number, + applicationId: number | bigint, params?: { includeAll?: boolean }, requestOptions?: ApiRequestOptions, ): Promise { @@ -232,7 +264,7 @@ export class ApiService { return this.httpRequest.request({ method: "GET", url: "/v2/applications/{application-id}", - path: { "application-id": applicationId }, + path: { "application-id": typeof applicationId === "bigint" ? applicationId.toString() : applicationId }, query: { "include-all": params?.includeAll }, headers, body: undefined, @@ -243,8 +275,15 @@ export class ApiService { } lookupApplicationLogsById( - applicationId: number, - params?: { limit?: number; next?: string; txid?: string; minRound?: number; maxRound?: number; senderAddress?: string }, + applicationId: number | bigint, + params?: { + limit?: number | bigint; + next?: string; + txid?: string; + minRound?: number | bigint; + maxRound?: number | bigint; + senderAddress?: string; + }, requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {}; @@ -255,13 +294,13 @@ export class ApiService { return this.httpRequest.request({ method: "GET", url: "/v2/applications/{application-id}/logs", - path: { "application-id": applicationId }, + path: { "application-id": typeof applicationId === "bigint" ? applicationId.toString() : applicationId }, query: { - limit: params?.limit, + limit: typeof params?.limit === "bigint" ? (params!.limit as bigint).toString() : params?.limit, next: params?.next, txid: params?.txid, - "min-round": params?.minRound, - "max-round": params?.maxRound, + "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, "sender-address": params?.senderAddress, }, headers, @@ -273,8 +312,14 @@ export class ApiService { } lookupAssetBalances( - assetId: number, - params?: { includeAll?: boolean; limit?: number; next?: string; currencyGreaterThan?: number; currencyLessThan?: number }, + assetId: number | bigint, + params?: { + includeAll?: boolean; + limit?: number | bigint; + next?: string; + currencyGreaterThan?: number | bigint; + currencyLessThan?: number | bigint; + }, requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {}; @@ -285,13 +330,17 @@ export class ApiService { return this.httpRequest.request({ method: "GET", url: "/v2/assets/{asset-id}/balances", - path: { "asset-id": assetId }, + path: { "asset-id": typeof assetId === "bigint" ? assetId.toString() : assetId }, query: { "include-all": params?.includeAll, - limit: params?.limit, + limit: typeof params?.limit === "bigint" ? (params!.limit as bigint).toString() : params?.limit, next: params?.next, - "currency-greater-than": params?.currencyGreaterThan, - "currency-less-than": params?.currencyLessThan, + "currency-greater-than": + typeof params?.currencyGreaterThan === "bigint" + ? (params!.currencyGreaterThan as bigint).toString() + : params?.currencyGreaterThan, + "currency-less-than": + typeof params?.currencyLessThan === "bigint" ? (params!.currencyLessThan as bigint).toString() : params?.currencyLessThan, }, headers, body: undefined, @@ -301,7 +350,11 @@ export class ApiService { }); } - lookupAssetById(assetId: number, params?: { includeAll?: boolean }, requestOptions?: ApiRequestOptions): Promise { + lookupAssetById( + assetId: number | bigint, + params?: { includeAll?: boolean }, + requestOptions?: ApiRequestOptions, + ): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -310,7 +363,7 @@ export class ApiService { return this.httpRequest.request({ method: "GET", url: "/v2/assets/{asset-id}", - path: { "asset-id": assetId }, + path: { "asset-id": typeof assetId === "bigint" ? assetId.toString() : assetId }, query: { "include-all": params?.includeAll }, headers, body: undefined, @@ -321,21 +374,21 @@ export class ApiService { } lookupAssetTransactions( - assetId: number, + assetId: number | bigint, params?: { - limit?: number; + limit?: number | bigint; next?: string; notePrefix?: string; txType?: "pay" | "keyreg" | "acfg" | "axfer" | "afrz" | "appl" | "stpf" | "hb"; sigType?: "sig" | "msig" | "lsig"; txid?: string; - round?: number; - minRound?: number; - maxRound?: number; + round?: number | bigint; + minRound?: number | bigint; + maxRound?: number | bigint; beforeTime?: string; afterTime?: string; - currencyGreaterThan?: number; - currencyLessThan?: number; + currencyGreaterThan?: number | bigint; + currencyLessThan?: number | bigint; address?: string; addressRole?: "sender" | "receiver" | "freeze-target"; excludeCloseTo?: boolean; @@ -351,21 +404,25 @@ export class ApiService { return this.httpRequest.request({ method: "GET", url: "/v2/assets/{asset-id}/transactions", - path: { "asset-id": assetId }, + path: { "asset-id": typeof assetId === "bigint" ? assetId.toString() : assetId }, query: { - limit: params?.limit, + limit: typeof params?.limit === "bigint" ? (params!.limit as bigint).toString() : params?.limit, next: params?.next, "note-prefix": params?.notePrefix, "tx-type": params?.txType, "sig-type": params?.sigType, txid: params?.txid, - round: params?.round, - "min-round": params?.minRound, - "max-round": params?.maxRound, + round: typeof params?.round === "bigint" ? (params!.round as bigint).toString() : params?.round, + "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, "before-time": params?.beforeTime, "after-time": params?.afterTime, - "currency-greater-than": params?.currencyGreaterThan, - "currency-less-than": params?.currencyLessThan, + "currency-greater-than": + typeof params?.currencyGreaterThan === "bigint" + ? (params!.currencyGreaterThan as bigint).toString() + : params?.currencyGreaterThan, + "currency-less-than": + typeof params?.currencyLessThan === "bigint" ? (params!.currencyLessThan as bigint).toString() : params?.currencyLessThan, address: params?.address, "address-role": params?.addressRole, "exclude-close-to": params?.excludeCloseTo, @@ -379,7 +436,7 @@ export class ApiService { }); } - lookupBlock(roundNumber: number, params?: { headerOnly?: boolean }, requestOptions?: ApiRequestOptions): Promise { + lookupBlock(roundNumber: number | bigint, params?: { headerOnly?: boolean }, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -388,7 +445,7 @@ export class ApiService { return this.httpRequest.request({ method: "GET", url: "/v2/blocks/{round-number}", - path: { "round-number": roundNumber }, + path: { "round-number": typeof roundNumber === "bigint" ? roundNumber.toString() : roundNumber }, query: { "header-only": params?.headerOnly }, headers, body: undefined, @@ -438,16 +495,16 @@ export class ApiService { searchForAccounts( params?: { - assetId?: number; - limit?: number; + assetId?: number | bigint; + limit?: number | bigint; next?: string; - currencyGreaterThan?: number; + currencyGreaterThan?: number | bigint; includeAll?: boolean; exclude?: "all" | "assets" | "created-assets" | "apps-local-state" | "created-apps" | "none"[]; - currencyLessThan?: number; + currencyLessThan?: number | bigint; authAddr?: string; - round?: number; - applicationId?: number; + round?: number | bigint; + applicationId?: number | bigint; onlineOnly?: boolean; }, requestOptions?: ApiRequestOptions, @@ -462,16 +519,20 @@ export class ApiService { url: "/v2/accounts", path: {}, query: { - "asset-id": params?.assetId, - limit: params?.limit, + "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, next: params?.next, - "currency-greater-than": params?.currencyGreaterThan, + "currency-greater-than": + typeof params?.currencyGreaterThan === "bigint" + ? (params!.currencyGreaterThan as bigint).toString() + : params?.currencyGreaterThan, "include-all": params?.includeAll, exclude: params?.exclude, - "currency-less-than": params?.currencyLessThan, + "currency-less-than": + typeof params?.currencyLessThan === "bigint" ? (params!.currencyLessThan as bigint).toString() : params?.currencyLessThan, "auth-addr": params?.authAddr, - round: params?.round, - "application-id": params?.applicationId, + round: typeof params?.round === "bigint" ? (params!.round as bigint).toString() : params?.round, + "application-id": typeof params?.applicationId === "bigint" ? (params!.applicationId as bigint).toString() : params?.applicationId, "online-only": params?.onlineOnly, }, headers, @@ -483,8 +544,8 @@ export class ApiService { } searchForApplicationBoxes( - applicationId: number, - params?: { limit?: number; next?: string }, + applicationId: number | bigint, + params?: { limit?: number | bigint; next?: string }, requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {}; @@ -495,8 +556,8 @@ export class ApiService { return this.httpRequest.request({ method: "GET", url: "/v2/applications/{application-id}/boxes", - path: { "application-id": applicationId }, - query: { limit: params?.limit, next: params?.next }, + 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 }, headers, body: undefined, mediaType: undefined, @@ -506,7 +567,7 @@ export class ApiService { } searchForApplications( - params?: { applicationId?: number; creator?: string; includeAll?: boolean; limit?: number; next?: string }, + params?: { applicationId?: number | bigint; creator?: string; includeAll?: boolean; limit?: number | bigint; next?: string }, requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {}; @@ -519,10 +580,10 @@ export class ApiService { url: "/v2/applications", path: {}, query: { - "application-id": params?.applicationId, + "application-id": typeof params?.applicationId === "bigint" ? (params!.applicationId as bigint).toString() : params?.applicationId, creator: params?.creator, "include-all": params?.includeAll, - limit: params?.limit, + limit: typeof params?.limit === "bigint" ? (params!.limit as bigint).toString() : params?.limit, next: params?.next, }, headers, @@ -534,7 +595,15 @@ export class ApiService { } searchForAssets( - params?: { includeAll?: boolean; limit?: number; next?: string; creator?: string; name?: string; unit?: string; assetId?: number }, + params?: { + includeAll?: boolean; + limit?: number | bigint; + next?: string; + creator?: string; + name?: string; + unit?: string; + assetId?: number | bigint; + }, requestOptions?: ApiRequestOptions, ): Promise { const headers: Record = {}; @@ -548,12 +617,12 @@ export class ApiService { path: {}, query: { "include-all": params?.includeAll, - limit: params?.limit, + limit: typeof params?.limit === "bigint" ? (params!.limit as bigint).toString() : params?.limit, next: params?.next, creator: params?.creator, name: params?.name, unit: params?.unit, - "asset-id": params?.assetId, + "asset-id": typeof params?.assetId === "bigint" ? (params!.assetId as bigint).toString() : params?.assetId, }, headers, body: undefined, @@ -565,10 +634,10 @@ export class ApiService { searchForBlockHeaders( params?: { - limit?: number; + limit?: number | bigint; next?: string; - minRound?: number; - maxRound?: number; + minRound?: number | bigint; + maxRound?: number | bigint; beforeTime?: string; afterTime?: string; proposers?: string[]; @@ -587,10 +656,10 @@ export class ApiService { url: "/v2/block-headers", path: {}, query: { - limit: params?.limit, + limit: typeof params?.limit === "bigint" ? (params!.limit as bigint).toString() : params?.limit, next: params?.next, - "min-round": params?.minRound, - "max-round": params?.maxRound, + "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, "before-time": params?.beforeTime, "after-time": params?.afterTime, proposers: params?.proposers, @@ -607,26 +676,26 @@ export class ApiService { searchForTransactions( params?: { - limit?: number; + 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; - minRound?: number; - maxRound?: number; - assetId?: number; + round?: number | bigint; + minRound?: number | bigint; + maxRound?: number | bigint; + assetId?: number | bigint; beforeTime?: string; afterTime?: string; - currencyGreaterThan?: number; - currencyLessThan?: number; + currencyGreaterThan?: number | bigint; + currencyLessThan?: number | bigint; address?: string; addressRole?: "sender" | "receiver" | "freeze-target"; excludeCloseTo?: boolean; rekeyTo?: boolean; - applicationId?: number; + applicationId?: number | bigint; }, requestOptions?: ApiRequestOptions, ): Promise { @@ -640,26 +709,30 @@ export class ApiService { url: "/v2/transactions", path: {}, query: { - limit: params?.limit, + limit: typeof params?.limit === "bigint" ? (params!.limit as bigint).toString() : params?.limit, next: params?.next, "note-prefix": params?.notePrefix, "tx-type": params?.txType, "sig-type": params?.sigType, "group-id": params?.groupId, txid: params?.txid, - round: params?.round, - "min-round": params?.minRound, - "max-round": params?.maxRound, - "asset-id": params?.assetId, + round: typeof params?.round === "bigint" ? (params!.round as bigint).toString() : params?.round, + "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, + "asset-id": typeof params?.assetId === "bigint" ? (params!.assetId as bigint).toString() : params?.assetId, "before-time": params?.beforeTime, "after-time": params?.afterTime, - "currency-greater-than": params?.currencyGreaterThan, - "currency-less-than": params?.currencyLessThan, + "currency-greater-than": + typeof params?.currencyGreaterThan === "bigint" + ? (params!.currencyGreaterThan as bigint).toString() + : params?.currencyGreaterThan, + "currency-less-than": + typeof params?.currencyLessThan === "bigint" ? (params!.currencyLessThan as bigint).toString() : params?.currencyLessThan, address: params?.address, "address-role": params?.addressRole, "exclude-close-to": params?.excludeCloseTo, "rekey-to": params?.rekeyTo, - "application-id": params?.applicationId, + "application-id": typeof params?.applicationId === "bigint" ? (params!.applicationId as bigint).toString() : params?.applicationId, }, headers, body: undefined, diff --git a/packages/typescript/indexer_client/src/apis/index.ts b/packages/typescript/indexer_client/src/apis/index.ts index c8244b99b..e9959ad67 100644 --- a/packages/typescript/indexer_client/src/apis/index.ts +++ b/packages/typescript/indexer_client/src/apis/index.ts @@ -1,2 +1,2 @@ // Barrel file for services -export { ApiService } from "./api.service"; +export { IndexerApi } from "./api.service"; diff --git a/packages/typescript/indexer_client/src/client.ts b/packages/typescript/indexer_client/src/client.ts index 310bdaba7..696b7bc03 100644 --- a/packages/typescript/indexer_client/src/client.ts +++ b/packages/typescript/indexer_client/src/client.ts @@ -1,13 +1,13 @@ -import type { OpenAPIConfig } from "./core/OpenAPI"; +import type { ClientConfig } from "./core/ClientConfig"; import { FetchHttpRequest } from "./core/FetchHttpRequest"; -import { ApiService } from "./apis/api.service"; +import { IndexerApi } from "./apis/api.service"; -export class Client { +export class IndexerClient { public readonly request: FetchHttpRequest; - public readonly api: ApiService; + public readonly api: IndexerApi; - constructor(config: OpenAPIConfig) { + constructor(config: ClientConfig) { this.request = new FetchHttpRequest(config); - this.api = new ApiService(this.request); + this.api = new IndexerApi(this.request); } } diff --git a/packages/typescript/indexer_client/src/core/BaseHttpRequest.ts b/packages/typescript/indexer_client/src/core/BaseHttpRequest.ts index 85cf8d865..45f2f0666 100644 --- a/packages/typescript/indexer_client/src/core/BaseHttpRequest.ts +++ b/packages/typescript/indexer_client/src/core/BaseHttpRequest.ts @@ -1,4 +1,4 @@ -import type { OpenAPIConfig } from "./OpenAPI"; +import type { ClientConfig } from "./ClientConfig"; export interface RequestOptions { method: string; @@ -16,6 +16,6 @@ export interface RequestOptions { export type ApiRequestOptions = RequestOptions; export abstract class BaseHttpRequest { - constructor(public readonly config: OpenAPIConfig) {} + constructor(public readonly config: ClientConfig) {} abstract request(options: RequestOptions): Promise; } diff --git a/packages/typescript/indexer_client/src/core/OpenAPI.ts b/packages/typescript/indexer_client/src/core/ClientConfig.ts similarity index 74% rename from packages/typescript/indexer_client/src/core/OpenAPI.ts rename to packages/typescript/indexer_client/src/core/ClientConfig.ts index fde885a4d..45cd2cf9f 100644 --- a/packages/typescript/indexer_client/src/core/OpenAPI.ts +++ b/packages/typescript/indexer_client/src/core/ClientConfig.ts @@ -1,9 +1,9 @@ /* - Minimal OpenAPI runtime config holder + Minimal client runtime config holder */ export type BaseURL = string; -export interface OpenAPIConfig { +export interface ClientConfig { BASE: BaseURL; VERSION?: string; WITH_CREDENTIALS?: boolean; @@ -15,8 +15,3 @@ export interface OpenAPIConfig { ENCODE_PATH?: (path: string) => string; INT_DECODING?: "safe" | "unsafe" | "mixed" | "bigint"; } - -export const OpenAPI: OpenAPIConfig = { - BASE: "", - INT_DECODING: "mixed", -}; diff --git a/packages/typescript/indexer_client/src/core/FetchHttpRequest.ts b/packages/typescript/indexer_client/src/core/FetchHttpRequest.ts index b47684434..bc0c4cb9a 100644 --- a/packages/typescript/indexer_client/src/core/FetchHttpRequest.ts +++ b/packages/typescript/indexer_client/src/core/FetchHttpRequest.ts @@ -1,5 +1,4 @@ import { BaseHttpRequest, type RequestOptions } from "./BaseHttpRequest"; -import { OpenAPI } from "./OpenAPI"; import { request as defaultRequest } from "./request"; export class FetchHttpRequest extends BaseHttpRequest { diff --git a/packages/typescript/indexer_client/src/core/casing.ts b/packages/typescript/indexer_client/src/core/casing.ts new file mode 100644 index 000000000..7ad409bd5 --- /dev/null +++ b/packages/typescript/indexer_client/src/core/casing.ts @@ -0,0 +1,52 @@ +function toCamel(segmented: string): string { + if (!segmented) return segmented; + // Fast path: if no hyphen, return as-is but ensure typical camel conversion for underscores + if (!segmented.includes("-")) return segmented.replace(/_([a-z0-9])/g, (_, c) => c.toUpperCase()); + return segmented + .split("-") + .map((part, index) => (index === 0 ? part : part.charAt(0).toUpperCase() + part.slice(1))) + .join(""); +} + +function toKebab(camel: string): string { + if (!camel) return camel; + // Convert camelCase or mixedCase to kebab-case; leave existing hyphens and numbers intact + return camel + .replace(/([a-z0-9])([A-Z])/g, "$1-$2") + .replace(/_/g, "-") + .toLowerCase(); +} + +function isPlainObject(value: unknown): value is Record { + if (value === null || typeof value !== "object") return false; + const proto = Object.getPrototypeOf(value); + return proto === Object.prototype || proto === null; +} + +export function toCamelCaseKeysDeep(value: T): T { + // eslint-disable-line @typescript-eslint/no-explicit-any + if (Array.isArray(value)) return value.map((v) => toCamelCaseKeysDeep(v)) as unknown as T; + if (value instanceof Uint8Array) return value; + if (!isPlainObject(value)) return value; + + const out: Record = {}; + for (const [k, v] of Object.entries(value)) { + const newKey = toCamel(k); + out[newKey] = toCamelCaseKeysDeep(v as unknown); + } + return out as unknown as T; +} + +export function toKebabCaseKeysDeep(value: T): T { + // eslint-disable-line @typescript-eslint/no-explicit-any + if (Array.isArray(value)) return value.map((v) => toKebabCaseKeysDeep(v)) as unknown as T; + if (value instanceof Uint8Array) return value; + if (!isPlainObject(value)) return value; + + const out: Record = {}; + for (const [k, v] of Object.entries(value)) { + const newKey = toKebab(k); + out[newKey] = toKebabCaseKeysDeep(v as unknown); + } + return out as unknown as T; +} diff --git a/packages/typescript/indexer_client/src/core/msgpack.ts b/packages/typescript/indexer_client/src/core/msgpack.ts index 1d2a5aa2f..a30aa9314 100644 --- a/packages/typescript/indexer_client/src/core/msgpack.ts +++ b/packages/typescript/indexer_client/src/core/msgpack.ts @@ -1,13 +1,132 @@ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -declare const require: any; -// eslint-disable-next-line @typescript-eslint/no-var-requires -const { decode } = require("algo-msgpack-with-bigint"); - +import { encode as msgpackEncode, decode as msgpackDecode } from "@msgpack/msgpack"; import type { IntDecoding } from "./json"; +/** + * Prepare value for Algorand-compliant msgpack encoding. + * Implements strict Algorand msgpack rules (matching go-algorand behavior): + * 1. Omit zero values, empty strings, and empty arrays (RecursiveEmptyCheck) + * 2. Convert bigints to smallest safe integer type (PositiveIntUnsigned) + * 3. Sorted keys and canonical encoding are handled by msgpackEncode options + * + * These rules apply universally for both API communication and transaction encoding, + * as go-algorand uses the same codec settings for all msgpack operations. + */ +function prepareForEncoding(value: any): any { + // eslint-disable-line @typescript-eslint/no-explicit-any + if (value === null || value === undefined) { + return undefined; + } + + // Handle numbers - omit zeros + if (typeof value === "number") { + if (value === 0) return undefined; + return value; + } + + // Handle bigints - omit zeros and convert to number when safe (for smaller encoding) + if (typeof value === "bigint") { + if (value === 0n) return undefined; + // Convert to number if it fits safely (implements PositiveIntUnsigned behavior) + if (value <= BigInt(Number.MAX_SAFE_INTEGER) && value >= BigInt(Number.MIN_SAFE_INTEGER)) { + return Number(value); + } + return value; + } + + // Handle strings - omit empty strings + if (typeof value === "string") { + if (value === "") return undefined; + return value; + } + + // Handle Uint8Array - omit empty arrays + if (value instanceof Uint8Array) { + if (value.length === 0) return undefined; + return value; + } + + // Handle arrays - omit empty arrays and filter undefined values + if (Array.isArray(value)) { + if (value.length === 0) return undefined; + const processed = value.map(prepareForEncoding).filter((v) => v !== undefined); + return processed.length > 0 ? processed : undefined; + } + + // Handle objects - omit empty objects and filter undefined values (RecursiveEmptyCheck) + if (value && typeof value === "object") { + const result: any = {}; // eslint-disable-line @typescript-eslint/no-explicit-any + for (const [k, v] of Object.entries(value)) { + const prepared = prepareForEncoding(v); + if (prepared !== undefined) { + result[k] = prepared; + } + } + // Return undefined if object is empty after filtering + return Object.keys(result).length > 0 ? result : undefined; + } + + return value; +} + +function convertIntegersToBigInt(value: any): any { + // eslint-disable-line @typescript-eslint/no-explicit-any + if (value === null || value === undefined) { + return value; + } + if (typeof value === "number" && Number.isInteger(value)) { + return BigInt(value); + } + if (typeof value === "bigint") { + return value; + } + if (value instanceof Uint8Array) { + return value; + } + if (Array.isArray(value)) { + return value.map(convertIntegersToBigInt); + } + if (value && typeof value === "object") { + const result: any = {}; // eslint-disable-line @typescript-eslint/no-explicit-any + for (const [k, v] of Object.entries(value)) { + result[k] = convertIntegersToBigInt(v); + } + return result; + } + return value; +} + +/** + * Encode a value as msgpack using Algorand's strict encoding rules. + * This matches go-algorand's protocol.CodecHandle settings: + * - Canonical = true (sorted keys, deterministic encoding) + * - RecursiveEmptyCheck = true (omit empty/zero values recursively) + * - PositiveIntUnsigned = true (use smallest unsigned integer types) + * + * @param value - The value to encode + * @returns Encoded msgpack bytes + */ +export function encodeMsgPack(value: any): Uint8Array { + // eslint-disable-line @typescript-eslint/no-explicit-any + const prepared = prepareForEncoding(value); + + // Ensure we return valid msgpack even if everything was omitted + const toEncode = prepared === undefined ? {} : prepared; + + return msgpackEncode(toEncode, { + sortKeys: true, // Canonical = true in go-algorand + forceIntegerToFloat: false, + ignoreUndefined: true, // Handle undefined values from prepareForEncoding + initialBufferSize: 2048, + useBigInt64: true, // Support for large integers + }); +} + export function decodeMsgPack(buffer: Uint8Array): any { // eslint-disable-line @typescript-eslint/no-explicit-any - return decode(buffer); + const decoded = msgpackDecode(buffer, { + useBigInt64: true, + }); + return convertIntegersToBigInt(decoded); } export function normalizeMsgPackIntegers(value: any, intDecoding: IntDecoding): any { diff --git a/packages/typescript/indexer_client/src/core/request.ts b/packages/typescript/indexer_client/src/core/request.ts index e33d274f1..38eb3d463 100644 --- a/packages/typescript/indexer_client/src/core/request.ts +++ b/packages/typescript/indexer_client/src/core/request.ts @@ -1,12 +1,14 @@ -import type { OpenAPIConfig } from "./OpenAPI"; +import type { ClientConfig } from "./ClientConfig"; import { ApiError } from "./ApiError"; import { parseJson, stringifyJson } from "./json"; -import { decodeMsgPack, normalizeMsgPackIntegers } from "./msgpack"; +import { decodeMsgPack, encodeMsgPack, normalizeMsgPackIntegers } from "./msgpack"; +import { toCamelCaseKeysDeep } from "./casing"; +import { toKebabCaseKeysDeep } from "./casing"; const encodeURIPath = (path: string): string => encodeURI(path).replace(/%5B/g, "[").replace(/%5D/g, "]"); export async function request( - config: OpenAPIConfig, + config: ClientConfig, options: { method: string; url: string; @@ -52,10 +54,24 @@ export async function request( headers["Authorization"] = `Basic ${btoa(`${config.USERNAME}:${config.PASSWORD}`)}`; } + // Prepare body based on media type + let body: any = undefined; + if (options.body != null) { + if (options.mediaType?.includes("json")) { + body = stringifyJson(toKebabCaseKeysDeep(options.body)); + } else if (options.mediaType?.includes("msgpack")) { + // Encode typed models to msgpack for requests + body = encodeMsgPack(toKebabCaseKeysDeep(options.body)); + } else { + // For binary/text, pass through as-is + body = options.body; + } + } + const response = await fetch(url.toString(), { method: options.method, headers, - body: options.body != null ? (options.mediaType?.includes("json") ? stringifyJson(options.body) : options.body) : undefined, + body, credentials: config.CREDENTIALS, }); @@ -63,7 +79,7 @@ export async function request( let body: any = undefined; try { const ct = response.headers.get("content-type"); - if (ct && ct.includes("application/json")) body = parseJson(await response.text(), config.INT_DECODING); + if (ct && ct.includes("application/json")) body = parseJson(await response.text(), config.INT_DECODING ?? "mixed"); else body = await response.text(); } catch {} throw new ApiError(url.toString(), response.status, body); @@ -74,17 +90,36 @@ export async function request( return value as unknown as T; } - // Parse by content-type first + // Parse response by content-type const contentType = response.headers.get("content-type") || ""; - if (contentType.includes("application/msgpack") || contentType.includes("application/x-binary")) { + + // Handle msgpack responses - decode to typed models + if (contentType.includes("application/msgpack")) { const buf = new Uint8Array(await response.arrayBuffer()); const decoded = decodeMsgPack(buf); - return normalizeMsgPackIntegers(decoded, config.INT_DECODING ?? "mixed") as T; + const normalized = normalizeMsgPackIntegers(decoded, config.INT_DECODING ?? "bigint"); + return toCamelCaseKeysDeep(normalized) as T; } + + // Handle raw binary responses (e.g., application/x-binary for raw transactions) + if (contentType.includes("application/x-binary") || contentType.includes("application/octet-stream")) { + // For raw binary, return as Uint8Array without decoding + return new Uint8Array(await response.arrayBuffer()) as unknown as T; + } + + // Handle JSON responses if (contentType.includes("application/json")) { const text = await response.text(); - return parseJson(text, config.INT_DECODING) as T; + const parsed = parseJson(text, config.INT_DECODING ?? "mixed"); + return toCamelCaseKeysDeep(parsed) as T; } + // Fallback to text - return (await response.text()) as unknown as T; + const text = await response.text(); + try { + const parsed = JSON.parse(text); + return toCamelCaseKeysDeep(parsed) as T; + } catch { + return text as unknown as T; + } } diff --git a/packages/typescript/indexer_client/src/index.ts b/packages/typescript/indexer_client/src/index.ts index e51ca64f4..9912e902e 100644 --- a/packages/typescript/indexer_client/src/index.ts +++ b/packages/typescript/indexer_client/src/index.ts @@ -1,4 +1,4 @@ -export * from "./core/OpenAPI"; +export * from "./core/ClientConfig"; export * from "./core/BaseHttpRequest"; export * from "./core/FetchHttpRequest"; export * from "./core/ApiError"; diff --git a/packages/typescript/indexer_client/src/models/account.ts b/packages/typescript/indexer_client/src/models/account.ts index 98e5803ec..531c7d224 100644 --- a/packages/typescript/indexer_client/src/models/account.ts +++ b/packages/typescript/indexer_client/src/models/account.ts @@ -9,32 +9,32 @@ import type { AccountParticipation, Application, ApplicationLocalState, Applicat export type Account = { address: string; amount: bigint; - "min-balance": bigint; - "amount-without-pending-rewards": bigint; - "apps-local-state"?: ApplicationLocalState[]; - "apps-total-schema"?: ApplicationStateSchema; - "apps-total-extra-pages"?: number; + minBalance: bigint; + amountWithoutPendingRewards: bigint; + appsLocalState?: ApplicationLocalState[]; + appsTotalSchema?: ApplicationStateSchema; + appsTotalExtraPages?: bigint; assets?: AssetHolding[]; - "created-apps"?: Application[]; - "created-assets"?: Asset[]; + createdApps?: Application[]; + createdAssets?: Asset[]; participation?: AccountParticipation; - "incentive-eligible"?: boolean; - "pending-rewards": bigint; - "reward-base"?: bigint; + incentiveEligible?: boolean; + pendingRewards: bigint; + rewardBase?: bigint; rewards: bigint; round: bigint; status: string; - "sig-type"?: "sig" | "msig" | "lsig"; - "total-apps-opted-in": number; - "total-assets-opted-in": number; - "total-box-bytes": number; - "total-boxes": number; - "total-created-apps": number; - "total-created-assets": number; - "auth-addr"?: string; - "last-proposed"?: bigint; - "last-heartbeat"?: bigint; + sigType?: "sig" | "msig" | "lsig"; + totalAppsOptedIn: bigint; + totalAssetsOptedIn: bigint; + totalBoxBytes: bigint; + totalBoxes: bigint; + totalCreatedApps: bigint; + totalCreatedAssets: bigint; + authAddr?: string; + lastProposed?: bigint; + lastHeartbeat?: bigint; deleted?: boolean; - "created-at-round"?: bigint; - "closed-at-round"?: bigint; + createdAtRound?: bigint; + closedAtRound?: bigint; }; diff --git a/packages/typescript/indexer_client/src/models/accountparticipation.ts b/packages/typescript/indexer_client/src/models/accountparticipation.ts index 2578b7231..b77cf3b00 100644 --- a/packages/typescript/indexer_client/src/models/accountparticipation.ts +++ b/packages/typescript/indexer_client/src/models/accountparticipation.ts @@ -2,10 +2,10 @@ * AccountParticipation describes the parameters used by this account in consensus protocol. */ export type AccountParticipation = { - "selection-participation-key": string; - "vote-first-valid": bigint; - "vote-key-dilution": bigint; - "vote-last-valid": bigint; - "vote-participation-key": string; - "state-proof-key"?: string; + selectionParticipationKey: string; + voteFirstValid: bigint; + voteKeyDilution: bigint; + voteLastValid: bigint; + voteParticipationKey: string; + stateProofKey?: string; }; diff --git a/packages/typescript/indexer_client/src/models/application.ts b/packages/typescript/indexer_client/src/models/application.ts index adc30f460..a0d50c8fa 100644 --- a/packages/typescript/indexer_client/src/models/application.ts +++ b/packages/typescript/indexer_client/src/models/application.ts @@ -3,10 +3,4 @@ import type { ApplicationParams } from "./index"; /** * Application index and its parameters */ -export type Application = { - id: bigint; - deleted?: boolean; - "created-at-round"?: bigint; - "deleted-at-round"?: bigint; - params: ApplicationParams; -}; +export type Application = { id: bigint; deleted?: boolean; createdAtRound?: bigint; deletedAtRound?: bigint; params: ApplicationParams }; diff --git a/packages/typescript/indexer_client/src/models/applicationlocalstate.ts b/packages/typescript/indexer_client/src/models/applicationlocalstate.ts index cdf81c8e6..c5afea98f 100644 --- a/packages/typescript/indexer_client/src/models/applicationlocalstate.ts +++ b/packages/typescript/indexer_client/src/models/applicationlocalstate.ts @@ -6,8 +6,8 @@ import type { ApplicationStateSchema, TealKeyValueStore } from "./index"; export type ApplicationLocalState = { id: bigint; deleted?: boolean; - "opted-in-at-round"?: bigint; - "closed-out-at-round"?: bigint; + optedInAtRound?: bigint; + closedOutAtRound?: bigint; schema: ApplicationStateSchema; - "key-value"?: TealKeyValueStore; + keyValue?: TealKeyValueStore; }; diff --git a/packages/typescript/indexer_client/src/models/applicationparams.ts b/packages/typescript/indexer_client/src/models/applicationparams.ts index 03582b67b..6c6a966e9 100644 --- a/packages/typescript/indexer_client/src/models/applicationparams.ts +++ b/packages/typescript/indexer_client/src/models/applicationparams.ts @@ -5,11 +5,11 @@ import type { ApplicationStateSchema, TealKeyValueStore } from "./index"; */ export type ApplicationParams = { creator?: string; - "approval-program"?: string; - "clear-state-program"?: string; - "extra-program-pages"?: number; - "local-state-schema"?: ApplicationStateSchema; - "global-state-schema"?: ApplicationStateSchema; - "global-state"?: TealKeyValueStore; - version?: number; + approvalProgram?: string; + clearStateProgram?: string; + extraProgramPages?: bigint; + localStateSchema?: ApplicationStateSchema; + globalStateSchema?: ApplicationStateSchema; + globalState?: TealKeyValueStore; + version?: bigint; }; diff --git a/packages/typescript/indexer_client/src/models/applicationstateschema.ts b/packages/typescript/indexer_client/src/models/applicationstateschema.ts index 80ddaa431..d40cb1f25 100644 --- a/packages/typescript/indexer_client/src/models/applicationstateschema.ts +++ b/packages/typescript/indexer_client/src/models/applicationstateschema.ts @@ -1,4 +1,4 @@ /** * Specifies maximums on the number of each type that may be stored. */ -export type ApplicationStateSchema = { "num-uint": number; "num-byte-slice": number }; +export type ApplicationStateSchema = { numUint: bigint; numByteSlice: bigint }; diff --git a/packages/typescript/indexer_client/src/models/asset.ts b/packages/typescript/indexer_client/src/models/asset.ts index dde90439b..9a6a3a3f9 100644 --- a/packages/typescript/indexer_client/src/models/asset.ts +++ b/packages/typescript/indexer_client/src/models/asset.ts @@ -3,4 +3,4 @@ import type { AssetParams } from "./index"; /** * Specifies both the unique identifier and the parameters for an asset */ -export type Asset = { index: bigint; deleted?: boolean; "created-at-round"?: bigint; "destroyed-at-round"?: bigint; params: AssetParams }; +export type Asset = { index: bigint; deleted?: boolean; createdAtRound?: bigint; destroyedAtRound?: bigint; params: AssetParams }; diff --git a/packages/typescript/indexer_client/src/models/assetholding.ts b/packages/typescript/indexer_client/src/models/assetholding.ts index ec5599a27..8c59e93a2 100644 --- a/packages/typescript/indexer_client/src/models/assetholding.ts +++ b/packages/typescript/indexer_client/src/models/assetholding.ts @@ -6,9 +6,9 @@ */ export type AssetHolding = { amount: bigint; - "asset-id": bigint; - "is-frozen": boolean; + assetId: bigint; + isFrozen: boolean; deleted?: boolean; - "opted-in-at-round"?: bigint; - "opted-out-at-round"?: bigint; + optedInAtRound?: bigint; + optedOutAtRound?: bigint; }; diff --git a/packages/typescript/indexer_client/src/models/assetparams.ts b/packages/typescript/indexer_client/src/models/assetparams.ts index a7a2e4e25..3ff1492fc 100644 --- a/packages/typescript/indexer_client/src/models/assetparams.ts +++ b/packages/typescript/indexer_client/src/models/assetparams.ts @@ -9,17 +9,17 @@ export type AssetParams = { clawback?: string; creator: string; - decimals: number; - "default-frozen"?: boolean; + decimals: bigint; + defaultFrozen?: boolean; freeze?: string; manager?: string; - "metadata-hash"?: string; + metadataHash?: string; name?: string; - "name-b64"?: string; + nameB64?: string; reserve?: string; total: bigint; - "unit-name"?: string; - "unit-name-b64"?: string; + unitName?: string; + unitNameB64?: string; url?: string; - "url-b64"?: string; + urlB64?: string; }; diff --git a/packages/typescript/indexer_client/src/models/block.ts b/packages/typescript/indexer_client/src/models/block.ts index 28a9d93dd..59183605c 100644 --- a/packages/typescript/indexer_client/src/models/block.ts +++ b/packages/typescript/indexer_client/src/models/block.ts @@ -8,22 +8,22 @@ import type { BlockRewards, BlockUpgradeState, BlockUpgradeVote, ParticipationUp */ export type Block = { proposer?: string; - "fees-collected"?: number; - bonus?: number; - "proposer-payout"?: number; - "genesis-hash": string; - "genesis-id": string; - "previous-block-hash": string; + feesCollected?: bigint; + bonus?: bigint; + proposerPayout?: bigint; + genesisHash: string; + genesisId: string; + previousBlockHash: string; rewards?: BlockRewards; round: bigint; seed: string; - "state-proof-tracking"?: StateProofTracking[]; - timestamp: number; + stateProofTracking?: StateProofTracking[]; + timestamp: bigint; transactions?: Transaction[]; - "transactions-root": string; - "transactions-root-sha256": string; - "txn-counter"?: number; - "upgrade-state"?: BlockUpgradeState; - "upgrade-vote"?: BlockUpgradeVote; - "participation-updates"?: ParticipationUpdates; + transactionsRoot: string; + transactionsRootSha256: string; + txnCounter?: bigint; + upgradeState?: BlockUpgradeState; + upgradeVote?: BlockUpgradeVote; + participationUpdates?: ParticipationUpdates; }; diff --git a/packages/typescript/indexer_client/src/models/blockrewards.ts b/packages/typescript/indexer_client/src/models/blockrewards.ts index e460c2776..6a7538e4d 100644 --- a/packages/typescript/indexer_client/src/models/blockrewards.ts +++ b/packages/typescript/indexer_client/src/models/blockrewards.ts @@ -2,10 +2,10 @@ * Fields relating to rewards, */ export type BlockRewards = { - "fee-sink": string; - "rewards-calculation-round": number; - "rewards-level": number; - "rewards-pool": string; - "rewards-rate": number; - "rewards-residue": number; + feeSink: string; + rewardsCalculationRound: bigint; + rewardsLevel: bigint; + rewardsPool: string; + rewardsRate: bigint; + rewardsResidue: bigint; }; diff --git a/packages/typescript/indexer_client/src/models/blockupgradestate.ts b/packages/typescript/indexer_client/src/models/blockupgradestate.ts index c0eee4425..d475773c3 100644 --- a/packages/typescript/indexer_client/src/models/blockupgradestate.ts +++ b/packages/typescript/indexer_client/src/models/blockupgradestate.ts @@ -2,9 +2,9 @@ * Fields relating to a protocol upgrade. */ export type BlockUpgradeState = { - "current-protocol": string; - "next-protocol"?: string; - "next-protocol-approvals"?: number; - "next-protocol-switch-on"?: number; - "next-protocol-vote-before"?: number; + currentProtocol: string; + nextProtocol?: string; + nextProtocolApprovals?: bigint; + nextProtocolSwitchOn?: bigint; + nextProtocolVoteBefore?: bigint; }; diff --git a/packages/typescript/indexer_client/src/models/blockupgradevote.ts b/packages/typescript/indexer_client/src/models/blockupgradevote.ts index 402675a6f..d31a05aae 100644 --- a/packages/typescript/indexer_client/src/models/blockupgradevote.ts +++ b/packages/typescript/indexer_client/src/models/blockupgradevote.ts @@ -1,4 +1,4 @@ /** * Fields relating to voting for a protocol upgrade. */ -export type BlockUpgradeVote = { "upgrade-approve"?: boolean; "upgrade-delay"?: number; "upgrade-propose"?: string }; +export type BlockUpgradeVote = { upgradeApprove?: boolean; upgradeDelay?: bigint; upgradePropose?: string }; diff --git a/packages/typescript/indexer_client/src/models/boxreference.ts b/packages/typescript/indexer_client/src/models/boxreference.ts index fce3cf41d..3d7fba0d8 100644 --- a/packages/typescript/indexer_client/src/models/boxreference.ts +++ b/packages/typescript/indexer_client/src/models/boxreference.ts @@ -1,4 +1,4 @@ /** * BoxReference names a box by its name and the application ID it belongs to. */ -export type BoxReference = { app: number; name: string }; +export type BoxReference = { app: bigint; name: string }; diff --git a/packages/typescript/indexer_client/src/models/evaldelta.ts b/packages/typescript/indexer_client/src/models/evaldelta.ts index a45620482..2d9fe7313 100644 --- a/packages/typescript/indexer_client/src/models/evaldelta.ts +++ b/packages/typescript/indexer_client/src/models/evaldelta.ts @@ -1,4 +1,4 @@ /** * Represents a TEAL value delta. */ -export type EvalDelta = { action: number; bytes?: string; uint?: bigint }; +export type EvalDelta = { action: bigint; bytes?: string; uint?: bigint }; diff --git a/packages/typescript/indexer_client/src/models/hashfactory.ts b/packages/typescript/indexer_client/src/models/hashfactory.ts index 19d640d10..deefd3795 100644 --- a/packages/typescript/indexer_client/src/models/hashfactory.ts +++ b/packages/typescript/indexer_client/src/models/hashfactory.ts @@ -1 +1 @@ -export type HashFactory = { "hash-type"?: number }; +export type HashFactory = { hashType?: bigint }; diff --git a/packages/typescript/indexer_client/src/models/hbprooffields.ts b/packages/typescript/indexer_client/src/models/hbprooffields.ts index f39f0c3da..79c31dc58 100644 --- a/packages/typescript/indexer_client/src/models/hbprooffields.ts +++ b/packages/typescript/indexer_client/src/models/hbprooffields.ts @@ -1,4 +1,4 @@ /** * \[hbprf\] HbProof is a signature using HeartbeatAddress's partkey, thereby showing it is online. */ -export type HbProofFields = { "hb-sig"?: string; "hb-pk"?: string; "hb-pk2"?: string; "hb-pk1sig"?: string; "hb-pk2sig"?: string }; +export type HbProofFields = { hbSig?: string; hbPk?: string; hbPk2?: string; hbPk1sig?: string; hbPk2sig?: string }; diff --git a/packages/typescript/indexer_client/src/models/healthcheck.ts b/packages/typescript/indexer_client/src/models/healthcheck.ts index 6f164901b..b3f107ee4 100644 --- a/packages/typescript/indexer_client/src/models/healthcheck.ts +++ b/packages/typescript/indexer_client/src/models/healthcheck.ts @@ -5,8 +5,8 @@ export type HealthCheck = { version: string; data?: {}; round: bigint; - "is-migrating": boolean; - "db-available": boolean; + isMigrating: boolean; + dbAvailable: boolean; message: string; errors?: string[]; }; diff --git a/packages/typescript/indexer_client/src/models/indexerstateproofmessage.ts b/packages/typescript/indexer_client/src/models/indexerstateproofmessage.ts index a78976c4c..ffcf9dc44 100644 --- a/packages/typescript/indexer_client/src/models/indexerstateproofmessage.ts +++ b/packages/typescript/indexer_client/src/models/indexerstateproofmessage.ts @@ -1,7 +1,7 @@ export type IndexerStateProofMessage = { - "block-headers-commitment"?: string; - "voters-commitment"?: string; - "ln-proven-weight"?: bigint; - "first-attested-round"?: bigint; - "latest-attested-round"?: bigint; + blockHeadersCommitment?: string; + votersCommitment?: string; + lnProvenWeight?: bigint; + firstAttestedRound?: bigint; + latestAttestedRound?: bigint; }; diff --git a/packages/typescript/indexer_client/src/models/lookupaccountapplocalstates.ts b/packages/typescript/indexer_client/src/models/lookupaccountapplocalstates.ts index 4bb6e6edc..3bb4a630a 100644 --- a/packages/typescript/indexer_client/src/models/lookupaccountapplocalstates.ts +++ b/packages/typescript/indexer_client/src/models/lookupaccountapplocalstates.ts @@ -3,4 +3,4 @@ import type { ApplicationLocalState } from "./index"; /** * (empty) */ -export type LookupAccountAppLocalStates = { "apps-local-states": ApplicationLocalState[]; "current-round": number; "next-token"?: string }; +export type LookupAccountAppLocalStates = { appsLocalStates: ApplicationLocalState[]; currentRound: bigint; nextToken?: string }; diff --git a/packages/typescript/indexer_client/src/models/lookupaccountassets.ts b/packages/typescript/indexer_client/src/models/lookupaccountassets.ts index ee28d1c31..dd1d11ba0 100644 --- a/packages/typescript/indexer_client/src/models/lookupaccountassets.ts +++ b/packages/typescript/indexer_client/src/models/lookupaccountassets.ts @@ -3,4 +3,4 @@ import type { AssetHolding } from "./index"; /** * (empty) */ -export type LookupAccountAssets = { "current-round": number; "next-token"?: string; assets: AssetHolding[] }; +export type LookupAccountAssets = { currentRound: bigint; nextToken?: string; assets: AssetHolding[] }; diff --git a/packages/typescript/indexer_client/src/models/lookupaccountbyid.ts b/packages/typescript/indexer_client/src/models/lookupaccountbyid.ts index 3b2305c9a..550103b49 100644 --- a/packages/typescript/indexer_client/src/models/lookupaccountbyid.ts +++ b/packages/typescript/indexer_client/src/models/lookupaccountbyid.ts @@ -3,4 +3,4 @@ import type { Account } from "./index"; /** * (empty) */ -export type LookupAccountById = { account: Account; "current-round": number }; +export type LookupAccountById = { account: Account; currentRound: bigint }; diff --git a/packages/typescript/indexer_client/src/models/lookupaccountcreatedapplications.ts b/packages/typescript/indexer_client/src/models/lookupaccountcreatedapplications.ts index 02cc0fc2a..e2635f2ce 100644 --- a/packages/typescript/indexer_client/src/models/lookupaccountcreatedapplications.ts +++ b/packages/typescript/indexer_client/src/models/lookupaccountcreatedapplications.ts @@ -3,4 +3,4 @@ import type { Application } from "./index"; /** * (empty) */ -export type LookupAccountCreatedApplications = { applications: Application[]; "current-round": number; "next-token"?: string }; +export type LookupAccountCreatedApplications = { applications: Application[]; currentRound: bigint; nextToken?: string }; diff --git a/packages/typescript/indexer_client/src/models/lookupaccountcreatedassets.ts b/packages/typescript/indexer_client/src/models/lookupaccountcreatedassets.ts index 771875fc4..8bb080ea8 100644 --- a/packages/typescript/indexer_client/src/models/lookupaccountcreatedassets.ts +++ b/packages/typescript/indexer_client/src/models/lookupaccountcreatedassets.ts @@ -3,4 +3,4 @@ import type { Asset } from "./index"; /** * (empty) */ -export type LookupAccountCreatedAssets = { assets: Asset[]; "current-round": number; "next-token"?: string }; +export type LookupAccountCreatedAssets = { assets: Asset[]; currentRound: bigint; nextToken?: string }; diff --git a/packages/typescript/indexer_client/src/models/lookupaccounttransactions.ts b/packages/typescript/indexer_client/src/models/lookupaccounttransactions.ts index a7c6ddcf5..89d48611f 100644 --- a/packages/typescript/indexer_client/src/models/lookupaccounttransactions.ts +++ b/packages/typescript/indexer_client/src/models/lookupaccounttransactions.ts @@ -3,4 +3,4 @@ import type { Transaction } from "./index"; /** * (empty) */ -export type LookupAccountTransactions = { "current-round": number; "next-token"?: string; transactions: Transaction[] }; +export type LookupAccountTransactions = { currentRound: bigint; nextToken?: string; transactions: Transaction[] }; diff --git a/packages/typescript/indexer_client/src/models/lookupapplicationbyid.ts b/packages/typescript/indexer_client/src/models/lookupapplicationbyid.ts index 729d684b1..a0f9b9679 100644 --- a/packages/typescript/indexer_client/src/models/lookupapplicationbyid.ts +++ b/packages/typescript/indexer_client/src/models/lookupapplicationbyid.ts @@ -3,4 +3,4 @@ import type { Application } from "./index"; /** * (empty) */ -export type LookupApplicationById = { application?: Application; "current-round": number }; +export type LookupApplicationById = { application?: Application; currentRound: bigint }; diff --git a/packages/typescript/indexer_client/src/models/lookupapplicationlogsbyid.ts b/packages/typescript/indexer_client/src/models/lookupapplicationlogsbyid.ts index 1e6024f24..04085fdea 100644 --- a/packages/typescript/indexer_client/src/models/lookupapplicationlogsbyid.ts +++ b/packages/typescript/indexer_client/src/models/lookupapplicationlogsbyid.ts @@ -3,9 +3,4 @@ import type { ApplicationLogData } from "./index"; /** * (empty) */ -export type LookupApplicationLogsById = { - "application-id": number; - "current-round": number; - "next-token"?: string; - "log-data"?: ApplicationLogData[]; -}; +export type LookupApplicationLogsById = { applicationId: bigint; currentRound: bigint; nextToken?: string; logData?: ApplicationLogData[] }; diff --git a/packages/typescript/indexer_client/src/models/lookupassetbalances.ts b/packages/typescript/indexer_client/src/models/lookupassetbalances.ts index 6ebe8375a..341040430 100644 --- a/packages/typescript/indexer_client/src/models/lookupassetbalances.ts +++ b/packages/typescript/indexer_client/src/models/lookupassetbalances.ts @@ -3,4 +3,4 @@ import type { MiniAssetHolding } from "./index"; /** * (empty) */ -export type LookupAssetBalances = { balances: MiniAssetHolding[]; "current-round": number; "next-token"?: string }; +export type LookupAssetBalances = { balances: MiniAssetHolding[]; currentRound: bigint; nextToken?: string }; diff --git a/packages/typescript/indexer_client/src/models/lookupassetbyid.ts b/packages/typescript/indexer_client/src/models/lookupassetbyid.ts index df3432ba3..6cb7b16f7 100644 --- a/packages/typescript/indexer_client/src/models/lookupassetbyid.ts +++ b/packages/typescript/indexer_client/src/models/lookupassetbyid.ts @@ -3,4 +3,4 @@ import type { Asset } from "./index"; /** * (empty) */ -export type LookupAssetById = { asset: Asset; "current-round": number }; +export type LookupAssetById = { asset: Asset; currentRound: bigint }; diff --git a/packages/typescript/indexer_client/src/models/lookupassettransactions.ts b/packages/typescript/indexer_client/src/models/lookupassettransactions.ts index 26cdcbd25..0e28ed9e5 100644 --- a/packages/typescript/indexer_client/src/models/lookupassettransactions.ts +++ b/packages/typescript/indexer_client/src/models/lookupassettransactions.ts @@ -3,4 +3,4 @@ import type { Transaction } from "./index"; /** * (empty) */ -export type LookupAssetTransactions = { "current-round": number; "next-token"?: string; transactions: Transaction[] }; +export type LookupAssetTransactions = { currentRound: bigint; nextToken?: string; transactions: Transaction[] }; diff --git a/packages/typescript/indexer_client/src/models/lookuptransaction.ts b/packages/typescript/indexer_client/src/models/lookuptransaction.ts index 7412f95bc..3dc7fa0f6 100644 --- a/packages/typescript/indexer_client/src/models/lookuptransaction.ts +++ b/packages/typescript/indexer_client/src/models/lookuptransaction.ts @@ -3,4 +3,4 @@ import type { Transaction } from "./index"; /** * (empty) */ -export type LookupTransaction = { transaction: Transaction; "current-round": number }; +export type LookupTransaction = { transaction: Transaction; currentRound: bigint }; diff --git a/packages/typescript/indexer_client/src/models/merklearrayproof.ts b/packages/typescript/indexer_client/src/models/merklearrayproof.ts index 2440c2e17..f41ad701f 100644 --- a/packages/typescript/indexer_client/src/models/merklearrayproof.ts +++ b/packages/typescript/indexer_client/src/models/merklearrayproof.ts @@ -1,3 +1,3 @@ import type { HashFactory } from "./index"; -export type MerkleArrayProof = { path?: string[]; "hash-factory"?: HashFactory; "tree-depth"?: number }; +export type MerkleArrayProof = { path?: string[]; hashFactory?: HashFactory; treeDepth?: bigint }; diff --git a/packages/typescript/indexer_client/src/models/miniassetholding.ts b/packages/typescript/indexer_client/src/models/miniassetholding.ts index 6bb3543b7..2b446c8fa 100644 --- a/packages/typescript/indexer_client/src/models/miniassetholding.ts +++ b/packages/typescript/indexer_client/src/models/miniassetholding.ts @@ -4,8 +4,8 @@ export type MiniAssetHolding = { address: string; amount: bigint; - "is-frozen": boolean; + isFrozen: boolean; deleted?: boolean; - "opted-in-at-round"?: bigint; - "opted-out-at-round"?: bigint; + optedInAtRound?: bigint; + optedOutAtRound?: bigint; }; diff --git a/packages/typescript/indexer_client/src/models/participationupdates.ts b/packages/typescript/indexer_client/src/models/participationupdates.ts index 614c1407c..bc79c6d50 100644 --- a/packages/typescript/indexer_client/src/models/participationupdates.ts +++ b/packages/typescript/indexer_client/src/models/participationupdates.ts @@ -1,4 +1,4 @@ /** * Participation account data that needs to be checked/acted on by the network. */ -export type ParticipationUpdates = { "expired-participation-accounts"?: string[]; "absent-participation-accounts"?: string[] }; +export type ParticipationUpdates = { expiredParticipationAccounts?: string[]; absentParticipationAccounts?: string[] }; diff --git a/packages/typescript/indexer_client/src/models/searchforaccounts.ts b/packages/typescript/indexer_client/src/models/searchforaccounts.ts index a5dcf8acd..cc5a7d973 100644 --- a/packages/typescript/indexer_client/src/models/searchforaccounts.ts +++ b/packages/typescript/indexer_client/src/models/searchforaccounts.ts @@ -3,4 +3,4 @@ import type { Account } from "./index"; /** * (empty) */ -export type SearchForAccounts = { accounts: Account[]; "current-round": number; "next-token"?: string }; +export type SearchForAccounts = { accounts: Account[]; currentRound: bigint; nextToken?: string }; diff --git a/packages/typescript/indexer_client/src/models/searchforapplicationboxes.ts b/packages/typescript/indexer_client/src/models/searchforapplicationboxes.ts index f17138753..df881d0af 100644 --- a/packages/typescript/indexer_client/src/models/searchforapplicationboxes.ts +++ b/packages/typescript/indexer_client/src/models/searchforapplicationboxes.ts @@ -3,4 +3,4 @@ import type { BoxDescriptor } from "./index"; /** * Box names of an application */ -export type SearchForApplicationBoxes = { "application-id": number; boxes: BoxDescriptor[]; "next-token"?: string }; +export type SearchForApplicationBoxes = { applicationId: bigint; boxes: BoxDescriptor[]; nextToken?: string }; diff --git a/packages/typescript/indexer_client/src/models/searchforapplications.ts b/packages/typescript/indexer_client/src/models/searchforapplications.ts index 5f2f5e43c..e36030879 100644 --- a/packages/typescript/indexer_client/src/models/searchforapplications.ts +++ b/packages/typescript/indexer_client/src/models/searchforapplications.ts @@ -3,4 +3,4 @@ import type { Application } from "./index"; /** * (empty) */ -export type SearchForApplications = { applications: Application[]; "current-round": number; "next-token"?: string }; +export type SearchForApplications = { applications: Application[]; currentRound: bigint; nextToken?: string }; diff --git a/packages/typescript/indexer_client/src/models/searchforassets.ts b/packages/typescript/indexer_client/src/models/searchforassets.ts index 3d237c06c..696b4b840 100644 --- a/packages/typescript/indexer_client/src/models/searchforassets.ts +++ b/packages/typescript/indexer_client/src/models/searchforassets.ts @@ -3,4 +3,4 @@ import type { Asset } from "./index"; /** * (empty) */ -export type SearchForAssets = { assets: Asset[]; "current-round": number; "next-token"?: string }; +export type SearchForAssets = { assets: Asset[]; currentRound: bigint; nextToken?: string }; diff --git a/packages/typescript/indexer_client/src/models/searchforblockheaders.ts b/packages/typescript/indexer_client/src/models/searchforblockheaders.ts index ae1763229..a07b9a1a4 100644 --- a/packages/typescript/indexer_client/src/models/searchforblockheaders.ts +++ b/packages/typescript/indexer_client/src/models/searchforblockheaders.ts @@ -3,4 +3,4 @@ import type { Block } from "./index"; /** * (empty) */ -export type SearchForBlockHeaders = { "current-round": number; "next-token"?: string; blocks: Block[] }; +export type SearchForBlockHeaders = { currentRound: bigint; nextToken?: string; blocks: Block[] }; diff --git a/packages/typescript/indexer_client/src/models/searchfortransactions.ts b/packages/typescript/indexer_client/src/models/searchfortransactions.ts index 65640be82..616cb291f 100644 --- a/packages/typescript/indexer_client/src/models/searchfortransactions.ts +++ b/packages/typescript/indexer_client/src/models/searchfortransactions.ts @@ -3,4 +3,4 @@ import type { Transaction } from "./index"; /** * (empty) */ -export type SearchForTransactions = { "current-round": number; "next-token"?: string; transactions: Transaction[] }; +export type SearchForTransactions = { currentRound: bigint; nextToken?: string; transactions: Transaction[] }; diff --git a/packages/typescript/indexer_client/src/models/stateprooffields.ts b/packages/typescript/indexer_client/src/models/stateprooffields.ts index c583170d8..9202cce7a 100644 --- a/packages/typescript/indexer_client/src/models/stateprooffields.ts +++ b/packages/typescript/indexer_client/src/models/stateprooffields.ts @@ -7,11 +7,11 @@ import type { MerkleArrayProof, StateProofReveal } from "./index"; * crypto/stateproof/structs.go : StateProof */ export type StateProofFields = { - "sig-commit"?: string; - "signed-weight"?: bigint; - "sig-proofs"?: MerkleArrayProof; - "part-proofs"?: MerkleArrayProof; - "salt-version"?: number; + sigCommit?: string; + signedWeight?: bigint; + sigProofs?: MerkleArrayProof; + partProofs?: MerkleArrayProof; + saltVersion?: bigint; reveals?: StateProofReveal[]; - "positions-to-reveal"?: bigint[]; + positionsToReveal?: bigint[]; }; diff --git a/packages/typescript/indexer_client/src/models/stateproofreveal.ts b/packages/typescript/indexer_client/src/models/stateproofreveal.ts index ee36a8fab..f4d30848b 100644 --- a/packages/typescript/indexer_client/src/models/stateproofreveal.ts +++ b/packages/typescript/indexer_client/src/models/stateproofreveal.ts @@ -1,3 +1,3 @@ import type { StateProofParticipant, StateProofSigSlot } from "./index"; -export type StateProofReveal = { position?: bigint; "sig-slot"?: StateProofSigSlot; participant?: StateProofParticipant }; +export type StateProofReveal = { position?: bigint; sigSlot?: StateProofSigSlot; participant?: StateProofParticipant }; diff --git a/packages/typescript/indexer_client/src/models/stateproofsignature.ts b/packages/typescript/indexer_client/src/models/stateproofsignature.ts index 6eff2a95c..394566b18 100644 --- a/packages/typescript/indexer_client/src/models/stateproofsignature.ts +++ b/packages/typescript/indexer_client/src/models/stateproofsignature.ts @@ -1,8 +1,3 @@ import type { MerkleArrayProof } from "./index"; -export type StateProofSignature = { - "falcon-signature"?: string; - "merkle-array-index"?: number; - proof?: MerkleArrayProof; - "verifying-key"?: string; -}; +export type StateProofSignature = { falconSignature?: string; merkleArrayIndex?: bigint; proof?: MerkleArrayProof; verifyingKey?: string }; diff --git a/packages/typescript/indexer_client/src/models/stateproofsigslot.ts b/packages/typescript/indexer_client/src/models/stateproofsigslot.ts index 7c4de01b3..330fc90d2 100644 --- a/packages/typescript/indexer_client/src/models/stateproofsigslot.ts +++ b/packages/typescript/indexer_client/src/models/stateproofsigslot.ts @@ -1,3 +1,3 @@ import type { StateProofSignature } from "./index"; -export type StateProofSigSlot = { signature?: StateProofSignature; "lower-sig-weight"?: bigint }; +export type StateProofSigSlot = { signature?: StateProofSignature; lowerSigWeight?: bigint }; diff --git a/packages/typescript/indexer_client/src/models/stateprooftracking.ts b/packages/typescript/indexer_client/src/models/stateprooftracking.ts index 86ea41947..cdd7e7e79 100644 --- a/packages/typescript/indexer_client/src/models/stateprooftracking.ts +++ b/packages/typescript/indexer_client/src/models/stateprooftracking.ts @@ -1 +1 @@ -export type StateProofTracking = { type?: bigint; "voters-commitment"?: string; "online-total-weight"?: number; "next-round"?: number }; +export type StateProofTracking = { type?: bigint; votersCommitment?: string; onlineTotalWeight?: bigint; nextRound?: bigint }; diff --git a/packages/typescript/indexer_client/src/models/stateproofverifier.ts b/packages/typescript/indexer_client/src/models/stateproofverifier.ts index e8a56c534..0aa06273b 100644 --- a/packages/typescript/indexer_client/src/models/stateproofverifier.ts +++ b/packages/typescript/indexer_client/src/models/stateproofverifier.ts @@ -1 +1 @@ -export type StateProofVerifier = { commitment?: string; "key-lifetime"?: bigint }; +export type StateProofVerifier = { commitment?: string; keyLifetime?: bigint }; diff --git a/packages/typescript/indexer_client/src/models/stateschema.ts b/packages/typescript/indexer_client/src/models/stateschema.ts index 30effa44f..4a2bbf42f 100644 --- a/packages/typescript/indexer_client/src/models/stateschema.ts +++ b/packages/typescript/indexer_client/src/models/stateschema.ts @@ -1,4 +1,4 @@ /** * 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. */ -export type StateSchema = { "num-uint": number; "num-byte-slice": number }; +export type StateSchema = { numUint: bigint; numByteSlice: bigint }; diff --git a/packages/typescript/indexer_client/src/models/tealvalue.ts b/packages/typescript/indexer_client/src/models/tealvalue.ts index c98f15d78..84e3993af 100644 --- a/packages/typescript/indexer_client/src/models/tealvalue.ts +++ b/packages/typescript/indexer_client/src/models/tealvalue.ts @@ -1,4 +1,4 @@ /** * Represents a TEAL value. */ -export type TealValue = { type: number; bytes: string; uint: bigint }; +export type TealValue = { type: bigint; bytes: string; uint: bigint }; diff --git a/packages/typescript/indexer_client/src/models/transaction.ts b/packages/typescript/indexer_client/src/models/transaction.ts index c84ef92a7..c44611627 100644 --- a/packages/typescript/indexer_client/src/models/transaction.ts +++ b/packages/typescript/indexer_client/src/models/transaction.ts @@ -20,39 +20,39 @@ import type { * data/transactions/transaction.go : Transaction */ export type Transaction = { - "application-transaction"?: TransactionApplication; - "asset-config-transaction"?: TransactionAssetConfig; - "asset-freeze-transaction"?: TransactionAssetFreeze; - "asset-transfer-transaction"?: TransactionAssetTransfer; - "state-proof-transaction"?: TransactionStateProof; - "heartbeat-transaction"?: TransactionHeartbeat; - "auth-addr"?: string; - "close-rewards"?: number; - "closing-amount"?: bigint; - "confirmed-round"?: bigint; - "created-application-index"?: number; - "created-asset-index"?: number; + applicationTransaction?: TransactionApplication; + assetConfigTransaction?: TransactionAssetConfig; + assetFreezeTransaction?: TransactionAssetFreeze; + assetTransferTransaction?: TransactionAssetTransfer; + stateProofTransaction?: TransactionStateProof; + heartbeatTransaction?: TransactionHeartbeat; + authAddr?: string; + closeRewards?: bigint; + closingAmount?: bigint; + confirmedRound?: bigint; + createdApplicationIndex?: bigint; + createdAssetIndex?: bigint; fee: bigint; - "first-valid": number; - "genesis-hash"?: string; - "genesis-id"?: string; + firstValid: bigint; + genesisHash?: string; + genesisId?: string; group?: string; id?: string; - "intra-round-offset"?: number; - "keyreg-transaction"?: TransactionKeyreg; - "last-valid": number; + intraRoundOffset?: bigint; + keyregTransaction?: TransactionKeyreg; + lastValid: bigint; lease?: string; note?: string; - "payment-transaction"?: TransactionPayment; - "receiver-rewards"?: number; - "rekey-to"?: string; - "round-time"?: number; + paymentTransaction?: TransactionPayment; + receiverRewards?: bigint; + rekeyTo?: string; + roundTime?: bigint; sender: string; - "sender-rewards"?: number; + senderRewards?: bigint; signature?: TransactionSignature; - "tx-type": "pay" | "keyreg" | "acfg" | "axfer" | "afrz" | "appl" | "stpf" | "hb"; - "local-state-delta"?: AccountStateDelta[]; - "global-state-delta"?: StateDelta; + txType: "pay" | "keyreg" | "acfg" | "axfer" | "afrz" | "appl" | "stpf" | "hb"; + localStateDelta?: AccountStateDelta[]; + globalStateDelta?: StateDelta; logs?: string[]; - "inner-txns"?: Transaction[]; + innerTxns?: Transaction[]; }; diff --git a/packages/typescript/indexer_client/src/models/transactionapplication.ts b/packages/typescript/indexer_client/src/models/transactionapplication.ts index a97b8e24c..24b61e63f 100644 --- a/packages/typescript/indexer_client/src/models/transactionapplication.ts +++ b/packages/typescript/indexer_client/src/models/transactionapplication.ts @@ -7,17 +7,17 @@ import type { BoxReference, OnCompletion, StateSchema } from "./index"; * data/transactions/application.go : ApplicationCallTxnFields */ export type TransactionApplication = { - "application-id": number; - "on-completion": OnCompletion; - "application-args"?: string[]; + applicationId: bigint; + onCompletion: OnCompletion; + applicationArgs?: string[]; accounts?: string[]; - "box-references"?: BoxReference[]; - "foreign-apps"?: number[]; - "foreign-assets"?: number[]; - "local-state-schema"?: StateSchema; - "global-state-schema"?: StateSchema; - "approval-program"?: string; - "clear-state-program"?: string; - "extra-program-pages"?: number; - "reject-version"?: number; + boxReferences?: BoxReference[]; + foreignApps?: bigint[]; + foreignAssets?: bigint[]; + localStateSchema?: StateSchema; + globalStateSchema?: StateSchema; + approvalProgram?: string; + clearStateProgram?: string; + extraProgramPages?: bigint; + rejectVersion?: bigint; }; diff --git a/packages/typescript/indexer_client/src/models/transactionassetconfig.ts b/packages/typescript/indexer_client/src/models/transactionassetconfig.ts index 92916045b..3562c7b66 100644 --- a/packages/typescript/indexer_client/src/models/transactionassetconfig.ts +++ b/packages/typescript/indexer_client/src/models/transactionassetconfig.ts @@ -10,4 +10,4 @@ import type { AssetParams } from "./index"; * Definition: * data/transactions/asset.go : AssetConfigTxnFields */ -export type TransactionAssetConfig = { "asset-id"?: bigint; params?: AssetParams }; +export type TransactionAssetConfig = { assetId?: bigint; params?: AssetParams }; diff --git a/packages/typescript/indexer_client/src/models/transactionassetfreeze.ts b/packages/typescript/indexer_client/src/models/transactionassetfreeze.ts index 0628282bf..d576f5c6f 100644 --- a/packages/typescript/indexer_client/src/models/transactionassetfreeze.ts +++ b/packages/typescript/indexer_client/src/models/transactionassetfreeze.ts @@ -4,4 +4,4 @@ * Definition: * data/transactions/asset.go : AssetFreezeTxnFields */ -export type TransactionAssetFreeze = { address: string; "asset-id": bigint; "new-freeze-status": boolean }; +export type TransactionAssetFreeze = { address: string; assetId: bigint; newFreezeStatus: boolean }; diff --git a/packages/typescript/indexer_client/src/models/transactionassettransfer.ts b/packages/typescript/indexer_client/src/models/transactionassettransfer.ts index eb5afffbe..adf87560f 100644 --- a/packages/typescript/indexer_client/src/models/transactionassettransfer.ts +++ b/packages/typescript/indexer_client/src/models/transactionassettransfer.ts @@ -6,9 +6,9 @@ */ export type TransactionAssetTransfer = { amount: bigint; - "asset-id": bigint; - "close-amount"?: bigint; - "close-to"?: string; + assetId: bigint; + closeAmount?: bigint; + closeTo?: string; receiver: string; sender?: string; }; diff --git a/packages/typescript/indexer_client/src/models/transactionheartbeat.ts b/packages/typescript/indexer_client/src/models/transactionheartbeat.ts index 4d1037cb6..b5468a326 100644 --- a/packages/typescript/indexer_client/src/models/transactionheartbeat.ts +++ b/packages/typescript/indexer_client/src/models/transactionheartbeat.ts @@ -6,10 +6,4 @@ import type { HbProofFields } from "./index"; * Definition: * data/transactions/heartbeat.go : HeartbeatTxnFields */ -export type TransactionHeartbeat = { - "hb-address": string; - "hb-proof": HbProofFields; - "hb-seed": string; - "hb-vote-id": string; - "hb-key-dilution": bigint; -}; +export type TransactionHeartbeat = { hbAddress: string; hbProof: HbProofFields; hbSeed: string; hbVoteId: string; hbKeyDilution: bigint }; diff --git a/packages/typescript/indexer_client/src/models/transactionkeyreg.ts b/packages/typescript/indexer_client/src/models/transactionkeyreg.ts index fd69a8ca4..bd4a3dbe8 100644 --- a/packages/typescript/indexer_client/src/models/transactionkeyreg.ts +++ b/packages/typescript/indexer_client/src/models/transactionkeyreg.ts @@ -5,11 +5,11 @@ * data/transactions/keyreg.go : KeyregTxnFields */ export type TransactionKeyreg = { - "non-participation"?: boolean; - "selection-participation-key"?: string; - "vote-first-valid"?: bigint; - "vote-key-dilution"?: bigint; - "vote-last-valid"?: bigint; - "vote-participation-key"?: string; - "state-proof-key"?: string; + nonParticipation?: boolean; + selectionParticipationKey?: string; + voteFirstValid?: bigint; + voteKeyDilution?: bigint; + voteLastValid?: bigint; + voteParticipationKey?: string; + stateProofKey?: string; }; diff --git a/packages/typescript/indexer_client/src/models/transactionpayment.ts b/packages/typescript/indexer_client/src/models/transactionpayment.ts index 69370a25f..3336d2c7d 100644 --- a/packages/typescript/indexer_client/src/models/transactionpayment.ts +++ b/packages/typescript/indexer_client/src/models/transactionpayment.ts @@ -4,4 +4,4 @@ * Definition: * data/transactions/payment.go : PaymentTxnFields */ -export type TransactionPayment = { amount: bigint; "close-amount"?: number; "close-remainder-to"?: string; receiver: string }; +export type TransactionPayment = { amount: bigint; closeAmount?: bigint; closeRemainderTo?: string; receiver: string }; diff --git a/packages/typescript/indexer_client/src/models/transactionsignaturelogicsig.ts b/packages/typescript/indexer_client/src/models/transactionsignaturelogicsig.ts index d708af8e5..8225eb602 100644 --- a/packages/typescript/indexer_client/src/models/transactionsignaturelogicsig.ts +++ b/packages/typescript/indexer_client/src/models/transactionsignaturelogicsig.ts @@ -9,6 +9,6 @@ import type { TransactionSignatureMultisig } from "./index"; export type TransactionSignatureLogicsig = { args?: string[]; logic: string; - "multisig-signature"?: TransactionSignatureMultisig; + multisigSignature?: TransactionSignatureMultisig; signature?: string; }; diff --git a/packages/typescript/indexer_client/src/models/transactionsignaturemultisig.ts b/packages/typescript/indexer_client/src/models/transactionsignaturemultisig.ts index 7bf1aca48..fd46723dc 100644 --- a/packages/typescript/indexer_client/src/models/transactionsignaturemultisig.ts +++ b/packages/typescript/indexer_client/src/models/transactionsignaturemultisig.ts @@ -8,6 +8,6 @@ import type { TransactionSignatureMultisigSubsignature } from "./index"; */ export type TransactionSignatureMultisig = { subsignature?: TransactionSignatureMultisigSubsignature[]; - threshold?: number; - version?: number; + threshold?: bigint; + version?: bigint; }; diff --git a/packages/typescript/indexer_client/src/models/transactionsignaturemultisigsubsignature.ts b/packages/typescript/indexer_client/src/models/transactionsignaturemultisigsubsignature.ts index 75d8df5f6..9043a3d3f 100644 --- a/packages/typescript/indexer_client/src/models/transactionsignaturemultisigsubsignature.ts +++ b/packages/typescript/indexer_client/src/models/transactionsignaturemultisigsubsignature.ts @@ -1 +1 @@ -export type TransactionSignatureMultisigSubsignature = { "public-key"?: string; signature?: string }; +export type TransactionSignatureMultisigSubsignature = { publicKey?: string; signature?: string }; diff --git a/packages/typescript/indexer_client/src/models/transactionstateproof.ts b/packages/typescript/indexer_client/src/models/transactionstateproof.ts index dbf6e0235..28492a22a 100644 --- a/packages/typescript/indexer_client/src/models/transactionstateproof.ts +++ b/packages/typescript/indexer_client/src/models/transactionstateproof.ts @@ -6,4 +6,4 @@ import type { IndexerStateProofMessage, StateProofFields } from "./index"; * Definition: * data/transactions/stateproof.go : StateProofTxnFields */ -export type TransactionStateProof = { "state-proof-type"?: bigint; "state-proof"?: StateProofFields; message?: IndexerStateProofMessage }; +export type TransactionStateProof = { stateProofType?: bigint; stateProof?: StateProofFields; message?: IndexerStateProofMessage }; diff --git a/packages/typescript/indexer_client/tests/config.ts b/packages/typescript/indexer_client/tests/config.ts new file mode 100644 index 000000000..eef43526b --- /dev/null +++ b/packages/typescript/indexer_client/tests/config.ts @@ -0,0 +1,131 @@ +import { describe } from "bun:test"; +import algosdk from "algosdk"; + +export interface IndexerTestConfig { + indexerBaseUrl: string; + indexerApiToken?: string; +} + +export interface CreatedAssetInfo { + assetId: number; + txId: string; +} + +export interface CreatedAppInfo { + appId: number; + txId: string; +} + +export async function getSenderMnemonic(): Promise { + if (process.env.SENDER_MNEMONIC) return process.env.SENDER_MNEMONIC; + // Try to derive from local KMD defaults + const kmdBase = process.env.KMD_BASE_URL ?? "http://localhost:4002"; + const kmdToken = process.env.KMD_API_TOKEN ?? "a".repeat(64); + const url = new URL(kmdBase); + const server = `${url.protocol}//${url.hostname}`; + const port = Number(url.port || 4002); + const kmd = new algosdk.Kmd(kmdToken, server, port); + const wallets = await kmd.listWallets(); + const wallet = wallets.wallets.find((w: any) => w.name === "unencrypted-default-wallet") ?? wallets.wallets[0]; + if (!wallet) throw new Error("No KMD wallet found on localnet"); + const handle = await kmd.initWalletHandle(wallet.id, ""); + try { + const keys = await kmd.listKeys(handle.wallet_handle_token); + let address: string | undefined = keys.addresses[0]; + if (!address) { + const gen = await kmd.generateKey(handle.wallet_handle_token); + address = gen.address; + } + const exported = await kmd.exportKey(handle.wallet_handle_token, "", address!); + const sk = new Uint8Array(exported.private_key); + return algosdk.secretKeyToMnemonic(sk); + } finally { + await kmd.releaseWalletHandle(handle.wallet_handle_token); + } +} + +/** + * Creates a small dummy asset on localnet and waits for confirmation. + * Returns the created asset id. Uses first wallet account (from KMD) or provided mnemonic via env. + */ +export async function createDummyAsset(): Promise { + const mnemonic = await getSenderMnemonic(); + const { addr, sk } = algosdk.mnemonicToSecretKey(mnemonic); + + const algod = new algosdk.Algodv2("a".repeat(64), "http://localhost", 4001); + const sp = await algod.getTransactionParams().do(); + + const txn = algosdk.makeAssetCreateTxnWithSuggestedParamsFromObject({ + sender: addr, + assetName: "DummyAsset", + unitName: "DUM", + total: 1_000_000, + decimals: 0, + defaultFrozen: false, + manager: addr, + reserve: addr, + freeze: addr, + clawback: addr, + suggestedParams: sp, + }); + + const signed = txn.signTxn(sk); + await algod.sendRawTransaction(signed).do(); + const txId = txn.txID(); + const pending = await algosdk.waitForConfirmation(algod, txId, 10); + const assetId = pending["asset-index"] as number; + return { assetId, txId }; +} + +/** + * Creates a minimal dummy application with no-op approval & clear programs. + * Returns the created app id. + */ +export async function createDummyApp(): Promise { + const mnemonic = await getSenderMnemonic(); + const { addr, sk } = algosdk.mnemonicToSecretKey(mnemonic); + + const algod = new algosdk.Algodv2("a".repeat(64), "http://localhost", 4001); + const sp = await algod.getTransactionParams().do(); + + const approvalProgramSource = "#pragma version 8\nint 1"; + const clearProgramSource = "#pragma version 8\nint 1"; + + const compile = async (source: string) => { + const res = await algod.compile(source).do(); + return new Uint8Array(Buffer.from(res.result, "base64")); + }; + + const approvalProgram = await compile(approvalProgramSource); + const clearProgram = await compile(clearProgramSource); + + const txn = algosdk.makeApplicationCreateTxnFromObject({ + sender: addr, + approvalProgram, + clearProgram, + numLocalInts: 0, + numLocalByteSlices: 0, + numGlobalInts: 1, + numGlobalByteSlices: 1, + onComplete: algosdk.OnApplicationComplete.NoOpOC, + suggestedParams: sp, + }); + + const signed = txn.signTxn(sk); + await algod.sendRawTransaction(signed).do(); + const txId = txn.txID(); + const pending = await algosdk.waitForConfirmation(algod, txId, 10); + const appId = pending["application-index"] as number; + return { appId, txId }; +} + +export function getIndexerEnv(): IndexerTestConfig { + return { + indexerBaseUrl: process.env.INDEXER_BASE_URL ?? "http://localhost:8980", + indexerApiToken: process.env.INDEXER_API_TOKEN ?? "a".repeat(64), + }; +} + +export function maybeDescribe(name: string, fn: (env: IndexerTestConfig) => void) { + describe(name, () => fn(getIndexerEnv())); +} diff --git a/packages/typescript/indexer_client/tests/generated/smoke.generated.spec.ts b/packages/typescript/indexer_client/tests/generated/smoke.generated.spec.ts deleted file mode 100644 index d2a0f9e98..000000000 --- a/packages/typescript/indexer_client/tests/generated/smoke.generated.spec.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* AUTO-GENERATED FILE - DO NOT EDIT DIRECTLY. - * This smoke test is generated by ts_oas_generator. - * Location: tests/generated/smoke.generated.spec.ts - */ -import { describe, expect, it } from "vitest"; -import { Client } from "../src/client"; - -const BASE = "http://localhost/"; - -declare global { - // eslint-disable-next-line no-var, vars-on-top - var fetch: any; -} - -describe("JSON BigInt parsing", () => { - it("parses bigint values using json-bigint", async () => { - const big = "18446744073709551615"; // > Number.MAX_SAFE_INTEGER - global.fetch = async () => ({ - ok: true, - headers: new Map([["content-type", "application/json"]]), - text: async () => JSON.stringify({ value: big }), - arrayBuffer: async () => new ArrayBuffer(0), - }); - - const client = new Client({ BASE }); - // Directly use request core to keep template-agnostic - const res = await client.request.request<{ value: bigint }>({ method: "GET", url: "/foo" }); - expect(typeof res.value).toBe("bigint"); - }); -}); - -describe("Msgpack binary response", () => { - it("decodes msgpack into structured data", async () => { - // eslint-disable-next-line @typescript-eslint/no-var-requires - const { encode } = require("algo-msgpack-with-bigint"); - const msg = { ok: 1n, small: 2 }; - const bytes: Uint8Array = encode(msg); - global.fetch = async () => ({ - ok: true, - headers: new Map([["content-type", "application/msgpack"]]), - text: async () => "", - arrayBuffer: async () => bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength), - }); - - const client = new Client({ BASE }); - const res = await client.request.request<{ ok: bigint | number; small: number }>({ method: "GET", url: "/foo", expectBinary: true }); - expect(res).toHaveProperty("ok"); - }); -}); diff --git a/packages/typescript/indexer_client/tests/helpers/env.ts b/packages/typescript/indexer_client/tests/helpers/env.ts deleted file mode 100644 index 0723ae150..000000000 --- a/packages/typescript/indexer_client/tests/helpers/env.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { describe } from "vitest"; - -export interface IndexerEnvConfig { - indexerBaseUrl: string; - indexerApiToken?: string; -} - -export function getIndexerEnv(): IndexerEnvConfig { - return { - indexerBaseUrl: process.env.INDEXER_BASE_URL ?? "http://localhost:8980", - // Default token for localnet (if required by reverse proxy) - indexerApiToken: process.env.INDEXER_API_TOKEN ?? "a".repeat(64), - }; -} - -export function maybeDescribe(name: string, fn: (env: IndexerEnvConfig) => void) { - describe(name, () => fn(getIndexerEnv())); -} diff --git a/packages/typescript/indexer_client/tests/helpers/wait.ts b/packages/typescript/indexer_client/tests/helpers/wait.ts deleted file mode 100644 index cfffdd399..000000000 --- a/packages/typescript/indexer_client/tests/helpers/wait.ts +++ /dev/null @@ -1,16 +0,0 @@ -export async function waitFor( - fn: () => Promise, - predicate: (v: T) => boolean, - opts?: { timeoutMs?: number; intervalMs?: number }, -): Promise { - const timeoutMs = opts?.timeoutMs ?? 10_000; - const intervalMs = opts?.intervalMs ?? 500; - const start = Date.now(); - // eslint-disable-next-line no-constant-condition - while (true) { - const v = await fn(); - if (predicate(v)) return v; - if (Date.now() - start > timeoutMs) throw new Error("waitFor: timeout"); - await new Promise((r) => setTimeout(r, intervalMs)); - } -} diff --git a/packages/typescript/indexer_client/tests/searchApplications.spec.ts b/packages/typescript/indexer_client/tests/searchApplications.spec.ts new file mode 100644 index 000000000..08a839ee7 --- /dev/null +++ b/packages/typescript/indexer_client/tests/searchApplications.spec.ts @@ -0,0 +1,79 @@ +import { expect, it } from "bun:test"; +import { IndexerClient } from "../src/client"; +import { maybeDescribe } from "./config"; + +maybeDescribe("Indexer searchApplications", (env) => { + it("searches for applications", async () => { + const client = new IndexerClient({ + BASE: env.indexerBaseUrl, + INT_DECODING: "bigint", + HEADERS: env.indexerApiToken ? { "X-Algo-API-Token": env.indexerApiToken } : undefined, + }); + + const res = await client.api.searchForApplications({ limit: 5 }); + + expect(res).toHaveProperty("applications"); + expect(Array.isArray(res.applications)).toBe(true); + + if (res.applications && res.applications.length > 0) { + const app = res.applications[0]; + expect(app).toHaveProperty("id"); + expect(app).toHaveProperty("params"); + + const params = app.params as any; + expect(params).toHaveProperty("creator"); + expect(params).toHaveProperty("approvalProgram"); + expect(params).toHaveProperty("clearStateProgram"); + } + }, 30_000); + + it("searches for a specific application by ID", async () => { + const client = new IndexerClient({ + BASE: env.indexerBaseUrl, + INT_DECODING: "bigint", + HEADERS: env.indexerApiToken ? { "X-Algo-API-Token": env.indexerApiToken } : undefined, + }); + + const searchRes = await client.api.searchForApplications({ limit: 1 }); + + if (searchRes.applications && searchRes.applications.length > 0) { + const appId = searchRes.applications[0].id; + + const res = await client.api.searchForApplications({ applicationId: appId }); + + expect(res).toHaveProperty("applications"); + expect(res.applications).toHaveLength(1); + expect(res.applications![0].id).toBe(appId); + } else { + console.log("No applications found in indexer, skipping specific ID test"); + } + }, 30_000); + + it("searches applications with pagination", async () => { + const client = new IndexerClient({ + BASE: env.indexerBaseUrl, + INT_DECODING: "bigint", + HEADERS: env.indexerApiToken ? { "X-Algo-API-Token": env.indexerApiToken } : undefined, + }); + + const firstPage = await client.api.searchForApplications({ limit: 2 }); + + expect(firstPage).toHaveProperty("applications"); + + if (firstPage["nextToken"]) { + const secondPage = await client.api.searchForApplications({ + limit: 2, + next: firstPage["nextToken"] as string, + }); + + expect(secondPage).toHaveProperty("applications"); + + if (firstPage.applications?.length && secondPage.applications?.length) { + const firstIds = firstPage.applications.map((a) => a.id); + const secondIds = secondPage.applications.map((a) => a.id); + + expect(firstIds).not.toEqual(secondIds); + } + } + }, 30_000); +}); diff --git a/packages/typescript/indexer_client/tests/searchTransactions.spec.ts b/packages/typescript/indexer_client/tests/searchTransactions.spec.ts index 4bc418884..4cf91ec9a 100644 --- a/packages/typescript/indexer_client/tests/searchTransactions.spec.ts +++ b/packages/typescript/indexer_client/tests/searchTransactions.spec.ts @@ -1,11 +1,12 @@ -import { expect, it } from "vitest"; -import { Client } from "../src/client"; -import { maybeDescribe } from "./helpers/env"; +import { expect, it } from "bun:test"; +import { IndexerClient } from "../src/client"; +import { maybeDescribe } from "./config"; maybeDescribe("Indexer searchTransactions", (env) => { it("searches for recent transactions", async () => { - const client = new Client({ + const client = new IndexerClient({ BASE: env.indexerBaseUrl, + INT_DECODING: "bigint", HEADERS: env.indexerApiToken ? { "X-Algo-API-Token": env.indexerApiToken } : undefined, }); const res = await client.api.searchForTransactions({ limit: 5 }); diff --git a/packages/typescript/indexer_client/tests/smoke.spec.ts b/packages/typescript/indexer_client/tests/smoke.spec.ts deleted file mode 100644 index c19a27e89..000000000 --- a/packages/typescript/indexer_client/tests/smoke.spec.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { describe, expect, it } from "vitest"; -import { Client } from "../src/client"; - -const BASE = "http://localhost/"; - -declare global { - // eslint-disable-next-line no-var, vars-on-top - var fetch: any; -} - -describe("JSON BigInt parsing", () => { - it("parses bigint values using json-bigint", async () => { - const big = "18446744073709551615"; // > Number.MAX_SAFE_INTEGER - global.fetch = async () => ({ - ok: true, - headers: new Map([["content-type", "application/json"]]), - text: async () => JSON.stringify({ value: big }), - arrayBuffer: async () => new ArrayBuffer(0), - }); - - const client = new Client({ BASE, INT_DECODING: "bigint" }); - // Directly use request core to keep template-agnostic - const res = await client.request.request<{ value: bigint }>({ method: "GET", url: "/foo" }); - expect(typeof res.value).toBe("bigint"); - }); -}); - -describe("Msgpack binary response", () => { - it("decodes msgpack into structured data", async () => { - // eslint-disable-next-line @typescript-eslint/no-var-requires - const { encode } = require("algo-msgpack-with-bigint"); - const payload = { ok: 1n, text: "hi" }; - const bytes: Uint8Array = encode(payload); - global.fetch = async () => ({ - ok: true, - headers: new Map([["content-type", "application/msgpack"]]), - text: async () => "", - arrayBuffer: async () => bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength), - }); - - const client = new Client({ BASE }); - const res = await client.request.request<{ ok: bigint | number; text: string }>({ method: "GET", url: "/foo", expectBinary: true }); - expect(res).toHaveProperty("ok"); - expect(res).toHaveProperty("text", "hi"); - }); -}); diff --git a/packages/typescript/indexer_client/tests/src/client.ts b/packages/typescript/indexer_client/tests/src/client.ts deleted file mode 100644 index 4b25d837e..000000000 --- a/packages/typescript/indexer_client/tests/src/client.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { OpenAPIConfig } from "../../src/core/OpenAPI"; -import { Client as BaseClient } from "../../src/client"; - -export * from "../../src/client"; - -export class Client extends BaseClient { - constructor(config: OpenAPIConfig) { - super({ INT_DECODING: config.INT_DECODING ?? "bigint", ...config }); - } -} diff --git a/tools/api_tools/src/main.rs b/tools/api_tools/src/main.rs index 2e34206cf..3bfa43755 100644 --- a/tools/api_tools/src/main.rs +++ b/tools/api_tools/src/main.rs @@ -95,14 +95,13 @@ fn run( } fn execute_command(command: &Commands) -> Result<()> { - fn clean_ts_package(rel_dir: &str) -> Result<()> { + fn clean_ts_package_with_preserve(rel_dir: &str, preserve: &[&str]) -> Result<()> { let root = get_repo_root(); let pkg_dir = root.join(rel_dir); if !pkg_dir.exists() { return Ok(()); } - let preserve: Vec<&str> = vec!["tests", "node_modules"]; for entry in fs::read_dir(&pkg_dir)? { let entry = entry?; let name = entry.file_name(); @@ -121,6 +120,10 @@ fn execute_command(command: &Commands) -> Result<()> { } Ok(()) } + fn clean_ts_package(rel_dir: &str) -> Result<()> { + let default_preserve: &[&str] = &["tests", "node_modules"]; + clean_ts_package_with_preserve(rel_dir, default_preserve) + } match command { Commands::TestOas => { run("uv run pytest", Some(Path::new("api/oas_generator")), None)?; @@ -226,6 +229,12 @@ fn execute_command(command: &Commands) -> Result<()> { Some(Path::new("packages/typescript/algod_client")), None, )?; + // Install dependencies + run( + "bun install", + Some(Path::new("packages/typescript/algod_client")), + None, + )?; // Build the generated package run( "bun run build", @@ -248,6 +257,12 @@ fn execute_command(command: &Commands) -> Result<()> { Some(Path::new("packages/typescript/indexer_client")), None, )?; + // Install dependencies + run( + "bun install", + Some(Path::new("packages/typescript/indexer_client")), + None, + )?; // Build the generated package run( "bun run build", @@ -281,6 +296,17 @@ fn execute_command(command: &Commands) -> Result<()> { Some(Path::new("packages/typescript/indexer_client")), None, )?; + // Install dependencies for both packages + run( + "bun install", + Some(Path::new("packages/typescript/algod_client")), + None, + )?; + run( + "bun install", + Some(Path::new("packages/typescript/indexer_client")), + None, + )?; // Build both packages run( "bun run build", From f39ef87bf8cf20e9f5380261edb8d1aa8b611811 Mon Sep 17 00:00:00 2001 From: Altynbek Orumbayev Date: Tue, 9 Sep 2025 22:15:28 +0200 Subject: [PATCH 3/4] refactor: code cleanup, docstrings; temporary duplicate of SignedTransaction from utils --- api/oas_generator/ts_oas_generator/cli.py | 13 +- .../ts_oas_generator/constants.py | 210 ++++ .../ts_oas_generator/generator/filters.py | 132 +- .../generator/template_engine.py | 1075 ++++++++++------- .../ts_oas_generator/parser/__init__.py | 5 + .../ts_oas_generator/parser/oas_parser.py | 49 + .../templates/apis/service.ts.j2 | 30 +- .../templates/base/README.md.j2 | 8 +- .../templates/base/package.json.j2 | 1 + .../base/src/core/BaseHttpRequest.ts.j2 | 1 - .../templates/base/src/core/msgpack.ts.j2 | 27 +- .../templates/base/src/core/request.ts.j2 | 3 +- .../templates/base/src/index.ts.j2 | 2 +- .../ts_oas_generator/templates/client.ts.j2 | 7 +- .../models/algokitsignedtransaction.ts.j2 | 277 +++++ .../templates/models/index.ts.j2 | 4 + packages/typescript/algod_client/README.md | 6 +- packages/typescript/algod_client/bun.lock | 9 + packages/typescript/algod_client/package.json | 1 + .../algod_client/src/apis/api.service.ts | 170 ++- .../typescript/algod_client/src/client.ts | 7 +- .../algod_client/src/core/BaseHttpRequest.ts | 1 - .../algod_client/src/core/msgpack.ts | 5 + .../algod_client/src/core/request.ts | 3 +- .../algod_client/src/models/abortcatchup.ts | 7 +- .../algod_client/src/models/account.ts | 115 ++ .../models/accountapplicationinformation.ts | 12 +- .../src/models/accountassetholding.ts | 5 +- .../src/models/accountassetinformation.ts | 12 +- .../src/models/accountassetsinformation.ts | 16 +- .../src/models/accountparticipation.ts | 23 + .../src/models/accountstatedelta.ts | 5 +- .../src/models/addparticipationkey.ts | 10 +- .../src/models/algokitsignedtransaction.ts | 277 +++++ .../algod_client/src/models/appcalllogs.ts | 17 +- .../algod_client/src/models/application.ts | 8 +- .../src/models/applicationinitialstates.ts | 7 + .../src/models/applicationkvstorage.ts | 12 +- .../src/models/applicationlocalreference.ts | 12 +- .../src/models/applicationlocalstate.ts | 9 +- .../src/models/applicationparams.ts | 19 + .../src/models/applicationstateoperation.ts | 23 +- .../src/models/applicationstateschema.ts | 12 +- .../algod_client/src/models/asset.ts | 8 +- .../algod_client/src/models/assetholding.ts | 17 +- .../src/models/assetholdingreference.ts | 12 +- .../algod_client/src/models/assetparams.ts | 59 + .../algod_client/src/models/avmkeyvalue.ts | 5 +- .../algod_client/src/models/avmvalue.ts | 17 +- .../typescript/algod_client/src/models/box.ts | 17 +- .../algod_client/src/models/boxdescriptor.ts | 7 +- .../algod_client/src/models/boxreference.ts | 12 +- .../algod_client/src/models/buildversion.ts | 9 +- .../src/models/debugsettingsprof.ts | 12 +- .../algod_client/src/models/dryrunrequest.ts | 16 +- .../algod_client/src/models/dryrunsource.ts | 10 +- .../algod_client/src/models/dryrunstate.ts | 19 +- .../src/models/dryruntxnresult.ts | 15 + .../algod_client/src/models/errorresponse.ts | 5 +- .../algod_client/src/models/evaldelta.ts | 17 +- .../src/models/evaldeltakeyvalue.ts | 5 +- .../src/models/genesisallocation.ts | 11 +- .../src/models/getapplicationboxes.ts | 7 +- .../algod_client/src/models/getblock.ts | 15 +- .../algod_client/src/models/getblockhash.ts | 10 +- .../algod_client/src/models/getblocklogs.ts | 7 +- .../src/models/getblocktimestampoffset.ts | 10 +- .../algod_client/src/models/getblocktxids.ts | 10 +- .../src/models/getpendingtransactions.ts | 14 +- .../models/getpendingtransactionsbyaddress.ts | 14 +- .../algod_client/src/models/getstatus.ts | 103 ++ .../algod_client/src/models/getsupply.ts | 17 +- .../algod_client/src/models/getsyncround.ts | 10 +- ...ansactiongroupledgerstatedeltasforround.ts | 7 +- .../algod_client/src/models/index.ts | 4 +- .../ledgerstatedeltafortransactiongroup.ts | 5 +- .../src/models/lightblockheaderproof.ts | 17 +- .../src/models/participationkey.ts | 27 + .../src/models/pendingtransactionresponse.ts | 55 +- .../algod_client/src/models/rawtransaction.ts | 10 +- .../algod_client/src/models/scratchchange.ts | 8 +- .../src/models/simulateinitialstates.ts | 7 +- .../src/models/simulaterequest.ts | 27 + .../models/simulaterequesttransactiongroup.ts | 9 +- .../src/models/simulatetraceconfig.ts | 22 +- .../src/models/simulatetransaction.ts | 14 +- .../models/simulatetransactiongroupresult.ts | 19 + .../src/models/simulatetransactionresult.ts | 12 + .../simulateunnamedresourcesaccessed.ts | 27 + .../src/models/simulationevaloverrides.ts | 23 + .../src/models/simulationopcodetraceunit.ts | 23 + .../models/simulationtransactionexectrace.ts | 35 + .../algod_client/src/models/startcatchup.ts | 7 +- .../algod_client/src/models/stateproof.ts | 9 +- .../src/models/stateproofmessage.ts | 19 + .../algod_client/src/models/tealcompile.ts | 20 +- .../src/models/tealdisassemble.ts | 10 +- .../algod_client/src/models/tealdryrun.ts | 13 +- .../algod_client/src/models/tealkeyvalue.ts | 5 +- .../algod_client/src/models/tealvalue.ts | 17 +- .../src/models/transactionparams.ts | 28 + .../src/models/transactionproof.ts | 29 +- .../algod_client/src/models/version.ts | 7 +- .../algod_client/src/models/waitforblock.ts | 103 ++ .../tests/pendingTransaction.spec.ts | 6 +- .../tests/simulateTransactions.spec.ts | 84 ++ .../tests/transactionParams.spec.ts | 2 +- packages/typescript/indexer_client/README.md | 8 +- packages/typescript/indexer_client/bun.lock | 9 + .../typescript/indexer_client/package.json | 1 + .../indexer_client/src/apis/api.service.ts | 81 +- .../typescript/indexer_client/src/client.ts | 7 +- .../src/core/BaseHttpRequest.ts | 1 - .../indexer_client/src/core/msgpack.ts | 5 + .../indexer_client/src/core/request.ts | 3 +- .../indexer_client/src/models/account.ts | 128 ++ .../src/models/accountparticipation.ts | 23 + .../src/models/accountstatedelta.ts | 5 +- .../src/models/algokitsignedtransaction.ts | 277 +++++ .../indexer_client/src/models/application.ts | 23 +- .../src/models/applicationlocalstate.ts | 15 + .../src/models/applicationlogdata.ts | 12 +- .../src/models/applicationparams.ts | 19 + .../src/models/applicationstateschema.ts | 12 +- .../indexer_client/src/models/asset.ts | 23 +- .../indexer_client/src/models/assetholding.ts | 23 + .../indexer_client/src/models/assetparams.ts | 59 + .../indexer_client/src/models/block.ts | 61 + .../indexer_client/src/models/blockrewards.ts | 23 + .../src/models/blockupgradestate.ts | 19 + .../src/models/blockupgradevote.ts | 17 +- .../indexer_client/src/models/box.ts | 17 +- .../src/models/boxdescriptor.ts | 7 +- .../indexer_client/src/models/boxreference.ts | 12 +- .../indexer_client/src/models/evaldelta.ts | 17 +- .../src/models/evaldeltakeyvalue.ts | 5 +- .../indexer_client/src/models/hashfactory.ts | 7 +- .../src/models/hbprooffields.ts | 27 +- .../indexer_client/src/models/healthcheck.ts | 3 + .../indexer_client/src/models/index.ts | 2 + .../src/models/indexerstateproofmessage.ts | 19 + .../src/models/lookupaccountapplocalstates.ts | 17 +- .../src/models/lookupaccountassets.ts | 16 +- .../src/models/lookupaccountbyid.ts | 12 +- .../lookupaccountcreatedapplications.ts | 17 +- .../src/models/lookupaccountcreatedassets.ts | 17 +- .../src/models/lookupaccounttransactions.ts | 16 +- .../src/models/lookupapplicationbyid.ts | 12 +- .../src/models/lookupapplicationlogsbyid.ts | 21 +- .../src/models/lookupassetbalances.ts | 17 +- .../src/models/lookupassetbyid.ts | 12 +- .../src/models/lookupassettransactions.ts | 16 +- .../src/models/lookuptransaction.ts | 12 +- .../src/models/merklearrayproof.ts | 13 +- .../src/models/miniassetholding.ts | 12 + .../src/models/participationupdates.ts | 12 +- .../src/models/searchforaccounts.ts | 17 +- .../src/models/searchforapplicationboxes.ts | 16 +- .../src/models/searchforapplications.ts | 17 +- .../src/models/searchforassets.ts | 17 +- .../src/models/searchforblockheaders.ts | 16 +- .../src/models/searchfortransactions.ts | 16 +- .../src/models/stateprooffields.ts | 19 + .../src/models/stateproofparticipant.ts | 9 +- .../src/models/stateproofreveal.ts | 9 +- .../src/models/stateproofsignature.ts | 11 +- .../src/models/stateproofsigslot.ts | 9 +- .../src/models/stateprooftracking.ts | 22 +- .../src/models/stateproofverifier.ts | 12 +- .../indexer_client/src/models/stateschema.ts | 12 +- .../indexer_client/src/models/tealkeyvalue.ts | 5 +- .../indexer_client/src/models/tealvalue.ts | 17 +- .../indexer_client/src/models/transaction.ts | 110 ++ .../src/models/transactionapplication.ts | 39 + .../src/models/transactionassetconfig.ts | 8 +- .../src/models/transactionassetfreeze.ts | 17 +- .../src/models/transactionassettransfer.ts | 23 + .../src/models/transactionheartbeat.ts | 23 +- .../src/models/transactionkeyreg.ts | 27 + .../src/models/transactionpayment.ts | 22 +- .../src/models/transactionsignature.ts | 10 +- .../models/transactionsignaturelogicsig.ts | 11 + .../models/transactionsignaturemultisig.ts | 11 + ...ransactionsignaturemultisigsubsignature.ts | 12 +- .../src/models/transactionstateproof.ts | 9 +- .../tests/searchApplications.spec.ts | 10 +- .../tests/searchTransactions.spec.ts | 2 +- 187 files changed, 4712 insertions(+), 885 deletions(-) create mode 100644 api/oas_generator/ts_oas_generator/constants.py create mode 100644 api/oas_generator/ts_oas_generator/parser/__init__.py create mode 100644 api/oas_generator/ts_oas_generator/parser/oas_parser.py create mode 100644 api/oas_generator/ts_oas_generator/templates/models/algokitsignedtransaction.ts.j2 create mode 100644 packages/typescript/algod_client/src/models/algokitsignedtransaction.ts create mode 100644 packages/typescript/algod_client/tests/simulateTransactions.spec.ts create mode 100644 packages/typescript/indexer_client/src/models/algokitsignedtransaction.ts diff --git a/api/oas_generator/ts_oas_generator/cli.py b/api/oas_generator/ts_oas_generator/cli.py index 2bb604508..e8bee5572 100644 --- a/api/oas_generator/ts_oas_generator/cli.py +++ b/api/oas_generator/ts_oas_generator/cli.py @@ -13,7 +13,8 @@ from collections.abc import Generator from pathlib import Path -from ts_oas_generator.generator.template_engine import TsCodeGenerator +from ts_oas_generator import constants +from ts_oas_generator.generator.template_engine import CodeGenerator from ts_oas_generator.utils.file_utils import write_files_to_disk # Exit codes for better error reporting @@ -45,14 +46,14 @@ def parse_command_line_args(args: list[str] | None = None) -> argparse.Namespace "--output", "-o", type=Path, - default=Path("./generated_ts"), + 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="api_ts_client", + default=constants.DEFAULT_PACKAGE_NAME, help="Name for the generated TypeScript package (default: %(default)s)", dest="package_name", ) @@ -100,7 +101,7 @@ def backup_and_prepare_output_dir(output_dir: Path) -> Generator[None, None, Non # 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="tsgen_bak_")) + backup_dir = Path(tempfile.mkdtemp(prefix=constants.BACKUP_DIR_PREFIX)) shutil.copytree(output_dir, backup_dir, dirs_exist_ok=True) # Ensure directory exists @@ -129,9 +130,9 @@ def main(args: list[str] | None = None) -> int: try: with backup_and_prepare_output_dir(parsed_args.output_dir): - generator = TsCodeGenerator(template_dir=parsed_args.template_dir) + generator = CodeGenerator(template_dir=parsed_args.template_dir) - generated_files = generator.generate_full( + generated_files = generator.generate( parsed_args.spec_file, parsed_args.output_dir, parsed_args.package_name, diff --git a/api/oas_generator/ts_oas_generator/constants.py b/api/oas_generator/ts_oas_generator/constants.py new file mode 100644 index 000000000..a353e69dd --- /dev/null +++ b/api/oas_generator/ts_oas_generator/constants.py @@ -0,0 +1,210 @@ +"""Constants for the TypeScript OAS generator using Enums for better organization.""" + +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" + + +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" + +# 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" + +# Template configuration +TEMPLATE_TRIM_BLOCKS: Final[bool] = True +TEMPLATE_LSTRIP_BLOCKS: Final[bool] = True diff --git a/api/oas_generator/ts_oas_generator/generator/filters.py b/api/oas_generator/ts_oas_generator/generator/filters.py index 18e14079f..bde6a2efd 100644 --- a/api/oas_generator/ts_oas_generator/generator/filters.py +++ b/api/oas_generator/ts_oas_generator/generator/filters.py @@ -8,6 +8,9 @@ import re from typing import Any +from ts_oas_generator import constants +from ts_oas_generator.constants import MediaType, OperationKey, SchemaKey, TypeScriptType + _IDENTIFIER_RE = re.compile(r"^[A-Za-z_][A-Za-z0-9_]*$") @@ -77,34 +80,42 @@ def _union(types: list[str]) -> str: def _intersection(types: list[str]) -> str: - parts = [t for t in types if t and t != "any"] - return " & ".join(parts) if parts else "any" + 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: dict[str, Any]) -> str: # OpenAPI 3.0 nullable flag - if schema.get("nullable") is True: - return _union([type_str, "null"]) + if schema.get(SchemaKey.NULLABLE) is True: + return _union([type_str, TypeScriptType.NULL]) # OpenAPI 3.1 union type with null - t = schema.get("type") - if isinstance(t, list) and "null" in t: - non_nulls = [x for x in t if x != "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({"type": non_nulls[0]}, None), "null"]) + return _union([ts_type({SchemaKey.TYPE: non_nulls[0]}, None), TypeScriptType.NULL]) # Else, build a union of all non-nulls + null - return _union([_union([ts_type({"type": n}, None) for n in non_nulls]), "null"]) + return _union([_union([ts_type({SchemaKey.TYPE: n}, None) for n in non_nulls]), TypeScriptType.NULL]) return type_str def _inline_object(schema: dict[str, Any], schemas: dict[str, Any] | None) -> str: - properties: dict[str, Any] = schema.get("properties", {}) or {} - required = set(schema.get("required", []) or []) + 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(): + # Add property description as doc comment + description = prop_schema.get("description") + if description: + doc_comment = ts_doc_comment(description) + # Format docstring for inline object (indent each line) + 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(prop_name) ts_t = ts_type(prop_schema, schemas) @@ -119,39 +130,48 @@ def _inline_object(schema: dict[str, Any], schemas: dict[str, Any] | None) -> st elif isinstance(addl, dict): parts.append(f"[key: string]: {ts_type(addl, schemas)};") - return "{" + (" ".join(parts)) + "}" + 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 "{}" def _map_primitive(schema_type: str, _schema_format: str | None, _schema: dict[str, Any]) -> str: if schema_type == "integer": # Default to bigint for blockchain-sized integers; keep int32 as number if _schema_format == "int32": - return "number" - return "bigint" + return TypeScriptType.NUMBER + return TypeScriptType.BIGINT if schema_type in ("number",): - return "number" + return TypeScriptType.NUMBER if schema_type == "string": # bytes/base64 remain string for JSON representation - return "string" + return TypeScriptType.STRING if schema_type == "boolean": - return "boolean" + return TypeScriptType.BOOLEAN - return "any" + return TypeScriptType.ANY def ts_enum_type(schema: dict[str, Any]) -> str | None: - if "enum" not in schema: + if SchemaKey.ENUM not in schema: return None - if schema.get("x-algokit-bigint") is True: + if schema.get(constants.X_ALGOKIT_BIGINT) is True: # For bigint-marked enums, use bigint type directly - return "bigint" + return TypeScriptType.BIGINT - type_val = schema.get("type") - values = schema.get("enum", []) + type_val = schema.get(SchemaKey.TYPE) + values = schema.get(SchemaKey.ENUM, []) if type_val == "string": return " | ".join([f"'{v!s}'" for v in values]) @@ -163,10 +183,15 @@ def ts_enum_type(schema: dict[str, Any]) -> str | None: return " | ".join([f"'{v!s}'" for v in values]) -def ts_type(schema: dict[str, Any] | None, schemas: dict[str, Any] | None = None) -> str: # noqa: PLR0911 +def ts_type(schema: dict[str, Any] | None, schemas: dict[str, Any] | None = None) -> str: # noqa: C901, PLR0911 """Map OpenAPI schema to a TypeScript type string.""" if not schema: - return "any" + return TypeScriptType.ANY + + # Vendor extension: x-algokit-signed-txn -> reference temporary AlgokitSignedTransaction model + # TODO(utils-ts): Remove this vendor extension mapping and rely on real utils SignedTransaction type + if isinstance(schema, dict) and schema.get(constants.X_ALGOKIT_SIGNED_TXN) is True: + return "AlgokitSignedTransaction" # Handle references if "$ref" in schema: @@ -174,35 +199,42 @@ def ts_type(schema: dict[str, Any] | None, schemas: dict[str, Any] | None = None return ts_pascal_case(ref_name) # Handle composed schemas - if "allOf" in schema: - return _intersection([ts_type(s, schemas) for s in schema.get("allOf", [])]) + if SchemaKey.ALL_OF in schema: + return _intersection([ts_type(s, schemas) for s in schema.get(SchemaKey.ALL_OF, [])]) - if "oneOf" in schema: - return _union([ts_type(s, schemas) for s in schema.get("oneOf", [])]) + if SchemaKey.ONE_OF in schema: + return _union([ts_type(s, schemas) for s in schema.get(SchemaKey.ONE_OF, [])]) - if "anyOf" in schema: - return _union([ts_type(s, schemas) for s in schema.get("anyOf", [])]) + if SchemaKey.ANY_OF in schema: + return _union([ts_type(s, schemas) for s in schema.get(SchemaKey.ANY_OF, [])]) # Enums enum_t = ts_enum_type(schema) if enum_t: return enum_t - schema_type = schema.get("type") + schema_type = schema.get(SchemaKey.TYPE) # Handle array of items if schema_type == "array": - items_schema = schema.get("items", {}) - items_type = ts_type(items_schema, schemas) + items_schema = schema.get(SchemaKey.ITEMS, {}) + # Apply vendor extension on nested items as well + # TODO(utils-ts): Remove when x-algokit-signed-txn is handled by utils types + if isinstance(items_schema, dict) and items_schema.get(constants.X_ALGOKIT_SIGNED_TXN) is True: + items_type = "AlgokitSignedTransaction" + else: + items_type = ts_type(items_schema, schemas) return f"{items_type}[]" # Object type - if schema_type == "object" or (not schema_type and ("properties" in schema or "additionalProperties" in schema)): + if schema_type == TypeScriptType.OBJECT or ( + not schema_type and (SchemaKey.PROPERTIES in schema or SchemaKey.ADDITIONAL_PROPERTIES in schema) + ): type_str = _inline_object(schema, schemas) return _nullable(type_str, schema) # Primitive types - type_str = _map_primitive(str(schema_type), schema.get("format"), schema) + type_str = _map_primitive(str(schema_type), schema.get(SchemaKey.FORMAT), schema) return _nullable(type_str, schema) @@ -211,10 +243,10 @@ def ts_type(schema: dict[str, Any] | None, schemas: dict[str, Any] | None = None def has_msgpack_2xx(responses: dict[str, Any]) -> bool: for status, resp in (responses or {}).items(): - if not str(status).startswith("2"): + if not str(status).startswith(constants.SUCCESS_STATUS_PREFIX): continue - content = (resp or {}).get("content", {}) - if any(ct in (content or {}) for ct in ("application/msgpack", "application/x-binary")): + content = (resp or {}).get(OperationKey.CONTENT, {}) + if any(ct in (content or {}) for ct in (MediaType.MSGPACK, MediaType.BINARY)): return True return False @@ -222,9 +254,9 @@ def has_msgpack_2xx(responses: dict[str, Any]) -> bool: def response_content_types(responses: dict[str, Any]) -> list[str]: cts: set[str] = set() for status, resp in (responses or {}).items(): - if not str(status).startswith("2"): + if not str(status).startswith(constants.SUCCESS_STATUS_PREFIX): continue - content = (resp or {}).get("content", {}) + content = (resp or {}).get(OperationKey.CONTENT, {}) for ct in content: cts.add(ct) return sorted(cts) @@ -238,6 +270,10 @@ def _traverse(obj: dict[str, Any]) -> None: # noqa: C901 if not obj or not isinstance(obj, dict): return + # Include vendor extension-based synthetic references + if obj.get(constants.X_ALGOKIT_SIGNED_TXN) is True: + refs.add("AlgokitSignedTransaction") + # Direct $ref if "$ref" in obj: ref_name = ts_pascal_case(_extract_ref_name(obj["$ref"])) @@ -247,23 +283,23 @@ def _traverse(obj: dict[str, Any]) -> None: # noqa: C901 return # Don't traverse further if this is a ref # Properties - if "properties" in obj and isinstance(obj["properties"], dict): - for prop_schema in obj["properties"].values(): + if SchemaKey.PROPERTIES in obj and isinstance(obj[SchemaKey.PROPERTIES], dict): + for prop_schema in obj[SchemaKey.PROPERTIES].values(): _traverse(prop_schema) # Array items - if "items" in obj: - _traverse(obj["items"]) + if SchemaKey.ITEMS in obj: + _traverse(obj[SchemaKey.ITEMS]) # Composed schemas - for key in ["allOf", "oneOf", "anyOf"]: + for key in [SchemaKey.ALL_OF, SchemaKey.ONE_OF, SchemaKey.ANY_OF]: if key in obj and isinstance(obj[key], list): for sub_schema in obj[key]: _traverse(sub_schema) # Additional properties - if "additionalProperties" in obj and isinstance(obj["additionalProperties"], dict): - _traverse(obj["additionalProperties"]) + if SchemaKey.ADDITIONAL_PROPERTIES in obj and isinstance(obj[SchemaKey.ADDITIONAL_PROPERTIES], dict): + _traverse(obj[SchemaKey.ADDITIONAL_PROPERTIES]) _traverse(schema) return sorted(refs) diff --git a/api/oas_generator/ts_oas_generator/generator/template_engine.py b/api/oas_generator/ts_oas_generator/generator/template_engine.py index 9247d7ee5..bfa8010fd 100644 --- a/api/oas_generator/ts_oas_generator/generator/template_engine.py +++ b/api/oas_generator/ts_oas_generator/generator/template_engine.py @@ -1,541 +1,678 @@ -""" -TypeScript Template Engine for OpenAPI Client Generation (Phase 2) - -Generates runtime plus models/services when a spec is provided. -""" - from __future__ import annotations import re +from dataclasses import dataclass +from enum import Enum from pathlib import Path from typing import Any from jinja2 import Environment, FileSystemLoader, select_autoescape -from rust_oas_generator.parser.oas_parser import OASParser +from ts_oas_generator import constants from ts_oas_generator.generator.filters import FILTERS, ts_camel_case, ts_pascal_case, ts_type +from ts_oas_generator.parser.oas_parser import OASParser + +# Type aliases for clarity +Schema = dict[str, Any] +Operation = dict[str, Any] +TemplateContext = dict[str, Any] +FileMap = dict[Path, str] + + +class ContentType(str, Enum): + """Supported content types.""" + + JSON = "application/json" + MSGPACK = "application/msgpack" + TEXT = "text/plain" + BINARY = "application/octet-stream" + + +@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] + # Content negotiation flags + returns_msgpack: bool = False + has_format_param: bool = False + format_var_name: str | 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, + } -_HTTP_METHODS = {"get", "post", "put", "delete", "patch", "head", "options"} + @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, + } -# Compact alias for the build context tuple to keep lines within ruff's E501 limit -BuildContext = tuple[ - dict[str, list[dict[str, Any]]], - set[str], - dict[str, Any], -] + @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, + } -class TsTemplateEngine: - """Template engine for generating TypeScript client code.""" +class TemplateRenderer: + """Handles template rendering operations.""" def __init__(self, template_dir: Path | None = None) -> None: if template_dir is None: - current_dir = Path(__file__).parent - template_dir = current_dir.parent / "templates" + template_dir = Path(__file__).parent.parent / constants.DEFAULT_TEMPLATE_DIR self.template_dir = Path(template_dir) - self.env = Environment( + self.env = self._create_environment() + + def _create_environment(self) -> Environment: + """Create and configure Jinja2 environment.""" + env = Environment( loader=FileSystemLoader(str(self.template_dir)), autoescape=select_autoescape(["html", "xml"]), - trim_blocks=True, - lstrip_blocks=True, + trim_blocks=constants.TEMPLATE_TRIM_BLOCKS, + lstrip_blocks=constants.TEMPLATE_LSTRIP_BLOCKS, ) + env.filters.update(FILTERS) + return env - self._register_filters() - self._register_globals() + def render(self, template_name: str, context: TemplateContext) -> str: + """Render a single template.""" + template = self.env.get_template(template_name) + return template.render(**context) - def _register_filters(self) -> None: - self.env.filters.update(FILTERS) + def render_batch(self, template_map: dict[Path, tuple[str, TemplateContext]]) -> FileMap: + """Render multiple templates.""" + return {path: self.render(template, context) for path, (template, context) in template_map.items()} - def _register_globals(self) -> None: - self.env.globals.update({}) - def render_template(self, template_name: str, context: dict[str, Any]) -> str: - template = self.env.get_template(template_name) - return template.render(**context) +class SchemaProcessor: + """Processes OpenAPI schemas and generates TypeScript models.""" + def __init__(self, renderer: TemplateRenderer) -> None: + self.renderer = renderer -class TsCodeGenerator: - """Generates TypeScript runtime and code from templates.""" + def generate_models(self, output_dir: Path, schemas: Schema) -> FileMap: + """Generate TypeScript model files from schemas.""" + models_dir = output_dir / constants.DirectoryName.SRC / constants.DirectoryName.MODELS + files: FileMap = {} - def __init__(self, template_dir: Path | None = None) -> None: - self.template_engine = TsTemplateEngine(template_dir) + # Generate individual model files + for name, schema in schemas.items(): + context = self._create_model_context(name, schema, schemas) + content = self.renderer.render(constants.MODEL_TEMPLATE, context) + files[models_dir / f"{name.lower()}{constants.MODEL_FILE_EXTENSION}"] = content - def generate_runtime( - self, - output_dir: Path, - package_name: str = "api_ts_client", - *, - custom_description: str | None = None, - ) -> dict[Path, str]: - """Generate runtime files under the provided output directory.""" - output_dir = Path(output_dir) - src_core = output_dir / "src" / "core" - base_name = ts_pascal_case(package_name) - base_core = base_name[:-6] if base_name.lower().endswith("client") else base_name - client_class_name = f"{base_core}Client" - service_class_name = f"{base_core}Api" + # Generate comprehensive AlgokitSignedTransaction model + # TODO(utils-ts): Delete this temporary model once utils-ts is part of the monorepo + files[models_dir / f"algokitsignedtransaction{constants.MODEL_FILE_EXTENSION}"] = self.renderer.render( + "models/algokitsignedtransaction.ts.j2", {} + ) - context = { - "package_name": package_name, - "custom_description": custom_description, - "client_class_name": client_class_name, - "service_class_name": service_class_name, + # Generate barrel export + files[models_dir / constants.INDEX_FILE] = self.renderer.render( + constants.MODELS_INDEX_TEMPLATE, + {"schemas": schemas, "include_temp_signed_txn": True}, + ) + + return files + + def _create_model_context(self, name: str, schema: Schema, all_schemas: Schema) -> TemplateContext: + """Create context for model template rendering.""" + 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), } - files: dict[Path, str] = {} - # Core runtime files - files[src_core / "ClientConfig.ts"] = self.template_engine.render_template( - "base/src/core/ClientConfig.ts.j2", context + @staticmethod + def _is_object_schema(schema: Schema) -> bool: + """Check if schema represents an object type.""" + 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] ) - files[src_core / "BaseHttpRequest.ts"] = self.template_engine.render_template( - "base/src/core/BaseHttpRequest.ts.j2", context + return (is_type_object or has_properties) and not has_composition + + @staticmethod + def _extract_properties(schema: Schema) -> list[dict[str, Any]]: + """Extract properties from an object schema.""" + properties = [] + required_fields = set(schema.get(constants.SchemaKey.REQUIRED, [])) + + for prop_name, prop_schema in (schema.get(constants.SchemaKey.PROPERTIES) or {}).items(): + properties.append( + { + "name": prop_name, + "schema": prop_schema, + "is_required": prop_name in required_fields, + } + ) + + return properties + + +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: Schema = {} + + def process_spec(self, spec: Schema) -> tuple[dict[str, list[OperationContext]], set[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, + }, ) - files[src_core / "FetchHttpRequest.ts"] = self.template_engine.render_template( - "base/src/core/FetchHttpRequest.ts.j2", context + + # Generate barrel export + files[apis_dir / constants.INDEX_FILE] = self.renderer.render( + constants.APIS_INDEX_TEMPLATE, {"service_class_name": service_class_name} ) - files[src_core / "ApiError.ts"] = self.template_engine.render_template("base/src/core/ApiError.ts.j2", context) - files[src_core / "request.ts"] = self.template_engine.render_template("base/src/core/request.ts.j2", context) - files[src_core / "CancelablePromise.ts"] = self.template_engine.render_template( - "base/src/core/CancelablePromise.ts.j2", context + + 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) + if not operation_id: + operation_id = ts_camel_case(f"{method.lower()}_{path}") + + # Process operation + context = self._create_operation_context( + operation_id=operation_id, + method=method.upper(), + path=path, + operation=operation, + path_params=path_params, + spec=spec, + ) + + context.tags = operation.get(constants.OperationKey.TAGS, [constants.DEFAULT_TAG]) + operations.append(context) + + return operations + + def _create_operation_context( # noqa: PLR0913 + self, operation_id: str, method: str, path: str, operation: Schema, path_params: list[Schema], spec: Schema + ) -> OperationContext: + """Create complete operation context.""" + # Merge path and operation parameters + all_params = [*path_params, *operation.get(constants.OperationKey.PARAMETERS, [])] + + # Process components + parameters = self._process_parameters(all_params, spec) + request_body = self._process_request_body(operation.get(constants.OperationKey.REQUEST_BODY), spec) + response_type, returns_msgpack = self._process_responses( + operation.get(constants.OperationKey.RESPONSES, {}), operation_id, spec ) - files[src_core / "json.ts"] = self.template_engine.render_template("base/src/core/json.ts.j2", context) - files[src_core / "msgpack.ts"] = self.template_engine.render_template("base/src/core/msgpack.ts.j2", context) - files[src_core / "casing.ts"] = self.template_engine.render_template("base/src/core/casing.ts.j2", context) - # Index barrel (runtime-only) - files[output_dir / "src" / "index.ts"] = self.template_engine.render_template("base/src/index.ts.j2", context) + # Build context + context = OperationContext( + operation_id=operation_id, + method=method, + path=path, + description=operation.get(constants.OperationKey.DESCRIPTION), + parameters=parameters, + request_body=request_body, + response_type=response_type, + import_types=set(), + returns_msgpack=returns_msgpack, + ) - # Project files - files[output_dir / "package.json"] = self.template_engine.render_template("base/package.json.j2", context) - files[output_dir / "tsconfig.json"] = self.template_engine.render_template("base/tsconfig.json.j2", context) - files[output_dir / "README.md"] = self.template_engine.render_template("base/README.md.j2", context) - files[output_dir / ".prettierignore"] = self.template_engine.render_template("base/.prettierignore.j2", context) + # Compute additional properties + self._compute_format_param(context) + 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")) + 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 = param.get(constants.OperationKey.IN, constants.ParamLocation.QUERY) + 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 files + return parameters - def _build_services_context(self, spec: dict[str, Any]) -> BuildContext: # noqa: C901, PLR0912, PLR0915 - """Build a per-tag mapping of operations for service generation. + def _process_request_body(self, request_body: Schema | None, spec: Schema) -> RequestBody | None: + """Process request body specification.""" - Returns (ops_by_tag, tags_set) - """ - paths = spec.get("paths", {}) - components = spec.get("components", {}) - schemas = components.get("schemas", {}) - model_names = {ts_pascal_case(name) for name in schemas} - builtin_types = {"Uint8Array", "void", "never", "string", "number", "bigint", "boolean"} + if not isinstance(request_body, dict): + return None - ops_by_tag: dict[str, list[dict[str, Any]]] = {} - tags_set: set[str] = set() - synthetic_models: dict[str, Any] = {} + content = request_body.get("content", {}) + schemas = self._get_schemas(spec) - token_re = re.compile(r"\b[A-Z][A-Za-z0-9_]*\b") + # 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) - def collect_model_types(type_str: str) -> set[str]: - found: set[str] = set() - for tok in token_re.findall(type_str or ""): - if tok in model_names and tok not in builtin_types: - found.add(tok) - return found + # 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, + ) - for path, path_item in paths.items(): - if not isinstance(path_item, dict): + def _process_responses(self, responses: Schema, operation_id: str, spec: Schema) -> tuple[str, bool, bool]: + """Process response specifications.""" + + return_types: list[str] = [] + returns_msgpack = False + supports_json = False + schemas = self._get_schemas(spec) + + for status, response in responses.items(): + if not str(status).startswith(constants.SUCCESS_STATUS_PREFIX): continue - for method, op in path_item.items(): - if method.lower() not in _HTTP_METHODS: - continue - if not isinstance(op, dict): - continue - operation_id = op.get("operationId") - if not operation_id: - # Fallback to verb + normalized path - operation_id = ts_camel_case(f"{method.lower()}_{path}") - - tags = op.get("tags", []) or ["default"] - parameters = op.get("parameters", []) - # Gather params from path level too - if isinstance(path_item.get("parameters"), list): - parameters = [*path_item.get("parameters", []), *parameters] - - # Prepare parameters - param_contexts: list[dict[str, Any]] = [] - # Track used variable names per operation to ensure uniqueness - used_var_names: set[str] = set() - reserved_words = { - "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", - } - for p in parameters: - param = p - if "$ref" in param: - # Resolve $ref - ref_path = param["$ref"].split("/")[1:] - node: Any = spec - for part in ref_path: - node = node.get(part, {}) - param = node - schema = param.get("schema", {}) or {} - t = ts_type(schema, schemas) - # When a parameter resolves to bigint, accept number | bigint for ergonomics - if t == "bigint": - t_sig = "number | bigint" - stringify_bigint = True + + content = (response or {}).get("content", {}) + returns_msgpack = returns_msgpack or constants.MediaType.MSGPACK in content + + if json_content := content.get(constants.MediaType.JSON): + supports_json = True + schema = json_content.get("schema", {}) + + if schema: + if self._should_synthesize_model(schema): + # Create synthetic model for inline object schemas + model_name = ts_pascal_case(operation_id) + if model_name not in self._model_names: + self._synthetic_models[model_name] = schema + self._model_names.add(model_name) + return_types.append(model_name) else: - t_sig = t - stringify_bigint = "bigint" in t_sig - - raw_name = str(param.get("name")) - base_var_name = ts_camel_case(raw_name) - # Avoid reserved words - if base_var_name in reserved_words: - base_var_name = f"{base_var_name}_" - var_name = base_var_name - # Ensure uniqueness by suffixing with numeric counter - if var_name in used_var_names: - i = 2 - while f"{base_var_name}{i}" in used_var_names: - i += 1 - var_name = f"{base_var_name}{i}" - used_var_names.add(var_name) - - param_contexts.append( - { - "name": raw_name, # original name used in path/query/header keys - "varName": var_name, # sanitized TS identifier for function signature - "in": param.get("in", "query"), - "required": param.get("required", False) or (param.get("in") == "path"), - "tsType": t_sig, - "description": param.get("description"), - "stringifyBigInt": stringify_bigint, - } - ) - - # Request body handling - request_body_ctx: dict[str, Any] | None = None - request_body_supports_msgpack = False - request_body_supports_json = False - rb = op.get("requestBody") - if isinstance(rb, dict): - content = rb.get("content", {}) - - # Check what content types are supported - if "application/msgpack" in content: - request_body_supports_msgpack = True - if "application/json" in content: - request_body_supports_json = True - - # Determine the type to use for TypeScript typing - # Prefer JSON schema for typing even when msgpack is used at runtime - if "application/json" in content: - sch = (content["application/json"] or {}).get("schema", {}) - request_body_ctx = { - "mediaType": ( - "application/msgpack" - if request_body_supports_msgpack and not request_body_supports_json - else "application/json" - ), - "tsType": ts_type(sch, schemas), - "required": rb.get("required", False), - "supportsMsgpack": request_body_supports_msgpack, - "supportsJson": request_body_supports_json, - } - elif "application/msgpack" in content: - # msgpack-only endpoint - infer type from msgpack schema if available - sch = (content["application/msgpack"] or {}).get("schema", {}) - request_body_ctx = { - "mediaType": "application/msgpack", - "tsType": ts_type(sch, schemas) if sch else "any", - "required": rb.get("required", False), - "supportsMsgpack": True, - "supportsJson": False, - } - elif "application/x-binary" in content or "application/octet-stream" in content: - # Raw binary transaction submission etc. - mt = "application/x-binary" if "application/x-binary" in content else "application/octet-stream" - request_body_ctx = { - "mediaType": mt, - "tsType": "Uint8Array", - "required": rb.get("required", False), - "supportsMsgpack": False, - "supportsJson": False, - } - elif "text/plain" in content: - sch = (content["text/plain"] or {}).get("schema", {}) - request_body_ctx = { - "mediaType": "text/plain", - "tsType": ts_type(sch, schemas), - "required": rb.get("required", False), - "supportsMsgpack": False, - "supportsJson": False, - } - - # Responses - responses = op.get("responses", {}) or {} - return_types: list[str] = [] - returns_msgpack = False - supports_json = False - for status, resp in responses.items(): - if not str(status).startswith("2"): - continue - content = (resp or {}).get("content", {}) - if "application/msgpack" in content: - returns_msgpack = True - # Prefer JSON schema for typing - if "application/json" in content: - supports_json = True - sch = (content["application/json"] or {}).get("schema", {}) - if sch: - # If inline object schema without $ref, synthesize a named model from operationId - if ( - isinstance(sch, dict) - and "$ref" not in sch - and ( - sch.get("type") == "object" or "properties" in sch or "additionalProperties" in sch - ) - ): - model_name = ts_pascal_case(operation_id) - if model_name not in model_names: - synthetic_models[model_name] = sch - model_names.add(model_name) - return_types.append(model_name) - else: - return_types.append(ts_type(sch, schemas)) - elif content: - # Fallback: take first content schema - first_ct = next(iter(content.values())) - sch = (first_ct or {}).get("schema", {}) - if sch: - return_types.append(ts_type(sch, schemas)) - - response_ts_type = "never" - if supports_json and return_types: - # Prefer JSON typing when available - uniq: list[str] = [] - for t in return_types: - if t not in uniq: - uniq.append(t) - response_ts_type = " | ".join(uniq) - elif returns_msgpack: - response_ts_type = "Uint8Array" - else: - response_ts_type = "void" - - # Build signature with required path params first, then params object and request options - path_params = [p for p in param_contexts if p.get("in") == "path"] - other_params = [p for p in param_contexts if p.get("in") in {"query", "header"}] - - # detect optional format param for content negotiation - has_format_param = False - format_var_name = None - for qp in other_params: - if qp.get("in") == "query" and qp.get("name") == "format": - has_format_param = True - format_var_name = qp.get("varName") - - sig_parts: list[str] = [f"{p['varName']}: {p['tsType']}" for p in path_params] - # params bag and request options - param_sigs: list[str] = [ - f"{p['varName']}{'' if p['required'] else '?'}: {p['tsType']}" for p in other_params - ] - if request_body_ctx: - body_required = bool((request_body_ctx or {}).get("required")) - body_type = str(request_body_ctx["tsType"]) - body_param_sig = f"body{'' if body_required else '?'}: {body_type}" - param_sigs.append(body_param_sig) - sig_parts.append("params?: { " + ", ".join(param_sigs) + " }") - sig_parts.append("requestOptions?: ApiRequestOptions") - - # Import types from embedded types - import_types: set[str] = set() - import_types |= collect_model_types(response_ts_type) - if request_body_ctx: - import_types |= collect_model_types(str(request_body_ctx.get("tsType") or "")) - # Also from parameter types (e.g., enums not needed as imports) - for p in param_contexts: - import_types |= collect_model_types(p.get("tsType") or "") - - op_ctx = { - "operationId": operation_id, - "method": method.upper(), - "path": path, - "parameters": param_contexts, - "pathParameters": path_params, - "otherParameters": other_params, - "requestBody": request_body_ctx, - "responseTsType": response_ts_type, - "acceptsMsgpack": returns_msgpack, - "returnsMsgpack": returns_msgpack, - "supportsJson": supports_json, - "requestBodySupportsMsgpack": request_body_supports_msgpack, - "requestBodySupportsJson": request_body_supports_json, - "hasFormatParam": has_format_param, - "formatVarName": format_var_name, - "signature": ", ".join(sig_parts), - "importTypes": sorted(import_types), - } + return_types.append(ts_type(schema, schemas)) + elif content and (schema := next(iter(content.values()), {}).get("schema")): + # Fallback to first content type with schema + return_types.append(ts_type(schema, schemas)) + + # Determine final response type + if supports_json and return_types: + response_type = " | ".join(dict.fromkeys(return_types)) # Deduplicate + 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_import_types(self, context: OperationContext) -> None: + """Collect model types that need importing.""" + token_re = re.compile(r"\b[A-Z][A-Za-z0-9_]*\b") + builtin_types = constants.TS_BUILTIN_TYPES + + def extract_types(type_str: str) -> set[str]: + if not type_str: + return set() + return {tok for tok in token_re.findall(type_str) if tok in self._model_names and tok not in builtin_types} + + # Collect from all type references + context.import_types = extract_types(context.response_type) + + if context.request_body: + 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) + ) + + @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 # - for tag in tags: - tags_set.add(tag) - ops_by_tag.setdefault(tag, []).append(op_ctx) + node = spec + for part in parts: + node = node.get(part, {}) + return node - # Stable sort operations per tag by operationId - for _tag, ops in ops_by_tag.items(): - ops.sort(key=lambda o: o.get("operationId") or "") + @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, {}) - return ops_by_tag, tags_set, synthetic_models - def generate_full( +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, - ) -> dict[Path, str]: - """Generate runtime + models + apis from a spec.""" + ) -> FileMap: + """Generate complete TypeScript client from OpenAPI spec.""" + # Parse specification parser = OASParser() parser.parse_file(spec_path) + spec = parser.spec_data or {} - files = self.generate_runtime(output_dir, package_name, custom_description=custom_description) + # Extract class names + client_class, service_class = self._extract_class_names(package_name) - spec_dict: dict[str, Any] = parser.spec_data or {} - components = spec_dict.get("components", {}) - raw_schemas: dict[str, Any] = components.get("schemas", {}) + # Generate base runtime + files = self._generate_runtime(output_dir, package_name, client_class, service_class, custom_description) - # Build operations and synthetic models - ops_by_tag, tags_set, synthetic_models = self._build_services_context(spec_dict) + # Process operations and schemas + ops_by_tag, tags, synthetic_models = self.operation_processor.process_spec(spec) - # Merge component schemas with synthetic models - combined_schemas: dict[str, Any] = dict(raw_schemas) - for m_name, m_schema in synthetic_models.items(): - if m_name not in combined_schemas: - combined_schemas[m_name] = m_schema + # Merge schemas + components = spec.get(constants.SchemaKey.COMPONENTS, {}) + base_schemas = components.get(constants.SchemaKey.COMPONENTS_SCHEMAS, {}) + all_schemas = {**base_schemas, **synthetic_models} - # Models - models_dir = Path(output_dir) / "src" / "models" - for name, schema in combined_schemas.items(): - content = self.template_engine.render_template( - "models/model.ts.j2", - {"schema_name": name, "schema": schema, "schemas": combined_schemas}, - ) - files[models_dir / f"{name.lower()}.ts"] = content + # Generate components + files.update(self.schema_processor.generate_models(output_dir, all_schemas)) + 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)) - # Models barrel - files[models_dir / "index.ts"] = self.template_engine.render_template( - "models/index.ts.j2", - {"schemas": combined_schemas}, - ) + return files - # Consolidated single service with all operations - apis_dir = Path(output_dir) / "src" / "apis" - all_ops: list[dict[str, Any]] = [] - seen_keys: set[tuple[str, str]] = set() - for tag in sorted(tags_set): - for op in ops_by_tag.get(tag, []): - key = (str(op.get("method")), str(op.get("path"))) - if key in seen_keys: - continue - seen_keys.add(key) - all_ops.append(op) - # Stable sort by operationId - all_ops.sort(key=lambda o: o.get("operationId") or "") - - # Aggregate imports - import_types: set[str] = set() - for op in all_ops: - for t in op.get("importTypes", []): - import_types.add(t) - - # Determine class names from package name (e.g., algod_client -> AlgodClient, AlgodApi) - base_name = ts_pascal_case(package_name) - base_core = base_name[:-6] if base_name.lower().endswith("client") else base_name - client_class_name = f"{base_core}Client" - service_class_name = f"{base_core}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 - svc_content = self.template_engine.render_template( - "apis/service.ts.j2", - { - "tag_name": "api", - "operations": all_ops, - "import_types": sorted(import_types), - "service_class_name": service_class_name, - }, - ) - files[apis_dir / "api.service.ts"] = svc_content + context = { + "package_name": package_name, + "custom_description": custom_description, + "client_class_name": client_class, + "service_class_name": service_class, + } - files[apis_dir / "index.ts"] = self.template_engine.render_template( - "apis/index.ts.j2", - {"service_class_name": service_class_name}, - ) + template_map = { + # Core runtime + core_dir / "ClientConfig.ts": ("base/src/core/ClientConfig.ts.j2", context), + core_dir / "BaseHttpRequest.ts": ("base/src/core/BaseHttpRequest.ts.j2", context), + core_dir / "FetchHttpRequest.ts": ("base/src/core/FetchHttpRequest.ts.j2", context), + core_dir / "ApiError.ts": ("base/src/core/ApiError.ts.j2", context), + core_dir / "request.ts": ("base/src/core/request.ts.j2", context), + core_dir / "CancelablePromise.ts": ("base/src/core/CancelablePromise.ts.j2", context), + core_dir / "json.ts": ("base/src/core/json.ts.j2", context), + core_dir / "msgpack.ts": ("base/src/core/msgpack.ts.j2", context), + core_dir / "casing.ts": ("base/src/core/casing.ts.j2", context), + # Project files + src_dir / "index.ts": ("base/src/index.ts.j2", context), + output_dir / "package.json": ("base/package.json.j2", context), + output_dir / "tsconfig.json": ("base/tsconfig.json.j2", context), + output_dir / "README.md": ("base/README.md.j2", context), + output_dir / ".prettierignore": ("base/.prettierignore.j2", context), + } - # Client (single service) - files[Path(output_dir) / "src" / "client.ts"] = self.template_engine.render_template( - "client.ts.j2", - {"service_class_name": service_class_name, "client_class_name": client_class_name}, - ) + 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, + }, + ), + src_dir / "index.ts": ("full/src/index.ts.j2", {}), + } - # Replace index with full barrel - files[Path(output_dir) / "src" / "index.ts"] = self.template_engine.render_template( - "full/src/index.ts.j2", - {}, - ) + return self.renderer.render_batch(template_map) - # Note: Generated smoke tests removed; prefer manual integration tests maintained by developers + @staticmethod + def _extract_class_names(package_name: str) -> tuple[str, str]: + """Extract client and service class names from package name.""" - return files + 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/api/oas_generator/ts_oas_generator/parser/__init__.py b/api/oas_generator/ts_oas_generator/parser/__init__.py new file mode 100644 index 000000000..fc70daada --- /dev/null +++ b/api/oas_generator/ts_oas_generator/parser/__init__.py @@ -0,0 +1,5 @@ +"""OpenAPI Specification parser for TypeScript generator.""" + +from ts_oas_generator.parser.oas_parser import OASParser + +__all__ = ["OASParser"] diff --git a/api/oas_generator/ts_oas_generator/parser/oas_parser.py b/api/oas_generator/ts_oas_generator/parser/oas_parser.py new file mode 100644 index 000000000..f4f0a5077 --- /dev/null +++ b/api/oas_generator/ts_oas_generator/parser/oas_parser.py @@ -0,0 +1,49 @@ +""" +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. +""" + +import json +from pathlib import Path +from typing import Any + + +class OASParser: + """Simple parser for OpenAPI 3.x specifications.""" + + # TODO: refine further once utils ts core is within same repo + # to handle x-algokit-signed-txn vendor extension + + 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(): + raise FileNotFoundError(f"OpenAPI spec file not found: {file_path}") + + 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/api/oas_generator/ts_oas_generator/templates/apis/service.ts.j2 b/api/oas_generator/ts_oas_generator/templates/apis/service.ts.j2 index eeac13eea..b9fca231e 100644 --- a/api/oas_generator/ts_oas_generator/templates/apis/service.ts.j2 +++ b/api/oas_generator/ts_oas_generator/templates/apis/service.ts.j2 @@ -7,6 +7,7 @@ export class {{ service_class_name }} { constructor(public readonly httpRequest: BaseHttpRequest) {} {% for op in operations %} + {{ op.description | ts_doc_comment }} {{ op.operationId | ts_camel_case }}( {%- for p in op.pathParameters %} {{ p.varName }}: {{ p.tsType }}, @@ -24,7 +25,7 @@ export class {{ service_class_name }} { requestOptions?: ApiRequestOptions ): Promise<{{ op.responseTsType }}> { const headers: Record = {}; -{% if op.acceptsMsgpack %} +{% if op.returnsMsgpack %} // Content negotiation (aligned with Rust behavior): // - Default to msgpack when available (better performance, smaller payload) // - Only use JSON if explicitly requested via format=json @@ -39,14 +40,14 @@ export class {{ service_class_name }} { headers['Accept'] = 'application/json'; {% endif %} {% if op.requestBody %} -{% if op.requestBodySupportsMsgpack and op.requestBodySupportsJson and op.hasFormatParam and op.formatVarName %} +{% if op.requestBody.supportsMsgpack and op.requestBody.supportsJson and op.hasFormatParam and op.formatVarName %} headers['Content-Type'] = params?.{{ op.formatVarName }} === 'json' ? 'application/json' : 'application/msgpack'; -{% elif op.requestBodySupportsMsgpack and not op.requestBodySupportsJson %} +{% elif op.requestBody.supportsMsgpack and not op.requestBody.supportsJson %} headers['Content-Type'] = 'application/msgpack'; -{% elif op.requestBodySupportsMsgpack and op.requestBodySupportsJson %} +{% elif op.requestBody.supportsMsgpack and op.requestBody.supportsJson %} headers['Content-Type'] = 'application/msgpack'; -{% elif op.requestBody.get('mediaType') %} - headers['Content-Type'] = '{{ op.requestBody['mediaType'] }}'; +{% elif op.requestBody.mediaType %} + headers['Content-Type'] = '{{ op.requestBody.mediaType }}'; {% endif %} {% endif %} @@ -73,29 +74,20 @@ export class {{ service_class_name }} { headers, body: {% if op.requestBody %}params?.body{% else %}undefined{% endif %}, {% if op.requestBody %} -{% if op.requestBodySupportsMsgpack and op.requestBodySupportsJson and op.hasFormatParam and op.formatVarName %} +{% if op.requestBody.supportsMsgpack and op.requestBody.supportsJson and op.hasFormatParam and op.formatVarName %} // Dynamic mediaType based on format parameter (prefer msgpack by default) mediaType: params?.{{ op.formatVarName }} === 'json' ? 'application/json' : 'application/msgpack', -{% elif op.requestBodySupportsMsgpack and not op.requestBodySupportsJson %} +{% elif op.requestBody.supportsMsgpack and not op.requestBody.supportsJson %} // Only msgpack supported for request body mediaType: 'application/msgpack', -{% elif op.requestBodySupportsMsgpack and op.requestBodySupportsJson %} +{% elif op.requestBody.supportsMsgpack and op.requestBody.supportsJson %} // Both supported, prefer msgpack for better performance mediaType: 'application/msgpack', {% else %} - mediaType: '{{ op.requestBody['mediaType'] }}', + mediaType: '{{ op.requestBody.mediaType }}', {% endif %} {% else %} mediaType: undefined, -{% endif %} -{% if op.returnsMsgpack %} -{% if op.hasFormatParam and op.formatVarName %} - expectBinary: params?.{{ op.formatVarName }} === 'json' ? false : true, -{% else %} - expectBinary: true, -{% endif %} -{% else %} - expectBinary: false, {% endif %} ...(requestOptions ?? {}), }); diff --git a/api/oas_generator/ts_oas_generator/templates/base/README.md.j2 b/api/oas_generator/ts_oas_generator/templates/base/README.md.j2 index 5c5937507..a26b47e29 100644 --- a/api/oas_generator/ts_oas_generator/templates/base/README.md.j2 +++ b/api/oas_generator/ts_oas_generator/templates/base/README.md.j2 @@ -12,11 +12,11 @@ Install dependencies and build: ### Configure base URL and create a client ```ts -import { FetchHttpRequest, type ClientConfig, {{ client_class_name }}, {{ service_class_name }} } from './dist/index.js'; +import { {{ client_class_name }} } from './dist/index.js'; -const client = new AlgodClient({ - BASE: env.algodBaseUrl, - HEADERS: env.algodApiToken ? { "X-Algo-API-Token": env.algodApiToken } : undefined, +const client = new {{ client_class_name }}({ + BASE: env.baseUrl, + HEADERS: env.apiToken ? { "X-Algo-API-Token": env.apiToken } : undefined, }); // client is now ready to use diff --git a/api/oas_generator/ts_oas_generator/templates/base/package.json.j2 b/api/oas_generator/ts_oas_generator/templates/base/package.json.j2 index d202e007d..d201d76e7 100644 --- a/api/oas_generator/ts_oas_generator/templates/base/package.json.j2 +++ b/api/oas_generator/ts_oas_generator/templates/base/package.json.j2 @@ -16,6 +16,7 @@ }, "devDependencies": { "@types/json-bigint": "^1.0.0", + "@types/bun": "^1.2.21", "@types/node": "^20.0.0", "algosdk": "^3.0.0", "typescript": "^5.5.0", diff --git a/api/oas_generator/ts_oas_generator/templates/base/src/core/BaseHttpRequest.ts.j2 b/api/oas_generator/ts_oas_generator/templates/base/src/core/BaseHttpRequest.ts.j2 index 5ca88bff5..a6bc9baa7 100644 --- a/api/oas_generator/ts_oas_generator/templates/base/src/core/BaseHttpRequest.ts.j2 +++ b/api/oas_generator/ts_oas_generator/templates/base/src/core/BaseHttpRequest.ts.j2 @@ -9,7 +9,6 @@ export interface RequestOptions { body?: any; mediaType?: string; responseHeader?: string; - expectBinary?: boolean; } // Backwards/ergonomic alias used by generated services diff --git a/api/oas_generator/ts_oas_generator/templates/base/src/core/msgpack.ts.j2 b/api/oas_generator/ts_oas_generator/templates/base/src/core/msgpack.ts.j2 index 1d0213abf..2f9ba0faf 100644 --- a/api/oas_generator/ts_oas_generator/templates/base/src/core/msgpack.ts.j2 +++ b/api/oas_generator/ts_oas_generator/templates/base/src/core/msgpack.ts.j2 @@ -1,4 +1,6 @@ import { encode as msgpackEncode, decode as msgpackDecode } from "@msgpack/msgpack"; +// TODO(utils-ts): Remove temporary type import when utils-ts is integrated +import type { AlgokitSignedTransaction } from '../models'; import type { IntDecoding } from './json'; /** @@ -7,7 +9,7 @@ import type { IntDecoding } from './json'; * 1. Omit zero values, empty strings, and empty arrays (RecursiveEmptyCheck) * 2. Convert bigints to smallest safe integer type (PositiveIntUnsigned) * 3. Sorted keys and canonical encoding are handled by msgpackEncode options - * + * * These rules apply universally for both API communication and transaction encoding, * as go-algorand uses the same codec settings for all msgpack operations. */ @@ -15,13 +17,13 @@ function prepareForEncoding(value: any): any { // eslint-disable-line @typescrip if (value === null || value === undefined) { return undefined; } - + // Handle numbers - omit zeros if (typeof value === 'number') { if (value === 0) return undefined; return value; } - + // Handle bigints - omit zeros and convert to number when safe (for smaller encoding) if (typeof value === 'bigint') { if (value === 0n) return undefined; @@ -31,26 +33,26 @@ function prepareForEncoding(value: any): any { // eslint-disable-line @typescrip } return value; } - + // Handle strings - omit empty strings if (typeof value === 'string') { if (value === '') return undefined; return value; } - + // Handle Uint8Array - omit empty arrays if (value instanceof Uint8Array) { if (value.length === 0) return undefined; return value; } - + // Handle arrays - omit empty arrays and filter undefined values if (Array.isArray(value)) { if (value.length === 0) return undefined; const processed = value.map(prepareForEncoding).filter(v => v !== undefined); return processed.length > 0 ? processed : undefined; } - + // Handle objects - omit empty objects and filter undefined values (RecursiveEmptyCheck) if (value && typeof value === 'object') { const result: any = {}; // eslint-disable-line @typescript-eslint/no-explicit-any @@ -63,7 +65,7 @@ function prepareForEncoding(value: any): any { // eslint-disable-line @typescrip // Return undefined if object is empty after filtering return Object.keys(result).length > 0 ? result : undefined; } - + return value; } @@ -99,16 +101,16 @@ function convertIntegersToBigInt(value: any): any { // eslint-disable-line @type * - Canonical = true (sorted keys, deterministic encoding) * - RecursiveEmptyCheck = true (omit empty/zero values recursively) * - PositiveIntUnsigned = true (use smallest unsigned integer types) - * + * * @param value - The value to encode * @returns Encoded msgpack bytes */ export function encodeMsgPack(value: any): Uint8Array { // eslint-disable-line @typescript-eslint/no-explicit-any const prepared = prepareForEncoding(value); - + // Ensure we return valid msgpack even if everything was omitted const toEncode = prepared === undefined ? {} : prepared; - + return msgpackEncode(toEncode, { sortKeys: true, // Canonical = true in go-algorand forceIntegerToFloat: false, @@ -148,6 +150,9 @@ export function normalizeMsgPackIntegers(value: any, intDecoding: IntDecoding): } } +// Helpers to map SignedTransactionDto <-> AlgokitSignedTransaction if present in responses +// No DTO helpers needed: once utils-ts is integrated, this file remains unchanged. + function traverse(obj: any, fn: (v: any) => void): void { // eslint-disable-line @typescript-eslint/no-explicit-any if (obj == null) return; fn(obj); diff --git a/api/oas_generator/ts_oas_generator/templates/base/src/core/request.ts.j2 b/api/oas_generator/ts_oas_generator/templates/base/src/core/request.ts.j2 index a8813f867..a96a58e24 100644 --- a/api/oas_generator/ts_oas_generator/templates/base/src/core/request.ts.j2 +++ b/api/oas_generator/ts_oas_generator/templates/base/src/core/request.ts.j2 @@ -16,7 +16,6 @@ export async function request(config: ClientConfig, options: { body?: any; mediaType?: string; responseHeader?: string; - expectBinary?: boolean; }): Promise { // Replace path params before constructing URL to avoid encoded braces preventing replacement let rawPath = options.url; @@ -95,6 +94,8 @@ export async function request(config: ClientConfig, options: { const buf = new Uint8Array(await response.arrayBuffer()); const decoded = decodeMsgPack(buf); const normalized = normalizeMsgPackIntegers(decoded, config.INT_DECODING ?? 'bigint'); + // Lightweight mapping: if the response contains arrays/objects with x-algokit-signed-txn shapes + // they will decode to DTOs and be assignable to AlgokitSignedTransaction via alias. return toCamelCaseKeysDeep(normalized) as T; } diff --git a/api/oas_generator/ts_oas_generator/templates/base/src/index.ts.j2 b/api/oas_generator/ts_oas_generator/templates/base/src/index.ts.j2 index 07fe9d426..9eb532395 100644 --- a/api/oas_generator/ts_oas_generator/templates/base/src/index.ts.j2 +++ b/api/oas_generator/ts_oas_generator/templates/base/src/index.ts.j2 @@ -5,7 +5,7 @@ export * from './core/ApiError'; export * from './core/CancelablePromise'; export * from './core/json'; export * from './core/casing'; -export { encodeMsgPack, decodeMsgPack } from './core/msgpack'; +export { encodeMsgPack, decodeMsgPack, normalizeMsgPackIntegers } from './core/msgpack'; // Generated export * from './models'; diff --git a/api/oas_generator/ts_oas_generator/templates/client.ts.j2 b/api/oas_generator/ts_oas_generator/templates/client.ts.j2 index 47946159e..f3d79dec1 100644 --- a/api/oas_generator/ts_oas_generator/templates/client.ts.j2 +++ b/api/oas_generator/ts_oas_generator/templates/client.ts.j2 @@ -2,12 +2,11 @@ import type { ClientConfig } from './core/ClientConfig'; import { FetchHttpRequest } from './core/FetchHttpRequest'; import { {{ service_class_name }} } from './apis/api.service'; -export class {{ client_class_name }} { +export class {{ client_class_name }} extends {{ service_class_name }} { public readonly request: FetchHttpRequest; - public readonly api: {{ service_class_name }}; constructor(config: ClientConfig) { - this.request = new FetchHttpRequest(config); - this.api = new {{ service_class_name }}(this.request); + super(new FetchHttpRequest(config)); + this.request = this.httpRequest as FetchHttpRequest; } } diff --git a/api/oas_generator/ts_oas_generator/templates/models/algokitsignedtransaction.ts.j2 b/api/oas_generator/ts_oas_generator/templates/models/algokitsignedtransaction.ts.j2 new file mode 100644 index 000000000..01e5e014a --- /dev/null +++ b/api/oas_generator/ts_oas_generator/templates/models/algokitsignedtransaction.ts.j2 @@ -0,0 +1,277 @@ +/** + * Temporary SignedTransaction model for msgpack encoding/decoding. + * This will be replaced when utils-ts is integrated into the monorepo. + * + * This type represents a signed Algorand transaction that can be + * encoded to msgpack format for the simulate endpoint. + */ + +/** + * Base transaction structure that all transaction types share + */ +export type BaseTransaction = { + /** Transaction type */ + type: "pay" | "axfer" | "afrz" | "acfg" | "keyreg" | "appl"; + + /** Sender address (base64 or string) */ + sender: string; + + /** Fee in microALGO */ + fee?: number | bigint; + + /** First valid round */ + firstValid: number | bigint; + + /** Last valid round */ + lastValid: number | bigint; + + /** Genesis ID */ + genesisId?: string; + + /** Genesis hash (base64) */ + genesisHash?: string; + + /** Transaction note (base64 or Uint8Array) */ + note?: string | Uint8Array; + + /** Lease (base64) */ + lease?: string; + + /** Rekey to address */ + rekeyTo?: string; + + /** Group ID (base64) */ + group?: string; +}; + +/** + * Payment transaction + */ +export type PaymentTransaction = BaseTransaction & { + type: "pay"; + + /** Receiver address */ + receiver: string; + + /** Amount in microALGO */ + amount: number | bigint; + + /** Close remainder to address */ + closeRemainderTo?: string; +}; + +/** + * Asset transfer transaction + */ +export type AssetTransferTransaction = BaseTransaction & { + type: "axfer"; + + /** Asset ID */ + assetIndex: number | bigint; + + /** Asset amount */ + amount: number | bigint; + + /** Asset receiver */ + receiver: string; + + /** Asset close to */ + closeRemainderTo?: string; + + /** Asset sender (for clawback) */ + assetSender?: string; +}; + +/** + * Asset config transaction + */ +export type AssetConfigTransaction = BaseTransaction & { + type: "acfg"; + + /** Asset ID (0 for creation) */ + assetIndex?: number | bigint; + + /** Asset parameters */ + assetParams?: { + total?: number | bigint; + decimals?: number; + defaultFrozen?: boolean; + unitName?: string; + assetName?: string; + url?: string; + metadataHash?: string; + manager?: string; + reserve?: string; + freeze?: string; + clawback?: string; + }; +}; + +/** + * Asset freeze transaction + */ +export type AssetFreezeTransaction = BaseTransaction & { + type: "afrz"; + + /** Asset ID */ + assetIndex: number | bigint; + + /** Address to freeze/unfreeze */ + freezeAccount: string; + + /** Freeze state */ + frozen: boolean; +}; + +/** + * Key registration transaction + */ +export type KeyRegTransaction = BaseTransaction & { + type: "keyreg"; + + /** Voting key */ + voteKey?: string; + + /** Selection key */ + selectionKey?: string; + + /** State proof key */ + stateProofKey?: string; + + /** First voting round */ + voteFirst?: number | bigint; + + /** Last voting round */ + voteLast?: number | bigint; + + /** Vote key dilution */ + voteKeyDilution?: number | bigint; + + /** Non-participation flag */ + nonParticipation?: boolean; +}; + +/** + * Application call transaction + */ +export type ApplicationTransaction = BaseTransaction & { + type: "appl"; + + /** Application ID (0 for creation) */ + applicationId: number | bigint; + + /** OnComplete action */ + onComplete: number; + + /** Application arguments (base64 encoded) */ + applicationArgs?: string[]; + + /** Accounts array */ + accounts?: string[]; + + /** Foreign apps */ + foreignApps?: (number | bigint)[]; + + /** Foreign assets */ + foreignAssets?: (number | bigint)[]; + + /** Approval program (base64) */ + approvalProgram?: string; + + /** Clear program (base64) */ + clearProgram?: string; + + /** Global state schema */ + globalStateSchema?: { + numUint: number; + numByteSlice: number; + }; + + /** Local state schema */ + localStateSchema?: { + numUint: number; + numByteSlice: number; + }; + + /** Extra program pages */ + extraProgramPages?: number; + + /** Boxes */ + boxes?: Array<{ + appIndex: number | bigint; + name: string; + }>; +}; + +/** + * Union type for all transaction types + */ +export type Transaction = + | PaymentTransaction + | AssetTransferTransaction + | AssetConfigTransaction + | AssetFreezeTransaction + | KeyRegTransaction + | ApplicationTransaction; + +/** + * Multisignature subsignature + */ +export type MultisigSubsignature = { + /** Public key (base64) */ + publicKey?: string; + + /** Signature (base64) */ + signature?: string; +}; + +/** + * Multisignature + */ +export type Multisignature = { + /** Version */ + version: number; + + /** Threshold */ + threshold: number; + + /** Subsignatures */ + subsignatures?: MultisigSubsignature[]; +}; + +/** + * Logic signature + */ +export type LogicSignature = { + /** Logic program (base64) */ + logic: string; + + /** Logic signature arguments (base64 encoded) */ + args?: string[]; + + /** Signature (base64) */ + signature?: string; + + /** Multisignature */ + multisignature?: Multisignature; +}; + +/** + * Signed transaction structure + */ +export type AlgokitSignedTransaction = { + /** The transaction */ + transaction: Transaction; + + /** ED25519 signature (base64) */ + signature?: string; + + /** Multisignature */ + multiSignature?: Multisignature; + + /** Logic signature */ + logicSignature?: LogicSignature; + + /** Auth address (for rekeyed accounts) */ + authAddress?: string; +}; diff --git a/api/oas_generator/ts_oas_generator/templates/models/index.ts.j2 b/api/oas_generator/ts_oas_generator/templates/models/index.ts.j2 index 0d7569af1..fb9b88117 100644 --- a/api/oas_generator/ts_oas_generator/templates/models/index.ts.j2 +++ b/api/oas_generator/ts_oas_generator/templates/models/index.ts.j2 @@ -2,3 +2,7 @@ {% for name, _ in schemas.items() %} export type { {{ name | ts_pascal_case }} } from './{{ name | lower }}'; {% endfor %} +{% if include_temp_signed_txn %} +// TODO(utils-ts): Remove this export when utils-ts provides SignedTransaction types +export type { AlgokitSignedTransaction } from './algokitsignedtransaction'; +{% endif %} diff --git a/packages/typescript/algod_client/README.md b/packages/typescript/algod_client/README.md index 37eb10225..8bb3f8c71 100644 --- a/packages/typescript/algod_client/README.md +++ b/packages/typescript/algod_client/README.md @@ -12,11 +12,11 @@ Install dependencies and build: ### Configure base URL and create a client ```ts -import { FetchHttpRequest, type ClientConfig, AlgodClient, AlgodApi } from "./dist/index.js"; +import { AlgodClient } from "./dist/index.js"; const client = new AlgodClient({ - BASE: env.algodBaseUrl, - HEADERS: env.algodApiToken ? { "X-Algo-API-Token": env.algodApiToken } : undefined, + BASE: env.baseUrl, + HEADERS: env.apiToken ? { "X-Algo-API-Token": env.apiToken } : undefined, }); // client is now ready to use diff --git a/packages/typescript/algod_client/bun.lock b/packages/typescript/algod_client/bun.lock index 33ffe1813..d848aadb6 100644 --- a/packages/typescript/algod_client/bun.lock +++ b/packages/typescript/algod_client/bun.lock @@ -8,6 +8,7 @@ "json-bigint": "^1.0.0", }, "devDependencies": { + "@types/bun": "^1.2.21", "@types/json-bigint": "^1.0.0", "@types/node": "^20.0.0", "algosdk": "^3.0.0", @@ -109,12 +110,16 @@ "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.50.1", "", { "os": "win32", "cpu": "x64" }, "sha512-StxAO/8ts62KZVRAm4JZYq9+NqNsV7RvimNK+YM7ry//zebEH6meuugqW/P5OFUCjyQgui+9fUxT6d5NShvMvA=="], + "@types/bun": ["@types/bun@1.2.21", "", { "dependencies": { "bun-types": "1.2.21" } }, "sha512-NiDnvEqmbfQ6dmZ3EeUO577s4P5bf4HCTXtI6trMc6f6RzirY5IrF3aIookuSpyslFzrnvv2lmEWv5HyC1X79A=="], + "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], "@types/json-bigint": ["@types/json-bigint@1.0.4", "", {}, "sha512-ydHooXLbOmxBbubnA7Eh+RpBzuaIiQjh8WGJYQB50JFGFrdxW7JzVlyEV7fAXw0T2sqJ1ysTneJbiyNLqZRAag=="], "@types/node": ["@types/node@20.19.13", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-yCAeZl7a0DxgNVteXFHt9+uyFbqXGy/ShC4BlcHkoE0AfGXYv/BUiplV72DjMYXHDBXFjhvr6DD1NiRVfB4j8g=="], + "@types/react": ["@types/react@19.1.12", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-cMoR+FoAf/Jyq6+Df2/Z41jISvGZZ2eTlnsaJRptmZ76Caldwy1odD4xTr/gNV9VLj0AWgg/nmkevIyUfIIq5w=="], + "@vitest/expect": ["@vitest/expect@2.1.9", "", { "dependencies": { "@vitest/spy": "2.1.9", "@vitest/utils": "2.1.9", "chai": "^5.1.2", "tinyrainbow": "^1.2.0" } }, "sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw=="], "@vitest/mocker": ["@vitest/mocker@2.1.9", "", { "dependencies": { "@vitest/spy": "2.1.9", "estree-walker": "^3.0.3", "magic-string": "^0.30.12" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^5.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg=="], @@ -137,12 +142,16 @@ "bignumber.js": ["bignumber.js@9.3.1", "", {}, "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ=="], + "bun-types": ["bun-types@1.2.21", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-sa2Tj77Ijc/NTLS0/Odjq/qngmEPZfbfnOERi0KRUYhT9R8M4VBioWVmMWE5GrYbKMc+5lVybXygLdibHaqVqw=="], + "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="], "chai": ["chai@5.3.3", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw=="], "check-error": ["check-error@2.1.1", "", {}, "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw=="], + "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], + "debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], "deep-eql": ["deep-eql@5.0.2", "", {}, "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q=="], diff --git a/packages/typescript/algod_client/package.json b/packages/typescript/algod_client/package.json index ec23cfbea..d846a2cf5 100644 --- a/packages/typescript/algod_client/package.json +++ b/packages/typescript/algod_client/package.json @@ -16,6 +16,7 @@ }, "devDependencies": { "@types/json-bigint": "^1.0.0", + "@types/bun": "^1.2.21", "@types/node": "^20.0.0", "algosdk": "^3.0.0", "typescript": "^5.5.0", diff --git a/packages/typescript/algod_client/src/apis/api.service.ts b/packages/typescript/algod_client/src/apis/api.service.ts index 62d0cbab6..5e0f34461 100644 --- a/packages/typescript/algod_client/src/apis/api.service.ts +++ b/packages/typescript/algod_client/src/apis/api.service.ts @@ -46,6 +46,9 @@ import type { export class AlgodApi { constructor(public readonly httpRequest: BaseHttpRequest) {} + /** + * Given a catchpoint, it aborts catching up to this catchpoint + */ abortCatchup(catchpoint: string, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -60,11 +63,13 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * 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. + */ accountApplicationInformation( address: string, applicationId: number | bigint, @@ -88,11 +93,13 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: params?.format === "json" ? false : true, ...(requestOptions ?? {}), }); } + /** + * 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. + */ accountAssetInformation( address: string, assetId: number | bigint, @@ -116,11 +123,13 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: params?.format === "json" ? false : true, ...(requestOptions ?? {}), }); } + /** + * Lookup an account's asset holdings. + */ accountAssetsInformation( address: string, params?: { limit?: number | bigint; next?: string }, @@ -139,11 +148,13 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Given a specific account public key, this call returns the account's status, balance and spendable amounts + */ accountInformation( address: string, params?: { exclude?: "all" | "none"; format?: "json" | "msgpack" }, @@ -166,7 +177,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: params?.format === "json" ? false : true, ...(requestOptions ?? {}), }); } @@ -187,11 +197,13 @@ export class AlgodApi { body: params?.body, // Only msgpack supported for request body mediaType: "application/msgpack", - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Given a participation ID, append state proof keys to a particular set of participation keys + */ appendKeys(participationId: string, params?: { body: string }, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -208,11 +220,13 @@ export class AlgodApi { body: params?.body, // Only msgpack supported for request body mediaType: "application/msgpack", - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Delete a given participation key by ID + */ deleteParticipationKeyById(participationId: string, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -227,7 +241,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } @@ -246,7 +259,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } @@ -273,11 +285,13 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * 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...'. + */ getApplicationBoxByName(applicationId: number | bigint, params?: { name: string }, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -292,11 +306,13 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * 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. + */ getApplicationBoxes( applicationId: number | bigint, params?: { max?: number | bigint }, @@ -315,11 +331,13 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Given a application ID, it returns application information including creator, approval and clear programs, global and local schemas, and global state. + */ getApplicationById(applicationId: number | bigint, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -334,11 +352,13 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Given a asset ID, it returns asset information including creator, name, total supply and special addresses. + */ getAssetById(assetId: number | bigint, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -353,7 +373,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } @@ -380,7 +399,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: params?.format === "json" ? false : true, ...(requestOptions ?? {}), }); } @@ -399,11 +417,13 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Get all of the logs from outer and inner app calls in the given round + */ getBlockLogs(round: number | bigint, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -418,11 +438,13 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Gets the current timestamp offset. + */ getBlockTimeStampOffset(requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -437,7 +459,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } @@ -456,11 +477,13 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Returns the merged (defaults + overrides) config file in json. + */ getConfig(requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -475,11 +498,13 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Retrieves the current settings for blocking and mutex profiles + */ getDebugSettingsProf(requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -494,11 +519,13 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Returns the entire genesis file in json. + */ getGenesis(requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -513,11 +540,13 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Get ledger deltas for a round. + */ getLedgerStateDelta( round: number | bigint, params?: { format?: "json" | "msgpack" }, @@ -540,11 +569,13 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: params?.format === "json" ? false : true, ...(requestOptions ?? {}), }); } + /** + * Get a ledger delta for a given transaction group. + */ getLedgerStateDeltaForTransactionGroup( id: string, params?: { format?: "json" | "msgpack" }, @@ -567,7 +598,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: params?.format === "json" ? false : true, ...(requestOptions ?? {}), }); } @@ -586,11 +616,13 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Given a participation ID, return information about that participation key + */ getParticipationKeyById(participationId: string, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -605,11 +637,13 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Return a list of participation keys + */ getParticipationKeys(requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -624,11 +658,13 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * 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. + */ getPendingTransactions( params?: { max?: number | bigint; format?: "json" | "msgpack" }, requestOptions?: ApiRequestOptions, @@ -650,11 +686,13 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: params?.format === "json" ? false : true, ...(requestOptions ?? {}), }); } + /** + * 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. + */ getPendingTransactionsByAddress( address: string, params?: { max?: number | bigint; format?: "json" | "msgpack" }, @@ -677,7 +715,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: params?.format === "json" ? false : true, ...(requestOptions ?? {}), }); } @@ -696,7 +733,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } @@ -715,7 +751,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } @@ -734,7 +769,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } @@ -753,11 +787,13 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Gets the minimum sync round for the ledger. + */ getSyncRound(requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -772,11 +808,13 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Get ledger deltas for transaction groups in a given round. + */ getTransactionGroupLedgerStateDeltasForRound( round: number | bigint, params?: { format?: "json" | "msgpack" }, @@ -799,7 +837,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: params?.format === "json" ? false : true, ...(requestOptions ?? {}), }); } @@ -823,11 +860,13 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Retrieves the supported API versions, binary build versions, and genesis information. + */ getVersion(requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -842,7 +881,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } @@ -861,7 +899,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } @@ -880,11 +917,17 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * 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) + * - transaction still in the pool (committed round = 0, pool error = "") + * - 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. + */ pendingTransactionInformation( txid: string, params?: { format?: "json" | "msgpack" }, @@ -907,11 +950,13 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: params?.format === "json" ? false : true, ...(requestOptions ?? {}), }); } + /** + * Enables blocking and mutex profiles, and returns the old settings + */ putDebugSettingsProf(requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -926,7 +971,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } @@ -946,7 +990,6 @@ export class AlgodApi { headers, body: params?.body, mediaType: "application/x-binary", - expectBinary: false, ...(requestOptions ?? {}), }); } @@ -966,11 +1009,13 @@ export class AlgodApi { headers, body: params?.body, mediaType: "application/x-binary", - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * 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. + */ setBlockTimeStampOffset(offset: number | bigint, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -985,11 +1030,13 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Sets the minimum sync round on the ledger. + */ setSyncRound(round: number | bigint, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -1004,11 +1051,13 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * 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. + */ shutdownNode(params?: { timeout?: number | bigint }, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -1023,7 +1072,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } @@ -1051,11 +1099,13 @@ export class AlgodApi { body: params?.body, // Dynamic mediaType based on format parameter (prefer msgpack by default) mediaType: params?.format === "json" ? "application/json" : "application/msgpack", - expectBinary: params?.format === "json" ? false : true, ...(requestOptions ?? {}), }); } + /** + * Given a catchpoint, it starts catching up to this catchpoint + */ startCatchup(catchpoint: string, params?: { min?: number | bigint }, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -1070,11 +1120,13 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Returns the entire swagger spec in json. + */ swaggerJson(requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -1089,11 +1141,13 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * 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. + */ tealCompile(params?: { sourcemap?: boolean; body: string }, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -1109,11 +1163,13 @@ export class AlgodApi { headers, body: params?.body, mediaType: "text/plain", - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * 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. + */ tealDisassemble(params?: { body: Uint8Array }, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -1129,11 +1185,13 @@ export class AlgodApi { headers, body: params?.body, mediaType: "application/x-binary", - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * 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. + */ tealDryrun(params?: { body?: DryrunRequest }, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -1150,7 +1208,6 @@ export class AlgodApi { body: params?.body, // Both supported, prefer msgpack for better performance mediaType: "application/msgpack", - expectBinary: false, ...(requestOptions ?? {}), }); } @@ -1169,11 +1226,13 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Unset the ledger sync round. + */ unsetSyncRound(requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -1188,11 +1247,13 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * 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. + */ waitForBlock(round: number | bigint, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -1207,7 +1268,6 @@ export class AlgodApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } diff --git a/packages/typescript/algod_client/src/client.ts b/packages/typescript/algod_client/src/client.ts index 2c8f50e71..2175e3a01 100644 --- a/packages/typescript/algod_client/src/client.ts +++ b/packages/typescript/algod_client/src/client.ts @@ -2,12 +2,11 @@ import type { ClientConfig } from "./core/ClientConfig"; import { FetchHttpRequest } from "./core/FetchHttpRequest"; import { AlgodApi } from "./apis/api.service"; -export class AlgodClient { +export class AlgodClient extends AlgodApi { public readonly request: FetchHttpRequest; - public readonly api: AlgodApi; constructor(config: ClientConfig) { - this.request = new FetchHttpRequest(config); - this.api = new AlgodApi(this.request); + super(new FetchHttpRequest(config)); + this.request = this.httpRequest as FetchHttpRequest; } } diff --git a/packages/typescript/algod_client/src/core/BaseHttpRequest.ts b/packages/typescript/algod_client/src/core/BaseHttpRequest.ts index 45f2f0666..4a8fbe3e1 100644 --- a/packages/typescript/algod_client/src/core/BaseHttpRequest.ts +++ b/packages/typescript/algod_client/src/core/BaseHttpRequest.ts @@ -9,7 +9,6 @@ export interface RequestOptions { body?: any; mediaType?: string; responseHeader?: string; - expectBinary?: boolean; } // Backwards/ergonomic alias used by generated services diff --git a/packages/typescript/algod_client/src/core/msgpack.ts b/packages/typescript/algod_client/src/core/msgpack.ts index a30aa9314..8e3025089 100644 --- a/packages/typescript/algod_client/src/core/msgpack.ts +++ b/packages/typescript/algod_client/src/core/msgpack.ts @@ -1,4 +1,6 @@ import { encode as msgpackEncode, decode as msgpackDecode } from "@msgpack/msgpack"; +// TODO(utils-ts): Remove temporary type import when utils-ts is integrated +import type { AlgokitSignedTransaction } from "../models"; import type { IntDecoding } from "./json"; /** @@ -153,6 +155,9 @@ export function normalizeMsgPackIntegers(value: any, intDecoding: IntDecoding): } } +// Helpers to map SignedTransactionDto <-> AlgokitSignedTransaction if present in responses +// No DTO helpers needed: once utils-ts is integrated, this file remains unchanged. + function traverse(obj: any, fn: (v: any) => void): void { // eslint-disable-line @typescript-eslint/no-explicit-any if (obj == null) return; diff --git a/packages/typescript/algod_client/src/core/request.ts b/packages/typescript/algod_client/src/core/request.ts index 38eb3d463..fbe1f771c 100644 --- a/packages/typescript/algod_client/src/core/request.ts +++ b/packages/typescript/algod_client/src/core/request.ts @@ -18,7 +18,6 @@ export async function request( body?: any; mediaType?: string; responseHeader?: string; - expectBinary?: boolean; }, ): Promise { // Replace path params before constructing URL to avoid encoded braces preventing replacement @@ -98,6 +97,8 @@ export async function request( const buf = new Uint8Array(await response.arrayBuffer()); const decoded = decodeMsgPack(buf); const normalized = normalizeMsgPackIntegers(decoded, config.INT_DECODING ?? "bigint"); + // Lightweight mapping: if the response contains arrays/objects with x-algokit-signed-txn shapes + // they will decode to DTOs and be assignable to AlgokitSignedTransaction via alias. return toCamelCaseKeysDeep(normalized) as T; } diff --git a/packages/typescript/algod_client/src/models/abortcatchup.ts b/packages/typescript/algod_client/src/models/abortcatchup.ts index 7bc622991..907aae39f 100644 --- a/packages/typescript/algod_client/src/models/abortcatchup.ts +++ b/packages/typescript/algod_client/src/models/abortcatchup.ts @@ -1,4 +1,9 @@ /** * An catchpoint abort response. */ -export type AbortCatchup = { catchupMessage: string }; +export type AbortCatchup = { + /** + * Catchup abort response string + */ + catchupMessage: string; +}; diff --git a/packages/typescript/algod_client/src/models/account.ts b/packages/typescript/algod_client/src/models/account.ts index 183c7871f..b3fe3f408 100644 --- a/packages/typescript/algod_client/src/models/account.ts +++ b/packages/typescript/algod_client/src/models/account.ts @@ -7,31 +7,146 @@ import type { AccountParticipation, Application, ApplicationLocalState, Applicat * data/basics/userBalance.go : AccountData */ export type Account = { + /** + * the account public key + */ address: string; + + /** + * \[algo\] total number of MicroAlgos in the account + */ amount: bigint; + + /** + * MicroAlgo balance required by the account. + * + * The requirement grows based on asset and application usage. + */ minBalance: bigint; + + /** + * specifies the amount of MicroAlgos in the account, without the pending rewards. + */ amountWithoutPendingRewards: bigint; + + /** + * \[appl\] applications local data stored in this account. + * + * Note the raw object uses `map[int] -> AppLocalState` for this type. + */ appsLocalState?: ApplicationLocalState[]; + + /** + * 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; appsTotalSchema?: ApplicationStateSchema; + + /** + * \[teap\] the sum of all extra application program pages for this account. + */ appsTotalExtraPages?: bigint; + + /** + * \[asset\] assets held by this account. + * + * Note the raw object uses `map[int] -> AssetHolding` for this type. + */ assets?: AssetHolding[]; + + /** + * The count of all assets that have been opted in, equivalent to the count of AssetHolding objects held by this account. + */ totalAssetsOptedIn: bigint; + + /** + * \[appp\] parameters of applications created by this account including app global data. + * + * Note: the raw account uses `map[int] -> AppParams` for this type. + */ createdApps?: Application[]; + + /** + * The count of all apps (AppParams objects) created by this account. + */ totalCreatedApps: bigint; + + /** + * \[apar\] parameters of assets created by this account. + * + * Note: the raw account uses `map[int] -> Asset` for this type. + */ createdAssets?: Asset[]; + + /** + * The count of all assets (AssetParams objects) created by this account. + */ totalCreatedAssets: bigint; + + /** + * \[tbx\] The number of existing boxes created by this account's app. + */ totalBoxes?: bigint; + + /** + * \[tbxb\] The total number of bytes used by this account's app's box keys and values. + */ totalBoxBytes?: bigint; participation?: AccountParticipation; + + /** + * Whether or not the account can receive block incentives if its balance is in range at proposal time. + */ incentiveEligible?: boolean; + + /** + * amount of MicroAlgos of pending rewards in this account. + */ pendingRewards: bigint; + + /** + * \[ebase\] used as part of the rewards computation. Only applicable to accounts which are participating. + */ rewardBase?: bigint; + + /** + * \[ern\] total rewards of MicroAlgos the account has received, including pending rewards. + */ rewards: bigint; + + /** + * The round for which this information is relevant. + */ round: bigint; + + /** + * \[onl\] delegation status of the account's MicroAlgos + * * Offline - indicates that the associated account is delegated. + * * Online - indicates that the associated account used as part of the delegation pool. + * * NotParticipating - indicates that the associated account is neither a delegator nor a delegate. + */ status: string; + + /** + * Indicates what type of signature is used by this account, must be one of: + * * sig + * * msig + * * lsig + */ sigType?: "sig" | "msig" | "lsig"; + + /** + * \[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. + */ authAddr?: string; + + /** + * The round in which this account last proposed the block. + */ lastProposed?: bigint; + + /** + * The round in which this account last went online, or explicitly renewed their online status. + */ lastHeartbeat?: bigint; }; diff --git a/packages/typescript/algod_client/src/models/accountapplicationinformation.ts b/packages/typescript/algod_client/src/models/accountapplicationinformation.ts index c80c9c212..4440b1dcc 100644 --- a/packages/typescript/algod_client/src/models/accountapplicationinformation.ts +++ b/packages/typescript/algod_client/src/models/accountapplicationinformation.ts @@ -1,6 +1,10 @@ import type { ApplicationLocalState, ApplicationParams } from "./index"; -/** - * 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. - */ -export type AccountApplicationInformation = { round: bigint; appLocalState?: ApplicationLocalState; createdApp?: ApplicationParams }; +export type AccountApplicationInformation = { + /** + * The round for which this information is relevant. + */ + round: bigint; + appLocalState?: ApplicationLocalState; + createdApp?: ApplicationParams; +}; diff --git a/packages/typescript/algod_client/src/models/accountassetholding.ts b/packages/typescript/algod_client/src/models/accountassetholding.ts index 5fbf11c31..e6efa5db0 100644 --- a/packages/typescript/algod_client/src/models/accountassetholding.ts +++ b/packages/typescript/algod_client/src/models/accountassetholding.ts @@ -3,4 +3,7 @@ import type { AssetHolding, AssetParams } from "./index"; /** * 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 type AccountAssetHolding = { + assetHolding: AssetHolding; + assetParams?: AssetParams; +}; diff --git a/packages/typescript/algod_client/src/models/accountassetinformation.ts b/packages/typescript/algod_client/src/models/accountassetinformation.ts index b0cfdb675..2a2cd6dac 100644 --- a/packages/typescript/algod_client/src/models/accountassetinformation.ts +++ b/packages/typescript/algod_client/src/models/accountassetinformation.ts @@ -1,6 +1,10 @@ import type { AssetHolding, AssetParams } from "./index"; -/** - * 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. - */ -export type AccountAssetInformation = { round: bigint; assetHolding?: AssetHolding; createdAsset?: AssetParams }; +export type AccountAssetInformation = { + /** + * The round for which this information is relevant. + */ + round: bigint; + assetHolding?: AssetHolding; + createdAsset?: AssetParams; +}; diff --git a/packages/typescript/algod_client/src/models/accountassetsinformation.ts b/packages/typescript/algod_client/src/models/accountassetsinformation.ts index 3e82d65e9..1cbb9b405 100644 --- a/packages/typescript/algod_client/src/models/accountassetsinformation.ts +++ b/packages/typescript/algod_client/src/models/accountassetsinformation.ts @@ -1,6 +1,14 @@ import type { AccountAssetHolding } from "./index"; -/** - * AccountAssetsInformationResponse contains a list of assets held by an account. - */ -export type AccountAssetsInformation = { round: bigint; nextToken?: string; assetHoldings?: AccountAssetHolding[] }; +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[]; +}; diff --git a/packages/typescript/algod_client/src/models/accountparticipation.ts b/packages/typescript/algod_client/src/models/accountparticipation.ts index b77cf3b00..8942954fe 100644 --- a/packages/typescript/algod_client/src/models/accountparticipation.ts +++ b/packages/typescript/algod_client/src/models/accountparticipation.ts @@ -2,10 +2,33 @@ * AccountParticipation describes the parameters used by this account in consensus protocol. */ export type AccountParticipation = { + /** + * \[sel\] Selection public key (if any) currently registered for this round. + */ selectionParticipationKey: string; + + /** + * \[voteFst\] First round for which this participation is valid. + */ voteFirstValid: bigint; + + /** + * \[voteKD\] Number of subkeys in each batch of participation keys. + */ voteKeyDilution: bigint; + + /** + * \[voteLst\] Last round for which this participation is valid. + */ voteLastValid: bigint; + + /** + * \[vote\] root participation public key (if any) currently registered for this round. + */ voteParticipationKey: string; + + /** + * \[stprf\] Root of the state proof key (if any) + */ stateProofKey?: string; }; diff --git a/packages/typescript/algod_client/src/models/accountstatedelta.ts b/packages/typescript/algod_client/src/models/accountstatedelta.ts index b2d101cad..5bd98a58e 100644 --- a/packages/typescript/algod_client/src/models/accountstatedelta.ts +++ b/packages/typescript/algod_client/src/models/accountstatedelta.ts @@ -3,4 +3,7 @@ import type { StateDelta } from "./index"; /** * Application state delta. */ -export type AccountStateDelta = { address: string; delta: StateDelta }; +export type AccountStateDelta = { + address: string; + delta: StateDelta; +}; diff --git a/packages/typescript/algod_client/src/models/addparticipationkey.ts b/packages/typescript/algod_client/src/models/addparticipationkey.ts index 77eb9f8b7..ae731eeb3 100644 --- a/packages/typescript/algod_client/src/models/addparticipationkey.ts +++ b/packages/typescript/algod_client/src/models/addparticipationkey.ts @@ -1,4 +1,6 @@ -/** - * Participation ID of the submission - */ -export type AddParticipationKey = { partId: string }; +export type AddParticipationKey = { + /** + * encoding of the participation ID. + */ + partId: string; +}; diff --git a/packages/typescript/algod_client/src/models/algokitsignedtransaction.ts b/packages/typescript/algod_client/src/models/algokitsignedtransaction.ts new file mode 100644 index 000000000..01e5e014a --- /dev/null +++ b/packages/typescript/algod_client/src/models/algokitsignedtransaction.ts @@ -0,0 +1,277 @@ +/** + * Temporary SignedTransaction model for msgpack encoding/decoding. + * This will be replaced when utils-ts is integrated into the monorepo. + * + * This type represents a signed Algorand transaction that can be + * encoded to msgpack format for the simulate endpoint. + */ + +/** + * Base transaction structure that all transaction types share + */ +export type BaseTransaction = { + /** Transaction type */ + type: "pay" | "axfer" | "afrz" | "acfg" | "keyreg" | "appl"; + + /** Sender address (base64 or string) */ + sender: string; + + /** Fee in microALGO */ + fee?: number | bigint; + + /** First valid round */ + firstValid: number | bigint; + + /** Last valid round */ + lastValid: number | bigint; + + /** Genesis ID */ + genesisId?: string; + + /** Genesis hash (base64) */ + genesisHash?: string; + + /** Transaction note (base64 or Uint8Array) */ + note?: string | Uint8Array; + + /** Lease (base64) */ + lease?: string; + + /** Rekey to address */ + rekeyTo?: string; + + /** Group ID (base64) */ + group?: string; +}; + +/** + * Payment transaction + */ +export type PaymentTransaction = BaseTransaction & { + type: "pay"; + + /** Receiver address */ + receiver: string; + + /** Amount in microALGO */ + amount: number | bigint; + + /** Close remainder to address */ + closeRemainderTo?: string; +}; + +/** + * Asset transfer transaction + */ +export type AssetTransferTransaction = BaseTransaction & { + type: "axfer"; + + /** Asset ID */ + assetIndex: number | bigint; + + /** Asset amount */ + amount: number | bigint; + + /** Asset receiver */ + receiver: string; + + /** Asset close to */ + closeRemainderTo?: string; + + /** Asset sender (for clawback) */ + assetSender?: string; +}; + +/** + * Asset config transaction + */ +export type AssetConfigTransaction = BaseTransaction & { + type: "acfg"; + + /** Asset ID (0 for creation) */ + assetIndex?: number | bigint; + + /** Asset parameters */ + assetParams?: { + total?: number | bigint; + decimals?: number; + defaultFrozen?: boolean; + unitName?: string; + assetName?: string; + url?: string; + metadataHash?: string; + manager?: string; + reserve?: string; + freeze?: string; + clawback?: string; + }; +}; + +/** + * Asset freeze transaction + */ +export type AssetFreezeTransaction = BaseTransaction & { + type: "afrz"; + + /** Asset ID */ + assetIndex: number | bigint; + + /** Address to freeze/unfreeze */ + freezeAccount: string; + + /** Freeze state */ + frozen: boolean; +}; + +/** + * Key registration transaction + */ +export type KeyRegTransaction = BaseTransaction & { + type: "keyreg"; + + /** Voting key */ + voteKey?: string; + + /** Selection key */ + selectionKey?: string; + + /** State proof key */ + stateProofKey?: string; + + /** First voting round */ + voteFirst?: number | bigint; + + /** Last voting round */ + voteLast?: number | bigint; + + /** Vote key dilution */ + voteKeyDilution?: number | bigint; + + /** Non-participation flag */ + nonParticipation?: boolean; +}; + +/** + * Application call transaction + */ +export type ApplicationTransaction = BaseTransaction & { + type: "appl"; + + /** Application ID (0 for creation) */ + applicationId: number | bigint; + + /** OnComplete action */ + onComplete: number; + + /** Application arguments (base64 encoded) */ + applicationArgs?: string[]; + + /** Accounts array */ + accounts?: string[]; + + /** Foreign apps */ + foreignApps?: (number | bigint)[]; + + /** Foreign assets */ + foreignAssets?: (number | bigint)[]; + + /** Approval program (base64) */ + approvalProgram?: string; + + /** Clear program (base64) */ + clearProgram?: string; + + /** Global state schema */ + globalStateSchema?: { + numUint: number; + numByteSlice: number; + }; + + /** Local state schema */ + localStateSchema?: { + numUint: number; + numByteSlice: number; + }; + + /** Extra program pages */ + extraProgramPages?: number; + + /** Boxes */ + boxes?: Array<{ + appIndex: number | bigint; + name: string; + }>; +}; + +/** + * Union type for all transaction types + */ +export type Transaction = + | PaymentTransaction + | AssetTransferTransaction + | AssetConfigTransaction + | AssetFreezeTransaction + | KeyRegTransaction + | ApplicationTransaction; + +/** + * Multisignature subsignature + */ +export type MultisigSubsignature = { + /** Public key (base64) */ + publicKey?: string; + + /** Signature (base64) */ + signature?: string; +}; + +/** + * Multisignature + */ +export type Multisignature = { + /** Version */ + version: number; + + /** Threshold */ + threshold: number; + + /** Subsignatures */ + subsignatures?: MultisigSubsignature[]; +}; + +/** + * Logic signature + */ +export type LogicSignature = { + /** Logic program (base64) */ + logic: string; + + /** Logic signature arguments (base64 encoded) */ + args?: string[]; + + /** Signature (base64) */ + signature?: string; + + /** Multisignature */ + multisignature?: Multisignature; +}; + +/** + * Signed transaction structure + */ +export type AlgokitSignedTransaction = { + /** The transaction */ + transaction: Transaction; + + /** ED25519 signature (base64) */ + signature?: string; + + /** Multisignature */ + multiSignature?: Multisignature; + + /** Logic signature */ + logicSignature?: LogicSignature; + + /** Auth address (for rekeyed accounts) */ + authAddress?: string; +}; diff --git a/packages/typescript/algod_client/src/models/appcalllogs.ts b/packages/typescript/algod_client/src/models/appcalllogs.ts index 04e727db5..cd1f24d7e 100644 --- a/packages/typescript/algod_client/src/models/appcalllogs.ts +++ b/packages/typescript/algod_client/src/models/appcalllogs.ts @@ -1,4 +1,19 @@ /** * 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 = { logs: string[]; applicationIndex: bigint; txId: string }; +export type AppCallLogs = { + /** + * An array of logs + */ + logs: string[]; + + /** + * The application from which the logs were generated + */ + applicationIndex: bigint; + + /** + * The transaction ID of the outer app call that lead to these logs + */ + txId: string; +}; diff --git a/packages/typescript/algod_client/src/models/application.ts b/packages/typescript/algod_client/src/models/application.ts index a04d775da..da46db81f 100644 --- a/packages/typescript/algod_client/src/models/application.ts +++ b/packages/typescript/algod_client/src/models/application.ts @@ -3,4 +3,10 @@ import type { ApplicationParams } from "./index"; /** * Application index and its parameters */ -export type Application = { id: bigint; params: ApplicationParams }; +export type Application = { + /** + * \[appidx\] application index. + */ + id: bigint; + params: ApplicationParams; +}; diff --git a/packages/typescript/algod_client/src/models/applicationinitialstates.ts b/packages/typescript/algod_client/src/models/applicationinitialstates.ts index a75123b82..241e0717e 100644 --- a/packages/typescript/algod_client/src/models/applicationinitialstates.ts +++ b/packages/typescript/algod_client/src/models/applicationinitialstates.ts @@ -4,7 +4,14 @@ import type { ApplicationKvstorage } from "./index"; * An application's initial global/local/box states that were accessed during simulation. */ export type ApplicationInitialStates = { + /** + * Application index. + */ id: bigint; + + /** + * An application's initial local states tied to different accounts. + */ appLocals?: ApplicationKvstorage[]; appGlobals?: ApplicationKvstorage; appBoxes?: ApplicationKvstorage; diff --git a/packages/typescript/algod_client/src/models/applicationkvstorage.ts b/packages/typescript/algod_client/src/models/applicationkvstorage.ts index d91bdb14f..eabe49e7c 100644 --- a/packages/typescript/algod_client/src/models/applicationkvstorage.ts +++ b/packages/typescript/algod_client/src/models/applicationkvstorage.ts @@ -3,4 +3,14 @@ import type { AvmKeyValue } from "./index"; /** * An application's global/local/box state. */ -export type ApplicationKvstorage = { kvs: AvmKeyValue[]; account?: string }; +export type ApplicationKvstorage = { + /** + * Key-Value pairs representing application states. + */ + kvs: AvmKeyValue[]; + + /** + * The address of the account associated with the local state. + */ + account?: string; +}; diff --git a/packages/typescript/algod_client/src/models/applicationlocalreference.ts b/packages/typescript/algod_client/src/models/applicationlocalreference.ts index 6236b71ba..bdc9d1ed5 100644 --- a/packages/typescript/algod_client/src/models/applicationlocalreference.ts +++ b/packages/typescript/algod_client/src/models/applicationlocalreference.ts @@ -1,4 +1,14 @@ /** * References an account's local state for an application. */ -export type ApplicationLocalReference = { account: string; app: bigint }; +export type ApplicationLocalReference = { + /** + * Address of the account with the local state. + */ + account: string; + + /** + * Application ID of the local state application. + */ + app: bigint; +}; diff --git a/packages/typescript/algod_client/src/models/applicationlocalstate.ts b/packages/typescript/algod_client/src/models/applicationlocalstate.ts index 59ebece87..6f1de2149 100644 --- a/packages/typescript/algod_client/src/models/applicationlocalstate.ts +++ b/packages/typescript/algod_client/src/models/applicationlocalstate.ts @@ -3,4 +3,11 @@ import type { ApplicationStateSchema, TealKeyValueStore } from "./index"; /** * Stores local state associated with an application. */ -export type ApplicationLocalState = { id: bigint; schema: ApplicationStateSchema; keyValue?: TealKeyValueStore }; +export type ApplicationLocalState = { + /** + * The application which this local state is for. + */ + id: bigint; + schema: ApplicationStateSchema; + keyValue?: TealKeyValueStore; +}; diff --git a/packages/typescript/algod_client/src/models/applicationparams.ts b/packages/typescript/algod_client/src/models/applicationparams.ts index 0ad5c10f3..aa6ae024a 100644 --- a/packages/typescript/algod_client/src/models/applicationparams.ts +++ b/packages/typescript/algod_client/src/models/applicationparams.ts @@ -4,12 +4,31 @@ import type { ApplicationStateSchema, TealKeyValueStore } from "./index"; * Stores the global information associated with an application. */ export type ApplicationParams = { + /** + * The address that created this application. This is the address where the parameters and global state for this application can be found. + */ creator: string; + + /** + * \[approv\] approval program. + */ approvalProgram: string; + + /** + * \[clearp\] approval program. + */ clearStateProgram: string; + + /** + * \[epp\] the amount of extra program pages available to this app. + */ extraProgramPages?: bigint; localStateSchema?: ApplicationStateSchema; globalStateSchema?: ApplicationStateSchema; globalState?: TealKeyValueStore; + + /** + * \[v\] the number of updates to the application programs + */ version?: bigint; }; diff --git a/packages/typescript/algod_client/src/models/applicationstateoperation.ts b/packages/typescript/algod_client/src/models/applicationstateoperation.ts index 5e7eba254..70d83cee6 100644 --- a/packages/typescript/algod_client/src/models/applicationstateoperation.ts +++ b/packages/typescript/algod_client/src/models/applicationstateoperation.ts @@ -3,4 +3,25 @@ import type { AvmValue } from "./index"; /** * An operation against an application's global/local/box state. */ -export type ApplicationStateOperation = { operation: string; appStateType: string; key: string; newValue?: AvmValue; account?: string }; +export type ApplicationStateOperation = { + /** + * Operation type. Value `w` is **write**, `d` is **delete**. + */ + operation: string; + + /** + * Type of application state. Value `g` is **global state**, `l` is **local state**, `b` is **boxes**. + */ + appStateType: string; + + /** + * The key (name) of the global/local/box state. + */ + key: string; + newValue?: AvmValue; + + /** + * For local state changes, the address of the account associated with the local state. + */ + account?: string; +}; diff --git a/packages/typescript/algod_client/src/models/applicationstateschema.ts b/packages/typescript/algod_client/src/models/applicationstateschema.ts index d40cb1f25..4b9f2fe0f 100644 --- a/packages/typescript/algod_client/src/models/applicationstateschema.ts +++ b/packages/typescript/algod_client/src/models/applicationstateschema.ts @@ -1,4 +1,14 @@ /** * Specifies maximums on the number of each type that may be stored. */ -export type ApplicationStateSchema = { numUint: bigint; numByteSlice: bigint }; +export type ApplicationStateSchema = { + /** + * \[nui\] num of uints. + */ + numUint: bigint; + + /** + * \[nbs\] num of byte slices. + */ + numByteSlice: bigint; +}; diff --git a/packages/typescript/algod_client/src/models/asset.ts b/packages/typescript/algod_client/src/models/asset.ts index 43f981b8c..fa1558d00 100644 --- a/packages/typescript/algod_client/src/models/asset.ts +++ b/packages/typescript/algod_client/src/models/asset.ts @@ -3,4 +3,10 @@ import type { AssetParams } from "./index"; /** * Specifies both the unique identifier and the parameters for an asset */ -export type Asset = { index: bigint; params: AssetParams }; +export type Asset = { + /** + * unique asset identifier + */ + index: bigint; + params: AssetParams; +}; diff --git a/packages/typescript/algod_client/src/models/assetholding.ts b/packages/typescript/algod_client/src/models/assetholding.ts index 710ebb107..39ae6b19f 100644 --- a/packages/typescript/algod_client/src/models/assetholding.ts +++ b/packages/typescript/algod_client/src/models/assetholding.ts @@ -4,4 +4,19 @@ * Definition: * data/basics/userBalance.go : AssetHolding */ -export type AssetHolding = { amount: bigint; assetId: bigint; isFrozen: boolean }; +export type AssetHolding = { + /** + * \[a\] number of units held. + */ + amount: bigint; + + /** + * Asset ID of the holding. + */ + assetId: bigint; + + /** + * \[f\] whether or not the holding is frozen. + */ + isFrozen: boolean; +}; diff --git a/packages/typescript/algod_client/src/models/assetholdingreference.ts b/packages/typescript/algod_client/src/models/assetholdingreference.ts index c8cf78492..67b6f116e 100644 --- a/packages/typescript/algod_client/src/models/assetholdingreference.ts +++ b/packages/typescript/algod_client/src/models/assetholdingreference.ts @@ -1,4 +1,14 @@ /** * References an asset held by an account. */ -export type AssetHoldingReference = { account: string; asset: bigint }; +export type AssetHoldingReference = { + /** + * Address of the account holding the asset. + */ + account: string; + + /** + * Asset ID of the holding. + */ + asset: bigint; +}; diff --git a/packages/typescript/algod_client/src/models/assetparams.ts b/packages/typescript/algod_client/src/models/assetparams.ts index 3ff1492fc..907b71fc5 100644 --- a/packages/typescript/algod_client/src/models/assetparams.ts +++ b/packages/typescript/algod_client/src/models/assetparams.ts @@ -7,19 +7,78 @@ * data/transactions/asset.go : AssetParams */ export type AssetParams = { + /** + * \[c\] Address of account used to clawback holdings of this asset. If empty, clawback is not permitted. + */ clawback?: string; + + /** + * 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. + */ creator: string; + + /** + * \[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; + + /** + * \[df\] Whether holdings of this asset are frozen by default. + */ defaultFrozen?: boolean; + + /** + * \[f\] Address of account used to freeze holdings of this asset. If empty, freezing is not permitted. + */ freeze?: string; + + /** + * \[m\] Address of account used to manage the keys of this asset and to destroy it. + */ manager?: string; + + /** + * \[am\] A commitment to some unspecified asset metadata. The format of this metadata is up to the application. + */ metadataHash?: string; + + /** + * \[an\] Name of this asset, as supplied by the creator. Included only when the asset name is composed of printable utf-8 characters. + */ name?: string; + + /** + * Base64 encoded name of this asset, as supplied by the creator. + */ nameB64?: string; + + /** + * \[r\] Address of account holding reserve (non-minted) units of this asset. + */ reserve?: string; + + /** + * \[t\] The total number of units of this asset. + */ total: bigint; + + /** + * \[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. + */ unitName?: string; + + /** + * Base64 encoded name of a unit of this asset, as supplied by the creator. + */ unitNameB64?: string; + + /** + * \[au\] URL where more information about the asset can be retrieved. Included only when the URL is composed of printable utf-8 characters. + */ url?: string; + + /** + * Base64 encoded URL where more information about the asset can be retrieved. + */ urlB64?: string; }; diff --git a/packages/typescript/algod_client/src/models/avmkeyvalue.ts b/packages/typescript/algod_client/src/models/avmkeyvalue.ts index 25d800891..e505463d0 100644 --- a/packages/typescript/algod_client/src/models/avmkeyvalue.ts +++ b/packages/typescript/algod_client/src/models/avmkeyvalue.ts @@ -3,4 +3,7 @@ import type { AvmValue } from "./index"; /** * Represents an AVM key-value pair in an application store. */ -export type AvmKeyValue = { key: string; value: AvmValue }; +export type AvmKeyValue = { + key: string; + value: AvmValue; +}; diff --git a/packages/typescript/algod_client/src/models/avmvalue.ts b/packages/typescript/algod_client/src/models/avmvalue.ts index 76857f2e1..8ab60116b 100644 --- a/packages/typescript/algod_client/src/models/avmvalue.ts +++ b/packages/typescript/algod_client/src/models/avmvalue.ts @@ -1,4 +1,19 @@ /** * Represents an AVM value. */ -export type AvmValue = { type: bigint; bytes?: string; uint?: bigint }; +export type AvmValue = { + /** + * value type. Value `1` refers to **bytes**, value `2` refers to **uint64** + */ + type: bigint; + + /** + * bytes value. + */ + bytes?: string; + + /** + * uint value. + */ + uint?: bigint; +}; diff --git a/packages/typescript/algod_client/src/models/box.ts b/packages/typescript/algod_client/src/models/box.ts index 90b5c64e6..f29851c2a 100644 --- a/packages/typescript/algod_client/src/models/box.ts +++ b/packages/typescript/algod_client/src/models/box.ts @@ -1,4 +1,19 @@ /** * Box name and its content. */ -export type Box = { round: bigint; name: string; value: string }; +export type Box = { + /** + * The round for which this information is relevant + */ + round: bigint; + + /** + * The box name, base64 encoded + */ + name: string; + + /** + * The box value, base64 encoded. + */ + value: string; +}; diff --git a/packages/typescript/algod_client/src/models/boxdescriptor.ts b/packages/typescript/algod_client/src/models/boxdescriptor.ts index adab97fe7..ea3dc0516 100644 --- a/packages/typescript/algod_client/src/models/boxdescriptor.ts +++ b/packages/typescript/algod_client/src/models/boxdescriptor.ts @@ -1,4 +1,9 @@ /** * Box descriptor describes a Box. */ -export type BoxDescriptor = { name: string }; +export type BoxDescriptor = { + /** + * Base64 encoded box name + */ + name: string; +}; diff --git a/packages/typescript/algod_client/src/models/boxreference.ts b/packages/typescript/algod_client/src/models/boxreference.ts index 6a0a75026..9178b3f9e 100644 --- a/packages/typescript/algod_client/src/models/boxreference.ts +++ b/packages/typescript/algod_client/src/models/boxreference.ts @@ -1,4 +1,14 @@ /** * References a box of an application. */ -export type BoxReference = { app: bigint; name: string }; +export type BoxReference = { + /** + * Application ID which this box belongs to + */ + app: bigint; + + /** + * Base64 encoded box name + */ + name: string; +}; diff --git a/packages/typescript/algod_client/src/models/buildversion.ts b/packages/typescript/algod_client/src/models/buildversion.ts index 33006a33f..9eb20305f 100644 --- a/packages/typescript/algod_client/src/models/buildversion.ts +++ b/packages/typescript/algod_client/src/models/buildversion.ts @@ -1 +1,8 @@ -export type BuildVersion = { branch: string; buildNumber: bigint; channel: string; commitHash: string; major: bigint; minor: bigint }; +export type BuildVersion = { + branch: string; + buildNumber: bigint; + channel: string; + commitHash: string; + major: bigint; + minor: bigint; +}; diff --git a/packages/typescript/algod_client/src/models/debugsettingsprof.ts b/packages/typescript/algod_client/src/models/debugsettingsprof.ts index 369d6d9a8..532ea51d2 100644 --- a/packages/typescript/algod_client/src/models/debugsettingsprof.ts +++ b/packages/typescript/algod_client/src/models/debugsettingsprof.ts @@ -1,4 +1,14 @@ /** * algod mutex and blocking profiling state. */ -export type DebugSettingsProf = { blockRate?: bigint; mutexRate?: bigint }; +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; +}; diff --git a/packages/typescript/algod_client/src/models/dryrunrequest.ts b/packages/typescript/algod_client/src/models/dryrunrequest.ts index f59b78b07..3d743c6a9 100644 --- a/packages/typescript/algod_client/src/models/dryrunrequest.ts +++ b/packages/typescript/algod_client/src/models/dryrunrequest.ts @@ -1,14 +1,26 @@ -import type { Account, Application, DryrunSource } from "./index"; +import type { Account, AlgokitSignedTransaction, Application, DryrunSource } from "./index"; /** * Request data type for dryrun endpoint. Given the Transactions and simulated ledger state upload, run TEAL scripts and return debugging information. */ export type DryrunRequest = { - txns: string[]; + txns: AlgokitSignedTransaction[]; accounts: Account[]; apps: Application[]; + + /** + * ProtocolVersion specifies a specific version string to operate under, otherwise whatever the current protocol of the network this algod is running in. + */ protocolVersion: string; + + /** + * Round is available to some TEAL scripts. Defaults to the current round on the network this algod is attached to. + */ round: bigint; + + /** + * LatestTimestamp is available to some TEAL scripts. Defaults to the latest confirmed timestamp this algod is attached to. + */ latestTimestamp: bigint; sources: DryrunSource[]; }; diff --git a/packages/typescript/algod_client/src/models/dryrunsource.ts b/packages/typescript/algod_client/src/models/dryrunsource.ts index d5f4621ce..7b4387a88 100644 --- a/packages/typescript/algod_client/src/models/dryrunsource.ts +++ b/packages/typescript/algod_client/src/models/dryrunsource.ts @@ -1,4 +1,12 @@ /** * DryrunSource is TEAL source text that gets uploaded, compiled, and inserted into transactions or application state. */ -export type DryrunSource = { fieldName: string; source: string; txnIndex: bigint; appIndex: bigint }; +export type DryrunSource = { + /** + * 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]. + */ + fieldName: string; + source: string; + txnIndex: bigint; + appIndex: bigint; +}; diff --git a/packages/typescript/algod_client/src/models/dryrunstate.ts b/packages/typescript/algod_client/src/models/dryrunstate.ts index ebeafd9d9..1155daea1 100644 --- a/packages/typescript/algod_client/src/models/dryrunstate.ts +++ b/packages/typescript/algod_client/src/models/dryrunstate.ts @@ -3,4 +3,21 @@ import type { TealValue } from "./index"; /** * Stores the TEAL eval step data */ -export type DryrunState = { line: bigint; pc: bigint; stack: TealValue[]; scratch?: TealValue[]; error?: string }; +export type DryrunState = { + /** + * Line number + */ + line: bigint; + + /** + * Program counter + */ + pc: bigint; + stack: TealValue[]; + scratch?: TealValue[]; + + /** + * Evaluation error if any + */ + error?: string; +}; diff --git a/packages/typescript/algod_client/src/models/dryruntxnresult.ts b/packages/typescript/algod_client/src/models/dryruntxnresult.ts index 0a7e4adec..e0f0f5568 100644 --- a/packages/typescript/algod_client/src/models/dryruntxnresult.ts +++ b/packages/typescript/algod_client/src/models/dryruntxnresult.ts @@ -4,7 +4,14 @@ import type { AccountStateDelta, DryrunState, StateDelta } from "./index"; * DryrunTxnResult contains any LogicSig or ApplicationCall program debug information and state updates from a dryrun. */ export type DryrunTxnResult = { + /** + * Disassembled program line by line. + */ disassembly: string[]; + + /** + * Disassembled lsig program line by line. + */ logicSigDisassembly?: string[]; logicSigTrace?: DryrunState[]; logicSigMessages?: string[]; @@ -13,6 +20,14 @@ export type DryrunTxnResult = { globalDelta?: StateDelta; localDeltas?: AccountStateDelta[]; logs?: string[]; + + /** + * Budget added during execution of app call transaction. + */ budgetAdded?: bigint; + + /** + * Budget consumed during execution of app call transaction. + */ budgetConsumed?: bigint; }; diff --git a/packages/typescript/algod_client/src/models/errorresponse.ts b/packages/typescript/algod_client/src/models/errorresponse.ts index 556c79515..90666a66e 100644 --- a/packages/typescript/algod_client/src/models/errorresponse.ts +++ b/packages/typescript/algod_client/src/models/errorresponse.ts @@ -1,4 +1,7 @@ /** * An error response with optional data field. */ -export type ErrorResponse = { data?: {}; message: string }; +export type ErrorResponse = { + data?: {}; + message: string; +}; diff --git a/packages/typescript/algod_client/src/models/evaldelta.ts b/packages/typescript/algod_client/src/models/evaldelta.ts index 2d9fe7313..0fc979b44 100644 --- a/packages/typescript/algod_client/src/models/evaldelta.ts +++ b/packages/typescript/algod_client/src/models/evaldelta.ts @@ -1,4 +1,19 @@ /** * Represents a TEAL value delta. */ -export type EvalDelta = { action: bigint; bytes?: string; uint?: bigint }; +export type EvalDelta = { + /** + * \[at\] delta action. + */ + action: bigint; + + /** + * \[bs\] bytes value. + */ + bytes?: string; + + /** + * \[ui\] uint value. + */ + uint?: bigint; +}; diff --git a/packages/typescript/algod_client/src/models/evaldeltakeyvalue.ts b/packages/typescript/algod_client/src/models/evaldeltakeyvalue.ts index 63d6ea4e1..7a56299ea 100644 --- a/packages/typescript/algod_client/src/models/evaldeltakeyvalue.ts +++ b/packages/typescript/algod_client/src/models/evaldeltakeyvalue.ts @@ -3,4 +3,7 @@ import type { EvalDelta } from "./index"; /** * Key-value pairs for StateDelta. */ -export type EvalDeltaKeyValue = { key: string; value: EvalDelta }; +export type EvalDeltaKeyValue = { + key: string; + value: EvalDelta; +}; diff --git a/packages/typescript/algod_client/src/models/genesisallocation.ts b/packages/typescript/algod_client/src/models/genesisallocation.ts index 2548faf65..f9a65f3f5 100644 --- a/packages/typescript/algod_client/src/models/genesisallocation.ts +++ b/packages/typescript/algod_client/src/models/genesisallocation.ts @@ -1,5 +1,14 @@ export type GenesisAllocation = { addr: string; comment: string; - state: { algo: bigint; onl: bigint; sel?: string; stprf?: string; vote?: string; voteKd?: bigint; voteFst?: bigint; voteLst?: bigint }; + state: { + algo: bigint; + onl: bigint; + sel?: string; + stprf?: string; + vote?: string; + voteKd?: bigint; + voteFst?: bigint; + voteLst?: bigint; + }; }; diff --git a/packages/typescript/algod_client/src/models/getapplicationboxes.ts b/packages/typescript/algod_client/src/models/getapplicationboxes.ts index e731154ce..5d21d0139 100644 --- a/packages/typescript/algod_client/src/models/getapplicationboxes.ts +++ b/packages/typescript/algod_client/src/models/getapplicationboxes.ts @@ -1,6 +1,5 @@ import type { BoxDescriptor } from "./index"; -/** - * Box names of an application - */ -export type GetApplicationBoxes = { boxes: BoxDescriptor[] }; +export type GetApplicationBoxes = { + boxes: BoxDescriptor[]; +}; diff --git a/packages/typescript/algod_client/src/models/getblock.ts b/packages/typescript/algod_client/src/models/getblock.ts index c6f11f9dc..19887c371 100644 --- a/packages/typescript/algod_client/src/models/getblock.ts +++ b/packages/typescript/algod_client/src/models/getblock.ts @@ -1,4 +1,11 @@ -/** - * Encoded block object. - */ -export type GetBlock = { block: {}; cert?: {} }; +export type GetBlock = { + /** + * Block header data. + */ + block: {}; + + /** + * Optional certificate object. This is only included when the format is set to message pack. + */ + cert?: {}; +}; diff --git a/packages/typescript/algod_client/src/models/getblockhash.ts b/packages/typescript/algod_client/src/models/getblockhash.ts index 642e0d0c0..9f76c369c 100644 --- a/packages/typescript/algod_client/src/models/getblockhash.ts +++ b/packages/typescript/algod_client/src/models/getblockhash.ts @@ -1,4 +1,6 @@ -/** - * Hash of a block header. - */ -export type GetBlockHash = { blockHash: string }; +export type GetBlockHash = { + /** + * Block header hash. + */ + blockHash: string; +}; diff --git a/packages/typescript/algod_client/src/models/getblocklogs.ts b/packages/typescript/algod_client/src/models/getblocklogs.ts index 1ecaa2f17..486b1785a 100644 --- a/packages/typescript/algod_client/src/models/getblocklogs.ts +++ b/packages/typescript/algod_client/src/models/getblocklogs.ts @@ -1,6 +1,5 @@ import type { AppCallLogs } from "./index"; -/** - * 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) - */ -export type GetBlockLogs = { logs: AppCallLogs[] }; +export type GetBlockLogs = { + logs: AppCallLogs[]; +}; diff --git a/packages/typescript/algod_client/src/models/getblocktimestampoffset.ts b/packages/typescript/algod_client/src/models/getblocktimestampoffset.ts index b79a134b9..9b5442390 100644 --- a/packages/typescript/algod_client/src/models/getblocktimestampoffset.ts +++ b/packages/typescript/algod_client/src/models/getblocktimestampoffset.ts @@ -1,4 +1,6 @@ -/** - * Response containing the timestamp offset in seconds - */ -export type GetBlockTimeStampOffset = { offset: bigint }; +export type GetBlockTimeStampOffset = { + /** + * Timestamp offset in seconds. + */ + offset: bigint; +}; diff --git a/packages/typescript/algod_client/src/models/getblocktxids.ts b/packages/typescript/algod_client/src/models/getblocktxids.ts index 57e9a2840..21ead88d4 100644 --- a/packages/typescript/algod_client/src/models/getblocktxids.ts +++ b/packages/typescript/algod_client/src/models/getblocktxids.ts @@ -1,4 +1,6 @@ -/** - * Top level transaction IDs in a block. - */ -export type GetBlockTxids = { blockTxids: string[] }; +export type GetBlockTxids = { + /** + * Block transaction IDs. + */ + blockTxids: string[]; +}; diff --git a/packages/typescript/algod_client/src/models/getpendingtransactions.ts b/packages/typescript/algod_client/src/models/getpendingtransactions.ts index 6d30718d0..9eaa2676d 100644 --- a/packages/typescript/algod_client/src/models/getpendingtransactions.ts +++ b/packages/typescript/algod_client/src/models/getpendingtransactions.ts @@ -1,4 +1,16 @@ +import type { AlgokitSignedTransaction } from "./index"; + /** * PendingTransactions is an array of signed transactions exactly as they were submitted. */ -export type GetPendingTransactions = { topTransactions: {}[]; totalTransactions: bigint }; +export type GetPendingTransactions = { + /** + * An array of signed transaction objects. + */ + topTransactions: AlgokitSignedTransaction[]; + + /** + * Total number of transactions in the pool. + */ + totalTransactions: bigint; +}; diff --git a/packages/typescript/algod_client/src/models/getpendingtransactionsbyaddress.ts b/packages/typescript/algod_client/src/models/getpendingtransactionsbyaddress.ts index 4a3897b17..806d2b9ed 100644 --- a/packages/typescript/algod_client/src/models/getpendingtransactionsbyaddress.ts +++ b/packages/typescript/algod_client/src/models/getpendingtransactionsbyaddress.ts @@ -1,4 +1,16 @@ +import type { AlgokitSignedTransaction } from "./index"; + /** * PendingTransactions is an array of signed transactions exactly as they were submitted. */ -export type GetPendingTransactionsByAddress = { topTransactions: {}[]; totalTransactions: bigint }; +export type GetPendingTransactionsByAddress = { + /** + * An array of signed transaction objects. + */ + topTransactions: AlgokitSignedTransaction[]; + + /** + * Total number of transactions in the pool. + */ + totalTransactions: bigint; +}; diff --git a/packages/typescript/algod_client/src/models/getstatus.ts b/packages/typescript/algod_client/src/models/getstatus.ts index 996bbdcbd..1ff7ebb7d 100644 --- a/packages/typescript/algod_client/src/models/getstatus.ts +++ b/packages/typescript/algod_client/src/models/getstatus.ts @@ -2,30 +2,133 @@ * NodeStatus contains the information about a node status */ export type GetStatus = { + /** + * CatchupTime in nanoseconds + */ catchupTime: bigint; + + /** + * LastRound indicates the last round seen + */ lastRound: bigint; + + /** + * LastVersion indicates the last consensus version supported + */ lastVersion: string; + + /** + * NextVersion of consensus protocol to use + */ nextVersion: string; + + /** + * NextVersionRound is the round at which the next consensus version will apply + */ nextVersionRound: bigint; + + /** + * NextVersionSupported indicates whether the next consensus version is supported by this node + */ nextVersionSupported: boolean; + + /** + * StoppedAtUnsupportedRound indicates that the node does not support the new rounds and has stopped making progress + */ stoppedAtUnsupportedRound: boolean; + + /** + * TimeSinceLastRound in nanoseconds + */ timeSinceLastRound: bigint; + + /** + * The last catchpoint seen by the node + */ lastCatchpoint?: string; + + /** + * The current catchpoint that is being caught up to + */ catchpoint?: string; + + /** + * The total number of accounts included in the current catchpoint + */ catchpointTotalAccounts?: bigint; + + /** + * The number of accounts from the current catchpoint that have been processed so far as part of the catchup + */ catchpointProcessedAccounts?: bigint; + + /** + * The number of accounts from the current catchpoint that have been verified so far as part of the catchup + */ catchpointVerifiedAccounts?: bigint; + + /** + * The total number of key-values (KVs) included in the current catchpoint + */ catchpointTotalKvs?: bigint; + + /** + * The number of key-values (KVs) from the current catchpoint that have been processed so far as part of the catchup + */ catchpointProcessedKvs?: bigint; + + /** + * The number of key-values (KVs) from the current catchpoint that have been verified so far as part of the catchup + */ catchpointVerifiedKvs?: bigint; + + /** + * The total number of blocks that are required to complete the current catchpoint catchup + */ catchpointTotalBlocks?: bigint; + + /** + * The number of blocks that have already been obtained by the node as part of the catchup + */ catchpointAcquiredBlocks?: bigint; + + /** + * Upgrade delay + */ upgradeDelay?: bigint; + + /** + * This node's upgrade vote + */ upgradeNodeVote?: boolean; + + /** + * Yes votes required for consensus upgrade + */ upgradeVotesRequired?: bigint; + + /** + * Total votes cast for consensus upgrade + */ upgradeVotes?: bigint; + + /** + * Yes votes cast for consensus upgrade + */ upgradeYesVotes?: bigint; + + /** + * No votes cast for consensus upgrade + */ upgradeNoVotes?: bigint; + + /** + * Next protocol round + */ upgradeNextProtocolVoteBefore?: bigint; + + /** + * Total voting rounds for current upgrade + */ upgradeVoteRounds?: bigint; }; diff --git a/packages/typescript/algod_client/src/models/getsupply.ts b/packages/typescript/algod_client/src/models/getsupply.ts index 81160e60a..5c23c20fc 100644 --- a/packages/typescript/algod_client/src/models/getsupply.ts +++ b/packages/typescript/algod_client/src/models/getsupply.ts @@ -1,4 +1,19 @@ /** * Supply represents the current supply of MicroAlgos in the system */ -export type GetSupply = { currentRound: bigint; onlineMoney: bigint; totalMoney: bigint }; +export type GetSupply = { + /** + * Round + */ + currentRound: bigint; + + /** + * OnlineMoney + */ + onlineMoney: bigint; + + /** + * TotalMoney + */ + totalMoney: bigint; +}; diff --git a/packages/typescript/algod_client/src/models/getsyncround.ts b/packages/typescript/algod_client/src/models/getsyncround.ts index c8ec6cfa3..7e0e2f85b 100644 --- a/packages/typescript/algod_client/src/models/getsyncround.ts +++ b/packages/typescript/algod_client/src/models/getsyncround.ts @@ -1,4 +1,6 @@ -/** - * Response containing the ledger's minimum sync round - */ -export type GetSyncRound = { round: bigint }; +export type GetSyncRound = { + /** + * The minimum sync round for the ledger. + */ + round: bigint; +}; diff --git a/packages/typescript/algod_client/src/models/gettransactiongroupledgerstatedeltasforround.ts b/packages/typescript/algod_client/src/models/gettransactiongroupledgerstatedeltasforround.ts index 6b47af74e..7d5637ea5 100644 --- a/packages/typescript/algod_client/src/models/gettransactiongroupledgerstatedeltasforround.ts +++ b/packages/typescript/algod_client/src/models/gettransactiongroupledgerstatedeltasforround.ts @@ -1,6 +1,5 @@ import type { LedgerStateDeltaForTransactionGroup } from "./index"; -/** - * Response containing all ledger state deltas for transaction groups, with their associated Ids, in a single round. - */ -export type GetTransactionGroupLedgerStateDeltasForRound = { deltas: LedgerStateDeltaForTransactionGroup[] }; +export type GetTransactionGroupLedgerStateDeltasForRound = { + deltas: LedgerStateDeltaForTransactionGroup[]; +}; diff --git a/packages/typescript/algod_client/src/models/index.ts b/packages/typescript/algod_client/src/models/index.ts index 2d1767152..cdff0a52e 100644 --- a/packages/typescript/algod_client/src/models/index.ts +++ b/packages/typescript/algod_client/src/models/index.ts @@ -66,6 +66,7 @@ export type { GetBlockHash } from "./getblockhash"; export type { GetBlockLogs } from "./getblocklogs"; export type { GetSupply } from "./getsupply"; export type { AddParticipationKey } from "./addparticipationkey"; +export type { ShutdownNode } from "./shutdownnode"; export type { GetStatus } from "./getstatus"; export type { WaitForBlock } from "./waitforblock"; export type { RawTransaction } from "./rawtransaction"; @@ -81,4 +82,5 @@ export type { StartCatchup } from "./startcatchup"; export type { AbortCatchup } from "./abortcatchup"; export type { TealDryrun } from "./tealdryrun"; export type { GetBlockTimeStampOffset } from "./getblocktimestampoffset"; -export type { ShutdownNode } from "./shutdownnode"; +// TODO(utils-ts): Remove this export when utils-ts provides SignedTransaction types +export type { AlgokitSignedTransaction } from "./algokitsignedtransaction"; diff --git a/packages/typescript/algod_client/src/models/ledgerstatedeltafortransactiongroup.ts b/packages/typescript/algod_client/src/models/ledgerstatedeltafortransactiongroup.ts index db48e7d25..93dbd407a 100644 --- a/packages/typescript/algod_client/src/models/ledgerstatedeltafortransactiongroup.ts +++ b/packages/typescript/algod_client/src/models/ledgerstatedeltafortransactiongroup.ts @@ -3,4 +3,7 @@ import type { LedgerStateDelta } from "./index"; /** * Contains a ledger delta for a single transaction group */ -export type LedgerStateDeltaForTransactionGroup = { delta: LedgerStateDelta; ids: string[] }; +export type LedgerStateDeltaForTransactionGroup = { + delta: LedgerStateDelta; + ids: string[]; +}; diff --git a/packages/typescript/algod_client/src/models/lightblockheaderproof.ts b/packages/typescript/algod_client/src/models/lightblockheaderproof.ts index 485a8ba75..1deab4349 100644 --- a/packages/typescript/algod_client/src/models/lightblockheaderproof.ts +++ b/packages/typescript/algod_client/src/models/lightblockheaderproof.ts @@ -1,4 +1,19 @@ /** * Proof of membership and position of a light block header. */ -export type LightBlockHeaderProof = { index: bigint; treedepth: bigint; proof: string }; +export type LightBlockHeaderProof = { + /** + * The index of the light block header in the vector commitment tree + */ + index: bigint; + + /** + * Represents the depth of the tree that is being proven, i.e. the number of edges from a leaf to the root. + */ + treedepth: bigint; + + /** + * The encoded proof. + */ + proof: string; +}; diff --git a/packages/typescript/algod_client/src/models/participationkey.ts b/packages/typescript/algod_client/src/models/participationkey.ts index a4cdfbd5a..536cede2a 100644 --- a/packages/typescript/algod_client/src/models/participationkey.ts +++ b/packages/typescript/algod_client/src/models/participationkey.ts @@ -4,12 +4,39 @@ import type { AccountParticipation } from "./index"; * 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; }; diff --git a/packages/typescript/algod_client/src/models/pendingtransactionresponse.ts b/packages/typescript/algod_client/src/models/pendingtransactionresponse.ts index f5413314d..43ce550f5 100644 --- a/packages/typescript/algod_client/src/models/pendingtransactionresponse.ts +++ b/packages/typescript/algod_client/src/models/pendingtransactionresponse.ts @@ -1,21 +1,72 @@ -import type { AccountStateDelta, StateDelta } from "./index"; +import type { AccountStateDelta, AlgokitSignedTransaction, StateDelta } from "./index"; /** * Details about a pending transaction. If the transaction was recently confirmed, includes confirmation details like the round and reward details. */ export type PendingTransactionResponse = { + /** + * The asset index if the transaction was found and it created an asset. + */ assetIndex?: bigint; + + /** + * The application index if the transaction was found and it created an application. + */ applicationIndex?: bigint; + + /** + * Rewards in microalgos applied to the close remainder to account. + */ closeRewards?: bigint; + + /** + * Closing amount for the transaction. + */ closingAmount?: bigint; + + /** + * The number of the asset's unit that were transferred to the close-to address. + */ assetClosingAmount?: bigint; + + /** + * The round where this transaction was confirmed, if present. + */ confirmedRound?: bigint; + + /** + * 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. + */ poolError: string; + + /** + * Rewards in microalgos applied to the receiver account. + */ receiverRewards?: bigint; + + /** + * Rewards in microalgos applied to the sender account. + */ senderRewards?: bigint; + + /** + * Local state key/value changes for the application being executed by this transaction. + */ localStateDelta?: AccountStateDelta[]; globalStateDelta?: StateDelta; + + /** + * Logs for the application being executed by this transaction. + */ logs?: string[]; + + /** + * Inner transactions produced by application execution. + */ innerTxns?: PendingTransactionResponse[]; - txn: {}; + + /** + * The raw signed transaction. + */ + txn: AlgokitSignedTransaction; }; diff --git a/packages/typescript/algod_client/src/models/rawtransaction.ts b/packages/typescript/algod_client/src/models/rawtransaction.ts index c0333feb1..5c58c8a17 100644 --- a/packages/typescript/algod_client/src/models/rawtransaction.ts +++ b/packages/typescript/algod_client/src/models/rawtransaction.ts @@ -1,4 +1,6 @@ -/** - * Transaction ID of the submission. - */ -export type RawTransaction = { txId: string }; +export type RawTransaction = { + /** + * encoding of the transaction hash. + */ + txId: string; +}; diff --git a/packages/typescript/algod_client/src/models/scratchchange.ts b/packages/typescript/algod_client/src/models/scratchchange.ts index 9764d99f9..259c74900 100644 --- a/packages/typescript/algod_client/src/models/scratchchange.ts +++ b/packages/typescript/algod_client/src/models/scratchchange.ts @@ -3,4 +3,10 @@ import type { AvmValue } from "./index"; /** * A write operation into a scratch slot. */ -export type ScratchChange = { slot: bigint; newValue: AvmValue }; +export type ScratchChange = { + /** + * The scratch slot written. + */ + slot: bigint; + newValue: AvmValue; +}; diff --git a/packages/typescript/algod_client/src/models/simulateinitialstates.ts b/packages/typescript/algod_client/src/models/simulateinitialstates.ts index b3d2b5890..c639801a6 100644 --- a/packages/typescript/algod_client/src/models/simulateinitialstates.ts +++ b/packages/typescript/algod_client/src/models/simulateinitialstates.ts @@ -3,4 +3,9 @@ import type { ApplicationInitialStates } from "./index"; /** * Initial states of resources that were accessed during simulation. */ -export type SimulateInitialStates = { appInitialStates?: ApplicationInitialStates[] }; +export type SimulateInitialStates = { + /** + * The initial states of accessed application before simulation. The order of this array is arbitrary. + */ + appInitialStates?: ApplicationInitialStates[]; +}; diff --git a/packages/typescript/algod_client/src/models/simulaterequest.ts b/packages/typescript/algod_client/src/models/simulaterequest.ts index d84776a7c..ab0718f8c 100644 --- a/packages/typescript/algod_client/src/models/simulaterequest.ts +++ b/packages/typescript/algod_client/src/models/simulaterequest.ts @@ -4,12 +4,39 @@ import type { SimulateRequestTransactionGroup, SimulateTraceConfig } from "./ind * Request type for simulation endpoint. */ export type SimulateRequest = { + /** + * The transaction groups to simulate. + */ txnGroups: SimulateRequestTransactionGroup[]; + + /** + * 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. + */ round?: bigint; + + /** + * Allows transactions without signatures to be simulated as if they had correct signatures. + */ allowEmptySignatures?: boolean; + + /** + * Lifts limits on log opcode usage during simulation. + */ allowMoreLogging?: boolean; + + /** + * Allows access to unnamed resources during simulation. + */ allowUnnamedResources?: boolean; + + /** + * Applies extra opcode budget during simulation for each transaction group. + */ extraOpcodeBudget?: bigint; execTraceConfig?: SimulateTraceConfig; + + /** + * If true, signers for transactions that are missing signatures will be fixed during evaluation. + */ fixSigners?: boolean; }; diff --git a/packages/typescript/algod_client/src/models/simulaterequesttransactiongroup.ts b/packages/typescript/algod_client/src/models/simulaterequesttransactiongroup.ts index 908390abe..758e6d1b2 100644 --- a/packages/typescript/algod_client/src/models/simulaterequesttransactiongroup.ts +++ b/packages/typescript/algod_client/src/models/simulaterequesttransactiongroup.ts @@ -1,4 +1,11 @@ +import type { AlgokitSignedTransaction } from "./index"; + /** * A transaction group to simulate. */ -export type SimulateRequestTransactionGroup = { txns: string[] }; +export type SimulateRequestTransactionGroup = { + /** + * An atomic transaction group. + */ + txns: AlgokitSignedTransaction[]; +}; diff --git a/packages/typescript/algod_client/src/models/simulatetraceconfig.ts b/packages/typescript/algod_client/src/models/simulatetraceconfig.ts index d1aafec43..905e989c9 100644 --- a/packages/typescript/algod_client/src/models/simulatetraceconfig.ts +++ b/packages/typescript/algod_client/src/models/simulatetraceconfig.ts @@ -1,4 +1,24 @@ /** * An object that configures simulation execution trace. */ -export type SimulateTraceConfig = { enable?: boolean; stackChange?: boolean; scratchChange?: boolean; stateChange?: boolean }; +export type SimulateTraceConfig = { + /** + * A boolean option for opting in execution trace features simulation endpoint. + */ + enable?: boolean; + + /** + * A boolean option enabling returning stack changes together with execution trace during simulation. + */ + stackChange?: boolean; + + /** + * A boolean option enabling returning scratch slot changes together with execution trace during simulation. + */ + scratchChange?: boolean; + + /** + * A boolean option enabling returning application state changes (global, local, and box changes) with the execution trace during simulation. + */ + stateChange?: boolean; +}; diff --git a/packages/typescript/algod_client/src/models/simulatetransaction.ts b/packages/typescript/algod_client/src/models/simulatetransaction.ts index 7377acab7..8995250a2 100644 --- a/packages/typescript/algod_client/src/models/simulatetransaction.ts +++ b/packages/typescript/algod_client/src/models/simulatetransaction.ts @@ -1,11 +1,19 @@ import type { SimulateInitialStates, SimulateTraceConfig, SimulateTransactionGroupResult, SimulationEvalOverrides } from "./index"; -/** - * Result of a transaction group simulation. - */ export type SimulateTransaction = { + /** + * The version of this response object. + */ version: bigint; + + /** + * The round immediately preceding this simulation. State changes through this round were used to run this simulation. + */ lastRound: bigint; + + /** + * A result object for each transaction group that was simulated. + */ txnGroups: SimulateTransactionGroupResult[]; evalOverrides?: SimulationEvalOverrides; execTraceConfig?: SimulateTraceConfig; diff --git a/packages/typescript/algod_client/src/models/simulatetransactiongroupresult.ts b/packages/typescript/algod_client/src/models/simulatetransactiongroupresult.ts index f6efbf98b..d5f1029a2 100644 --- a/packages/typescript/algod_client/src/models/simulatetransactiongroupresult.ts +++ b/packages/typescript/algod_client/src/models/simulatetransactiongroupresult.ts @@ -4,10 +4,29 @@ import type { SimulateTransactionResult, SimulateUnnamedResourcesAccessed } from * Simulation result for an atomic transaction group */ export type SimulateTransactionGroupResult = { + /** + * Simulation result for individual transactions + */ txnResults: SimulateTransactionResult[]; + + /** + * If present, indicates that the transaction group failed and specifies why that happened + */ failureMessage?: string; + + /** + * 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[]; + + /** + * Total budget added during execution of app calls in the transaction group. + */ appBudgetAdded?: bigint; + + /** + * Total budget consumed during execution of app calls in the transaction group. + */ appBudgetConsumed?: bigint; unnamedResourcesAccessed?: SimulateUnnamedResourcesAccessed; }; diff --git a/packages/typescript/algod_client/src/models/simulatetransactionresult.ts b/packages/typescript/algod_client/src/models/simulatetransactionresult.ts index a75a1dc8e..a9d0a5488 100644 --- a/packages/typescript/algod_client/src/models/simulatetransactionresult.ts +++ b/packages/typescript/algod_client/src/models/simulatetransactionresult.ts @@ -5,9 +5,21 @@ import type { PendingTransactionResponse, SimulateUnnamedResourcesAccessed, Simu */ export type SimulateTransactionResult = { txnResult: PendingTransactionResponse; + + /** + * Budget used during execution of an app call transaction. This value includes budged used by inner app calls spawned by this transaction. + */ appBudgetConsumed?: bigint; + + /** + * Budget used during execution of a logic sig transaction. + */ logicSigBudgetConsumed?: bigint; execTrace?: SimulationTransactionExecTrace; unnamedResourcesAccessed?: SimulateUnnamedResourcesAccessed; + + /** + * The account that needed to sign this transaction when no signature was provided and the provided signer was incorrect. + */ fixedSigner?: string; }; diff --git a/packages/typescript/algod_client/src/models/simulateunnamedresourcesaccessed.ts b/packages/typescript/algod_client/src/models/simulateunnamedresourcesaccessed.ts index 8b2872702..33b1f51fb 100644 --- a/packages/typescript/algod_client/src/models/simulateunnamedresourcesaccessed.ts +++ b/packages/typescript/algod_client/src/models/simulateunnamedresourcesaccessed.ts @@ -4,11 +4,38 @@ import type { ApplicationLocalReference, AssetHoldingReference, BoxReference } f * 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. */ export type SimulateUnnamedResourcesAccessed = { + /** + * The unnamed accounts that were referenced. The order of this array is arbitrary. + */ accounts?: string[]; + + /** + * The unnamed assets that were referenced. The order of this array is arbitrary. + */ assets?: bigint[]; + + /** + * The unnamed applications that were referenced. The order of this array is arbitrary. + */ apps?: bigint[]; + + /** + * The unnamed boxes that were referenced. The order of this array is arbitrary. + */ boxes?: BoxReference[]; + + /** + * 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; + + /** + * The unnamed asset holdings that were referenced. The order of this array is arbitrary. + */ assetHoldings?: AssetHoldingReference[]; + + /** + * The unnamed application local states that were referenced. The order of this array is arbitrary. + */ appLocals?: ApplicationLocalReference[]; }; diff --git a/packages/typescript/algod_client/src/models/simulationevaloverrides.ts b/packages/typescript/algod_client/src/models/simulationevaloverrides.ts index 1bcd0a8a9..185c3c423 100644 --- a/packages/typescript/algod_client/src/models/simulationevaloverrides.ts +++ b/packages/typescript/algod_client/src/models/simulationevaloverrides.ts @@ -2,10 +2,33 @@ * 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. */ export type SimulationEvalOverrides = { + /** + * If true, transactions without signatures are allowed and simulated as if they were properly signed. + */ allowEmptySignatures?: boolean; + + /** + * If true, allows access to unnamed resources during simulation. + */ allowUnnamedResources?: boolean; + + /** + * The maximum log calls one can make during simulation + */ maxLogCalls?: bigint; + + /** + * The maximum byte number to log during simulation + */ maxLogSize?: bigint; + + /** + * The extra opcode budget added to each transaction group during simulation + */ extraOpcodeBudget?: bigint; + + /** + * If true, signers for transactions that are missing signatures will be fixed during evaluation. + */ fixSigners?: boolean; }; diff --git a/packages/typescript/algod_client/src/models/simulationopcodetraceunit.ts b/packages/typescript/algod_client/src/models/simulationopcodetraceunit.ts index 25f9507fd..aba87b9f9 100644 --- a/packages/typescript/algod_client/src/models/simulationopcodetraceunit.ts +++ b/packages/typescript/algod_client/src/models/simulationopcodetraceunit.ts @@ -4,10 +4,33 @@ import type { ApplicationStateOperation, AvmValue, ScratchChange } from "./index * The set of trace information and effect from evaluating a single opcode. */ export type SimulationOpcodeTraceUnit = { + /** + * The program counter of the current opcode being evaluated. + */ pc: bigint; + + /** + * The writes into scratch slots. + */ scratchChanges?: ScratchChange[]; + + /** + * The operations against the current application's states. + */ stateChanges?: ApplicationStateOperation[]; + + /** + * The indexes of the traces for inner transactions spawned by this opcode, if any. + */ spawnedInners?: bigint[]; + + /** + * The number of deleted stack values by this opcode. + */ stackPopCount?: bigint; + + /** + * The values added by this opcode to the stack. + */ stackAdditions?: AvmValue[]; }; diff --git a/packages/typescript/algod_client/src/models/simulationtransactionexectrace.ts b/packages/typescript/algod_client/src/models/simulationtransactionexectrace.ts index f5b5f7c73..faa54cfc9 100644 --- a/packages/typescript/algod_client/src/models/simulationtransactionexectrace.ts +++ b/packages/typescript/algod_client/src/models/simulationtransactionexectrace.ts @@ -4,13 +4,48 @@ import type { SimulationOpcodeTraceUnit } from "./index"; * The execution trace of calling an app or a logic sig, containing the inner app call trace in a recursive way. */ export type SimulationTransactionExecTrace = { + /** + * Program trace that contains a trace of opcode effects in an approval program. + */ approvalProgramTrace?: SimulationOpcodeTraceUnit[]; + + /** + * SHA512_256 hash digest of the approval program executed in transaction. + */ approvalProgramHash?: string; + + /** + * Program trace that contains a trace of opcode effects in a clear state program. + */ clearStateProgramTrace?: SimulationOpcodeTraceUnit[]; + + /** + * SHA512_256 hash digest of the clear state program executed in transaction. + */ clearStateProgramHash?: string; + + /** + * If true, indicates that the clear state program failed and any persistent state changes it produced should be reverted once the program exits. + */ clearStateRollback?: boolean; + + /** + * 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. + */ clearStateRollbackError?: string; + + /** + * Program trace that contains a trace of opcode effects in a logic sig. + */ logicSigTrace?: SimulationOpcodeTraceUnit[]; + + /** + * SHA512_256 hash digest of the logic sig executed in transaction. + */ logicSigHash?: string; + + /** + * An array of SimulationTransactionExecTrace representing the execution trace of any inner transactions executed. + */ innerTrace?: SimulationTransactionExecTrace[]; }; diff --git a/packages/typescript/algod_client/src/models/startcatchup.ts b/packages/typescript/algod_client/src/models/startcatchup.ts index 2f7bfa331..9fb9e47f6 100644 --- a/packages/typescript/algod_client/src/models/startcatchup.ts +++ b/packages/typescript/algod_client/src/models/startcatchup.ts @@ -1,4 +1,9 @@ /** * An catchpoint start response. */ -export type StartCatchup = { catchupMessage: string }; +export type StartCatchup = { + /** + * Catchup start response string + */ + catchupMessage: string; +}; diff --git a/packages/typescript/algod_client/src/models/stateproof.ts b/packages/typescript/algod_client/src/models/stateproof.ts index 4a84b36c6..2b899fea8 100644 --- a/packages/typescript/algod_client/src/models/stateproof.ts +++ b/packages/typescript/algod_client/src/models/stateproof.ts @@ -3,4 +3,11 @@ import type { StateProofMessage } from "./index"; /** * Represents a state proof and its corresponding message */ -export type StateProof = { message: StateProofMessage; stateProof: string }; +export type StateProof = { + message: StateProofMessage; + + /** + * The encoded StateProof for the message. + */ + stateProof: string; +}; diff --git a/packages/typescript/algod_client/src/models/stateproofmessage.ts b/packages/typescript/algod_client/src/models/stateproofmessage.ts index 655081702..b428bb568 100644 --- a/packages/typescript/algod_client/src/models/stateproofmessage.ts +++ b/packages/typescript/algod_client/src/models/stateproofmessage.ts @@ -2,9 +2,28 @@ * Represents the message that the state proofs are attesting to. */ export type StateProofMessage = { + /** + * The vector commitment root on all light block headers within a state proof interval. + */ blockHeadersCommitment: string; + + /** + * The vector commitment root of the top N accounts to sign the next StateProof. + */ votersCommitment: string; + + /** + * 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. + */ lnProvenWeight: bigint; + + /** + * The first round the message attests to. + */ firstAttestedRound: bigint; + + /** + * The last round the message attests to. + */ lastAttestedRound: bigint; }; diff --git a/packages/typescript/algod_client/src/models/tealcompile.ts b/packages/typescript/algod_client/src/models/tealcompile.ts index e83ba6919..0a2f32ebf 100644 --- a/packages/typescript/algod_client/src/models/tealcompile.ts +++ b/packages/typescript/algod_client/src/models/tealcompile.ts @@ -1,4 +1,16 @@ -/** - * Teal compile Result - */ -export type TealCompile = { hash: string; result: string; sourcemap?: {} }; +export type TealCompile = { + /** + * base32 SHA512_256 of program bytes (Address style) + */ + hash: string; + + /** + * base64 encoded program bytes + */ + result: string; + + /** + * JSON of the source map + */ + sourcemap?: {}; +}; diff --git a/packages/typescript/algod_client/src/models/tealdisassemble.ts b/packages/typescript/algod_client/src/models/tealdisassemble.ts index 9ce7813e5..fae49cc5b 100644 --- a/packages/typescript/algod_client/src/models/tealdisassemble.ts +++ b/packages/typescript/algod_client/src/models/tealdisassemble.ts @@ -1,4 +1,6 @@ -/** - * Teal disassembly Result - */ -export type TealDisassemble = { result: string }; +export type TealDisassemble = { + /** + * disassembled Teal code + */ + result: string; +}; diff --git a/packages/typescript/algod_client/src/models/tealdryrun.ts b/packages/typescript/algod_client/src/models/tealdryrun.ts index 329a98664..ab01907b9 100644 --- a/packages/typescript/algod_client/src/models/tealdryrun.ts +++ b/packages/typescript/algod_client/src/models/tealdryrun.ts @@ -1,6 +1,11 @@ import type { DryrunTxnResult } from "./index"; -/** - * DryrunResponse contains per-txn debug information from a dryrun. - */ -export type TealDryrun = { txns: DryrunTxnResult[]; error: string; protocolVersion: string }; +export type TealDryrun = { + txns: DryrunTxnResult[]; + error: string; + + /** + * Protocol version is the protocol version Dryrun was operated under. + */ + protocolVersion: string; +}; diff --git a/packages/typescript/algod_client/src/models/tealkeyvalue.ts b/packages/typescript/algod_client/src/models/tealkeyvalue.ts index aeeee7399..98cf88806 100644 --- a/packages/typescript/algod_client/src/models/tealkeyvalue.ts +++ b/packages/typescript/algod_client/src/models/tealkeyvalue.ts @@ -3,4 +3,7 @@ import type { TealValue } from "./index"; /** * Represents a key-value pair in an application store. */ -export type TealKeyValue = { key: string; value: TealValue }; +export type TealKeyValue = { + key: string; + value: TealValue; +}; diff --git a/packages/typescript/algod_client/src/models/tealvalue.ts b/packages/typescript/algod_client/src/models/tealvalue.ts index 84e3993af..7b0384694 100644 --- a/packages/typescript/algod_client/src/models/tealvalue.ts +++ b/packages/typescript/algod_client/src/models/tealvalue.ts @@ -1,4 +1,19 @@ /** * Represents a TEAL value. */ -export type TealValue = { type: bigint; bytes: string; uint: bigint }; +export type TealValue = { + /** + * \[tt\] value type. Value `1` refers to **bytes**, value `2` refers to **uint** + */ + type: bigint; + + /** + * \[tb\] bytes value. + */ + bytes: string; + + /** + * \[ui\] uint value. + */ + uint: bigint; +}; diff --git a/packages/typescript/algod_client/src/models/transactionparams.ts b/packages/typescript/algod_client/src/models/transactionparams.ts index e19dbd33b..147da2d3c 100644 --- a/packages/typescript/algod_client/src/models/transactionparams.ts +++ b/packages/typescript/algod_client/src/models/transactionparams.ts @@ -3,10 +3,38 @@ * a new transaction. */ export type TransactionParams = { + /** + * ConsensusVersion indicates the consensus protocol version + * as of LastRound. + */ consensusVersion: string; + + /** + * Fee is the suggested transaction fee + * Fee is in units of micro-Algos per byte. + * Fee may fall to zero but transactions must still have a fee of + * at least MinTxnFee for the current network protocol. + */ fee: bigint; + + /** + * GenesisHash is the hash of the genesis block. + */ genesisHash: string; + + /** + * GenesisID is an ID listed in the genesis block. + */ genesisId: string; + + /** + * LastRound indicates the last round seen + */ lastRound: bigint; + + /** + * The minimum transaction fee (not per byte) required for the + * txn to validate for the current network protocol. + */ minFee: bigint; }; diff --git a/packages/typescript/algod_client/src/models/transactionproof.ts b/packages/typescript/algod_client/src/models/transactionproof.ts index 583d9208b..438413cd9 100644 --- a/packages/typescript/algod_client/src/models/transactionproof.ts +++ b/packages/typescript/algod_client/src/models/transactionproof.ts @@ -1,4 +1,31 @@ /** * Proof of transaction in a block. */ -export type TransactionProof = { proof: string; stibhash: string; treedepth: bigint; idx: bigint; hashtype: "sha512_256" | "sha256" }; +export type TransactionProof = { + /** + * Proof of transaction membership. + */ + proof: string; + + /** + * Hash of SignedTxnInBlock for verifying proof. + */ + stibhash: string; + + /** + * Represents the depth of the tree that is being proven, i.e. the number of edges from a leaf to the root. + */ + treedepth: bigint; + + /** + * Index of the transaction in the block's payset. + */ + idx: bigint; + + /** + * The type of hash function used to create the proof, must be one of: + * * sha512_256 + * * sha256 + */ + hashtype: "sha512_256" | "sha256"; +}; diff --git a/packages/typescript/algod_client/src/models/version.ts b/packages/typescript/algod_client/src/models/version.ts index 060cea5a6..ce89e685b 100644 --- a/packages/typescript/algod_client/src/models/version.ts +++ b/packages/typescript/algod_client/src/models/version.ts @@ -3,4 +3,9 @@ import type { BuildVersion } from "./index"; /** * algod version information. */ -export type Version = { build: BuildVersion; genesisHashB64: string; genesisId: string; versions: string[] }; +export type Version = { + build: BuildVersion; + genesisHashB64: string; + genesisId: string; + versions: string[]; +}; diff --git a/packages/typescript/algod_client/src/models/waitforblock.ts b/packages/typescript/algod_client/src/models/waitforblock.ts index 3c8378223..08e9d313f 100644 --- a/packages/typescript/algod_client/src/models/waitforblock.ts +++ b/packages/typescript/algod_client/src/models/waitforblock.ts @@ -2,30 +2,133 @@ * NodeStatus contains the information about a node status */ export type WaitForBlock = { + /** + * CatchupTime in nanoseconds + */ catchupTime: bigint; + + /** + * LastRound indicates the last round seen + */ lastRound: bigint; + + /** + * LastVersion indicates the last consensus version supported + */ lastVersion: string; + + /** + * NextVersion of consensus protocol to use + */ nextVersion: string; + + /** + * NextVersionRound is the round at which the next consensus version will apply + */ nextVersionRound: bigint; + + /** + * NextVersionSupported indicates whether the next consensus version is supported by this node + */ nextVersionSupported: boolean; + + /** + * StoppedAtUnsupportedRound indicates that the node does not support the new rounds and has stopped making progress + */ stoppedAtUnsupportedRound: boolean; + + /** + * TimeSinceLastRound in nanoseconds + */ timeSinceLastRound: bigint; + + /** + * The last catchpoint seen by the node + */ lastCatchpoint?: string; + + /** + * The current catchpoint that is being caught up to + */ catchpoint?: string; + + /** + * The total number of accounts included in the current catchpoint + */ catchpointTotalAccounts?: bigint; + + /** + * The number of accounts from the current catchpoint that have been processed so far as part of the catchup + */ catchpointProcessedAccounts?: bigint; + + /** + * The number of accounts from the current catchpoint that have been verified so far as part of the catchup + */ catchpointVerifiedAccounts?: bigint; + + /** + * The total number of key-values (KVs) included in the current catchpoint + */ catchpointTotalKvs?: bigint; + + /** + * The number of key-values (KVs) from the current catchpoint that have been processed so far as part of the catchup + */ catchpointProcessedKvs?: bigint; + + /** + * The number of key-values (KVs) from the current catchpoint that have been verified so far as part of the catchup + */ catchpointVerifiedKvs?: bigint; + + /** + * The total number of blocks that are required to complete the current catchpoint catchup + */ catchpointTotalBlocks?: bigint; + + /** + * The number of blocks that have already been obtained by the node as part of the catchup + */ catchpointAcquiredBlocks?: bigint; + + /** + * Upgrade delay + */ upgradeDelay?: bigint; + + /** + * This node's upgrade vote + */ upgradeNodeVote?: boolean; + + /** + * Yes votes required for consensus upgrade + */ upgradeVotesRequired?: bigint; + + /** + * Total votes cast for consensus upgrade + */ upgradeVotes?: bigint; + + /** + * Yes votes cast for consensus upgrade + */ upgradeYesVotes?: bigint; + + /** + * No votes cast for consensus upgrade + */ upgradeNoVotes?: bigint; + + /** + * Next protocol round + */ upgradeNextProtocolVoteBefore?: bigint; + + /** + * Total voting rounds for current upgrade + */ upgradeVoteRounds?: bigint; }; diff --git a/packages/typescript/algod_client/tests/pendingTransaction.spec.ts b/packages/typescript/algod_client/tests/pendingTransaction.spec.ts index 5e1114c9f..bb2cd93eb 100644 --- a/packages/typescript/algod_client/tests/pendingTransaction.spec.ts +++ b/packages/typescript/algod_client/tests/pendingTransaction.spec.ts @@ -14,7 +14,7 @@ maybeDescribe("Algod pendingTransaction", (env) => { const mnemonic = env.senderMnemonic ?? (await getSenderMnemonic()); const acct = algosdk.mnemonicToSecretKey(mnemonic); - const sp = await client.api.transactionParams(); + const sp = await client.transactionParams(); // Build simple self-payment of 0 microalgos (allowed) as a noop const txn = algosdk.makePaymentTxnWithSuggestedParamsFromObject({ @@ -33,13 +33,13 @@ maybeDescribe("Algod pendingTransaction", (env) => { }); const signed = txn.signTxn(acct.sk); - const sendResult = await client.api.rawTransaction({ body: signed }); + const sendResult = await client.rawTransaction({ body: signed }); const txId = sendResult.txId as string; let pending: PendingTransactionResponse | undefined; const maxAttempts = 10; for (let i = 0; i < maxAttempts; i++) { - pending = await client.api.pendingTransactionInformation(txId, { format: "msgpack" }); + pending = await client.pendingTransactionInformation(txId, { format: "msgpack" }); if (pending?.confirmedRound || pending?.poolError) { break; } diff --git a/packages/typescript/algod_client/tests/simulateTransactions.spec.ts b/packages/typescript/algod_client/tests/simulateTransactions.spec.ts new file mode 100644 index 000000000..e790f4674 --- /dev/null +++ b/packages/typescript/algod_client/tests/simulateTransactions.spec.ts @@ -0,0 +1,84 @@ +import { expect, it } from "bun:test"; +import { AlgodClient, ClientConfig, SimulateRequest } from "../src"; +import { getSenderMnemonic, maybeDescribe } from "./config"; +import algosdk from "algosdk"; + +maybeDescribe("simulateTransactions", (env) => { + it("should simulate two transactions and decode msgpack response", async () => { + const client = new AlgodClient({ + BASE: env.algodBaseUrl, + HEADERS: { "X-Algo-API-Token": env.algodApiToken ?? "" }, + INT_DECODING: "bigint", + } as ClientConfig); + + const mnemonic = env.senderMnemonic ?? (await getSenderMnemonic()); + const acct = algosdk.mnemonicToSecretKey(mnemonic); + let sp = await client.transactionParams(); + + // Create two transactions similar to Rust test + // Transaction 1: Simple payment + const txn1 = algosdk.makePaymentTxnWithSuggestedParamsFromObject({ + sender: acct.addr, + receiver: acct.addr, + amount: 100000, // 0.1 ALGO + suggestedParams: { + minFee: Number(sp["minFee"]), + fee: Number(sp["minFee"]), + firstValid: Number(sp["lastRound"]), + flatFee: true, + lastValid: Number(sp["lastRound"]) + 1000, + genesisHash: algosdk.base64ToBytes(sp["genesisHash"]), + genesisID: sp["genesisId"] as string, + }, + }); + + // Transaction 2: Payment with note (matching Rust test) + sp = await client.transactionParams(); + const txn2 = algosdk.makePaymentTxnWithSuggestedParamsFromObject({ + sender: acct.addr, + receiver: acct.addr, + amount: 100000, // 0.1 ALGO + note: new TextEncoder().encode("0aa50d27-b8f7-4d77-a1fb-551fd55df2bc"), + suggestedParams: { + minFee: Number(sp["minFee"]), + fee: Number(sp["minFee"]), + firstValid: Number(sp["lastRound"]), + flatFee: true, + lastValid: Number(sp["lastRound"]) + 1000, + genesisHash: algosdk.base64ToBytes(sp["genesisHash"]), + genesisID: sp["genesisId"] as string, + }, + }); + + // Create simulate request matching Rust structure + const simulateRequest: SimulateRequest = { + txnGroups: [ + { + txns: [ + { + txn: JSON.parse(algosdk.encodeJSON(txn1)), + }, + { + txn: JSON.parse(algosdk.encodeJSON(txn2)), + }, + ], + }, + ], + allowEmptySignatures: true, + allowMoreLogging: true, + allowUnnamedResources: true, + extraOpcodeBudget: 1000n, + execTraceConfig: { + enable: true, + stackChange: true, + scratchChange: true, + stateChange: true, + }, + fixSigners: true, + }; + + const res = await client.simulateTransaction({ format: "msgpack", body: simulateRequest }); + expect(res.txnGroups.length).toBe(1); + expect(res.txnGroups[0].txnResults.length).toBe(2); + }, 20000); +}); diff --git a/packages/typescript/algod_client/tests/transactionParams.spec.ts b/packages/typescript/algod_client/tests/transactionParams.spec.ts index 22b0f1ad6..973720bc3 100644 --- a/packages/typescript/algod_client/tests/transactionParams.spec.ts +++ b/packages/typescript/algod_client/tests/transactionParams.spec.ts @@ -9,7 +9,7 @@ maybeDescribe("Algod transactionParams", (env) => { INT_DECODING: "bigint", HEADERS: env.algodApiToken ? { "X-Algo-API-Token": env.algodApiToken } : undefined, }); - const params = await client.api.transactionParams(); + const params = await client.transactionParams(); expect(params).toHaveProperty("genesisId"); expect(typeof params["lastRound"]).toBe("bigint"); expect(typeof params["minFee"]).toBe("bigint"); diff --git a/packages/typescript/indexer_client/README.md b/packages/typescript/indexer_client/README.md index b37a9aed2..1f01e2214 100644 --- a/packages/typescript/indexer_client/README.md +++ b/packages/typescript/indexer_client/README.md @@ -12,11 +12,11 @@ Install dependencies and build: ### Configure base URL and create a client ```ts -import { FetchHttpRequest, type ClientConfig, IndexerClient, IndexerApi } from "./dist/index.js"; +import { IndexerClient } from "./dist/index.js"; -const client = new AlgodClient({ - BASE: env.algodBaseUrl, - HEADERS: env.algodApiToken ? { "X-Algo-API-Token": env.algodApiToken } : undefined, +const client = new IndexerClient({ + BASE: env.baseUrl, + HEADERS: env.apiToken ? { "X-Algo-API-Token": env.apiToken } : undefined, }); // client is now ready to use diff --git a/packages/typescript/indexer_client/bun.lock b/packages/typescript/indexer_client/bun.lock index 84f470649..b0815b8bf 100644 --- a/packages/typescript/indexer_client/bun.lock +++ b/packages/typescript/indexer_client/bun.lock @@ -8,6 +8,7 @@ "json-bigint": "^1.0.0", }, "devDependencies": { + "@types/bun": "^1.2.21", "@types/json-bigint": "^1.0.0", "@types/node": "^20.0.0", "algosdk": "^3.0.0", @@ -109,12 +110,16 @@ "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.50.1", "", { "os": "win32", "cpu": "x64" }, "sha512-StxAO/8ts62KZVRAm4JZYq9+NqNsV7RvimNK+YM7ry//zebEH6meuugqW/P5OFUCjyQgui+9fUxT6d5NShvMvA=="], + "@types/bun": ["@types/bun@1.2.21", "", { "dependencies": { "bun-types": "1.2.21" } }, "sha512-NiDnvEqmbfQ6dmZ3EeUO577s4P5bf4HCTXtI6trMc6f6RzirY5IrF3aIookuSpyslFzrnvv2lmEWv5HyC1X79A=="], + "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], "@types/json-bigint": ["@types/json-bigint@1.0.4", "", {}, "sha512-ydHooXLbOmxBbubnA7Eh+RpBzuaIiQjh8WGJYQB50JFGFrdxW7JzVlyEV7fAXw0T2sqJ1ysTneJbiyNLqZRAag=="], "@types/node": ["@types/node@20.19.13", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-yCAeZl7a0DxgNVteXFHt9+uyFbqXGy/ShC4BlcHkoE0AfGXYv/BUiplV72DjMYXHDBXFjhvr6DD1NiRVfB4j8g=="], + "@types/react": ["@types/react@19.1.12", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-cMoR+FoAf/Jyq6+Df2/Z41jISvGZZ2eTlnsaJRptmZ76Caldwy1odD4xTr/gNV9VLj0AWgg/nmkevIyUfIIq5w=="], + "@vitest/expect": ["@vitest/expect@2.1.9", "", { "dependencies": { "@vitest/spy": "2.1.9", "@vitest/utils": "2.1.9", "chai": "^5.1.2", "tinyrainbow": "^1.2.0" } }, "sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw=="], "@vitest/mocker": ["@vitest/mocker@2.1.9", "", { "dependencies": { "@vitest/spy": "2.1.9", "estree-walker": "^3.0.3", "magic-string": "^0.30.12" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^5.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg=="], @@ -137,12 +142,16 @@ "bignumber.js": ["bignumber.js@9.3.1", "", {}, "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ=="], + "bun-types": ["bun-types@1.2.21", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-sa2Tj77Ijc/NTLS0/Odjq/qngmEPZfbfnOERi0KRUYhT9R8M4VBioWVmMWE5GrYbKMc+5lVybXygLdibHaqVqw=="], + "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="], "chai": ["chai@5.3.3", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw=="], "check-error": ["check-error@2.1.1", "", {}, "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw=="], + "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], + "debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], "deep-eql": ["deep-eql@5.0.2", "", {}, "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q=="], diff --git a/packages/typescript/indexer_client/package.json b/packages/typescript/indexer_client/package.json index 2f939d500..75f58d49b 100644 --- a/packages/typescript/indexer_client/package.json +++ b/packages/typescript/indexer_client/package.json @@ -16,6 +16,7 @@ }, "devDependencies": { "@types/json-bigint": "^1.0.0", + "@types/bun": "^1.2.21", "@types/node": "^20.0.0", "algosdk": "^3.0.0", "typescript": "^5.5.0", diff --git a/packages/typescript/indexer_client/src/apis/api.service.ts b/packages/typescript/indexer_client/src/apis/api.service.ts index feb1396c1..1049f0ab3 100644 --- a/packages/typescript/indexer_client/src/apis/api.service.ts +++ b/packages/typescript/indexer_client/src/apis/api.service.ts @@ -26,6 +26,9 @@ import type { export class IndexerApi { constructor(public readonly httpRequest: BaseHttpRequest) {} + /** + * Lookup an account's asset holdings, optionally for a specific ID. + */ lookupAccountAppLocalStates( accountId: string, params?: { applicationId?: number | bigint; includeAll?: boolean; limit?: number | bigint; next?: string }, @@ -49,11 +52,13 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Lookup an account's asset holdings, optionally for a specific ID. + */ lookupAccountAssets( accountId: string, params?: { assetId?: number | bigint; includeAll?: boolean; limit?: number | bigint; next?: string }, @@ -77,11 +82,13 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Lookup account information. + */ lookupAccountById( accountId: string, params?: { @@ -108,11 +115,13 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Lookup an account's created application parameters, optionally for a specific ID. + */ lookupAccountCreatedApplications( accountId: string, params?: { applicationId?: number | bigint; includeAll?: boolean; limit?: number | bigint; next?: string }, @@ -136,11 +145,13 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Lookup an account's created asset parameters, optionally for a specific ID. + */ lookupAccountCreatedAssets( accountId: string, params?: { assetId?: number | bigint; includeAll?: boolean; limit?: number | bigint; next?: string }, @@ -164,11 +175,13 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Lookup account transactions. Transactions are returned newest to oldest. + */ lookupAccountTransactions( accountId: string, params?: { @@ -223,11 +236,13 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * 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...'. + */ lookupApplicationBoxByIdandName( applicationId: number | bigint, params?: { name: string }, @@ -246,11 +261,13 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Lookup application. + */ lookupApplicationById( applicationId: number | bigint, params?: { includeAll?: boolean }, @@ -269,11 +286,13 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Lookup application logs. + */ lookupApplicationLogsById( applicationId: number | bigint, params?: { @@ -306,11 +325,13 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Lookup the list of accounts who hold this asset + */ lookupAssetBalances( assetId: number | bigint, params?: { @@ -345,11 +366,13 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Lookup asset information. + */ lookupAssetById( assetId: number | bigint, params?: { includeAll?: boolean }, @@ -368,11 +391,13 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Lookup transactions for an asset. Transactions are returned oldest to newest. + */ lookupAssetTransactions( assetId: number | bigint, params?: { @@ -431,11 +456,13 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Lookup block. + */ lookupBlock(roundNumber: number | bigint, params?: { headerOnly?: boolean }, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -450,11 +477,13 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Lookup a single transaction. + */ lookupTransaction(txid: string, requestOptions?: ApiRequestOptions): Promise { const headers: Record = {}; headers["Accept"] = "application/json"; @@ -469,7 +498,6 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } @@ -488,11 +516,13 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Search for accounts. + */ searchForAccounts( params?: { assetId?: number | bigint; @@ -538,11 +568,13 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Given an application ID, returns the box names of that application sorted lexicographically. + */ searchForApplicationBoxes( applicationId: number | bigint, params?: { limit?: number | bigint; next?: string }, @@ -561,11 +593,13 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Search for applications + */ searchForApplications( params?: { applicationId?: number | bigint; creator?: string; includeAll?: boolean; limit?: number | bigint; next?: string }, requestOptions?: ApiRequestOptions, @@ -589,11 +623,13 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Search for assets. + */ searchForAssets( params?: { includeAll?: boolean; @@ -627,11 +663,13 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Search for block headers. Block headers are returned in ascending round order. Transactions are not included in the output. + */ searchForBlockHeaders( params?: { limit?: number | bigint; @@ -669,11 +707,13 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } + /** + * Search for transactions. Transactions are returned oldest to newest unless the address parameter is used, in which case results are returned newest to oldest. + */ searchForTransactions( params?: { limit?: number | bigint; @@ -737,7 +777,6 @@ export class IndexerApi { headers, body: undefined, mediaType: undefined, - expectBinary: false, ...(requestOptions ?? {}), }); } diff --git a/packages/typescript/indexer_client/src/client.ts b/packages/typescript/indexer_client/src/client.ts index 696b7bc03..ca5fb161b 100644 --- a/packages/typescript/indexer_client/src/client.ts +++ b/packages/typescript/indexer_client/src/client.ts @@ -2,12 +2,11 @@ import type { ClientConfig } from "./core/ClientConfig"; import { FetchHttpRequest } from "./core/FetchHttpRequest"; import { IndexerApi } from "./apis/api.service"; -export class IndexerClient { +export class IndexerClient extends IndexerApi { public readonly request: FetchHttpRequest; - public readonly api: IndexerApi; constructor(config: ClientConfig) { - this.request = new FetchHttpRequest(config); - this.api = new IndexerApi(this.request); + super(new FetchHttpRequest(config)); + this.request = this.httpRequest as FetchHttpRequest; } } diff --git a/packages/typescript/indexer_client/src/core/BaseHttpRequest.ts b/packages/typescript/indexer_client/src/core/BaseHttpRequest.ts index 45f2f0666..4a8fbe3e1 100644 --- a/packages/typescript/indexer_client/src/core/BaseHttpRequest.ts +++ b/packages/typescript/indexer_client/src/core/BaseHttpRequest.ts @@ -9,7 +9,6 @@ export interface RequestOptions { body?: any; mediaType?: string; responseHeader?: string; - expectBinary?: boolean; } // Backwards/ergonomic alias used by generated services diff --git a/packages/typescript/indexer_client/src/core/msgpack.ts b/packages/typescript/indexer_client/src/core/msgpack.ts index a30aa9314..8e3025089 100644 --- a/packages/typescript/indexer_client/src/core/msgpack.ts +++ b/packages/typescript/indexer_client/src/core/msgpack.ts @@ -1,4 +1,6 @@ import { encode as msgpackEncode, decode as msgpackDecode } from "@msgpack/msgpack"; +// TODO(utils-ts): Remove temporary type import when utils-ts is integrated +import type { AlgokitSignedTransaction } from "../models"; import type { IntDecoding } from "./json"; /** @@ -153,6 +155,9 @@ export function normalizeMsgPackIntegers(value: any, intDecoding: IntDecoding): } } +// Helpers to map SignedTransactionDto <-> AlgokitSignedTransaction if present in responses +// No DTO helpers needed: once utils-ts is integrated, this file remains unchanged. + function traverse(obj: any, fn: (v: any) => void): void { // eslint-disable-line @typescript-eslint/no-explicit-any if (obj == null) return; diff --git a/packages/typescript/indexer_client/src/core/request.ts b/packages/typescript/indexer_client/src/core/request.ts index 38eb3d463..fbe1f771c 100644 --- a/packages/typescript/indexer_client/src/core/request.ts +++ b/packages/typescript/indexer_client/src/core/request.ts @@ -18,7 +18,6 @@ export async function request( body?: any; mediaType?: string; responseHeader?: string; - expectBinary?: boolean; }, ): Promise { // Replace path params before constructing URL to avoid encoded braces preventing replacement @@ -98,6 +97,8 @@ export async function request( const buf = new Uint8Array(await response.arrayBuffer()); const decoded = decodeMsgPack(buf); const normalized = normalizeMsgPackIntegers(decoded, config.INT_DECODING ?? "bigint"); + // Lightweight mapping: if the response contains arrays/objects with x-algokit-signed-txn shapes + // they will decode to DTOs and be assignable to AlgokitSignedTransaction via alias. return toCamelCaseKeysDeep(normalized) as T; } diff --git a/packages/typescript/indexer_client/src/models/account.ts b/packages/typescript/indexer_client/src/models/account.ts index 531c7d224..2ace9e8ea 100644 --- a/packages/typescript/indexer_client/src/models/account.ts +++ b/packages/typescript/indexer_client/src/models/account.ts @@ -7,34 +7,162 @@ import type { AccountParticipation, Application, ApplicationLocalState, Applicat * data/basics/userBalance.go : AccountData */ export type Account = { + /** + * the account public key + */ address: string; + + /** + * total number of MicroAlgos in the account + */ amount: bigint; + + /** + * MicroAlgo balance required by the account. + * + * The requirement grows based on asset and application usage. + */ minBalance: bigint; + + /** + * specifies the amount of MicroAlgos in the account, without the pending rewards. + */ amountWithoutPendingRewards: bigint; + + /** + * application local data stored in this account. + * + * Note the raw object uses `map[int] -> AppLocalState` for this type. + */ appsLocalState?: ApplicationLocalState[]; appsTotalSchema?: ApplicationStateSchema; + + /** + * the sum of all extra application program pages for this account. + */ appsTotalExtraPages?: bigint; + + /** + * assets held by this account. + * + * Note the raw object uses `map[int] -> AssetHolding` for this type. + */ assets?: AssetHolding[]; + + /** + * parameters of applications created by this account including app global data. + * + * Note: the raw account uses `map[int] -> AppParams` for this type. + */ createdApps?: Application[]; + + /** + * parameters of assets created by this account. + * + * Note: the raw account uses `map[int] -> Asset` for this type. + */ createdAssets?: Asset[]; participation?: AccountParticipation; + + /** + * can the account receive block incentives if its balance is in range at proposal time. + */ incentiveEligible?: boolean; + + /** + * amount of MicroAlgos of pending rewards in this account. + */ pendingRewards: bigint; + + /** + * used as part of the rewards computation. Only applicable to accounts which are participating. + */ rewardBase?: bigint; + + /** + * total rewards of MicroAlgos the account has received, including pending rewards. + */ rewards: bigint; + + /** + * The round for which this information is relevant. + */ round: bigint; + + /** + * voting status of the account's MicroAlgos + * * Offline - indicates that the associated account is delegated. + * * Online - indicates that the associated account used as part of the delegation pool. + * * NotParticipating - indicates that the associated account is neither a delegator nor a delegate. + */ status: string; + + /** + * the type of signature used by this account, must be one of: + * * sig + * * msig + * * lsig + * * or null if unknown + */ sigType?: "sig" | "msig" | "lsig"; + + /** + * 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; + + /** + * The count of all assets that have been opted in, equivalent to the count of AssetHolding objects held by this account. + */ totalAssetsOptedIn: bigint; + + /** + * 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; + + /** + * For app-accounts only. The total number of boxes which belong to the associated application. + */ totalBoxes: bigint; + + /** + * The count of all apps (AppParams objects) created by this account. + */ totalCreatedApps: bigint; + + /** + * The count of all assets (AssetParams objects) created by this account. + */ totalCreatedAssets: bigint; + + /** + * 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. + */ authAddr?: string; + + /** + * The round in which this account last proposed the block. + */ lastProposed?: bigint; + + /** + * The round in which this account last went online, or explicitly renewed their online status. + */ lastHeartbeat?: bigint; + + /** + * Whether or not this account is currently closed. + */ deleted?: boolean; + + /** + * Round during which this account first appeared in a transaction. + */ createdAtRound?: bigint; + + /** + * Round during which this account was most recently closed. + */ closedAtRound?: bigint; }; diff --git a/packages/typescript/indexer_client/src/models/accountparticipation.ts b/packages/typescript/indexer_client/src/models/accountparticipation.ts index b77cf3b00..6e1f6b9c5 100644 --- a/packages/typescript/indexer_client/src/models/accountparticipation.ts +++ b/packages/typescript/indexer_client/src/models/accountparticipation.ts @@ -2,10 +2,33 @@ * AccountParticipation describes the parameters used by this account in consensus protocol. */ export type AccountParticipation = { + /** + * Selection public key (if any) currently registered for this round. + */ selectionParticipationKey: string; + + /** + * First round for which this participation is valid. + */ voteFirstValid: bigint; + + /** + * Number of subkeys in each batch of participation keys. + */ voteKeyDilution: bigint; + + /** + * Last round for which this participation is valid. + */ voteLastValid: bigint; + + /** + * root participation public key (if any) currently registered for this round. + */ voteParticipationKey: string; + + /** + * Root of the state proof key (if any) + */ stateProofKey?: string; }; diff --git a/packages/typescript/indexer_client/src/models/accountstatedelta.ts b/packages/typescript/indexer_client/src/models/accountstatedelta.ts index b2d101cad..5bd98a58e 100644 --- a/packages/typescript/indexer_client/src/models/accountstatedelta.ts +++ b/packages/typescript/indexer_client/src/models/accountstatedelta.ts @@ -3,4 +3,7 @@ import type { StateDelta } from "./index"; /** * Application state delta. */ -export type AccountStateDelta = { address: string; delta: StateDelta }; +export type AccountStateDelta = { + address: string; + delta: StateDelta; +}; diff --git a/packages/typescript/indexer_client/src/models/algokitsignedtransaction.ts b/packages/typescript/indexer_client/src/models/algokitsignedtransaction.ts new file mode 100644 index 000000000..01e5e014a --- /dev/null +++ b/packages/typescript/indexer_client/src/models/algokitsignedtransaction.ts @@ -0,0 +1,277 @@ +/** + * Temporary SignedTransaction model for msgpack encoding/decoding. + * This will be replaced when utils-ts is integrated into the monorepo. + * + * This type represents a signed Algorand transaction that can be + * encoded to msgpack format for the simulate endpoint. + */ + +/** + * Base transaction structure that all transaction types share + */ +export type BaseTransaction = { + /** Transaction type */ + type: "pay" | "axfer" | "afrz" | "acfg" | "keyreg" | "appl"; + + /** Sender address (base64 or string) */ + sender: string; + + /** Fee in microALGO */ + fee?: number | bigint; + + /** First valid round */ + firstValid: number | bigint; + + /** Last valid round */ + lastValid: number | bigint; + + /** Genesis ID */ + genesisId?: string; + + /** Genesis hash (base64) */ + genesisHash?: string; + + /** Transaction note (base64 or Uint8Array) */ + note?: string | Uint8Array; + + /** Lease (base64) */ + lease?: string; + + /** Rekey to address */ + rekeyTo?: string; + + /** Group ID (base64) */ + group?: string; +}; + +/** + * Payment transaction + */ +export type PaymentTransaction = BaseTransaction & { + type: "pay"; + + /** Receiver address */ + receiver: string; + + /** Amount in microALGO */ + amount: number | bigint; + + /** Close remainder to address */ + closeRemainderTo?: string; +}; + +/** + * Asset transfer transaction + */ +export type AssetTransferTransaction = BaseTransaction & { + type: "axfer"; + + /** Asset ID */ + assetIndex: number | bigint; + + /** Asset amount */ + amount: number | bigint; + + /** Asset receiver */ + receiver: string; + + /** Asset close to */ + closeRemainderTo?: string; + + /** Asset sender (for clawback) */ + assetSender?: string; +}; + +/** + * Asset config transaction + */ +export type AssetConfigTransaction = BaseTransaction & { + type: "acfg"; + + /** Asset ID (0 for creation) */ + assetIndex?: number | bigint; + + /** Asset parameters */ + assetParams?: { + total?: number | bigint; + decimals?: number; + defaultFrozen?: boolean; + unitName?: string; + assetName?: string; + url?: string; + metadataHash?: string; + manager?: string; + reserve?: string; + freeze?: string; + clawback?: string; + }; +}; + +/** + * Asset freeze transaction + */ +export type AssetFreezeTransaction = BaseTransaction & { + type: "afrz"; + + /** Asset ID */ + assetIndex: number | bigint; + + /** Address to freeze/unfreeze */ + freezeAccount: string; + + /** Freeze state */ + frozen: boolean; +}; + +/** + * Key registration transaction + */ +export type KeyRegTransaction = BaseTransaction & { + type: "keyreg"; + + /** Voting key */ + voteKey?: string; + + /** Selection key */ + selectionKey?: string; + + /** State proof key */ + stateProofKey?: string; + + /** First voting round */ + voteFirst?: number | bigint; + + /** Last voting round */ + voteLast?: number | bigint; + + /** Vote key dilution */ + voteKeyDilution?: number | bigint; + + /** Non-participation flag */ + nonParticipation?: boolean; +}; + +/** + * Application call transaction + */ +export type ApplicationTransaction = BaseTransaction & { + type: "appl"; + + /** Application ID (0 for creation) */ + applicationId: number | bigint; + + /** OnComplete action */ + onComplete: number; + + /** Application arguments (base64 encoded) */ + applicationArgs?: string[]; + + /** Accounts array */ + accounts?: string[]; + + /** Foreign apps */ + foreignApps?: (number | bigint)[]; + + /** Foreign assets */ + foreignAssets?: (number | bigint)[]; + + /** Approval program (base64) */ + approvalProgram?: string; + + /** Clear program (base64) */ + clearProgram?: string; + + /** Global state schema */ + globalStateSchema?: { + numUint: number; + numByteSlice: number; + }; + + /** Local state schema */ + localStateSchema?: { + numUint: number; + numByteSlice: number; + }; + + /** Extra program pages */ + extraProgramPages?: number; + + /** Boxes */ + boxes?: Array<{ + appIndex: number | bigint; + name: string; + }>; +}; + +/** + * Union type for all transaction types + */ +export type Transaction = + | PaymentTransaction + | AssetTransferTransaction + | AssetConfigTransaction + | AssetFreezeTransaction + | KeyRegTransaction + | ApplicationTransaction; + +/** + * Multisignature subsignature + */ +export type MultisigSubsignature = { + /** Public key (base64) */ + publicKey?: string; + + /** Signature (base64) */ + signature?: string; +}; + +/** + * Multisignature + */ +export type Multisignature = { + /** Version */ + version: number; + + /** Threshold */ + threshold: number; + + /** Subsignatures */ + subsignatures?: MultisigSubsignature[]; +}; + +/** + * Logic signature + */ +export type LogicSignature = { + /** Logic program (base64) */ + logic: string; + + /** Logic signature arguments (base64 encoded) */ + args?: string[]; + + /** Signature (base64) */ + signature?: string; + + /** Multisignature */ + multisignature?: Multisignature; +}; + +/** + * Signed transaction structure + */ +export type AlgokitSignedTransaction = { + /** The transaction */ + transaction: Transaction; + + /** ED25519 signature (base64) */ + signature?: string; + + /** Multisignature */ + multiSignature?: Multisignature; + + /** Logic signature */ + logicSignature?: LogicSignature; + + /** Auth address (for rekeyed accounts) */ + authAddress?: string; +}; diff --git a/packages/typescript/indexer_client/src/models/application.ts b/packages/typescript/indexer_client/src/models/application.ts index a0d50c8fa..c72de3ec0 100644 --- a/packages/typescript/indexer_client/src/models/application.ts +++ b/packages/typescript/indexer_client/src/models/application.ts @@ -3,4 +3,25 @@ import type { ApplicationParams } from "./index"; /** * Application index and its parameters */ -export type Application = { id: bigint; deleted?: boolean; createdAtRound?: bigint; deletedAtRound?: bigint; params: ApplicationParams }; +export type Application = { + /** + * application index. + */ + id: bigint; + + /** + * Whether or not this application is currently deleted. + */ + deleted?: boolean; + + /** + * Round when this application was created. + */ + createdAtRound?: bigint; + + /** + * Round when this application was deleted. + */ + deletedAtRound?: bigint; + params: ApplicationParams; +}; diff --git a/packages/typescript/indexer_client/src/models/applicationlocalstate.ts b/packages/typescript/indexer_client/src/models/applicationlocalstate.ts index c5afea98f..e1b3aa959 100644 --- a/packages/typescript/indexer_client/src/models/applicationlocalstate.ts +++ b/packages/typescript/indexer_client/src/models/applicationlocalstate.ts @@ -4,9 +4,24 @@ import type { ApplicationStateSchema, TealKeyValueStore } from "./index"; * Stores local state associated with an application. */ export type ApplicationLocalState = { + /** + * The application which this local state is for. + */ id: bigint; + + /** + * Whether or not the application local state is currently deleted from its account. + */ deleted?: boolean; + + /** + * Round when the account opted into the application. + */ optedInAtRound?: bigint; + + /** + * Round when account closed out of the application. + */ closedOutAtRound?: bigint; schema: ApplicationStateSchema; keyValue?: TealKeyValueStore; diff --git a/packages/typescript/indexer_client/src/models/applicationlogdata.ts b/packages/typescript/indexer_client/src/models/applicationlogdata.ts index 91b880ceb..c8933ef89 100644 --- a/packages/typescript/indexer_client/src/models/applicationlogdata.ts +++ b/packages/typescript/indexer_client/src/models/applicationlogdata.ts @@ -1,4 +1,14 @@ /** * Stores the global information associated with an application. */ -export type ApplicationLogData = { txid: string; logs: string[] }; +export type ApplicationLogData = { + /** + * Transaction ID + */ + txid: string; + + /** + * Logs for the application being executed by the transaction. + */ + logs: string[]; +}; diff --git a/packages/typescript/indexer_client/src/models/applicationparams.ts b/packages/typescript/indexer_client/src/models/applicationparams.ts index 6c6a966e9..ce76a15cb 100644 --- a/packages/typescript/indexer_client/src/models/applicationparams.ts +++ b/packages/typescript/indexer_client/src/models/applicationparams.ts @@ -4,12 +4,31 @@ import type { ApplicationStateSchema, TealKeyValueStore } from "./index"; * Stores the global information associated with an application. */ export type ApplicationParams = { + /** + * The address that created this application. This is the address where the parameters and global state for this application can be found. + */ creator?: string; + + /** + * approval program. + */ approvalProgram?: string; + + /** + * clear state program. + */ clearStateProgram?: string; + + /** + * the number of extra program pages available to this app. + */ extraProgramPages?: bigint; localStateSchema?: ApplicationStateSchema; globalStateSchema?: ApplicationStateSchema; globalState?: TealKeyValueStore; + + /** + * the number of updates to the application programs + */ version?: bigint; }; diff --git a/packages/typescript/indexer_client/src/models/applicationstateschema.ts b/packages/typescript/indexer_client/src/models/applicationstateschema.ts index d40cb1f25..2cbaa7e17 100644 --- a/packages/typescript/indexer_client/src/models/applicationstateschema.ts +++ b/packages/typescript/indexer_client/src/models/applicationstateschema.ts @@ -1,4 +1,14 @@ /** * Specifies maximums on the number of each type that may be stored. */ -export type ApplicationStateSchema = { numUint: bigint; numByteSlice: bigint }; +export type ApplicationStateSchema = { + /** + * number of uints. + */ + numUint: bigint; + + /** + * number of byte slices. + */ + numByteSlice: bigint; +}; diff --git a/packages/typescript/indexer_client/src/models/asset.ts b/packages/typescript/indexer_client/src/models/asset.ts index 9a6a3a3f9..820dafc03 100644 --- a/packages/typescript/indexer_client/src/models/asset.ts +++ b/packages/typescript/indexer_client/src/models/asset.ts @@ -3,4 +3,25 @@ import type { AssetParams } from "./index"; /** * Specifies both the unique identifier and the parameters for an asset */ -export type Asset = { index: bigint; deleted?: boolean; createdAtRound?: bigint; destroyedAtRound?: bigint; params: AssetParams }; +export type Asset = { + /** + * unique asset identifier + */ + index: bigint; + + /** + * Whether or not this asset is currently deleted. + */ + deleted?: boolean; + + /** + * Round during which this asset was created. + */ + createdAtRound?: bigint; + + /** + * Round during which this asset was destroyed. + */ + destroyedAtRound?: bigint; + params: AssetParams; +}; diff --git a/packages/typescript/indexer_client/src/models/assetholding.ts b/packages/typescript/indexer_client/src/models/assetholding.ts index 8c59e93a2..ff3dd3ee3 100644 --- a/packages/typescript/indexer_client/src/models/assetholding.ts +++ b/packages/typescript/indexer_client/src/models/assetholding.ts @@ -5,10 +5,33 @@ * data/basics/userBalance.go : AssetHolding */ export type AssetHolding = { + /** + * number of units held. + */ amount: bigint; + + /** + * Asset ID of the holding. + */ assetId: bigint; + + /** + * whether or not the holding is frozen. + */ isFrozen: boolean; + + /** + * Whether or not the asset holding is currently deleted from its account. + */ deleted?: boolean; + + /** + * Round during which the account opted into this asset holding. + */ optedInAtRound?: bigint; + + /** + * Round during which the account opted out of this asset holding. + */ optedOutAtRound?: bigint; }; diff --git a/packages/typescript/indexer_client/src/models/assetparams.ts b/packages/typescript/indexer_client/src/models/assetparams.ts index 3ff1492fc..c0fa71843 100644 --- a/packages/typescript/indexer_client/src/models/assetparams.ts +++ b/packages/typescript/indexer_client/src/models/assetparams.ts @@ -7,19 +7,78 @@ * data/transactions/asset.go : AssetParams */ export type AssetParams = { + /** + * Address of account used to clawback holdings of this asset. If empty, clawback is not permitted. + */ clawback?: string; + + /** + * 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. + */ creator: string; + + /** + * 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; + + /** + * Whether holdings of this asset are frozen by default. + */ defaultFrozen?: boolean; + + /** + * Address of account used to freeze holdings of this asset. If empty, freezing is not permitted. + */ freeze?: string; + + /** + * Address of account used to manage the keys of this asset and to destroy it. + */ manager?: string; + + /** + * A commitment to some unspecified asset metadata. The format of this metadata is up to the application. + */ metadataHash?: string; + + /** + * Name of this asset, as supplied by the creator. Included only when the asset name is composed of printable utf-8 characters. + */ name?: string; + + /** + * Base64 encoded name of this asset, as supplied by the creator. + */ nameB64?: string; + + /** + * Address of account holding reserve (non-minted) units of this asset. + */ reserve?: string; + + /** + * The total number of units of this asset. + */ total: bigint; + + /** + * 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. + */ unitName?: string; + + /** + * Base64 encoded name of a unit of this asset, as supplied by the creator. + */ unitNameB64?: string; + + /** + * URL where more information about the asset can be retrieved. Included only when the URL is composed of printable utf-8 characters. + */ url?: string; + + /** + * Base64 encoded URL where more information about the asset can be retrieved. + */ urlB64?: string; }; diff --git a/packages/typescript/indexer_client/src/models/block.ts b/packages/typescript/indexer_client/src/models/block.ts index 59183605c..2af378131 100644 --- a/packages/typescript/indexer_client/src/models/block.ts +++ b/packages/typescript/indexer_client/src/models/block.ts @@ -7,21 +7,82 @@ import type { BlockRewards, BlockUpgradeState, BlockUpgradeVote, ParticipationUp * data/bookkeeping/block.go : Block */ export type Block = { + /** + * the proposer of this block. + */ proposer?: string; + + /** + * the sum of all fees paid by transactions in this block. + */ feesCollected?: bigint; + + /** + * the potential bonus payout for this block. + */ bonus?: bigint; + + /** + * the actual amount transferred to the proposer from the fee sink. + */ proposerPayout?: bigint; + + /** + * \[gh\] hash to which this block belongs. + */ genesisHash: string; + + /** + * \[gen\] ID to which this block belongs. + */ genesisId: string; + + /** + * \[prev\] Previous block hash. + */ previousBlockHash: string; rewards?: BlockRewards; + + /** + * \[rnd\] Current round on which this block was appended to the chain. + */ round: bigint; + + /** + * \[seed\] Sortition seed. + */ seed: string; + + /** + * Tracks the status of state proofs. + */ stateProofTracking?: StateProofTracking[]; + + /** + * \[ts\] Block creation timestamp in seconds since epoch + */ timestamp: bigint; + + /** + * \[txns\] list of transactions corresponding to a given round. + */ transactions?: Transaction[]; + + /** + * \[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. + */ transactionsRoot: string; + + /** + * \[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. + */ transactionsRootSha256: string; + + /** + * \[tc\] TxnCounter counts the number of transactions committed in the ledger, from the time at which support for this feature was introduced. + * + * Specifically, TxnCounter is the number of the next transaction that will be committed after this block. It is 0 when no transactions have ever been committed (since TxnCounter started being supported). + */ txnCounter?: bigint; upgradeState?: BlockUpgradeState; upgradeVote?: BlockUpgradeVote; diff --git a/packages/typescript/indexer_client/src/models/blockrewards.ts b/packages/typescript/indexer_client/src/models/blockrewards.ts index 6a7538e4d..36cabebb8 100644 --- a/packages/typescript/indexer_client/src/models/blockrewards.ts +++ b/packages/typescript/indexer_client/src/models/blockrewards.ts @@ -2,10 +2,33 @@ * Fields relating to rewards, */ export type BlockRewards = { + /** + * \[fees\] accepts transaction fees, it can only spend to the incentive pool. + */ feeSink: string; + + /** + * \[rwcalr\] number of leftover MicroAlgos after the distribution of rewards-rate MicroAlgos for every reward unit in the next round. + */ rewardsCalculationRound: bigint; + + /** + * \[earn\] How many rewards, in MicroAlgos, have been distributed to each RewardUnit of MicroAlgos since genesis. + */ rewardsLevel: bigint; + + /** + * \[rwd\] accepts periodic injections from the fee-sink and continually redistributes them as rewards. + */ rewardsPool: string; + + /** + * \[rate\] Number of new MicroAlgos added to the participation stake from rewards at the next round. + */ rewardsRate: bigint; + + /** + * \[frac\] Number of leftover MicroAlgos after the distribution of RewardsRate/rewardUnits MicroAlgos for every reward unit in the next round. + */ rewardsResidue: bigint; }; diff --git a/packages/typescript/indexer_client/src/models/blockupgradestate.ts b/packages/typescript/indexer_client/src/models/blockupgradestate.ts index d475773c3..a039d56cd 100644 --- a/packages/typescript/indexer_client/src/models/blockupgradestate.ts +++ b/packages/typescript/indexer_client/src/models/blockupgradestate.ts @@ -2,9 +2,28 @@ * Fields relating to a protocol upgrade. */ export type BlockUpgradeState = { + /** + * \[proto\] The current protocol version. + */ currentProtocol: string; + + /** + * \[nextproto\] The next proposed protocol version. + */ nextProtocol?: string; + + /** + * \[nextyes\] Number of blocks which approved the protocol upgrade. + */ nextProtocolApprovals?: bigint; + + /** + * \[nextswitch\] Round on which the protocol upgrade will take effect. + */ nextProtocolSwitchOn?: bigint; + + /** + * \[nextbefore\] Deadline round for this protocol upgrade (No votes will be consider after this round). + */ nextProtocolVoteBefore?: bigint; }; diff --git a/packages/typescript/indexer_client/src/models/blockupgradevote.ts b/packages/typescript/indexer_client/src/models/blockupgradevote.ts index d31a05aae..c3ba66050 100644 --- a/packages/typescript/indexer_client/src/models/blockupgradevote.ts +++ b/packages/typescript/indexer_client/src/models/blockupgradevote.ts @@ -1,4 +1,19 @@ /** * Fields relating to voting for a protocol upgrade. */ -export type BlockUpgradeVote = { upgradeApprove?: boolean; upgradeDelay?: bigint; upgradePropose?: string }; +export type BlockUpgradeVote = { + /** + * \[upgradeyes\] Indicates a yes vote for the current proposal. + */ + upgradeApprove?: boolean; + + /** + * \[upgradedelay\] Indicates the time between acceptance and execution. + */ + upgradeDelay?: bigint; + + /** + * \[upgradeprop\] Indicates a proposed upgrade. + */ + upgradePropose?: string; +}; diff --git a/packages/typescript/indexer_client/src/models/box.ts b/packages/typescript/indexer_client/src/models/box.ts index 90b5c64e6..8dc50db48 100644 --- a/packages/typescript/indexer_client/src/models/box.ts +++ b/packages/typescript/indexer_client/src/models/box.ts @@ -1,4 +1,19 @@ /** * Box name and its content. */ -export type Box = { round: bigint; name: string; value: string }; +export type Box = { + /** + * The round for which this information is relevant + */ + round: bigint; + + /** + * \[name\] box name, base64 encoded + */ + name: string; + + /** + * \[value\] box value, base64 encoded. + */ + value: string; +}; diff --git a/packages/typescript/indexer_client/src/models/boxdescriptor.ts b/packages/typescript/indexer_client/src/models/boxdescriptor.ts index 076918a2e..44cf46559 100644 --- a/packages/typescript/indexer_client/src/models/boxdescriptor.ts +++ b/packages/typescript/indexer_client/src/models/boxdescriptor.ts @@ -1,4 +1,9 @@ /** * Box descriptor describes an app box without a value. */ -export type BoxDescriptor = { name: string }; +export type BoxDescriptor = { + /** + * Base64 encoded box name + */ + name: string; +}; diff --git a/packages/typescript/indexer_client/src/models/boxreference.ts b/packages/typescript/indexer_client/src/models/boxreference.ts index 3d7fba0d8..86ce6955f 100644 --- a/packages/typescript/indexer_client/src/models/boxreference.ts +++ b/packages/typescript/indexer_client/src/models/boxreference.ts @@ -1,4 +1,14 @@ /** * BoxReference names a box by its name and the application ID it belongs to. */ -export type BoxReference = { app: bigint; name: string }; +export type BoxReference = { + /** + * Application ID to which the box belongs, or zero if referring to the called application. + */ + app: bigint; + + /** + * Base64 encoded box name + */ + name: string; +}; diff --git a/packages/typescript/indexer_client/src/models/evaldelta.ts b/packages/typescript/indexer_client/src/models/evaldelta.ts index 2d9fe7313..0fc979b44 100644 --- a/packages/typescript/indexer_client/src/models/evaldelta.ts +++ b/packages/typescript/indexer_client/src/models/evaldelta.ts @@ -1,4 +1,19 @@ /** * Represents a TEAL value delta. */ -export type EvalDelta = { action: bigint; bytes?: string; uint?: bigint }; +export type EvalDelta = { + /** + * \[at\] delta action. + */ + action: bigint; + + /** + * \[bs\] bytes value. + */ + bytes?: string; + + /** + * \[ui\] uint value. + */ + uint?: bigint; +}; diff --git a/packages/typescript/indexer_client/src/models/evaldeltakeyvalue.ts b/packages/typescript/indexer_client/src/models/evaldeltakeyvalue.ts index 63d6ea4e1..7a56299ea 100644 --- a/packages/typescript/indexer_client/src/models/evaldeltakeyvalue.ts +++ b/packages/typescript/indexer_client/src/models/evaldeltakeyvalue.ts @@ -3,4 +3,7 @@ import type { EvalDelta } from "./index"; /** * Key-value pairs for StateDelta. */ -export type EvalDeltaKeyValue = { key: string; value: EvalDelta }; +export type EvalDeltaKeyValue = { + key: string; + value: EvalDelta; +}; diff --git a/packages/typescript/indexer_client/src/models/hashfactory.ts b/packages/typescript/indexer_client/src/models/hashfactory.ts index deefd3795..06fcc203a 100644 --- a/packages/typescript/indexer_client/src/models/hashfactory.ts +++ b/packages/typescript/indexer_client/src/models/hashfactory.ts @@ -1 +1,6 @@ -export type HashFactory = { hashType?: bigint }; +export type HashFactory = { + /** + * \[t\] + */ + hashType?: bigint; +}; diff --git a/packages/typescript/indexer_client/src/models/hbprooffields.ts b/packages/typescript/indexer_client/src/models/hbprooffields.ts index 79c31dc58..468f9747f 100644 --- a/packages/typescript/indexer_client/src/models/hbprooffields.ts +++ b/packages/typescript/indexer_client/src/models/hbprooffields.ts @@ -1,4 +1,29 @@ /** * \[hbprf\] HbProof is a signature using HeartbeatAddress's partkey, thereby showing it is online. */ -export type HbProofFields = { hbSig?: string; hbPk?: string; hbPk2?: string; hbPk1sig?: string; hbPk2sig?: string }; +export type HbProofFields = { + /** + * \[s\] Signature of the heartbeat message. + */ + hbSig?: string; + + /** + * \[p\] Public key of the heartbeat message. + */ + hbPk?: string; + + /** + * \[p2\] Key for new-style two-level ephemeral signature. + */ + hbPk2?: string; + + /** + * \[p1s\] Signature of OneTimeSignatureSubkeyOffsetID(PK, Batch, Offset) under the key PK2. + */ + hbPk1sig?: string; + + /** + * \[p2s\] Signature of OneTimeSignatureSubkeyBatchID(PK2, Batch) under the master key (OneTimeSignatureVerifier). + */ + hbPk2sig?: string; +}; diff --git a/packages/typescript/indexer_client/src/models/healthcheck.ts b/packages/typescript/indexer_client/src/models/healthcheck.ts index b3f107ee4..bf4621a0e 100644 --- a/packages/typescript/indexer_client/src/models/healthcheck.ts +++ b/packages/typescript/indexer_client/src/models/healthcheck.ts @@ -2,6 +2,9 @@ * A health check response. */ export type HealthCheck = { + /** + * Current version. + */ version: string; data?: {}; round: bigint; diff --git a/packages/typescript/indexer_client/src/models/index.ts b/packages/typescript/indexer_client/src/models/index.ts index f5e8f0d60..a9918c6f4 100644 --- a/packages/typescript/indexer_client/src/models/index.ts +++ b/packages/typescript/indexer_client/src/models/index.ts @@ -71,3 +71,5 @@ export type { LookupAssetTransactions } from "./lookupassettransactions"; export type { SearchForBlockHeaders } from "./searchforblockheaders"; export type { LookupTransaction } from "./lookuptransaction"; export type { SearchForTransactions } from "./searchfortransactions"; +// TODO(utils-ts): Remove this export when utils-ts provides SignedTransaction types +export type { AlgokitSignedTransaction } from "./algokitsignedtransaction"; diff --git a/packages/typescript/indexer_client/src/models/indexerstateproofmessage.ts b/packages/typescript/indexer_client/src/models/indexerstateproofmessage.ts index ffcf9dc44..a57ed36c3 100644 --- a/packages/typescript/indexer_client/src/models/indexerstateproofmessage.ts +++ b/packages/typescript/indexer_client/src/models/indexerstateproofmessage.ts @@ -1,7 +1,26 @@ export type IndexerStateProofMessage = { + /** + * \[b\] + */ blockHeadersCommitment?: string; + + /** + * \[v\] + */ votersCommitment?: string; + + /** + * \[P\] + */ lnProvenWeight?: bigint; + + /** + * \[f\] + */ firstAttestedRound?: bigint; + + /** + * \[l\] + */ latestAttestedRound?: bigint; }; diff --git a/packages/typescript/indexer_client/src/models/lookupaccountapplocalstates.ts b/packages/typescript/indexer_client/src/models/lookupaccountapplocalstates.ts index 3bb4a630a..ebe5ff185 100644 --- a/packages/typescript/indexer_client/src/models/lookupaccountapplocalstates.ts +++ b/packages/typescript/indexer_client/src/models/lookupaccountapplocalstates.ts @@ -1,6 +1,15 @@ import type { ApplicationLocalState } from "./index"; -/** - * (empty) - */ -export type LookupAccountAppLocalStates = { appsLocalStates: ApplicationLocalState[]; currentRound: bigint; nextToken?: string }; +export type LookupAccountAppLocalStates = { + appsLocalStates: ApplicationLocalState[]; + + /** + * Round at which the results were computed. + */ + currentRound: bigint; + + /** + * Used for pagination, when making another request provide this token with the next parameter. + */ + nextToken?: string; +}; diff --git a/packages/typescript/indexer_client/src/models/lookupaccountassets.ts b/packages/typescript/indexer_client/src/models/lookupaccountassets.ts index dd1d11ba0..c23e690bc 100644 --- a/packages/typescript/indexer_client/src/models/lookupaccountassets.ts +++ b/packages/typescript/indexer_client/src/models/lookupaccountassets.ts @@ -1,6 +1,14 @@ import type { AssetHolding } from "./index"; -/** - * (empty) - */ -export type LookupAccountAssets = { currentRound: bigint; nextToken?: string; assets: AssetHolding[] }; +export type LookupAccountAssets = { + /** + * Round at which the results were computed. + */ + currentRound: bigint; + + /** + * Used for pagination, when making another request provide this token with the next parameter. + */ + nextToken?: string; + assets: AssetHolding[]; +}; diff --git a/packages/typescript/indexer_client/src/models/lookupaccountbyid.ts b/packages/typescript/indexer_client/src/models/lookupaccountbyid.ts index 550103b49..aafafdaf2 100644 --- a/packages/typescript/indexer_client/src/models/lookupaccountbyid.ts +++ b/packages/typescript/indexer_client/src/models/lookupaccountbyid.ts @@ -1,6 +1,10 @@ import type { Account } from "./index"; -/** - * (empty) - */ -export type LookupAccountById = { account: Account; currentRound: bigint }; +export type LookupAccountById = { + account: Account; + + /** + * Round at which the results were computed. + */ + currentRound: bigint; +}; diff --git a/packages/typescript/indexer_client/src/models/lookupaccountcreatedapplications.ts b/packages/typescript/indexer_client/src/models/lookupaccountcreatedapplications.ts index e2635f2ce..19c2f8d95 100644 --- a/packages/typescript/indexer_client/src/models/lookupaccountcreatedapplications.ts +++ b/packages/typescript/indexer_client/src/models/lookupaccountcreatedapplications.ts @@ -1,6 +1,15 @@ import type { Application } from "./index"; -/** - * (empty) - */ -export type LookupAccountCreatedApplications = { applications: Application[]; currentRound: bigint; nextToken?: string }; +export type LookupAccountCreatedApplications = { + applications: Application[]; + + /** + * Round at which the results were computed. + */ + currentRound: bigint; + + /** + * Used for pagination, when making another request provide this token with the next parameter. + */ + nextToken?: string; +}; diff --git a/packages/typescript/indexer_client/src/models/lookupaccountcreatedassets.ts b/packages/typescript/indexer_client/src/models/lookupaccountcreatedassets.ts index 8bb080ea8..d6deec27a 100644 --- a/packages/typescript/indexer_client/src/models/lookupaccountcreatedassets.ts +++ b/packages/typescript/indexer_client/src/models/lookupaccountcreatedassets.ts @@ -1,6 +1,15 @@ import type { Asset } from "./index"; -/** - * (empty) - */ -export type LookupAccountCreatedAssets = { assets: Asset[]; currentRound: bigint; nextToken?: string }; +export type LookupAccountCreatedAssets = { + assets: Asset[]; + + /** + * Round at which the results were computed. + */ + currentRound: bigint; + + /** + * Used for pagination, when making another request provide this token with the next parameter. + */ + nextToken?: string; +}; diff --git a/packages/typescript/indexer_client/src/models/lookupaccounttransactions.ts b/packages/typescript/indexer_client/src/models/lookupaccounttransactions.ts index 89d48611f..c1304fcfd 100644 --- a/packages/typescript/indexer_client/src/models/lookupaccounttransactions.ts +++ b/packages/typescript/indexer_client/src/models/lookupaccounttransactions.ts @@ -1,6 +1,14 @@ import type { Transaction } from "./index"; -/** - * (empty) - */ -export type LookupAccountTransactions = { currentRound: bigint; nextToken?: string; transactions: Transaction[] }; +export type LookupAccountTransactions = { + /** + * Round at which the results were computed. + */ + currentRound: bigint; + + /** + * Used for pagination, when making another request provide this token with the next parameter. + */ + nextToken?: string; + transactions: Transaction[]; +}; diff --git a/packages/typescript/indexer_client/src/models/lookupapplicationbyid.ts b/packages/typescript/indexer_client/src/models/lookupapplicationbyid.ts index a0f9b9679..f5b47b7c1 100644 --- a/packages/typescript/indexer_client/src/models/lookupapplicationbyid.ts +++ b/packages/typescript/indexer_client/src/models/lookupapplicationbyid.ts @@ -1,6 +1,10 @@ import type { Application } from "./index"; -/** - * (empty) - */ -export type LookupApplicationById = { application?: Application; currentRound: bigint }; +export type LookupApplicationById = { + application?: Application; + + /** + * Round at which the results were computed. + */ + currentRound: bigint; +}; diff --git a/packages/typescript/indexer_client/src/models/lookupapplicationlogsbyid.ts b/packages/typescript/indexer_client/src/models/lookupapplicationlogsbyid.ts index 04085fdea..f3345d430 100644 --- a/packages/typescript/indexer_client/src/models/lookupapplicationlogsbyid.ts +++ b/packages/typescript/indexer_client/src/models/lookupapplicationlogsbyid.ts @@ -1,6 +1,19 @@ import type { ApplicationLogData } from "./index"; -/** - * (empty) - */ -export type LookupApplicationLogsById = { applicationId: bigint; currentRound: bigint; nextToken?: string; logData?: ApplicationLogData[] }; +export type LookupApplicationLogsById = { + /** + * \[appidx\] application index. + */ + applicationId: bigint; + + /** + * Round at which the results were computed. + */ + currentRound: bigint; + + /** + * Used for pagination, when making another request provide this token with the next parameter. + */ + nextToken?: string; + logData?: ApplicationLogData[]; +}; diff --git a/packages/typescript/indexer_client/src/models/lookupassetbalances.ts b/packages/typescript/indexer_client/src/models/lookupassetbalances.ts index 341040430..c128393c5 100644 --- a/packages/typescript/indexer_client/src/models/lookupassetbalances.ts +++ b/packages/typescript/indexer_client/src/models/lookupassetbalances.ts @@ -1,6 +1,15 @@ import type { MiniAssetHolding } from "./index"; -/** - * (empty) - */ -export type LookupAssetBalances = { balances: MiniAssetHolding[]; currentRound: bigint; nextToken?: string }; +export type LookupAssetBalances = { + balances: MiniAssetHolding[]; + + /** + * Round at which the results were computed. + */ + currentRound: bigint; + + /** + * Used for pagination, when making another request provide this token with the next parameter. + */ + nextToken?: string; +}; diff --git a/packages/typescript/indexer_client/src/models/lookupassetbyid.ts b/packages/typescript/indexer_client/src/models/lookupassetbyid.ts index 6cb7b16f7..83fcb75da 100644 --- a/packages/typescript/indexer_client/src/models/lookupassetbyid.ts +++ b/packages/typescript/indexer_client/src/models/lookupassetbyid.ts @@ -1,6 +1,10 @@ import type { Asset } from "./index"; -/** - * (empty) - */ -export type LookupAssetById = { asset: Asset; currentRound: bigint }; +export type LookupAssetById = { + asset: Asset; + + /** + * Round at which the results were computed. + */ + currentRound: bigint; +}; diff --git a/packages/typescript/indexer_client/src/models/lookupassettransactions.ts b/packages/typescript/indexer_client/src/models/lookupassettransactions.ts index 0e28ed9e5..2ecb72045 100644 --- a/packages/typescript/indexer_client/src/models/lookupassettransactions.ts +++ b/packages/typescript/indexer_client/src/models/lookupassettransactions.ts @@ -1,6 +1,14 @@ import type { Transaction } from "./index"; -/** - * (empty) - */ -export type LookupAssetTransactions = { currentRound: bigint; nextToken?: string; transactions: Transaction[] }; +export type LookupAssetTransactions = { + /** + * Round at which the results were computed. + */ + currentRound: bigint; + + /** + * Used for pagination, when making another request provide this token with the next parameter. + */ + nextToken?: string; + transactions: Transaction[]; +}; diff --git a/packages/typescript/indexer_client/src/models/lookuptransaction.ts b/packages/typescript/indexer_client/src/models/lookuptransaction.ts index 3dc7fa0f6..b846e0c4b 100644 --- a/packages/typescript/indexer_client/src/models/lookuptransaction.ts +++ b/packages/typescript/indexer_client/src/models/lookuptransaction.ts @@ -1,6 +1,10 @@ import type { Transaction } from "./index"; -/** - * (empty) - */ -export type LookupTransaction = { transaction: Transaction; currentRound: bigint }; +export type LookupTransaction = { + transaction: Transaction; + + /** + * Round at which the results were computed. + */ + currentRound: bigint; +}; diff --git a/packages/typescript/indexer_client/src/models/merklearrayproof.ts b/packages/typescript/indexer_client/src/models/merklearrayproof.ts index f41ad701f..ce1cedb61 100644 --- a/packages/typescript/indexer_client/src/models/merklearrayproof.ts +++ b/packages/typescript/indexer_client/src/models/merklearrayproof.ts @@ -1,3 +1,14 @@ import type { HashFactory } from "./index"; -export type MerkleArrayProof = { path?: string[]; hashFactory?: HashFactory; treeDepth?: bigint }; +export type MerkleArrayProof = { + /** + * \[pth\] + */ + path?: string[]; + hashFactory?: HashFactory; + + /** + * \[td\] + */ + treeDepth?: bigint; +}; diff --git a/packages/typescript/indexer_client/src/models/miniassetholding.ts b/packages/typescript/indexer_client/src/models/miniassetholding.ts index 2b446c8fa..725c7b01d 100644 --- a/packages/typescript/indexer_client/src/models/miniassetholding.ts +++ b/packages/typescript/indexer_client/src/models/miniassetholding.ts @@ -5,7 +5,19 @@ export type MiniAssetHolding = { address: string; amount: bigint; isFrozen: boolean; + + /** + * Whether or not this asset holding is currently deleted from its account. + */ deleted?: boolean; + + /** + * Round during which the account opted into the asset. + */ optedInAtRound?: bigint; + + /** + * Round during which the account opted out of the asset. + */ optedOutAtRound?: bigint; }; diff --git a/packages/typescript/indexer_client/src/models/participationupdates.ts b/packages/typescript/indexer_client/src/models/participationupdates.ts index bc79c6d50..241971c4e 100644 --- a/packages/typescript/indexer_client/src/models/participationupdates.ts +++ b/packages/typescript/indexer_client/src/models/participationupdates.ts @@ -1,4 +1,14 @@ /** * Participation account data that needs to be checked/acted on by the network. */ -export type ParticipationUpdates = { expiredParticipationAccounts?: string[]; absentParticipationAccounts?: string[] }; +export type ParticipationUpdates = { + /** + * \[partupdrmv\] a list of online accounts that needs to be converted to offline since their participation key expired. + */ + expiredParticipationAccounts?: string[]; + + /** + * \[partupabs\] a list of online accounts that need to be suspended. + */ + absentParticipationAccounts?: string[]; +}; diff --git a/packages/typescript/indexer_client/src/models/searchforaccounts.ts b/packages/typescript/indexer_client/src/models/searchforaccounts.ts index cc5a7d973..9d71b1d95 100644 --- a/packages/typescript/indexer_client/src/models/searchforaccounts.ts +++ b/packages/typescript/indexer_client/src/models/searchforaccounts.ts @@ -1,6 +1,15 @@ import type { Account } from "./index"; -/** - * (empty) - */ -export type SearchForAccounts = { accounts: Account[]; currentRound: bigint; nextToken?: string }; +export type SearchForAccounts = { + accounts: Account[]; + + /** + * Round at which the results were computed. + */ + currentRound: bigint; + + /** + * Used for pagination, when making another request provide this token with the next parameter. + */ + nextToken?: string; +}; diff --git a/packages/typescript/indexer_client/src/models/searchforapplicationboxes.ts b/packages/typescript/indexer_client/src/models/searchforapplicationboxes.ts index df881d0af..50967c7c6 100644 --- a/packages/typescript/indexer_client/src/models/searchforapplicationboxes.ts +++ b/packages/typescript/indexer_client/src/models/searchforapplicationboxes.ts @@ -1,6 +1,14 @@ import type { BoxDescriptor } from "./index"; -/** - * Box names of an application - */ -export type SearchForApplicationBoxes = { applicationId: bigint; boxes: BoxDescriptor[]; nextToken?: string }; +export type SearchForApplicationBoxes = { + /** + * \[appidx\] application index. + */ + applicationId: bigint; + boxes: BoxDescriptor[]; + + /** + * Used for pagination, when making another request provide this token with the next parameter. + */ + nextToken?: string; +}; diff --git a/packages/typescript/indexer_client/src/models/searchforapplications.ts b/packages/typescript/indexer_client/src/models/searchforapplications.ts index e36030879..f514fce25 100644 --- a/packages/typescript/indexer_client/src/models/searchforapplications.ts +++ b/packages/typescript/indexer_client/src/models/searchforapplications.ts @@ -1,6 +1,15 @@ import type { Application } from "./index"; -/** - * (empty) - */ -export type SearchForApplications = { applications: Application[]; currentRound: bigint; nextToken?: string }; +export type SearchForApplications = { + applications: Application[]; + + /** + * Round at which the results were computed. + */ + currentRound: bigint; + + /** + * Used for pagination, when making another request provide this token with the next parameter. + */ + nextToken?: string; +}; diff --git a/packages/typescript/indexer_client/src/models/searchforassets.ts b/packages/typescript/indexer_client/src/models/searchforassets.ts index 696b4b840..39ecbf627 100644 --- a/packages/typescript/indexer_client/src/models/searchforassets.ts +++ b/packages/typescript/indexer_client/src/models/searchforassets.ts @@ -1,6 +1,15 @@ import type { Asset } from "./index"; -/** - * (empty) - */ -export type SearchForAssets = { assets: Asset[]; currentRound: bigint; nextToken?: string }; +export type SearchForAssets = { + assets: Asset[]; + + /** + * Round at which the results were computed. + */ + currentRound: bigint; + + /** + * Used for pagination, when making another request provide this token with the next parameter. + */ + nextToken?: string; +}; diff --git a/packages/typescript/indexer_client/src/models/searchforblockheaders.ts b/packages/typescript/indexer_client/src/models/searchforblockheaders.ts index a07b9a1a4..b88cae8df 100644 --- a/packages/typescript/indexer_client/src/models/searchforblockheaders.ts +++ b/packages/typescript/indexer_client/src/models/searchforblockheaders.ts @@ -1,6 +1,14 @@ import type { Block } from "./index"; -/** - * (empty) - */ -export type SearchForBlockHeaders = { currentRound: bigint; nextToken?: string; blocks: Block[] }; +export type SearchForBlockHeaders = { + /** + * Round at which the results were computed. + */ + currentRound: bigint; + + /** + * Used for pagination, when making another request provide this token with the next parameter. + */ + nextToken?: string; + blocks: Block[]; +}; diff --git a/packages/typescript/indexer_client/src/models/searchfortransactions.ts b/packages/typescript/indexer_client/src/models/searchfortransactions.ts index 616cb291f..4970c85a3 100644 --- a/packages/typescript/indexer_client/src/models/searchfortransactions.ts +++ b/packages/typescript/indexer_client/src/models/searchfortransactions.ts @@ -1,6 +1,14 @@ import type { Transaction } from "./index"; -/** - * (empty) - */ -export type SearchForTransactions = { currentRound: bigint; nextToken?: string; transactions: Transaction[] }; +export type SearchForTransactions = { + /** + * Round at which the results were computed. + */ + currentRound: bigint; + + /** + * Used for pagination, when making another request provide this token with the next parameter. + */ + nextToken?: string; + transactions: Transaction[]; +}; diff --git a/packages/typescript/indexer_client/src/models/stateprooffields.ts b/packages/typescript/indexer_client/src/models/stateprooffields.ts index 9202cce7a..dee577875 100644 --- a/packages/typescript/indexer_client/src/models/stateprooffields.ts +++ b/packages/typescript/indexer_client/src/models/stateprooffields.ts @@ -7,11 +7,30 @@ import type { MerkleArrayProof, StateProofReveal } from "./index"; * crypto/stateproof/structs.go : StateProof */ export type StateProofFields = { + /** + * \[c\] + */ sigCommit?: string; + + /** + * \[w\] + */ signedWeight?: bigint; sigProofs?: MerkleArrayProof; partProofs?: MerkleArrayProof; + + /** + * \[v\] Salt version of the merkle signature. + */ saltVersion?: bigint; + + /** + * \[r\] Note that this is actually stored as a map[uint64] - Reveal in the actual msgp + */ reveals?: StateProofReveal[]; + + /** + * \[pr\] Sequence of reveal positions. + */ positionsToReveal?: bigint[]; }; diff --git a/packages/typescript/indexer_client/src/models/stateproofparticipant.ts b/packages/typescript/indexer_client/src/models/stateproofparticipant.ts index fe4097183..77775e516 100644 --- a/packages/typescript/indexer_client/src/models/stateproofparticipant.ts +++ b/packages/typescript/indexer_client/src/models/stateproofparticipant.ts @@ -1,3 +1,10 @@ import type { StateProofVerifier } from "./index"; -export type StateProofParticipant = { verifier?: StateProofVerifier; weight?: bigint }; +export type StateProofParticipant = { + verifier?: StateProofVerifier; + + /** + * \[w\] + */ + weight?: bigint; +}; diff --git a/packages/typescript/indexer_client/src/models/stateproofreveal.ts b/packages/typescript/indexer_client/src/models/stateproofreveal.ts index f4d30848b..c7d46775c 100644 --- a/packages/typescript/indexer_client/src/models/stateproofreveal.ts +++ b/packages/typescript/indexer_client/src/models/stateproofreveal.ts @@ -1,3 +1,10 @@ import type { StateProofParticipant, StateProofSigSlot } from "./index"; -export type StateProofReveal = { position?: bigint; sigSlot?: StateProofSigSlot; participant?: StateProofParticipant }; +export type StateProofReveal = { + /** + * The position in the signature and participants arrays corresponding to this entry. + */ + position?: bigint; + sigSlot?: StateProofSigSlot; + participant?: StateProofParticipant; +}; diff --git a/packages/typescript/indexer_client/src/models/stateproofsignature.ts b/packages/typescript/indexer_client/src/models/stateproofsignature.ts index 394566b18..e7b74825e 100644 --- a/packages/typescript/indexer_client/src/models/stateproofsignature.ts +++ b/packages/typescript/indexer_client/src/models/stateproofsignature.ts @@ -1,3 +1,12 @@ import type { MerkleArrayProof } from "./index"; -export type StateProofSignature = { falconSignature?: string; merkleArrayIndex?: bigint; proof?: MerkleArrayProof; verifyingKey?: string }; +export type StateProofSignature = { + falconSignature?: string; + merkleArrayIndex?: bigint; + proof?: MerkleArrayProof; + + /** + * \[vkey\] + */ + verifyingKey?: string; +}; diff --git a/packages/typescript/indexer_client/src/models/stateproofsigslot.ts b/packages/typescript/indexer_client/src/models/stateproofsigslot.ts index 330fc90d2..23fe2fbd7 100644 --- a/packages/typescript/indexer_client/src/models/stateproofsigslot.ts +++ b/packages/typescript/indexer_client/src/models/stateproofsigslot.ts @@ -1,3 +1,10 @@ import type { StateProofSignature } from "./index"; -export type StateProofSigSlot = { signature?: StateProofSignature; lowerSigWeight?: bigint }; +export type StateProofSigSlot = { + signature?: StateProofSignature; + + /** + * \[l\] The total weight of signatures in the lower-numbered slots. + */ + lowerSigWeight?: bigint; +}; diff --git a/packages/typescript/indexer_client/src/models/stateprooftracking.ts b/packages/typescript/indexer_client/src/models/stateprooftracking.ts index cdd7e7e79..d9f6f8cf3 100644 --- a/packages/typescript/indexer_client/src/models/stateprooftracking.ts +++ b/packages/typescript/indexer_client/src/models/stateprooftracking.ts @@ -1 +1,21 @@ -export type StateProofTracking = { type?: bigint; votersCommitment?: string; onlineTotalWeight?: bigint; nextRound?: bigint }; +export type StateProofTracking = { + /** + * State Proof Type. Note the raw object uses map with this as key. + */ + type?: bigint; + + /** + * \[v\] Root of a vector commitment containing online accounts that will help sign the proof. + */ + votersCommitment?: string; + + /** + * \[t\] The total number of microalgos held by the online accounts during the StateProof round. + */ + onlineTotalWeight?: bigint; + + /** + * \[n\] Next round for which we will accept a state proof transaction. + */ + nextRound?: bigint; +}; diff --git a/packages/typescript/indexer_client/src/models/stateproofverifier.ts b/packages/typescript/indexer_client/src/models/stateproofverifier.ts index 0aa06273b..d236b4fc3 100644 --- a/packages/typescript/indexer_client/src/models/stateproofverifier.ts +++ b/packages/typescript/indexer_client/src/models/stateproofverifier.ts @@ -1 +1,11 @@ -export type StateProofVerifier = { commitment?: string; keyLifetime?: bigint }; +export type StateProofVerifier = { + /** + * \[cmt\] Represents the root of the vector commitment tree. + */ + commitment?: string; + + /** + * \[lf\] Key lifetime. + */ + keyLifetime?: bigint; +}; diff --git a/packages/typescript/indexer_client/src/models/stateschema.ts b/packages/typescript/indexer_client/src/models/stateschema.ts index 4a2bbf42f..131429ca0 100644 --- a/packages/typescript/indexer_client/src/models/stateschema.ts +++ b/packages/typescript/indexer_client/src/models/stateschema.ts @@ -1,4 +1,14 @@ /** * 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. */ -export type StateSchema = { numUint: bigint; numByteSlice: bigint }; +export type StateSchema = { + /** + * Maximum number of TEAL uints that may be stored in the key/value store. + */ + numUint: bigint; + + /** + * Maximum number of TEAL byte slices that may be stored in the key/value store. + */ + numByteSlice: bigint; +}; diff --git a/packages/typescript/indexer_client/src/models/tealkeyvalue.ts b/packages/typescript/indexer_client/src/models/tealkeyvalue.ts index aeeee7399..98cf88806 100644 --- a/packages/typescript/indexer_client/src/models/tealkeyvalue.ts +++ b/packages/typescript/indexer_client/src/models/tealkeyvalue.ts @@ -3,4 +3,7 @@ import type { TealValue } from "./index"; /** * Represents a key-value pair in an application store. */ -export type TealKeyValue = { key: string; value: TealValue }; +export type TealKeyValue = { + key: string; + value: TealValue; +}; diff --git a/packages/typescript/indexer_client/src/models/tealvalue.ts b/packages/typescript/indexer_client/src/models/tealvalue.ts index 84e3993af..2390ea5f1 100644 --- a/packages/typescript/indexer_client/src/models/tealvalue.ts +++ b/packages/typescript/indexer_client/src/models/tealvalue.ts @@ -1,4 +1,19 @@ /** * Represents a TEAL value. */ -export type TealValue = { type: bigint; bytes: string; uint: bigint }; +export type TealValue = { + /** + * type of the value. Value `1` refers to **bytes**, value `2` refers to **uint** + */ + type: bigint; + + /** + * bytes value. + */ + bytes: string; + + /** + * uint value. + */ + uint: bigint; +}; diff --git a/packages/typescript/indexer_client/src/models/transaction.ts b/packages/typescript/indexer_client/src/models/transaction.ts index c44611627..08e9a3ff8 100644 --- a/packages/typescript/indexer_client/src/models/transaction.ts +++ b/packages/typescript/indexer_client/src/models/transaction.ts @@ -26,33 +26,143 @@ export type Transaction = { assetTransferTransaction?: TransactionAssetTransfer; stateProofTransaction?: TransactionStateProof; heartbeatTransaction?: TransactionHeartbeat; + + /** + * \[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. + */ authAddr?: string; + + /** + * \[rc\] rewards applied to close-remainder-to account. + */ closeRewards?: bigint; + + /** + * \[ca\] closing amount for transaction. + */ closingAmount?: bigint; + + /** + * Round when the transaction was confirmed. + */ confirmedRound?: bigint; + + /** + * Specifies an application index (ID) if an application was created with this transaction. + */ createdApplicationIndex?: bigint; + + /** + * Specifies an asset index (ID) if an asset was created with this transaction. + */ createdAssetIndex?: bigint; + + /** + * \[fee\] Transaction fee. + */ fee: bigint; + + /** + * \[fv\] First valid round for this transaction. + */ firstValid: bigint; + + /** + * \[gh\] Hash of genesis block. + */ genesisHash?: string; + + /** + * \[gen\] genesis block ID. + */ genesisId?: string; + + /** + * \[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. + */ group?: string; + + /** + * Transaction ID + */ id?: string; + + /** + * Offset into the round where this transaction was confirmed. + */ intraRoundOffset?: bigint; keyregTransaction?: TransactionKeyreg; + + /** + * \[lv\] Last valid round for this transaction. + */ lastValid: bigint; + + /** + * \[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. + */ lease?: string; + + /** + * \[note\] Free form data. + */ note?: string; paymentTransaction?: TransactionPayment; + + /** + * \[rr\] rewards applied to receiver account. + */ receiverRewards?: bigint; + + /** + * \[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. + */ rekeyTo?: string; + + /** + * Time when the block this transaction is in was confirmed. + */ roundTime?: bigint; + + /** + * \[snd\] Sender's address. + */ sender: string; + + /** + * \[rs\] rewards applied to sender account. + */ senderRewards?: bigint; signature?: TransactionSignature; + + /** + * \[type\] Indicates what type of transaction this is. Different types have different fields. + * + * Valid types, and where their fields are stored: + * * \[pay\] payment-transaction + * * \[keyreg\] keyreg-transaction + * * \[acfg\] asset-config-transaction + * * \[axfer\] asset-transfer-transaction + * * \[afrz\] asset-freeze-transaction + * * \[appl\] application-transaction + * * \[stpf\] state-proof-transaction + * * \[hb\] heartbeat-transaction + */ txType: "pay" | "keyreg" | "acfg" | "axfer" | "afrz" | "appl" | "stpf" | "hb"; + + /** + * \[ld\] Local state key/value changes for the application being executed by this transaction. + */ localStateDelta?: AccountStateDelta[]; globalStateDelta?: StateDelta; + + /** + * \[lg\] Logs for the application being executed by this transaction. + */ logs?: string[]; + + /** + * Inner transactions produced by application execution. + */ innerTxns?: Transaction[]; }; diff --git a/packages/typescript/indexer_client/src/models/transactionapplication.ts b/packages/typescript/indexer_client/src/models/transactionapplication.ts index 24b61e63f..45eb5aa7d 100644 --- a/packages/typescript/indexer_client/src/models/transactionapplication.ts +++ b/packages/typescript/indexer_client/src/models/transactionapplication.ts @@ -7,17 +7,56 @@ import type { BoxReference, OnCompletion, StateSchema } from "./index"; * data/transactions/application.go : ApplicationCallTxnFields */ export type TransactionApplication = { + /** + * \[apid\] ID of the application being configured or empty if creating. + */ applicationId: bigint; onCompletion: OnCompletion; + + /** + * \[apaa\] transaction specific arguments accessed from the application's approval-program and clear-state-program. + */ applicationArgs?: string[]; + + /** + * \[apat\] List of accounts in addition to the sender that may be accessed from the application's approval-program and clear-state-program. + */ accounts?: string[]; + + /** + * \[apbx\] the boxes that can be accessed by this transaction (and others in the same group). + */ boxReferences?: BoxReference[]; + + /** + * \[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. + */ foreignApps?: bigint[]; + + /** + * \[apas\] lists the assets whose parameters may be accessed by this application's ApprovalProgram and ClearStateProgram. The access is read-only. + */ foreignAssets?: bigint[]; localStateSchema?: StateSchema; globalStateSchema?: StateSchema; + + /** + * \[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. + */ approvalProgram?: string; + + /** + * \[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. + */ clearStateProgram?: string; + + /** + * \[epp\] specifies the additional app program len requested in pages. + */ extraProgramPages?: bigint; + + /** + * \[aprv\] the lowest application version for which this transaction should immediately fail. 0 indicates that no version check should be performed. + */ rejectVersion?: bigint; }; diff --git a/packages/typescript/indexer_client/src/models/transactionassetconfig.ts b/packages/typescript/indexer_client/src/models/transactionassetconfig.ts index 3562c7b66..0fbbbc08e 100644 --- a/packages/typescript/indexer_client/src/models/transactionassetconfig.ts +++ b/packages/typescript/indexer_client/src/models/transactionassetconfig.ts @@ -10,4 +10,10 @@ import type { AssetParams } from "./index"; * Definition: * data/transactions/asset.go : AssetConfigTxnFields */ -export type TransactionAssetConfig = { assetId?: bigint; params?: AssetParams }; +export type TransactionAssetConfig = { + /** + * \[xaid\] ID of the asset being configured or empty if creating. + */ + assetId?: bigint; + params?: AssetParams; +}; diff --git a/packages/typescript/indexer_client/src/models/transactionassetfreeze.ts b/packages/typescript/indexer_client/src/models/transactionassetfreeze.ts index d576f5c6f..ab67f38c4 100644 --- a/packages/typescript/indexer_client/src/models/transactionassetfreeze.ts +++ b/packages/typescript/indexer_client/src/models/transactionassetfreeze.ts @@ -4,4 +4,19 @@ * Definition: * data/transactions/asset.go : AssetFreezeTxnFields */ -export type TransactionAssetFreeze = { address: string; assetId: bigint; newFreezeStatus: boolean }; +export type TransactionAssetFreeze = { + /** + * \[fadd\] Address of the account whose asset is being frozen or thawed. + */ + address: string; + + /** + * \[faid\] ID of the asset being frozen or thawed. + */ + assetId: bigint; + + /** + * \[afrz\] The new freeze status. + */ + newFreezeStatus: boolean; +}; diff --git a/packages/typescript/indexer_client/src/models/transactionassettransfer.ts b/packages/typescript/indexer_client/src/models/transactionassettransfer.ts index adf87560f..268b7e374 100644 --- a/packages/typescript/indexer_client/src/models/transactionassettransfer.ts +++ b/packages/typescript/indexer_client/src/models/transactionassettransfer.ts @@ -5,10 +5,33 @@ * data/transactions/asset.go : AssetTransferTxnFields */ export type TransactionAssetTransfer = { + /** + * \[aamt\] Amount of asset to transfer. A zero amount transferred to self allocates that asset in the account's Assets map. + */ amount: bigint; + + /** + * \[xaid\] ID of the asset being transferred. + */ assetId: bigint; + + /** + * Number of assets transferred to the close-to account as part of the transaction. + */ closeAmount?: bigint; + + /** + * \[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. + */ closeTo?: string; + + /** + * \[arcv\] Recipient address of the transfer. + */ receiver: string; + + /** + * \[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. + */ sender?: string; }; diff --git a/packages/typescript/indexer_client/src/models/transactionheartbeat.ts b/packages/typescript/indexer_client/src/models/transactionheartbeat.ts index b5468a326..c5cb1f2a0 100644 --- a/packages/typescript/indexer_client/src/models/transactionheartbeat.ts +++ b/packages/typescript/indexer_client/src/models/transactionheartbeat.ts @@ -6,4 +6,25 @@ import type { HbProofFields } from "./index"; * Definition: * data/transactions/heartbeat.go : HeartbeatTxnFields */ -export type TransactionHeartbeat = { hbAddress: string; hbProof: HbProofFields; hbSeed: string; hbVoteId: string; hbKeyDilution: bigint }; +export type TransactionHeartbeat = { + /** + * \[hbad\] HbAddress is the account this txn is proving onlineness for. + */ + hbAddress: string; + hbProof: HbProofFields; + + /** + * \[hbsd\] HbSeed must be the block seed for the this transaction's firstValid block. + */ + hbSeed: string; + + /** + * \[hbvid\] HbVoteID must match the HbAddress account's current VoteID. + */ + hbVoteId: string; + + /** + * \[hbkd\] HbKeyDilution must match HbAddress account's current KeyDilution. + */ + hbKeyDilution: bigint; +}; diff --git a/packages/typescript/indexer_client/src/models/transactionkeyreg.ts b/packages/typescript/indexer_client/src/models/transactionkeyreg.ts index bd4a3dbe8..e8b15bd54 100644 --- a/packages/typescript/indexer_client/src/models/transactionkeyreg.ts +++ b/packages/typescript/indexer_client/src/models/transactionkeyreg.ts @@ -5,11 +5,38 @@ * data/transactions/keyreg.go : KeyregTxnFields */ export type TransactionKeyreg = { + /** + * \[nonpart\] Mark the account as participating or non-participating. + */ nonParticipation?: boolean; + + /** + * \[selkey\] Public key used with the Verified Random Function (VRF) result during committee selection. + */ selectionParticipationKey?: string; + + /** + * \[votefst\] First round this participation key is valid. + */ voteFirstValid?: bigint; + + /** + * \[votekd\] Number of subkeys in each batch of participation keys. + */ voteKeyDilution?: bigint; + + /** + * \[votelst\] Last round this participation key is valid. + */ voteLastValid?: bigint; + + /** + * \[votekey\] Participation public key used in key registration transactions. + */ voteParticipationKey?: string; + + /** + * \[sprfkey\] State proof key used in key registration transactions. + */ stateProofKey?: string; }; diff --git a/packages/typescript/indexer_client/src/models/transactionpayment.ts b/packages/typescript/indexer_client/src/models/transactionpayment.ts index 3336d2c7d..e7747cd6a 100644 --- a/packages/typescript/indexer_client/src/models/transactionpayment.ts +++ b/packages/typescript/indexer_client/src/models/transactionpayment.ts @@ -4,4 +4,24 @@ * Definition: * data/transactions/payment.go : PaymentTxnFields */ -export type TransactionPayment = { amount: bigint; closeAmount?: bigint; closeRemainderTo?: string; receiver: string }; +export type TransactionPayment = { + /** + * \[amt\] number of MicroAlgos intended to be transferred. + */ + amount: bigint; + + /** + * Number of MicroAlgos that were sent to the close-remainder-to address when closing the sender account. + */ + closeAmount?: bigint; + + /** + * \[close\] when set, indicates that the sending account should be closed and all remaining funds be transferred to this address. + */ + closeRemainderTo?: string; + + /** + * \[rcv\] receiver's address. + */ + receiver: string; +}; diff --git a/packages/typescript/indexer_client/src/models/transactionsignature.ts b/packages/typescript/indexer_client/src/models/transactionsignature.ts index 48f303a62..82911f4e3 100644 --- a/packages/typescript/indexer_client/src/models/transactionsignature.ts +++ b/packages/typescript/indexer_client/src/models/transactionsignature.ts @@ -3,4 +3,12 @@ import type { TransactionSignatureLogicsig, TransactionSignatureMultisig } from /** * Validation signature associated with some data. Only one of the signatures should be provided. */ -export type TransactionSignature = { logicsig?: TransactionSignatureLogicsig; multisig?: TransactionSignatureMultisig; sig?: string }; +export type TransactionSignature = { + logicsig?: TransactionSignatureLogicsig; + multisig?: TransactionSignatureMultisig; + + /** + * \[sig\] Standard ed25519 signature. + */ + sig?: string; +}; diff --git a/packages/typescript/indexer_client/src/models/transactionsignaturelogicsig.ts b/packages/typescript/indexer_client/src/models/transactionsignaturelogicsig.ts index 8225eb602..eb3f33d53 100644 --- a/packages/typescript/indexer_client/src/models/transactionsignaturelogicsig.ts +++ b/packages/typescript/indexer_client/src/models/transactionsignaturelogicsig.ts @@ -7,8 +7,19 @@ import type { TransactionSignatureMultisig } from "./index"; * data/transactions/logicsig.go */ export type TransactionSignatureLogicsig = { + /** + * \[arg\] Logic arguments, base64 encoded. + */ args?: string[]; + + /** + * \[l\] Program signed by a signature or multi signature, or hashed to be the address of an account. Base64 encoded TEAL program. + */ logic: string; multisigSignature?: TransactionSignatureMultisig; + + /** + * \[sig\] ed25519 signature. + */ signature?: string; }; diff --git a/packages/typescript/indexer_client/src/models/transactionsignaturemultisig.ts b/packages/typescript/indexer_client/src/models/transactionsignaturemultisig.ts index fd46723dc..834521580 100644 --- a/packages/typescript/indexer_client/src/models/transactionsignaturemultisig.ts +++ b/packages/typescript/indexer_client/src/models/transactionsignaturemultisig.ts @@ -7,7 +7,18 @@ import type { TransactionSignatureMultisigSubsignature } from "./index"; * crypto/multisig.go : MultisigSig */ export type TransactionSignatureMultisig = { + /** + * \[subsig\] holds pairs of public key and signatures. + */ subsignature?: TransactionSignatureMultisigSubsignature[]; + + /** + * \[thr\] + */ threshold?: bigint; + + /** + * \[v\] + */ version?: bigint; }; diff --git a/packages/typescript/indexer_client/src/models/transactionsignaturemultisigsubsignature.ts b/packages/typescript/indexer_client/src/models/transactionsignaturemultisigsubsignature.ts index 9043a3d3f..d06dc8614 100644 --- a/packages/typescript/indexer_client/src/models/transactionsignaturemultisigsubsignature.ts +++ b/packages/typescript/indexer_client/src/models/transactionsignaturemultisigsubsignature.ts @@ -1 +1,11 @@ -export type TransactionSignatureMultisigSubsignature = { publicKey?: string; signature?: string }; +export type TransactionSignatureMultisigSubsignature = { + /** + * \[pk\] + */ + publicKey?: string; + + /** + * \[s\] + */ + signature?: string; +}; diff --git a/packages/typescript/indexer_client/src/models/transactionstateproof.ts b/packages/typescript/indexer_client/src/models/transactionstateproof.ts index 28492a22a..1b98c0e56 100644 --- a/packages/typescript/indexer_client/src/models/transactionstateproof.ts +++ b/packages/typescript/indexer_client/src/models/transactionstateproof.ts @@ -6,4 +6,11 @@ import type { IndexerStateProofMessage, StateProofFields } from "./index"; * Definition: * data/transactions/stateproof.go : StateProofTxnFields */ -export type TransactionStateProof = { stateProofType?: bigint; stateProof?: StateProofFields; message?: IndexerStateProofMessage }; +export type TransactionStateProof = { + /** + * \[sptype\] Type of the state proof. Integer representing an entry defined in protocol/stateproof.go + */ + stateProofType?: bigint; + stateProof?: StateProofFields; + message?: IndexerStateProofMessage; +}; diff --git a/packages/typescript/indexer_client/tests/searchApplications.spec.ts b/packages/typescript/indexer_client/tests/searchApplications.spec.ts index 08a839ee7..6fe43f793 100644 --- a/packages/typescript/indexer_client/tests/searchApplications.spec.ts +++ b/packages/typescript/indexer_client/tests/searchApplications.spec.ts @@ -10,7 +10,7 @@ maybeDescribe("Indexer searchApplications", (env) => { HEADERS: env.indexerApiToken ? { "X-Algo-API-Token": env.indexerApiToken } : undefined, }); - const res = await client.api.searchForApplications({ limit: 5 }); + const res = await client.searchForApplications({ limit: 5 }); expect(res).toHaveProperty("applications"); expect(Array.isArray(res.applications)).toBe(true); @@ -34,12 +34,12 @@ maybeDescribe("Indexer searchApplications", (env) => { HEADERS: env.indexerApiToken ? { "X-Algo-API-Token": env.indexerApiToken } : undefined, }); - const searchRes = await client.api.searchForApplications({ limit: 1 }); + const searchRes = await client.searchForApplications({ limit: 1 }); if (searchRes.applications && searchRes.applications.length > 0) { const appId = searchRes.applications[0].id; - const res = await client.api.searchForApplications({ applicationId: appId }); + const res = await client.searchForApplications({ applicationId: appId }); expect(res).toHaveProperty("applications"); expect(res.applications).toHaveLength(1); @@ -56,12 +56,12 @@ maybeDescribe("Indexer searchApplications", (env) => { HEADERS: env.indexerApiToken ? { "X-Algo-API-Token": env.indexerApiToken } : undefined, }); - const firstPage = await client.api.searchForApplications({ limit: 2 }); + const firstPage = await client.searchForApplications({ limit: 2 }); expect(firstPage).toHaveProperty("applications"); if (firstPage["nextToken"]) { - const secondPage = await client.api.searchForApplications({ + const secondPage = await client.searchForApplications({ limit: 2, next: firstPage["nextToken"] as string, }); diff --git a/packages/typescript/indexer_client/tests/searchTransactions.spec.ts b/packages/typescript/indexer_client/tests/searchTransactions.spec.ts index 4cf91ec9a..b7e6a8a41 100644 --- a/packages/typescript/indexer_client/tests/searchTransactions.spec.ts +++ b/packages/typescript/indexer_client/tests/searchTransactions.spec.ts @@ -9,7 +9,7 @@ maybeDescribe("Indexer searchTransactions", (env) => { INT_DECODING: "bigint", HEADERS: env.indexerApiToken ? { "X-Algo-API-Token": env.indexerApiToken } : undefined, }); - const res = await client.api.searchForTransactions({ limit: 5 }); + const res = await client.searchForTransactions({ limit: 5 }); expect(res).toHaveProperty("transactions"); expect(Array.isArray(res.transactions)).toBe(true); }); From 3198ae0d940a84d059bed1bf33a0fa39f8fe911c Mon Sep 17 00:00:00 2001 From: Altynbek Orumbayev Date: Fri, 19 Sep 2025 22:17:09 +0200 Subject: [PATCH 4/4] refactor: wip ensure kebab-case names for generated models in for TS clients --- .../ts_oas_generator/constants.py | 4 + .../ts_oas_generator/generator/filters.py | 9 +- .../generator/template_engine.py | 53 ++++-- .../templates/base/src/core/casing.ts.j2 | 7 +- .../templates/base/src/core/codecs.ts.j2 | 87 ++++++++++ .../templates/base/src/core/rename-map.ts.j2 | 15 ++ .../templates/models/index.ts.j2 | 2 +- .../templates/models/model.ts.j2 | 3 +- packages/typescript/algod_client/bun.lock | 58 +++---- .../algod_client/src/core/casing.ts | 6 + .../algod_client/src/core/codecs.ts | 87 ++++++++++ .../algod_client/src/core/rename-map.ts | 13 ++ .../{abortcatchup.ts => abort-catchup.ts} | 0 ....ts => account-application-information.ts} | 0 ...setholding.ts => account-asset-holding.ts} | 0 ...mation.ts => account-asset-information.ts} | 0 ...ation.ts => account-assets-information.ts} | 0 ...ticipation.ts => account-participation.ts} | 0 ...ntstatedelta.ts => account-state-delta.ts} | 0 ...ipationkey.ts => add-participation-key.ts} | 0 .../{appcalllogs.ts => app-call-logs.ts} | 2 +- ...tates.ts => application-initial-states.ts} | 0 ...nkvstorage.ts => application-kvstorage.ts} | 0 ...ence.ts => application-local-reference.ts} | 0 ...calstate.ts => application-local-state.ts} | 0 ...icationparams.ts => application-params.ts} | 0 ...tion.ts => application-state-operation.ts} | 0 ...eschema.ts => application-state-schema.ts} | 0 ...eference.ts => asset-holding-reference.ts} | 0 .../{assetholding.ts => asset-holding.ts} | 0 .../{assetparams.ts => asset-params.ts} | 0 .../{avmkeyvalue.ts => avm-key-value.ts} | 0 .../src/models/{avmvalue.ts => avm-value.ts} | 0 .../{boxdescriptor.ts => box-descriptor.ts} | 0 .../{boxreference.ts => box-reference.ts} | 0 .../{buildversion.ts => build-version.ts} | 0 ...settingsprof.ts => debug-settings-prof.ts} | 0 .../{dryrunrequest.ts => dryrun-request.ts} | 0 .../{dryrunsource.ts => dryrun-source.ts} | 0 .../{dryrunstate.ts => dryrun-state.ts} | 0 ...ryruntxnresult.ts => dryrun-txn-result.ts} | 0 .../{errorresponse.ts => error-response.ts} | 0 ...ltakeyvalue.ts => eval-delta-key-value.ts} | 0 .../models/{evaldelta.ts => eval-delta.ts} | 0 ...sisallocation.ts => genesis-allocation.ts} | 0 ...ationboxes.ts => get-application-boxes.ts} | 0 .../{getblockhash.ts => get-block-hash.ts} | 0 .../{getblocklogs.ts => get-block-logs.ts} | 0 ...fset.ts => get-block-time-stamp-offset.ts} | 0 .../{getblocktxids.ts => get-block-txids.ts} | 0 .../src/models/{getblock.ts => get-block.ts} | 0 ...=> get-pending-transactions-by-address.ts} | 0 ...actions.ts => get-pending-transactions.ts} | 0 .../models/{getstatus.ts => get-status.ts} | 0 .../models/{getsupply.ts => get-supply.ts} | 0 .../{getsyncround.ts => get-sync-round.ts} | 0 ...on-group-ledger-state-deltas-for-round.ts} | 0 .../algod_client/src/models/index.ts | 154 +++++++++--------- ...dger-state-delta-for-transaction-group.ts} | 0 ...gerstatedelta.ts => ledger-state-delta.ts} | 0 ...erproof.ts => light-block-header-proof.ts} | 0 ...rticipationkey.ts => participation-key.ts} | 0 ...nse.ts => pending-transaction-response.ts} | 4 +- .../{rawtransaction.ts => raw-transaction.ts} | 0 .../{scratchchange.ts => scratch-change.ts} | 0 .../{shutdownnode.ts => shutdown-node.ts} | 0 ...alstates.ts => simulate-initial-states.ts} | 0 ... => simulate-request-transaction-group.ts} | 0 ...simulaterequest.ts => simulate-request.ts} | 0 ...raceconfig.ts => simulate-trace-config.ts} | 0 ...s => simulate-transaction-group-result.ts} | 0 ...sult.ts => simulate-transaction-result.ts} | 0 ...transaction.ts => simulate-transaction.ts} | 0 ...=> simulate-unnamed-resources-accessed.ts} | 0 ...rrides.ts => simulation-eval-overrides.ts} | 0 ...nit.ts => simulation-opcode-trace-unit.ts} | 0 ...s => simulation-transaction-exec-trace.ts} | 0 .../{startcatchup.ts => start-catchup.ts} | 0 .../models/{statedelta.ts => state-delta.ts} | 0 ...proofmessage.ts => state-proof-message.ts} | 0 .../models/{stateproof.ts => state-proof.ts} | 0 .../{tealcompile.ts => teal-compile.ts} | 0 ...tealdisassemble.ts => teal-disassemble.ts} | 0 .../models/{tealdryrun.ts => teal-dryrun.ts} | 0 ...yvaluestore.ts => teal-key-value-store.ts} | 0 .../{tealkeyvalue.ts => teal-key-value.ts} | 0 .../models/{tealvalue.ts => teal-value.ts} | 0 ...sactionparams.ts => transaction-params.ts} | 0 ...ansactionproof.ts => transaction-proof.ts} | 0 .../{waitforblock.ts => wait-for-block.ts} | 0 packages/typescript/indexer_client/bun.lock | 58 +++---- .../indexer_client/src/core/casing.ts | 6 + .../indexer_client/src/core/codecs.ts | 87 ++++++++++ .../indexer_client/src/core/rename-map.ts | 7 + ...ticipation.ts => account-participation.ts} | 0 ...ntstatedelta.ts => account-state-delta.ts} | 0 ...calstate.ts => application-local-state.ts} | 0 ...tionlogdata.ts => application-log-data.ts} | 0 ...icationparams.ts => application-params.ts} | 0 ...eschema.ts => application-state-schema.ts} | 0 .../{assetholding.ts => asset-holding.ts} | 0 .../{assetparams.ts => asset-params.ts} | 0 .../{blockrewards.ts => block-rewards.ts} | 0 ...upgradestate.ts => block-upgrade-state.ts} | 0 ...ckupgradevote.ts => block-upgrade-vote.ts} | 0 .../{boxdescriptor.ts => box-descriptor.ts} | 0 .../{boxreference.ts => box-reference.ts} | 0 ...ltakeyvalue.ts => eval-delta-key-value.ts} | 0 .../models/{evaldelta.ts => eval-delta.ts} | 0 .../{hashfactory.ts => hash-factory.ts} | 0 .../{hbprooffields.ts => hb-proof-fields.ts} | 0 .../{healthcheck.ts => health-check.ts} | 0 .../indexer_client/src/models/index.ts | 130 +++++++-------- ...sage.ts => indexer-state-proof-message.ts} | 0 ....ts => lookup-account-app-local-states.ts} | 0 ...ountassets.ts => lookup-account-assets.ts} | 0 ...accountbyid.ts => lookup-account-by-id.ts} | 0 ...=> lookup-account-created-applications.ts} | 0 ...ts.ts => lookup-account-created-assets.ts} | 0 ...ions.ts => lookup-account-transactions.ts} | 0 ...ionbyid.ts => lookup-application-by-id.ts} | 0 ...id.ts => lookup-application-logs-by-id.ts} | 0 ...etbalances.ts => lookup-asset-balances.ts} | 0 ...okupassetbyid.ts => lookup-asset-by-id.ts} | 0 ...ctions.ts => lookup-asset-transactions.ts} | 0 ...uptransaction.ts => lookup-transaction.ts} | 0 ...klearrayproof.ts => merkle-array-proof.ts} | 0 ...iassetholding.ts => mini-asset-holding.ts} | 0 .../{oncompletion.ts => on-completion.ts} | 0 ...ionupdates.ts => participation-updates.ts} | 0 ...hforaccounts.ts => search-for-accounts.ts} | 0 ...xes.ts => search-for-application-boxes.ts} | 0 ...ications.ts => search-for-applications.ts} | 0 ...earchforassets.ts => search-for-assets.ts} | 0 ...headers.ts => search-for-block-headers.ts} | 0 ...sactions.ts => search-for-transactions.ts} | 0 .../models/{statedelta.ts => state-delta.ts} | 0 ...teprooffields.ts => state-proof-fields.ts} | 0 ...ticipant.ts => state-proof-participant.ts} | 0 ...teproofreveal.ts => state-proof-reveal.ts} | 0 ...roofsigslot.ts => state-proof-sig-slot.ts} | 0 ...fsignature.ts => state-proof-signature.ts} | 0 ...ooftracking.ts => state-proof-tracking.ts} | 0 ...oofverifier.ts => state-proof-verifier.ts} | 0 .../{stateschema.ts => state-schema.ts} | 0 ...yvaluestore.ts => teal-key-value-store.ts} | 0 .../{tealkeyvalue.ts => teal-key-value.ts} | 0 .../models/{tealvalue.ts => teal-value.ts} | 0 ...lication.ts => transaction-application.ts} | 0 ...tconfig.ts => transaction-asset-config.ts} | 0 ...tfreeze.ts => transaction-asset-freeze.ts} | 0 ...nsfer.ts => transaction-asset-transfer.ts} | 0 ...nheartbeat.ts => transaction-heartbeat.ts} | 0 ...sactionkeyreg.ts => transaction-keyreg.ts} | 0 ...ctionpayment.ts => transaction-payment.ts} | 0 ...g.ts => transaction-signature-logicsig.ts} | 0 ...action-signature-multisig-subsignature.ts} | 0 ...g.ts => transaction-signature-multisig.ts} | 0 ...nsignature.ts => transaction-signature.ts} | 0 ...ateproof.ts => transaction-state-proof.ts} | 0 160 files changed, 574 insertions(+), 218 deletions(-) create mode 100644 api/oas_generator/ts_oas_generator/templates/base/src/core/codecs.ts.j2 create mode 100644 api/oas_generator/ts_oas_generator/templates/base/src/core/rename-map.ts.j2 create mode 100644 packages/typescript/algod_client/src/core/codecs.ts create mode 100644 packages/typescript/algod_client/src/core/rename-map.ts rename packages/typescript/algod_client/src/models/{abortcatchup.ts => abort-catchup.ts} (100%) rename packages/typescript/algod_client/src/models/{accountapplicationinformation.ts => account-application-information.ts} (100%) rename packages/typescript/algod_client/src/models/{accountassetholding.ts => account-asset-holding.ts} (100%) rename packages/typescript/algod_client/src/models/{accountassetinformation.ts => account-asset-information.ts} (100%) rename packages/typescript/algod_client/src/models/{accountassetsinformation.ts => account-assets-information.ts} (100%) rename packages/typescript/algod_client/src/models/{accountparticipation.ts => account-participation.ts} (100%) rename packages/typescript/algod_client/src/models/{accountstatedelta.ts => account-state-delta.ts} (100%) rename packages/typescript/algod_client/src/models/{addparticipationkey.ts => add-participation-key.ts} (100%) rename packages/typescript/algod_client/src/models/{appcalllogs.ts => app-call-logs.ts} (93%) rename packages/typescript/algod_client/src/models/{applicationinitialstates.ts => application-initial-states.ts} (100%) rename packages/typescript/algod_client/src/models/{applicationkvstorage.ts => application-kvstorage.ts} (100%) rename packages/typescript/algod_client/src/models/{applicationlocalreference.ts => application-local-reference.ts} (100%) rename packages/typescript/algod_client/src/models/{applicationlocalstate.ts => application-local-state.ts} (100%) rename packages/typescript/algod_client/src/models/{applicationparams.ts => application-params.ts} (100%) rename packages/typescript/algod_client/src/models/{applicationstateoperation.ts => application-state-operation.ts} (100%) rename packages/typescript/algod_client/src/models/{applicationstateschema.ts => application-state-schema.ts} (100%) rename packages/typescript/algod_client/src/models/{assetholdingreference.ts => asset-holding-reference.ts} (100%) rename packages/typescript/algod_client/src/models/{assetholding.ts => asset-holding.ts} (100%) rename packages/typescript/algod_client/src/models/{assetparams.ts => asset-params.ts} (100%) rename packages/typescript/algod_client/src/models/{avmkeyvalue.ts => avm-key-value.ts} (100%) rename packages/typescript/algod_client/src/models/{avmvalue.ts => avm-value.ts} (100%) rename packages/typescript/algod_client/src/models/{boxdescriptor.ts => box-descriptor.ts} (100%) rename packages/typescript/algod_client/src/models/{boxreference.ts => box-reference.ts} (100%) rename packages/typescript/algod_client/src/models/{buildversion.ts => build-version.ts} (100%) rename packages/typescript/algod_client/src/models/{debugsettingsprof.ts => debug-settings-prof.ts} (100%) rename packages/typescript/algod_client/src/models/{dryrunrequest.ts => dryrun-request.ts} (100%) rename packages/typescript/algod_client/src/models/{dryrunsource.ts => dryrun-source.ts} (100%) rename packages/typescript/algod_client/src/models/{dryrunstate.ts => dryrun-state.ts} (100%) rename packages/typescript/algod_client/src/models/{dryruntxnresult.ts => dryrun-txn-result.ts} (100%) rename packages/typescript/algod_client/src/models/{errorresponse.ts => error-response.ts} (100%) rename packages/typescript/algod_client/src/models/{evaldeltakeyvalue.ts => eval-delta-key-value.ts} (100%) rename packages/typescript/algod_client/src/models/{evaldelta.ts => eval-delta.ts} (100%) rename packages/typescript/algod_client/src/models/{genesisallocation.ts => genesis-allocation.ts} (100%) rename packages/typescript/algod_client/src/models/{getapplicationboxes.ts => get-application-boxes.ts} (100%) rename packages/typescript/algod_client/src/models/{getblockhash.ts => get-block-hash.ts} (100%) rename packages/typescript/algod_client/src/models/{getblocklogs.ts => get-block-logs.ts} (100%) rename packages/typescript/algod_client/src/models/{getblocktimestampoffset.ts => get-block-time-stamp-offset.ts} (100%) rename packages/typescript/algod_client/src/models/{getblocktxids.ts => get-block-txids.ts} (100%) rename packages/typescript/algod_client/src/models/{getblock.ts => get-block.ts} (100%) rename packages/typescript/algod_client/src/models/{getpendingtransactionsbyaddress.ts => get-pending-transactions-by-address.ts} (100%) rename packages/typescript/algod_client/src/models/{getpendingtransactions.ts => get-pending-transactions.ts} (100%) rename packages/typescript/algod_client/src/models/{getstatus.ts => get-status.ts} (100%) rename packages/typescript/algod_client/src/models/{getsupply.ts => get-supply.ts} (100%) rename packages/typescript/algod_client/src/models/{getsyncround.ts => get-sync-round.ts} (100%) rename packages/typescript/algod_client/src/models/{gettransactiongroupledgerstatedeltasforround.ts => get-transaction-group-ledger-state-deltas-for-round.ts} (100%) rename packages/typescript/algod_client/src/models/{ledgerstatedeltafortransactiongroup.ts => ledger-state-delta-for-transaction-group.ts} (100%) rename packages/typescript/algod_client/src/models/{ledgerstatedelta.ts => ledger-state-delta.ts} (100%) rename packages/typescript/algod_client/src/models/{lightblockheaderproof.ts => light-block-header-proof.ts} (100%) rename packages/typescript/algod_client/src/models/{participationkey.ts => participation-key.ts} (100%) rename packages/typescript/algod_client/src/models/{pendingtransactionresponse.ts => pending-transaction-response.ts} (97%) rename packages/typescript/algod_client/src/models/{rawtransaction.ts => raw-transaction.ts} (100%) rename packages/typescript/algod_client/src/models/{scratchchange.ts => scratch-change.ts} (100%) rename packages/typescript/algod_client/src/models/{shutdownnode.ts => shutdown-node.ts} (100%) rename packages/typescript/algod_client/src/models/{simulateinitialstates.ts => simulate-initial-states.ts} (100%) rename packages/typescript/algod_client/src/models/{simulaterequesttransactiongroup.ts => simulate-request-transaction-group.ts} (100%) rename packages/typescript/algod_client/src/models/{simulaterequest.ts => simulate-request.ts} (100%) rename packages/typescript/algod_client/src/models/{simulatetraceconfig.ts => simulate-trace-config.ts} (100%) rename packages/typescript/algod_client/src/models/{simulatetransactiongroupresult.ts => simulate-transaction-group-result.ts} (100%) rename packages/typescript/algod_client/src/models/{simulatetransactionresult.ts => simulate-transaction-result.ts} (100%) rename packages/typescript/algod_client/src/models/{simulatetransaction.ts => simulate-transaction.ts} (100%) rename packages/typescript/algod_client/src/models/{simulateunnamedresourcesaccessed.ts => simulate-unnamed-resources-accessed.ts} (100%) rename packages/typescript/algod_client/src/models/{simulationevaloverrides.ts => simulation-eval-overrides.ts} (100%) rename packages/typescript/algod_client/src/models/{simulationopcodetraceunit.ts => simulation-opcode-trace-unit.ts} (100%) rename packages/typescript/algod_client/src/models/{simulationtransactionexectrace.ts => simulation-transaction-exec-trace.ts} (100%) rename packages/typescript/algod_client/src/models/{startcatchup.ts => start-catchup.ts} (100%) rename packages/typescript/algod_client/src/models/{statedelta.ts => state-delta.ts} (100%) rename packages/typescript/algod_client/src/models/{stateproofmessage.ts => state-proof-message.ts} (100%) rename packages/typescript/algod_client/src/models/{stateproof.ts => state-proof.ts} (100%) rename packages/typescript/algod_client/src/models/{tealcompile.ts => teal-compile.ts} (100%) rename packages/typescript/algod_client/src/models/{tealdisassemble.ts => teal-disassemble.ts} (100%) rename packages/typescript/algod_client/src/models/{tealdryrun.ts => teal-dryrun.ts} (100%) rename packages/typescript/algod_client/src/models/{tealkeyvaluestore.ts => teal-key-value-store.ts} (100%) rename packages/typescript/algod_client/src/models/{tealkeyvalue.ts => teal-key-value.ts} (100%) rename packages/typescript/algod_client/src/models/{tealvalue.ts => teal-value.ts} (100%) rename packages/typescript/algod_client/src/models/{transactionparams.ts => transaction-params.ts} (100%) rename packages/typescript/algod_client/src/models/{transactionproof.ts => transaction-proof.ts} (100%) rename packages/typescript/algod_client/src/models/{waitforblock.ts => wait-for-block.ts} (100%) create mode 100644 packages/typescript/indexer_client/src/core/codecs.ts create mode 100644 packages/typescript/indexer_client/src/core/rename-map.ts rename packages/typescript/indexer_client/src/models/{accountparticipation.ts => account-participation.ts} (100%) rename packages/typescript/indexer_client/src/models/{accountstatedelta.ts => account-state-delta.ts} (100%) rename packages/typescript/indexer_client/src/models/{applicationlocalstate.ts => application-local-state.ts} (100%) rename packages/typescript/indexer_client/src/models/{applicationlogdata.ts => application-log-data.ts} (100%) rename packages/typescript/indexer_client/src/models/{applicationparams.ts => application-params.ts} (100%) rename packages/typescript/indexer_client/src/models/{applicationstateschema.ts => application-state-schema.ts} (100%) rename packages/typescript/indexer_client/src/models/{assetholding.ts => asset-holding.ts} (100%) rename packages/typescript/indexer_client/src/models/{assetparams.ts => asset-params.ts} (100%) rename packages/typescript/indexer_client/src/models/{blockrewards.ts => block-rewards.ts} (100%) rename packages/typescript/indexer_client/src/models/{blockupgradestate.ts => block-upgrade-state.ts} (100%) rename packages/typescript/indexer_client/src/models/{blockupgradevote.ts => block-upgrade-vote.ts} (100%) rename packages/typescript/indexer_client/src/models/{boxdescriptor.ts => box-descriptor.ts} (100%) rename packages/typescript/indexer_client/src/models/{boxreference.ts => box-reference.ts} (100%) rename packages/typescript/indexer_client/src/models/{evaldeltakeyvalue.ts => eval-delta-key-value.ts} (100%) rename packages/typescript/indexer_client/src/models/{evaldelta.ts => eval-delta.ts} (100%) rename packages/typescript/indexer_client/src/models/{hashfactory.ts => hash-factory.ts} (100%) rename packages/typescript/indexer_client/src/models/{hbprooffields.ts => hb-proof-fields.ts} (100%) rename packages/typescript/indexer_client/src/models/{healthcheck.ts => health-check.ts} (100%) rename packages/typescript/indexer_client/src/models/{indexerstateproofmessage.ts => indexer-state-proof-message.ts} (100%) rename packages/typescript/indexer_client/src/models/{lookupaccountapplocalstates.ts => lookup-account-app-local-states.ts} (100%) rename packages/typescript/indexer_client/src/models/{lookupaccountassets.ts => lookup-account-assets.ts} (100%) rename packages/typescript/indexer_client/src/models/{lookupaccountbyid.ts => lookup-account-by-id.ts} (100%) rename packages/typescript/indexer_client/src/models/{lookupaccountcreatedapplications.ts => lookup-account-created-applications.ts} (100%) rename packages/typescript/indexer_client/src/models/{lookupaccountcreatedassets.ts => lookup-account-created-assets.ts} (100%) rename packages/typescript/indexer_client/src/models/{lookupaccounttransactions.ts => lookup-account-transactions.ts} (100%) rename packages/typescript/indexer_client/src/models/{lookupapplicationbyid.ts => lookup-application-by-id.ts} (100%) rename packages/typescript/indexer_client/src/models/{lookupapplicationlogsbyid.ts => lookup-application-logs-by-id.ts} (100%) rename packages/typescript/indexer_client/src/models/{lookupassetbalances.ts => lookup-asset-balances.ts} (100%) rename packages/typescript/indexer_client/src/models/{lookupassetbyid.ts => lookup-asset-by-id.ts} (100%) rename packages/typescript/indexer_client/src/models/{lookupassettransactions.ts => lookup-asset-transactions.ts} (100%) rename packages/typescript/indexer_client/src/models/{lookuptransaction.ts => lookup-transaction.ts} (100%) rename packages/typescript/indexer_client/src/models/{merklearrayproof.ts => merkle-array-proof.ts} (100%) rename packages/typescript/indexer_client/src/models/{miniassetholding.ts => mini-asset-holding.ts} (100%) rename packages/typescript/indexer_client/src/models/{oncompletion.ts => on-completion.ts} (100%) rename packages/typescript/indexer_client/src/models/{participationupdates.ts => participation-updates.ts} (100%) rename packages/typescript/indexer_client/src/models/{searchforaccounts.ts => search-for-accounts.ts} (100%) rename packages/typescript/indexer_client/src/models/{searchforapplicationboxes.ts => search-for-application-boxes.ts} (100%) rename packages/typescript/indexer_client/src/models/{searchforapplications.ts => search-for-applications.ts} (100%) rename packages/typescript/indexer_client/src/models/{searchforassets.ts => search-for-assets.ts} (100%) rename packages/typescript/indexer_client/src/models/{searchforblockheaders.ts => search-for-block-headers.ts} (100%) rename packages/typescript/indexer_client/src/models/{searchfortransactions.ts => search-for-transactions.ts} (100%) rename packages/typescript/indexer_client/src/models/{statedelta.ts => state-delta.ts} (100%) rename packages/typescript/indexer_client/src/models/{stateprooffields.ts => state-proof-fields.ts} (100%) rename packages/typescript/indexer_client/src/models/{stateproofparticipant.ts => state-proof-participant.ts} (100%) rename packages/typescript/indexer_client/src/models/{stateproofreveal.ts => state-proof-reveal.ts} (100%) rename packages/typescript/indexer_client/src/models/{stateproofsigslot.ts => state-proof-sig-slot.ts} (100%) rename packages/typescript/indexer_client/src/models/{stateproofsignature.ts => state-proof-signature.ts} (100%) rename packages/typescript/indexer_client/src/models/{stateprooftracking.ts => state-proof-tracking.ts} (100%) rename packages/typescript/indexer_client/src/models/{stateproofverifier.ts => state-proof-verifier.ts} (100%) rename packages/typescript/indexer_client/src/models/{stateschema.ts => state-schema.ts} (100%) rename packages/typescript/indexer_client/src/models/{tealkeyvaluestore.ts => teal-key-value-store.ts} (100%) rename packages/typescript/indexer_client/src/models/{tealkeyvalue.ts => teal-key-value.ts} (100%) rename packages/typescript/indexer_client/src/models/{tealvalue.ts => teal-value.ts} (100%) rename packages/typescript/indexer_client/src/models/{transactionapplication.ts => transaction-application.ts} (100%) rename packages/typescript/indexer_client/src/models/{transactionassetconfig.ts => transaction-asset-config.ts} (100%) rename packages/typescript/indexer_client/src/models/{transactionassetfreeze.ts => transaction-asset-freeze.ts} (100%) rename packages/typescript/indexer_client/src/models/{transactionassettransfer.ts => transaction-asset-transfer.ts} (100%) rename packages/typescript/indexer_client/src/models/{transactionheartbeat.ts => transaction-heartbeat.ts} (100%) rename packages/typescript/indexer_client/src/models/{transactionkeyreg.ts => transaction-keyreg.ts} (100%) rename packages/typescript/indexer_client/src/models/{transactionpayment.ts => transaction-payment.ts} (100%) rename packages/typescript/indexer_client/src/models/{transactionsignaturelogicsig.ts => transaction-signature-logicsig.ts} (100%) rename packages/typescript/indexer_client/src/models/{transactionsignaturemultisigsubsignature.ts => transaction-signature-multisig-subsignature.ts} (100%) rename packages/typescript/indexer_client/src/models/{transactionsignaturemultisig.ts => transaction-signature-multisig.ts} (100%) rename packages/typescript/indexer_client/src/models/{transactionsignature.ts => transaction-signature.ts} (100%) rename packages/typescript/indexer_client/src/models/{transactionstateproof.ts => transaction-state-proof.ts} (100%) diff --git a/api/oas_generator/ts_oas_generator/constants.py b/api/oas_generator/ts_oas_generator/constants.py index a353e69dd..31c654db9 100644 --- a/api/oas_generator/ts_oas_generator/constants.py +++ b/api/oas_generator/ts_oas_generator/constants.py @@ -198,6 +198,10 @@ class HttpMethod(StrEnum): 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_" diff --git a/api/oas_generator/ts_oas_generator/generator/filters.py b/api/oas_generator/ts_oas_generator/generator/filters.py index bde6a2efd..6c2a6eb0f 100644 --- a/api/oas_generator/ts_oas_generator/generator/filters.py +++ b/api/oas_generator/ts_oas_generator/generator/filters.py @@ -59,6 +59,11 @@ def ts_camel_case(name: str) -> str: return pas[:1].lower() + pas[1:] if pas else pas +def ts_kebab_case(name: str) -> str: + parts = _split_words(name) + return "-".join(p.lower() for p in parts) + + 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}'" @@ -108,6 +113,7 @@ def _inline_object(schema: dict[str, Any], schemas: dict[str, Any] | None) -> st 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: @@ -117,7 +123,7 @@ def _inline_object(schema: dict[str, Any], schemas: dict[str, Any] | None) -> st parts.append(f"\n {indented_doc}") # Generate camelCase TS property names for better DX - ts_name = ts_camel_case(prop_name) + 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};") @@ -313,6 +319,7 @@ def _traverse(obj: dict[str, Any]) -> None: # noqa: C901 "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, diff --git a/api/oas_generator/ts_oas_generator/generator/template_engine.py b/api/oas_generator/ts_oas_generator/generator/template_engine.py index bfa8010fd..6396ce07d 100644 --- a/api/oas_generator/ts_oas_generator/generator/template_engine.py +++ b/api/oas_generator/ts_oas_generator/generator/template_engine.py @@ -9,7 +9,7 @@ from jinja2 import Environment, FileSystemLoader, select_autoescape from ts_oas_generator import constants -from ts_oas_generator.generator.filters import FILTERS, ts_camel_case, ts_pascal_case, ts_type +from ts_oas_generator.generator.filters import FILTERS, ts_camel_case, ts_kebab_case, ts_pascal_case, ts_type from ts_oas_generator.parser.oas_parser import OASParser # Type aliases for clarity @@ -120,7 +120,6 @@ def __init__(self, template_dir: Path | None = None) -> None: self.env = self._create_environment() def _create_environment(self) -> Environment: - """Create and configure Jinja2 environment.""" env = Environment( loader=FileSystemLoader(str(self.template_dir)), autoescape=select_autoescape(["html", "xml"]), @@ -131,12 +130,10 @@ def _create_environment(self) -> Environment: return env def render(self, template_name: str, context: TemplateContext) -> str: - """Render a single template.""" template = self.env.get_template(template_name) return template.render(**context) def render_batch(self, template_map: dict[Path, tuple[str, TemplateContext]]) -> FileMap: - """Render multiple templates.""" return {path: self.render(template, context) for path, (template, context) in template_map.items()} @@ -145,9 +142,10 @@ class SchemaProcessor: 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: Schema) -> FileMap: - """Generate TypeScript model files from schemas.""" models_dir = output_dir / constants.DirectoryName.SRC / constants.DirectoryName.MODELS files: FileMap = {} @@ -155,15 +153,14 @@ def generate_models(self, output_dir: Path, schemas: Schema) -> FileMap: for name, schema in schemas.items(): context = self._create_model_context(name, schema, schemas) content = self.renderer.render(constants.MODEL_TEMPLATE, context) - files[models_dir / f"{name.lower()}{constants.MODEL_FILE_EXTENSION}"] = content + file_name = f"{ts_kebab_case(name)}{constants.MODEL_FILE_EXTENSION}" + files[models_dir / file_name] = content - # Generate comprehensive AlgokitSignedTransaction model # TODO(utils-ts): Delete this temporary model once utils-ts is part of the monorepo files[models_dir / f"algokitsignedtransaction{constants.MODEL_FILE_EXTENSION}"] = self.renderer.render( "models/algokitsignedtransaction.ts.j2", {} ) - # Generate barrel export files[models_dir / constants.INDEX_FILE] = self.renderer.render( constants.MODELS_INDEX_TEMPLATE, {"schemas": schemas, "include_temp_signed_txn": True}, @@ -172,7 +169,6 @@ def generate_models(self, output_dir: Path, schemas: Schema) -> FileMap: return files def _create_model_context(self, name: str, schema: Schema, all_schemas: Schema) -> TemplateContext: - """Create context for model template rendering.""" is_object = self._is_object_schema(schema) properties = self._extract_properties(schema) if is_object else [] @@ -188,7 +184,6 @@ def _create_model_context(self, name: str, schema: Schema, all_schemas: Schema) @staticmethod def _is_object_schema(schema: Schema) -> bool: - """Check if schema represents an object type.""" is_type_object = schema.get(constants.SchemaKey.TYPE) == constants.TypeScriptType.OBJECT has_properties = constants.SchemaKey.PROPERTIES in schema has_composition = any( @@ -196,13 +191,12 @@ def _is_object_schema(schema: Schema) -> bool: ) return (is_type_object or has_properties) and not has_composition - @staticmethod - def _extract_properties(schema: Schema) -> list[dict[str, Any]]: - """Extract properties from an object schema.""" + 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, @@ -213,6 +207,19 @@ def _extract_properties(schema: Schema) -> list[dict[str, Any]]: return properties + def _register_rename(self, wire_name: str, schema: dict[str, Any]) -> 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 + class OperationProcessor: """Processes OpenAPI operations and generates API services.""" @@ -609,6 +616,7 @@ def generate( files.update(self.schema_processor.generate_models(output_dir, all_schemas)) 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)) + files.update(self._generate_rename_map(output_dir)) return files @@ -642,6 +650,7 @@ def _generate_runtime( core_dir / "json.ts": ("base/src/core/json.ts.j2", context), core_dir / "msgpack.ts": ("base/src/core/msgpack.ts.j2", context), core_dir / "casing.ts": ("base/src/core/casing.ts.j2", context), + core_dir / "codecs.ts": ("base/src/core/codecs.ts.j2", context), # Project files src_dir / "index.ts": ("base/src/index.ts.j2", context), output_dir / "package.json": ("base/package.json.j2", context), @@ -669,6 +678,24 @@ def _generate_client_files(self, output_dir: Path, client_class: str, service_cl return self.renderer.render_batch(template_map) + def _generate_rename_map(self, output_dir: Path) -> FileMap: + """Render rename map supporting vendor rename extensions.""" + wire_to_canonical, camel_to_wire = self.schema_processor.rename_mappings + + core_dir = output_dir / constants.DirectoryName.SRC / constants.DirectoryName.CORE + # TODO(utils-ts): leverage rename metadata when emitting DTO mappers so base64 fields can flow into Uint8Array by default. + return { + core_dir / "rename-map.ts": ( + self.renderer.render( + "base/src/core/rename-map.ts.j2", + { + "wire_to_canonical": wire_to_canonical, + "camel_to_wire": camel_to_wire, + }, + ) + ) + } + @staticmethod def _extract_class_names(package_name: str) -> tuple[str, str]: """Extract client and service class names from package name.""" diff --git a/api/oas_generator/ts_oas_generator/templates/base/src/core/casing.ts.j2 b/api/oas_generator/ts_oas_generator/templates/base/src/core/casing.ts.j2 index a1642dbb4..636a0a6e5 100644 --- a/api/oas_generator/ts_oas_generator/templates/base/src/core/casing.ts.j2 +++ b/api/oas_generator/ts_oas_generator/templates/base/src/core/casing.ts.j2 @@ -1,4 +1,8 @@ +import { CANONICAL_CAMEL_TO_WIRE, WIRE_TO_CANONICAL } from './rename-map'; + function toCamel(segmented: string): string { + const override = WIRE_TO_CANONICAL[segmented]; + if (override) segmented = override; if (!segmented) return segmented; // Fast path: if no hyphen, return as-is but ensure typical camel conversion for underscores if (!segmented.includes('-')) return segmented.replace(/_([a-z0-9])/g, (_, c) => c.toUpperCase()); @@ -9,6 +13,8 @@ function toCamel(segmented: string): string { } function toKebab(camel: string): string { + const override = CANONICAL_CAMEL_TO_WIRE[camel]; + if (override) return override; if (!camel) return camel; // Convert camelCase or mixedCase to kebab-case; leave existing hyphens and numbers intact return camel @@ -49,4 +55,3 @@ export function toKebabCaseKeysDeep(value: T): T { // eslint-disable-li return out as unknown as T; } - diff --git a/api/oas_generator/ts_oas_generator/templates/base/src/core/codecs.ts.j2 b/api/oas_generator/ts_oas_generator/templates/base/src/core/codecs.ts.j2 new file mode 100644 index 000000000..a3a9c769a --- /dev/null +++ b/api/oas_generator/ts_oas_generator/templates/base/src/core/codecs.ts.j2 @@ -0,0 +1,87 @@ +// Temporary copy of codec helpers from utils-ts until the shared core moves into the monorepo. +// These keep the generated clients self-contained and ready for future DTO <-> domain mappers. + +export abstract class Codec { + public abstract defaultValue(): TEncoded; + + protected toEncoded(value: T): TEncoded { + return value as unknown as TEncoded; + } + + protected fromEncoded(value: TEncoded): T { + return value as unknown as T; + } + + protected isDefaultValue(value: T): boolean { + return this.toEncoded(value) === this.defaultValue(); + } + + public encode(value?: T): TEncoded | undefined { + return value !== undefined && !this.isDefaultValue(value) ? this.toEncoded(value) : undefined; + } + + public decode(value: TEncoded | undefined): T { + return this.fromEncoded(value ?? this.defaultValue()); + } + + public decodeOptional(value: TEncoded | undefined): T | undefined { + if (value === undefined) { + return undefined; + } + return this.fromEncoded(value); + } +} + +export class NumberCodec extends Codec { + public defaultValue(): number { + return 0; + } +} + +export class BigIntCodec extends Codec { + public defaultValue(): bigint { + return 0n; + } + + protected fromEncoded(value: number | bigint): bigint { + return typeof value === 'bigint' ? value : BigInt(value); + } +} + +export class StringCodec extends Codec { + public defaultValue(): string { + return ''; + } +} + +export class BytesCodec extends Codec { + public defaultValue(): Uint8Array { + return new Uint8Array(); + } + + protected isDefaultValue(value: Uint8Array): boolean { + return value.byteLength === 0; + } +} + +export class BooleanCodec extends Codec { + public defaultValue(): boolean { + return false; + } +} + +export class OmitEmptyObjectCodec extends Codec { + public defaultValue(): T | undefined { + return undefined; + } + + protected isDefaultValue(value: T): boolean { + return Object.values(value).filter((x) => x !== undefined).length === 0; + } +} + +export const numberCodec = new NumberCodec(); +export const bigIntCodec = new BigIntCodec(); +export const stringCodec = new StringCodec(); +export const bytesCodec = new BytesCodec(); +export const booleanCodec = new BooleanCodec(); diff --git a/api/oas_generator/ts_oas_generator/templates/base/src/core/rename-map.ts.j2 b/api/oas_generator/ts_oas_generator/templates/base/src/core/rename-map.ts.j2 new file mode 100644 index 000000000..513e9cb8e --- /dev/null +++ b/api/oas_generator/ts_oas_generator/templates/base/src/core/rename-map.ts.j2 @@ -0,0 +1,15 @@ +/* Auto-generated rename hints derived from OpenAPI vendor extensions. */ + +export const WIRE_TO_CANONICAL: Record = { +{% for wire, canonical in wire_to_canonical|dictsort %} + '{{ wire }}': '{{ canonical }}', +{% endfor %} +}; + +export const CANONICAL_CAMEL_TO_WIRE: Record = { +{% for camel, wire in camel_to_wire|dictsort %} + '{{ camel }}': '{{ wire }}', +{% endfor %} +}; + +export const HAS_RENAME_HINTS = Object.keys(WIRE_TO_CANONICAL).length > 0; diff --git a/api/oas_generator/ts_oas_generator/templates/models/index.ts.j2 b/api/oas_generator/ts_oas_generator/templates/models/index.ts.j2 index fb9b88117..9c4aa83fe 100644 --- a/api/oas_generator/ts_oas_generator/templates/models/index.ts.j2 +++ b/api/oas_generator/ts_oas_generator/templates/models/index.ts.j2 @@ -1,6 +1,6 @@ // Barrel file for models {% for name, _ in schemas.items() %} -export type { {{ name | ts_pascal_case }} } from './{{ name | lower }}'; +export type { {{ name | ts_pascal_case }} } from './{{ name | ts_kebab_case }}'; {% endfor %} {% if include_temp_signed_txn %} // TODO(utils-ts): Remove this export when utils-ts provides SignedTransaction types diff --git a/api/oas_generator/ts_oas_generator/templates/models/model.ts.j2 b/api/oas_generator/ts_oas_generator/templates/models/model.ts.j2 index 77a3749a6..a0e1b1832 100644 --- a/api/oas_generator/ts_oas_generator/templates/models/model.ts.j2 +++ b/api/oas_generator/ts_oas_generator/templates/models/model.ts.j2 @@ -9,8 +9,9 @@ import type { {{ refTypes | join(', ') }} } from './index'; {% 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 prop_name, prop_schema in (schema.get('properties') or {}).items() %} + {% set canonical_name = prop_schema.get('x-algokit-field-rename') or prop_name %} {{ prop_schema.description | ts_doc_comment }} - {{ prop_name | ts_camel_case }}{{ '' if (schema.get('required') or []) | list | select('equalto', prop_name) | list | length > 0 else '?' }}: {{ prop_schema | ts_type(schemas) }}; + {{ canonical_name | ts_camel_case }}{{ '' if (schema.get('required') or []) | list | select('equalto', prop_name) | list | length > 0 else '?' }}: {{ prop_schema | ts_type(schemas) }}; {% endfor %} {% if schema.get('additionalProperties') is sameas true %} [key: string]: any; diff --git a/packages/typescript/algod_client/bun.lock b/packages/typescript/algod_client/bun.lock index d848aadb6..d45b4e902 100644 --- a/packages/typescript/algod_client/bun.lock +++ b/packages/typescript/algod_client/bun.lock @@ -68,57 +68,59 @@ "@msgpack/msgpack": ["@msgpack/msgpack@3.1.2", "", {}, "sha512-JEW4DEtBzfe8HvUYecLU9e6+XJnKDlUAIve8FvPzF3Kzs6Xo/KuZkZJsDH0wJXl/qEZbeeE7edxDNY3kMs39hQ=="], - "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.50.1", "", { "os": "android", "cpu": "arm" }, "sha512-HJXwzoZN4eYTdD8bVV22DN8gsPCAj3V20NHKOs8ezfXanGpmVPR7kalUHd+Y31IJp9stdB87VKPFbsGY3H/2ag=="], + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.52.0", "", { "os": "android", "cpu": "arm" }, "sha512-VxDYCDqOaR7NXzAtvRx7G1u54d2kEHopb28YH/pKzY6y0qmogP3gG7CSiWsq9WvDFxOQMpNEyjVAHZFXfH3o/A=="], - "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.50.1", "", { "os": "android", "cpu": "arm64" }, "sha512-PZlsJVcjHfcH53mOImyt3bc97Ep3FJDXRpk9sMdGX0qgLmY0EIWxCag6EigerGhLVuL8lDVYNnSo8qnTElO4xw=="], + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.52.0", "", { "os": "android", "cpu": "arm64" }, "sha512-pqDirm8koABIKvzL59YI9W9DWbRlTX7RWhN+auR8HXJxo89m4mjqbah7nJZjeKNTNYopqL+yGg+0mhCpf3xZtQ=="], - "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.50.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-xc6i2AuWh++oGi4ylOFPmzJOEeAa2lJeGUGb4MudOtgfyyjr4UPNK+eEWTPLvmPJIY/pgw6ssFIox23SyrkkJw=="], + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.52.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-YCdWlY/8ltN6H78HnMsRHYlPiKvqKagBP1r+D7SSylxX+HnsgXGCmLiV3Y4nSyY9hW8qr8U9LDUx/Lo7M6MfmQ=="], - "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.50.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-2ofU89lEpDYhdLAbRdeyz/kX3Y2lpYc6ShRnDjY35bZhd2ipuDMDi6ZTQ9NIag94K28nFMofdnKeHR7BT0CATw=="], + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.52.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-z4nw6y1j+OOSGzuVbSWdIp1IUks9qNw4dc7z7lWuWDKojY38VMWBlEN7F9jk5UXOkUcp97vA1N213DF+Lz8BRg=="], - "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.50.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-wOsE6H2u6PxsHY/BeFHA4VGQN3KUJFZp7QJBmDYI983fgxq5Th8FDkVuERb2l9vDMs1D5XhOrhBrnqcEY6l8ZA=="], + "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.52.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-Q/dv9Yvyr5rKlK8WQJZVrp5g2SOYeZUs9u/t2f9cQ2E0gJjYB/BWoedXfUT0EcDJefi2zzVfhcOj8drWCzTviw=="], - "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.50.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-A/xeqaHTlKbQggxCqispFAcNjycpUEHP52mwMQZUNqDUJFFYtPHCXS1VAG29uMlDzIVr+i00tSFWFLivMcoIBQ=="], + "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.52.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-kdBsLs4Uile/fbjZVvCRcKB4q64R+1mUq0Yd7oU1CMm1Av336ajIFqNFovByipciuUQjBCPMxwJhCgfG2re3rg=="], - "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.50.1", "", { "os": "linux", "cpu": "arm" }, "sha512-54v4okehwl5TaSIkpp97rAHGp7t3ghinRd/vyC1iXqXMfjYUTm7TfYmCzXDoHUPTTf36L8pr0E7YsD3CfB3ZDg=="], + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.52.0", "", { "os": "linux", "cpu": "arm" }, "sha512-aL6hRwu0k7MTUESgkg7QHY6CoqPgr6gdQXRJI1/VbFlUMwsSzPGSR7sG5d+MCbYnJmJwThc2ol3nixj1fvI/zQ=="], - "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.50.1", "", { "os": "linux", "cpu": "arm" }, "sha512-p/LaFyajPN/0PUHjv8TNyxLiA7RwmDoVY3flXHPSzqrGcIp/c2FjwPPP5++u87DGHtw+5kSH5bCJz0mvXngYxw=="], + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.52.0", "", { "os": "linux", "cpu": "arm" }, "sha512-BTs0M5s1EJejgIBJhCeiFo7GZZ2IXWkFGcyZhxX4+8usnIo5Mti57108vjXFIQmmJaRyDwmV59Tw64Ap1dkwMw=="], - "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.50.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-2AbMhFFkTo6Ptna1zO7kAXXDLi7H9fGTbVaIq2AAYO7yzcAsuTNWPHhb2aTA6GPiP+JXh85Y8CiS54iZoj4opw=="], + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.52.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-uj672IVOU9m08DBGvoPKPi/J8jlVgjh12C9GmjjBxCTQc3XtVmRkRKyeHSmIKQpvJ7fIm1EJieBUcnGSzDVFyw=="], - "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.50.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-Cgef+5aZwuvesQNw9eX7g19FfKX5/pQRIyhoXLCiBOrWopjo7ycfB292TX9MDcDijiuIJlx1IzJz3IoCPfqs9w=="], + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.52.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-/+IVbeDMDCtB/HP/wiWsSzduD10SEGzIZX2945KSgZRNi4TSkjHqRJtNTVtVb8IRwhJ65ssI56krlLik+zFWkw=="], - "@rollup/rollup-linux-loongarch64-gnu": ["@rollup/rollup-linux-loongarch64-gnu@4.50.1", "", { "os": "linux", "cpu": "none" }, "sha512-RPhTwWMzpYYrHrJAS7CmpdtHNKtt2Ueo+BlLBjfZEhYBhK00OsEqM08/7f+eohiF6poe0YRDDd8nAvwtE/Y62Q=="], + "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.52.0", "", { "os": "linux", "cpu": "none" }, "sha512-U1vVzvSWtSMWKKrGoROPBXMh3Vwn93TA9V35PldokHGqiUbF6erSzox/5qrSMKp6SzakvyjcPiVF8yB1xKr9Pg=="], - "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.50.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-eSGMVQw9iekut62O7eBdbiccRguuDgiPMsw++BVUg+1K7WjZXHOg/YOT9SWMzPZA+w98G+Fa1VqJgHZOHHnY0Q=="], + "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.52.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-X/4WfuBAdQRH8cK3DYl8zC00XEE6aM472W+QCycpQJeLWVnHfkv7RyBFVaTqNUMsTgIX8ihMjCvFF9OUgeABzw=="], - "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.50.1", "", { "os": "linux", "cpu": "none" }, "sha512-S208ojx8a4ciIPrLgazF6AgdcNJzQE4+S9rsmOmDJkusvctii+ZvEuIC4v/xFqzbuP8yDjn73oBlNDgF6YGSXQ=="], + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.52.0", "", { "os": "linux", "cpu": "none" }, "sha512-xIRYc58HfWDBZoLmWfWXg2Sq8VCa2iJ32B7mqfWnkx5mekekl0tMe7FHpY8I72RXEcUkaWawRvl3qA55og+cwQ=="], - "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.50.1", "", { "os": "linux", "cpu": "none" }, "sha512-3Ag8Ls1ggqkGUvSZWYcdgFwriy2lWo+0QlYgEFra/5JGtAd6C5Hw59oojx1DeqcA2Wds2ayRgvJ4qxVTzCHgzg=="], + "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.52.0", "", { "os": "linux", "cpu": "none" }, "sha512-mbsoUey05WJIOz8U1WzNdf+6UMYGwE3fZZnQqsM22FZ3wh1N887HT6jAOjXs6CNEK3Ntu2OBsyQDXfIjouI4dw=="], - "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.50.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-t9YrKfaxCYe7l7ldFERE1BRg/4TATxIg+YieHQ966jwvo7ddHJxPj9cNFWLAzhkVsbBvNA4qTbPVNsZKBO4NSg=="], + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.52.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-qP6aP970bucEi5KKKR4AuPFd8aTx9EF6BvutvYxmZuWLJHmnq4LvBfp0U+yFDMGwJ+AIJEH5sIP+SNypauMWzg=="], - "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.50.1", "", { "os": "linux", "cpu": "x64" }, "sha512-MCgtFB2+SVNuQmmjHf+wfI4CMxy3Tk8XjA5Z//A0AKD7QXUYFMQcns91K6dEHBvZPCnhJSyDWLApk40Iq/H3tA=="], + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.52.0", "", { "os": "linux", "cpu": "x64" }, "sha512-nmSVN+F2i1yKZ7rJNKO3G7ZzmxJgoQBQZ/6c4MuS553Grmr7WqR7LLDcYG53Z2m9409z3JLt4sCOhLdbKQ3HmA=="], - "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.50.1", "", { "os": "linux", "cpu": "x64" }, "sha512-nEvqG+0jeRmqaUMuwzlfMKwcIVffy/9KGbAGyoa26iu6eSngAYQ512bMXuqqPrlTyfqdlB9FVINs93j534UJrg=="], + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.52.0", "", { "os": "linux", "cpu": "x64" }, "sha512-2d0qRo33G6TfQVjaMR71P+yJVGODrt5V6+T0BDYH4EMfGgdC/2HWDVjSSFw888GSzAZUwuska3+zxNUCDco6rQ=="], - "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.50.1", "", { "os": "none", "cpu": "arm64" }, "sha512-RDsLm+phmT3MJd9SNxA9MNuEAO/J2fhW8GXk62G/B4G7sLVumNFbRwDL6v5NrESb48k+QMqdGbHgEtfU0LCpbA=="], + "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.52.0", "", { "os": "none", "cpu": "arm64" }, "sha512-A1JalX4MOaFAAyGgpO7XP5khquv/7xKzLIyLmhNrbiCxWpMlnsTYr8dnsWM7sEeotNmxvSOEL7F65j0HXFcFsw=="], - "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.50.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-hpZB/TImk2FlAFAIsoElM3tLzq57uxnGYwplg6WDyAxbYczSi8O2eQ+H2Lx74504rwKtZ3N2g4bCUkiamzS6TQ=="], + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.52.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-YQugafP/rH0eOOHGjmNgDURrpYHrIX0yuojOI8bwCyXwxC9ZdTd3vYkmddPX0oHONLXu9Rb1dDmT0VNpjkzGGw=="], - "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.50.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-SXjv8JlbzKM0fTJidX4eVsH+Wmnp0/WcD8gJxIZyR6Gay5Qcsmdbi9zVtnbkGPG8v2vMR1AD06lGWy5FLMcG7A=="], + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.52.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-zYdUYhi3Qe2fndujBqL5FjAFzvNeLxtIqfzNEVKD1I7C37/chv1VxhscWSQHTNfjPCrBFQMnynwA3kpZpZ8w4A=="], - "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.50.1", "", { "os": "win32", "cpu": "x64" }, "sha512-StxAO/8ts62KZVRAm4JZYq9+NqNsV7RvimNK+YM7ry//zebEH6meuugqW/P5OFUCjyQgui+9fUxT6d5NShvMvA=="], + "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.52.0", "", { "os": "win32", "cpu": "x64" }, "sha512-fGk03kQylNaCOQ96HDMeT7E2n91EqvCDd3RwvT5k+xNdFCeMGnj5b5hEgTGrQuyidqSsD3zJDQ21QIaxXqTBJw=="], - "@types/bun": ["@types/bun@1.2.21", "", { "dependencies": { "bun-types": "1.2.21" } }, "sha512-NiDnvEqmbfQ6dmZ3EeUO577s4P5bf4HCTXtI6trMc6f6RzirY5IrF3aIookuSpyslFzrnvv2lmEWv5HyC1X79A=="], + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.52.0", "", { "os": "win32", "cpu": "x64" }, "sha512-6iKDCVSIUQ8jPMoIV0OytRKniaYyy5EbY/RRydmLW8ZR3cEBhxbWl5ro0rkUNe0ef6sScvhbY79HrjRm8i3vDQ=="], + + "@types/bun": ["@types/bun@1.2.22", "", { "dependencies": { "bun-types": "1.2.22" } }, "sha512-5A/KrKos2ZcN0c6ljRSOa1fYIyCKhZfIVYeuyb4snnvomnpFqC0tTsEkdqNxbAgExV384OETQ//WAjl3XbYqQA=="], "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], "@types/json-bigint": ["@types/json-bigint@1.0.4", "", {}, "sha512-ydHooXLbOmxBbubnA7Eh+RpBzuaIiQjh8WGJYQB50JFGFrdxW7JzVlyEV7fAXw0T2sqJ1ysTneJbiyNLqZRAag=="], - "@types/node": ["@types/node@20.19.13", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-yCAeZl7a0DxgNVteXFHt9+uyFbqXGy/ShC4BlcHkoE0AfGXYv/BUiplV72DjMYXHDBXFjhvr6DD1NiRVfB4j8g=="], + "@types/node": ["@types/node@20.19.17", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-gfehUI8N1z92kygssiuWvLiwcbOB3IRktR6hTDgJlXMYh5OvkPSRmgfoBUmfZt+vhwJtX7v1Yw4KvvAf7c5QKQ=="], - "@types/react": ["@types/react@19.1.12", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-cMoR+FoAf/Jyq6+Df2/Z41jISvGZZ2eTlnsaJRptmZ76Caldwy1odD4xTr/gNV9VLj0AWgg/nmkevIyUfIIq5w=="], + "@types/react": ["@types/react@19.1.13", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-hHkbU/eoO3EG5/MZkuFSKmYqPbSVk5byPFa3e7y/8TybHiLMACgI8seVYlicwk7H5K/rI2px9xrQp/C+AUDTiQ=="], "@vitest/expect": ["@vitest/expect@2.1.9", "", { "dependencies": { "@vitest/spy": "2.1.9", "@vitest/utils": "2.1.9", "chai": "^5.1.2", "tinyrainbow": "^1.2.0" } }, "sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw=="], @@ -136,13 +138,13 @@ "algorand-msgpack": ["algorand-msgpack@1.1.0", "", {}, "sha512-08k7pBQnkaUB5p+jL7f1TRaUIlTSDE0cesFu1mD7llLao+1cAhtvvZmGE3OnisTd0xOn118QMw74SRqddqaYvw=="], - "algosdk": ["algosdk@3.4.0", "", { "dependencies": { "algorand-msgpack": "^1.1.0", "hi-base32": "^0.5.1", "js-sha256": "^0.9.0", "js-sha3": "^0.8.0", "js-sha512": "^0.8.0", "json-bigint": "^1.0.0", "tweetnacl": "^1.0.3", "vlq": "^2.0.4" } }, "sha512-95NYlVxMsHKs9gV8/hUvNTRAqmRC55wtesGR53j37fjP/sHUWd1gxNGTNBy0d1+o4jDKxVaasVgUHh78IqgtCw=="], + "algosdk": ["algosdk@3.5.0", "", { "dependencies": { "algorand-msgpack": "^1.1.0", "hi-base32": "^0.5.1", "js-sha256": "^0.9.0", "js-sha3": "^0.8.0", "js-sha512": "^0.8.0", "json-bigint": "^1.0.0", "tweetnacl": "^1.0.3", "vlq": "^2.0.4" } }, "sha512-9Q6lKAbl5Zz0VKjAMC7OYpnpDqmK/qa5LOALKxcF/jBs5k309lMezFC3ka0dSXPq64IKsUzhShSdOZrwYfr7tA=="], "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="], "bignumber.js": ["bignumber.js@9.3.1", "", {}, "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ=="], - "bun-types": ["bun-types@1.2.21", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-sa2Tj77Ijc/NTLS0/Odjq/qngmEPZfbfnOERi0KRUYhT9R8M4VBioWVmMWE5GrYbKMc+5lVybXygLdibHaqVqw=="], + "bun-types": ["bun-types@1.2.22", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-hwaAu8tct/Zn6Zft4U9BsZcXkYomzpHJX28ofvx7k0Zz2HNz54n1n+tDgxoWFGB4PcFvJXJQloPhaV2eP3Q6EA=="], "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="], @@ -152,7 +154,7 @@ "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], - "debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], + "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], "deep-eql": ["deep-eql@5.0.2", "", {}, "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q=="], @@ -192,7 +194,7 @@ "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], - "rollup": ["rollup@4.50.1", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.50.1", "@rollup/rollup-android-arm64": "4.50.1", "@rollup/rollup-darwin-arm64": "4.50.1", "@rollup/rollup-darwin-x64": "4.50.1", "@rollup/rollup-freebsd-arm64": "4.50.1", "@rollup/rollup-freebsd-x64": "4.50.1", "@rollup/rollup-linux-arm-gnueabihf": "4.50.1", "@rollup/rollup-linux-arm-musleabihf": "4.50.1", "@rollup/rollup-linux-arm64-gnu": "4.50.1", "@rollup/rollup-linux-arm64-musl": "4.50.1", "@rollup/rollup-linux-loongarch64-gnu": "4.50.1", "@rollup/rollup-linux-ppc64-gnu": "4.50.1", "@rollup/rollup-linux-riscv64-gnu": "4.50.1", "@rollup/rollup-linux-riscv64-musl": "4.50.1", "@rollup/rollup-linux-s390x-gnu": "4.50.1", "@rollup/rollup-linux-x64-gnu": "4.50.1", "@rollup/rollup-linux-x64-musl": "4.50.1", "@rollup/rollup-openharmony-arm64": "4.50.1", "@rollup/rollup-win32-arm64-msvc": "4.50.1", "@rollup/rollup-win32-ia32-msvc": "4.50.1", "@rollup/rollup-win32-x64-msvc": "4.50.1", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-78E9voJHwnXQMiQdiqswVLZwJIzdBKJ1GdI5Zx6XwoFKUIk09/sSrr+05QFzvYb8q6Y9pPV45zzDuYa3907TZA=="], + "rollup": ["rollup@4.52.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.52.0", "@rollup/rollup-android-arm64": "4.52.0", "@rollup/rollup-darwin-arm64": "4.52.0", "@rollup/rollup-darwin-x64": "4.52.0", "@rollup/rollup-freebsd-arm64": "4.52.0", "@rollup/rollup-freebsd-x64": "4.52.0", "@rollup/rollup-linux-arm-gnueabihf": "4.52.0", "@rollup/rollup-linux-arm-musleabihf": "4.52.0", "@rollup/rollup-linux-arm64-gnu": "4.52.0", "@rollup/rollup-linux-arm64-musl": "4.52.0", "@rollup/rollup-linux-loong64-gnu": "4.52.0", "@rollup/rollup-linux-ppc64-gnu": "4.52.0", "@rollup/rollup-linux-riscv64-gnu": "4.52.0", "@rollup/rollup-linux-riscv64-musl": "4.52.0", "@rollup/rollup-linux-s390x-gnu": "4.52.0", "@rollup/rollup-linux-x64-gnu": "4.52.0", "@rollup/rollup-linux-x64-musl": "4.52.0", "@rollup/rollup-openharmony-arm64": "4.52.0", "@rollup/rollup-win32-arm64-msvc": "4.52.0", "@rollup/rollup-win32-ia32-msvc": "4.52.0", "@rollup/rollup-win32-x64-gnu": "4.52.0", "@rollup/rollup-win32-x64-msvc": "4.52.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-+IuescNkTJQgX7AkIDtITipZdIGcWF0pnVvZTWStiazUmcGA2ag8dfg0urest2XlXUi9kuhfQ+qmdc5Stc3z7g=="], "siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="], diff --git a/packages/typescript/algod_client/src/core/casing.ts b/packages/typescript/algod_client/src/core/casing.ts index 7ad409bd5..724bfac1f 100644 --- a/packages/typescript/algod_client/src/core/casing.ts +++ b/packages/typescript/algod_client/src/core/casing.ts @@ -1,4 +1,8 @@ +import { CANONICAL_CAMEL_TO_WIRE, WIRE_TO_CANONICAL } from "./rename-map"; + function toCamel(segmented: string): string { + const override = WIRE_TO_CANONICAL[segmented]; + if (override) segmented = override; if (!segmented) return segmented; // Fast path: if no hyphen, return as-is but ensure typical camel conversion for underscores if (!segmented.includes("-")) return segmented.replace(/_([a-z0-9])/g, (_, c) => c.toUpperCase()); @@ -9,6 +13,8 @@ function toCamel(segmented: string): string { } function toKebab(camel: string): string { + const override = CANONICAL_CAMEL_TO_WIRE[camel]; + if (override) return override; if (!camel) return camel; // Convert camelCase or mixedCase to kebab-case; leave existing hyphens and numbers intact return camel diff --git a/packages/typescript/algod_client/src/core/codecs.ts b/packages/typescript/algod_client/src/core/codecs.ts new file mode 100644 index 000000000..27ec22973 --- /dev/null +++ b/packages/typescript/algod_client/src/core/codecs.ts @@ -0,0 +1,87 @@ +// Temporary copy of codec helpers from utils-ts until the shared core moves into the monorepo. +// These keep the generated clients self-contained and ready for future DTO <-> domain mappers. + +export abstract class Codec { + public abstract defaultValue(): TEncoded; + + protected toEncoded(value: T): TEncoded { + return value as unknown as TEncoded; + } + + protected fromEncoded(value: TEncoded): T { + return value as unknown as T; + } + + protected isDefaultValue(value: T): boolean { + return this.toEncoded(value) === this.defaultValue(); + } + + public encode(value?: T): TEncoded | undefined { + return value !== undefined && !this.isDefaultValue(value) ? this.toEncoded(value) : undefined; + } + + public decode(value: TEncoded | undefined): T { + return this.fromEncoded(value ?? this.defaultValue()); + } + + public decodeOptional(value: TEncoded | undefined): T | undefined { + if (value === undefined) { + return undefined; + } + return this.fromEncoded(value); + } +} + +export class NumberCodec extends Codec { + public defaultValue(): number { + return 0; + } +} + +export class BigIntCodec extends Codec { + public defaultValue(): bigint { + return 0n; + } + + protected fromEncoded(value: number | bigint): bigint { + return typeof value === "bigint" ? value : BigInt(value); + } +} + +export class StringCodec extends Codec { + public defaultValue(): string { + return ""; + } +} + +export class BytesCodec extends Codec { + public defaultValue(): Uint8Array { + return new Uint8Array(); + } + + protected isDefaultValue(value: Uint8Array): boolean { + return value.byteLength === 0; + } +} + +export class BooleanCodec extends Codec { + public defaultValue(): boolean { + return false; + } +} + +export class OmitEmptyObjectCodec extends Codec { + public defaultValue(): T | undefined { + return undefined; + } + + protected isDefaultValue(value: T): boolean { + return Object.values(value).filter((x) => x !== undefined).length === 0; + } +} + +export const numberCodec = new NumberCodec(); +export const bigIntCodec = new BigIntCodec(); +export const stringCodec = new StringCodec(); +export const bytesCodec = new BytesCodec(); +export const booleanCodec = new BooleanCodec(); diff --git a/packages/typescript/algod_client/src/core/rename-map.ts b/packages/typescript/algod_client/src/core/rename-map.ts new file mode 100644 index 000000000..15643f517 --- /dev/null +++ b/packages/typescript/algod_client/src/core/rename-map.ts @@ -0,0 +1,13 @@ +/* Auto-generated rename hints derived from OpenAPI vendor extensions. */ + +export const WIRE_TO_CANONICAL: Record = { + "application-index": "app_id", + "asset-index": "asset_id", +}; + +export const CANONICAL_CAMEL_TO_WIRE: Record = { + appId: "application-index", + assetId: "asset-index", +}; + +export const HAS_RENAME_HINTS = Object.keys(WIRE_TO_CANONICAL).length > 0; diff --git a/packages/typescript/algod_client/src/models/abortcatchup.ts b/packages/typescript/algod_client/src/models/abort-catchup.ts similarity index 100% rename from packages/typescript/algod_client/src/models/abortcatchup.ts rename to packages/typescript/algod_client/src/models/abort-catchup.ts diff --git a/packages/typescript/algod_client/src/models/accountapplicationinformation.ts b/packages/typescript/algod_client/src/models/account-application-information.ts similarity index 100% rename from packages/typescript/algod_client/src/models/accountapplicationinformation.ts rename to packages/typescript/algod_client/src/models/account-application-information.ts diff --git a/packages/typescript/algod_client/src/models/accountassetholding.ts b/packages/typescript/algod_client/src/models/account-asset-holding.ts similarity index 100% rename from packages/typescript/algod_client/src/models/accountassetholding.ts rename to packages/typescript/algod_client/src/models/account-asset-holding.ts diff --git a/packages/typescript/algod_client/src/models/accountassetinformation.ts b/packages/typescript/algod_client/src/models/account-asset-information.ts similarity index 100% rename from packages/typescript/algod_client/src/models/accountassetinformation.ts rename to packages/typescript/algod_client/src/models/account-asset-information.ts diff --git a/packages/typescript/algod_client/src/models/accountassetsinformation.ts b/packages/typescript/algod_client/src/models/account-assets-information.ts similarity index 100% rename from packages/typescript/algod_client/src/models/accountassetsinformation.ts rename to packages/typescript/algod_client/src/models/account-assets-information.ts diff --git a/packages/typescript/algod_client/src/models/accountparticipation.ts b/packages/typescript/algod_client/src/models/account-participation.ts similarity index 100% rename from packages/typescript/algod_client/src/models/accountparticipation.ts rename to packages/typescript/algod_client/src/models/account-participation.ts diff --git a/packages/typescript/algod_client/src/models/accountstatedelta.ts b/packages/typescript/algod_client/src/models/account-state-delta.ts similarity index 100% rename from packages/typescript/algod_client/src/models/accountstatedelta.ts rename to packages/typescript/algod_client/src/models/account-state-delta.ts diff --git a/packages/typescript/algod_client/src/models/addparticipationkey.ts b/packages/typescript/algod_client/src/models/add-participation-key.ts similarity index 100% rename from packages/typescript/algod_client/src/models/addparticipationkey.ts rename to packages/typescript/algod_client/src/models/add-participation-key.ts diff --git a/packages/typescript/algod_client/src/models/appcalllogs.ts b/packages/typescript/algod_client/src/models/app-call-logs.ts similarity index 93% rename from packages/typescript/algod_client/src/models/appcalllogs.ts rename to packages/typescript/algod_client/src/models/app-call-logs.ts index cd1f24d7e..0d9efc35a 100644 --- a/packages/typescript/algod_client/src/models/appcalllogs.ts +++ b/packages/typescript/algod_client/src/models/app-call-logs.ts @@ -10,7 +10,7 @@ export type AppCallLogs = { /** * The application from which the logs were generated */ - applicationIndex: bigint; + appId: bigint; /** * The transaction ID of the outer app call that lead to these logs diff --git a/packages/typescript/algod_client/src/models/applicationinitialstates.ts b/packages/typescript/algod_client/src/models/application-initial-states.ts similarity index 100% rename from packages/typescript/algod_client/src/models/applicationinitialstates.ts rename to packages/typescript/algod_client/src/models/application-initial-states.ts diff --git a/packages/typescript/algod_client/src/models/applicationkvstorage.ts b/packages/typescript/algod_client/src/models/application-kvstorage.ts similarity index 100% rename from packages/typescript/algod_client/src/models/applicationkvstorage.ts rename to packages/typescript/algod_client/src/models/application-kvstorage.ts diff --git a/packages/typescript/algod_client/src/models/applicationlocalreference.ts b/packages/typescript/algod_client/src/models/application-local-reference.ts similarity index 100% rename from packages/typescript/algod_client/src/models/applicationlocalreference.ts rename to packages/typescript/algod_client/src/models/application-local-reference.ts diff --git a/packages/typescript/algod_client/src/models/applicationlocalstate.ts b/packages/typescript/algod_client/src/models/application-local-state.ts similarity index 100% rename from packages/typescript/algod_client/src/models/applicationlocalstate.ts rename to packages/typescript/algod_client/src/models/application-local-state.ts diff --git a/packages/typescript/algod_client/src/models/applicationparams.ts b/packages/typescript/algod_client/src/models/application-params.ts similarity index 100% rename from packages/typescript/algod_client/src/models/applicationparams.ts rename to packages/typescript/algod_client/src/models/application-params.ts diff --git a/packages/typescript/algod_client/src/models/applicationstateoperation.ts b/packages/typescript/algod_client/src/models/application-state-operation.ts similarity index 100% rename from packages/typescript/algod_client/src/models/applicationstateoperation.ts rename to packages/typescript/algod_client/src/models/application-state-operation.ts diff --git a/packages/typescript/algod_client/src/models/applicationstateschema.ts b/packages/typescript/algod_client/src/models/application-state-schema.ts similarity index 100% rename from packages/typescript/algod_client/src/models/applicationstateschema.ts rename to packages/typescript/algod_client/src/models/application-state-schema.ts diff --git a/packages/typescript/algod_client/src/models/assetholdingreference.ts b/packages/typescript/algod_client/src/models/asset-holding-reference.ts similarity index 100% rename from packages/typescript/algod_client/src/models/assetholdingreference.ts rename to packages/typescript/algod_client/src/models/asset-holding-reference.ts diff --git a/packages/typescript/algod_client/src/models/assetholding.ts b/packages/typescript/algod_client/src/models/asset-holding.ts similarity index 100% rename from packages/typescript/algod_client/src/models/assetholding.ts rename to packages/typescript/algod_client/src/models/asset-holding.ts diff --git a/packages/typescript/algod_client/src/models/assetparams.ts b/packages/typescript/algod_client/src/models/asset-params.ts similarity index 100% rename from packages/typescript/algod_client/src/models/assetparams.ts rename to packages/typescript/algod_client/src/models/asset-params.ts diff --git a/packages/typescript/algod_client/src/models/avmkeyvalue.ts b/packages/typescript/algod_client/src/models/avm-key-value.ts similarity index 100% rename from packages/typescript/algod_client/src/models/avmkeyvalue.ts rename to packages/typescript/algod_client/src/models/avm-key-value.ts diff --git a/packages/typescript/algod_client/src/models/avmvalue.ts b/packages/typescript/algod_client/src/models/avm-value.ts similarity index 100% rename from packages/typescript/algod_client/src/models/avmvalue.ts rename to packages/typescript/algod_client/src/models/avm-value.ts diff --git a/packages/typescript/algod_client/src/models/boxdescriptor.ts b/packages/typescript/algod_client/src/models/box-descriptor.ts similarity index 100% rename from packages/typescript/algod_client/src/models/boxdescriptor.ts rename to packages/typescript/algod_client/src/models/box-descriptor.ts diff --git a/packages/typescript/algod_client/src/models/boxreference.ts b/packages/typescript/algod_client/src/models/box-reference.ts similarity index 100% rename from packages/typescript/algod_client/src/models/boxreference.ts rename to packages/typescript/algod_client/src/models/box-reference.ts diff --git a/packages/typescript/algod_client/src/models/buildversion.ts b/packages/typescript/algod_client/src/models/build-version.ts similarity index 100% rename from packages/typescript/algod_client/src/models/buildversion.ts rename to packages/typescript/algod_client/src/models/build-version.ts diff --git a/packages/typescript/algod_client/src/models/debugsettingsprof.ts b/packages/typescript/algod_client/src/models/debug-settings-prof.ts similarity index 100% rename from packages/typescript/algod_client/src/models/debugsettingsprof.ts rename to packages/typescript/algod_client/src/models/debug-settings-prof.ts diff --git a/packages/typescript/algod_client/src/models/dryrunrequest.ts b/packages/typescript/algod_client/src/models/dryrun-request.ts similarity index 100% rename from packages/typescript/algod_client/src/models/dryrunrequest.ts rename to packages/typescript/algod_client/src/models/dryrun-request.ts diff --git a/packages/typescript/algod_client/src/models/dryrunsource.ts b/packages/typescript/algod_client/src/models/dryrun-source.ts similarity index 100% rename from packages/typescript/algod_client/src/models/dryrunsource.ts rename to packages/typescript/algod_client/src/models/dryrun-source.ts diff --git a/packages/typescript/algod_client/src/models/dryrunstate.ts b/packages/typescript/algod_client/src/models/dryrun-state.ts similarity index 100% rename from packages/typescript/algod_client/src/models/dryrunstate.ts rename to packages/typescript/algod_client/src/models/dryrun-state.ts diff --git a/packages/typescript/algod_client/src/models/dryruntxnresult.ts b/packages/typescript/algod_client/src/models/dryrun-txn-result.ts similarity index 100% rename from packages/typescript/algod_client/src/models/dryruntxnresult.ts rename to packages/typescript/algod_client/src/models/dryrun-txn-result.ts diff --git a/packages/typescript/algod_client/src/models/errorresponse.ts b/packages/typescript/algod_client/src/models/error-response.ts similarity index 100% rename from packages/typescript/algod_client/src/models/errorresponse.ts rename to packages/typescript/algod_client/src/models/error-response.ts diff --git a/packages/typescript/algod_client/src/models/evaldeltakeyvalue.ts b/packages/typescript/algod_client/src/models/eval-delta-key-value.ts similarity index 100% rename from packages/typescript/algod_client/src/models/evaldeltakeyvalue.ts rename to packages/typescript/algod_client/src/models/eval-delta-key-value.ts diff --git a/packages/typescript/algod_client/src/models/evaldelta.ts b/packages/typescript/algod_client/src/models/eval-delta.ts similarity index 100% rename from packages/typescript/algod_client/src/models/evaldelta.ts rename to packages/typescript/algod_client/src/models/eval-delta.ts diff --git a/packages/typescript/algod_client/src/models/genesisallocation.ts b/packages/typescript/algod_client/src/models/genesis-allocation.ts similarity index 100% rename from packages/typescript/algod_client/src/models/genesisallocation.ts rename to packages/typescript/algod_client/src/models/genesis-allocation.ts diff --git a/packages/typescript/algod_client/src/models/getapplicationboxes.ts b/packages/typescript/algod_client/src/models/get-application-boxes.ts similarity index 100% rename from packages/typescript/algod_client/src/models/getapplicationboxes.ts rename to packages/typescript/algod_client/src/models/get-application-boxes.ts diff --git a/packages/typescript/algod_client/src/models/getblockhash.ts b/packages/typescript/algod_client/src/models/get-block-hash.ts similarity index 100% rename from packages/typescript/algod_client/src/models/getblockhash.ts rename to packages/typescript/algod_client/src/models/get-block-hash.ts diff --git a/packages/typescript/algod_client/src/models/getblocklogs.ts b/packages/typescript/algod_client/src/models/get-block-logs.ts similarity index 100% rename from packages/typescript/algod_client/src/models/getblocklogs.ts rename to packages/typescript/algod_client/src/models/get-block-logs.ts diff --git a/packages/typescript/algod_client/src/models/getblocktimestampoffset.ts b/packages/typescript/algod_client/src/models/get-block-time-stamp-offset.ts similarity index 100% rename from packages/typescript/algod_client/src/models/getblocktimestampoffset.ts rename to packages/typescript/algod_client/src/models/get-block-time-stamp-offset.ts diff --git a/packages/typescript/algod_client/src/models/getblocktxids.ts b/packages/typescript/algod_client/src/models/get-block-txids.ts similarity index 100% rename from packages/typescript/algod_client/src/models/getblocktxids.ts rename to packages/typescript/algod_client/src/models/get-block-txids.ts diff --git a/packages/typescript/algod_client/src/models/getblock.ts b/packages/typescript/algod_client/src/models/get-block.ts similarity index 100% rename from packages/typescript/algod_client/src/models/getblock.ts rename to packages/typescript/algod_client/src/models/get-block.ts diff --git a/packages/typescript/algod_client/src/models/getpendingtransactionsbyaddress.ts b/packages/typescript/algod_client/src/models/get-pending-transactions-by-address.ts similarity index 100% rename from packages/typescript/algod_client/src/models/getpendingtransactionsbyaddress.ts rename to packages/typescript/algod_client/src/models/get-pending-transactions-by-address.ts diff --git a/packages/typescript/algod_client/src/models/getpendingtransactions.ts b/packages/typescript/algod_client/src/models/get-pending-transactions.ts similarity index 100% rename from packages/typescript/algod_client/src/models/getpendingtransactions.ts rename to packages/typescript/algod_client/src/models/get-pending-transactions.ts diff --git a/packages/typescript/algod_client/src/models/getstatus.ts b/packages/typescript/algod_client/src/models/get-status.ts similarity index 100% rename from packages/typescript/algod_client/src/models/getstatus.ts rename to packages/typescript/algod_client/src/models/get-status.ts diff --git a/packages/typescript/algod_client/src/models/getsupply.ts b/packages/typescript/algod_client/src/models/get-supply.ts similarity index 100% rename from packages/typescript/algod_client/src/models/getsupply.ts rename to packages/typescript/algod_client/src/models/get-supply.ts diff --git a/packages/typescript/algod_client/src/models/getsyncround.ts b/packages/typescript/algod_client/src/models/get-sync-round.ts similarity index 100% rename from packages/typescript/algod_client/src/models/getsyncround.ts rename to packages/typescript/algod_client/src/models/get-sync-round.ts diff --git a/packages/typescript/algod_client/src/models/gettransactiongroupledgerstatedeltasforround.ts b/packages/typescript/algod_client/src/models/get-transaction-group-ledger-state-deltas-for-round.ts similarity index 100% rename from packages/typescript/algod_client/src/models/gettransactiongroupledgerstatedeltasforround.ts rename to packages/typescript/algod_client/src/models/get-transaction-group-ledger-state-deltas-for-round.ts diff --git a/packages/typescript/algod_client/src/models/index.ts b/packages/typescript/algod_client/src/models/index.ts index cdff0a52e..b297969ac 100644 --- a/packages/typescript/algod_client/src/models/index.ts +++ b/packages/typescript/algod_client/src/models/index.ts @@ -1,86 +1,86 @@ // Barrel file for models -export type { GenesisAllocation } from "./genesisallocation"; +export type { GenesisAllocation } from "./genesis-allocation"; export type { Genesis } from "./genesis"; -export type { LedgerStateDelta } from "./ledgerstatedelta"; -export type { LedgerStateDeltaForTransactionGroup } from "./ledgerstatedeltafortransactiongroup"; +export type { LedgerStateDelta } from "./ledger-state-delta"; +export type { LedgerStateDeltaForTransactionGroup } from "./ledger-state-delta-for-transaction-group"; export type { Account } from "./account"; -export type { AccountAssetHolding } from "./accountassetholding"; -export type { AccountParticipation } from "./accountparticipation"; +export type { AccountAssetHolding } from "./account-asset-holding"; +export type { AccountParticipation } from "./account-participation"; export type { Asset } from "./asset"; -export type { AssetHolding } from "./assetholding"; -export type { AssetParams } from "./assetparams"; -export type { AssetHoldingReference } from "./assetholdingreference"; -export type { ApplicationLocalReference } from "./applicationlocalreference"; -export type { ApplicationStateSchema } from "./applicationstateschema"; -export type { ApplicationLocalState } from "./applicationlocalstate"; -export type { ParticipationKey } from "./participationkey"; -export type { TealKeyValueStore } from "./tealkeyvaluestore"; -export type { TealKeyValue } from "./tealkeyvalue"; -export type { TealValue } from "./tealvalue"; -export type { AvmValue } from "./avmvalue"; -export type { AvmKeyValue } from "./avmkeyvalue"; -export type { StateDelta } from "./statedelta"; -export type { AccountStateDelta } from "./accountstatedelta"; -export type { EvalDeltaKeyValue } from "./evaldeltakeyvalue"; -export type { EvalDelta } from "./evaldelta"; +export type { AssetHolding } from "./asset-holding"; +export type { AssetParams } from "./asset-params"; +export type { AssetHoldingReference } from "./asset-holding-reference"; +export type { ApplicationLocalReference } from "./application-local-reference"; +export type { ApplicationStateSchema } from "./application-state-schema"; +export type { ApplicationLocalState } from "./application-local-state"; +export type { ParticipationKey } from "./participation-key"; +export type { TealKeyValueStore } from "./teal-key-value-store"; +export type { TealKeyValue } from "./teal-key-value"; +export type { TealValue } from "./teal-value"; +export type { AvmValue } from "./avm-value"; +export type { AvmKeyValue } from "./avm-key-value"; +export type { StateDelta } from "./state-delta"; +export type { AccountStateDelta } from "./account-state-delta"; +export type { EvalDeltaKeyValue } from "./eval-delta-key-value"; +export type { EvalDelta } from "./eval-delta"; export type { Application } from "./application"; -export type { ApplicationParams } from "./applicationparams"; -export type { DryrunState } from "./dryrunstate"; -export type { DryrunTxnResult } from "./dryruntxnresult"; -export type { ErrorResponse } from "./errorresponse"; -export type { DryrunRequest } from "./dryrunrequest"; -export type { DryrunSource } from "./dryrunsource"; -export type { SimulateRequest } from "./simulaterequest"; -export type { SimulateRequestTransactionGroup } from "./simulaterequesttransactiongroup"; -export type { SimulateTraceConfig } from "./simulatetraceconfig"; +export type { ApplicationParams } from "./application-params"; +export type { DryrunState } from "./dryrun-state"; +export type { DryrunTxnResult } from "./dryrun-txn-result"; +export type { ErrorResponse } from "./error-response"; +export type { DryrunRequest } from "./dryrun-request"; +export type { DryrunSource } from "./dryrun-source"; +export type { SimulateRequest } from "./simulate-request"; +export type { SimulateRequestTransactionGroup } from "./simulate-request-transaction-group"; +export type { SimulateTraceConfig } from "./simulate-trace-config"; export type { Box } from "./box"; -export type { BoxDescriptor } from "./boxdescriptor"; -export type { BoxReference } from "./boxreference"; +export type { BoxDescriptor } from "./box-descriptor"; +export type { BoxReference } from "./box-reference"; export type { Version } from "./version"; -export type { DebugSettingsProf } from "./debugsettingsprof"; -export type { BuildVersion } from "./buildversion"; -export type { PendingTransactionResponse } from "./pendingtransactionresponse"; -export type { SimulateTransactionGroupResult } from "./simulatetransactiongroupresult"; -export type { SimulateTransactionResult } from "./simulatetransactionresult"; -export type { StateProof } from "./stateproof"; -export type { LightBlockHeaderProof } from "./lightblockheaderproof"; -export type { StateProofMessage } from "./stateproofmessage"; -export type { SimulationEvalOverrides } from "./simulationevaloverrides"; -export type { ScratchChange } from "./scratchchange"; -export type { ApplicationStateOperation } from "./applicationstateoperation"; -export type { ApplicationKvstorage } from "./applicationkvstorage"; -export type { ApplicationInitialStates } from "./applicationinitialstates"; -export type { SimulationOpcodeTraceUnit } from "./simulationopcodetraceunit"; -export type { SimulationTransactionExecTrace } from "./simulationtransactionexectrace"; -export type { SimulateUnnamedResourcesAccessed } from "./simulateunnamedresourcesaccessed"; -export type { SimulateInitialStates } from "./simulateinitialstates"; -export type { AppCallLogs } from "./appcalllogs"; -export type { TransactionProof } from "./transactionproof"; -export type { AccountAssetInformation } from "./accountassetinformation"; -export type { AccountAssetsInformation } from "./accountassetsinformation"; -export type { AccountApplicationInformation } from "./accountapplicationinformation"; -export type { GetPendingTransactionsByAddress } from "./getpendingtransactionsbyaddress"; -export type { GetBlock } from "./getblock"; -export type { GetBlockTxids } from "./getblocktxids"; -export type { GetBlockHash } from "./getblockhash"; -export type { GetBlockLogs } from "./getblocklogs"; -export type { GetSupply } from "./getsupply"; -export type { AddParticipationKey } from "./addparticipationkey"; -export type { ShutdownNode } from "./shutdownnode"; -export type { GetStatus } from "./getstatus"; -export type { WaitForBlock } from "./waitforblock"; -export type { RawTransaction } from "./rawtransaction"; -export type { SimulateTransaction } from "./simulatetransaction"; -export type { TransactionParams } from "./transactionparams"; -export type { GetPendingTransactions } from "./getpendingtransactions"; -export type { GetTransactionGroupLedgerStateDeltasForRound } from "./gettransactiongroupledgerstatedeltasforround"; -export type { GetApplicationBoxes } from "./getapplicationboxes"; -export type { GetSyncRound } from "./getsyncround"; -export type { TealCompile } from "./tealcompile"; -export type { TealDisassemble } from "./tealdisassemble"; -export type { StartCatchup } from "./startcatchup"; -export type { AbortCatchup } from "./abortcatchup"; -export type { TealDryrun } from "./tealdryrun"; -export type { GetBlockTimeStampOffset } from "./getblocktimestampoffset"; +export type { DebugSettingsProf } from "./debug-settings-prof"; +export type { BuildVersion } from "./build-version"; +export type { PendingTransactionResponse } from "./pending-transaction-response"; +export type { SimulateTransactionGroupResult } from "./simulate-transaction-group-result"; +export type { SimulateTransactionResult } from "./simulate-transaction-result"; +export type { StateProof } from "./state-proof"; +export type { LightBlockHeaderProof } from "./light-block-header-proof"; +export type { StateProofMessage } from "./state-proof-message"; +export type { SimulationEvalOverrides } from "./simulation-eval-overrides"; +export type { ScratchChange } from "./scratch-change"; +export type { ApplicationStateOperation } from "./application-state-operation"; +export type { ApplicationKvstorage } from "./application-kvstorage"; +export type { ApplicationInitialStates } from "./application-initial-states"; +export type { SimulationOpcodeTraceUnit } from "./simulation-opcode-trace-unit"; +export type { SimulationTransactionExecTrace } from "./simulation-transaction-exec-trace"; +export type { SimulateUnnamedResourcesAccessed } from "./simulate-unnamed-resources-accessed"; +export type { SimulateInitialStates } from "./simulate-initial-states"; +export type { AppCallLogs } from "./app-call-logs"; +export type { TransactionProof } from "./transaction-proof"; +export type { AccountAssetInformation } from "./account-asset-information"; +export type { AccountAssetsInformation } from "./account-assets-information"; +export type { AccountApplicationInformation } from "./account-application-information"; +export type { GetPendingTransactionsByAddress } from "./get-pending-transactions-by-address"; +export type { GetBlock } from "./get-block"; +export type { GetBlockTxids } from "./get-block-txids"; +export type { GetBlockHash } from "./get-block-hash"; +export type { GetBlockLogs } from "./get-block-logs"; +export type { GetSupply } from "./get-supply"; +export type { AddParticipationKey } from "./add-participation-key"; +export type { ShutdownNode } from "./shutdown-node"; +export type { GetStatus } from "./get-status"; +export type { WaitForBlock } from "./wait-for-block"; +export type { RawTransaction } from "./raw-transaction"; +export type { SimulateTransaction } from "./simulate-transaction"; +export type { TransactionParams } from "./transaction-params"; +export type { GetPendingTransactions } from "./get-pending-transactions"; +export type { GetTransactionGroupLedgerStateDeltasForRound } from "./get-transaction-group-ledger-state-deltas-for-round"; +export type { GetApplicationBoxes } from "./get-application-boxes"; +export type { GetSyncRound } from "./get-sync-round"; +export type { TealCompile } from "./teal-compile"; +export type { TealDisassemble } from "./teal-disassemble"; +export type { StartCatchup } from "./start-catchup"; +export type { AbortCatchup } from "./abort-catchup"; +export type { TealDryrun } from "./teal-dryrun"; +export type { GetBlockTimeStampOffset } from "./get-block-time-stamp-offset"; // TODO(utils-ts): Remove this export when utils-ts provides SignedTransaction types export type { AlgokitSignedTransaction } from "./algokitsignedtransaction"; diff --git a/packages/typescript/algod_client/src/models/ledgerstatedeltafortransactiongroup.ts b/packages/typescript/algod_client/src/models/ledger-state-delta-for-transaction-group.ts similarity index 100% rename from packages/typescript/algod_client/src/models/ledgerstatedeltafortransactiongroup.ts rename to packages/typescript/algod_client/src/models/ledger-state-delta-for-transaction-group.ts diff --git a/packages/typescript/algod_client/src/models/ledgerstatedelta.ts b/packages/typescript/algod_client/src/models/ledger-state-delta.ts similarity index 100% rename from packages/typescript/algod_client/src/models/ledgerstatedelta.ts rename to packages/typescript/algod_client/src/models/ledger-state-delta.ts diff --git a/packages/typescript/algod_client/src/models/lightblockheaderproof.ts b/packages/typescript/algod_client/src/models/light-block-header-proof.ts similarity index 100% rename from packages/typescript/algod_client/src/models/lightblockheaderproof.ts rename to packages/typescript/algod_client/src/models/light-block-header-proof.ts diff --git a/packages/typescript/algod_client/src/models/participationkey.ts b/packages/typescript/algod_client/src/models/participation-key.ts similarity index 100% rename from packages/typescript/algod_client/src/models/participationkey.ts rename to packages/typescript/algod_client/src/models/participation-key.ts diff --git a/packages/typescript/algod_client/src/models/pendingtransactionresponse.ts b/packages/typescript/algod_client/src/models/pending-transaction-response.ts similarity index 97% rename from packages/typescript/algod_client/src/models/pendingtransactionresponse.ts rename to packages/typescript/algod_client/src/models/pending-transaction-response.ts index 43ce550f5..05d2193a9 100644 --- a/packages/typescript/algod_client/src/models/pendingtransactionresponse.ts +++ b/packages/typescript/algod_client/src/models/pending-transaction-response.ts @@ -7,12 +7,12 @@ export type PendingTransactionResponse = { /** * The asset index if the transaction was found and it created an asset. */ - assetIndex?: bigint; + assetId?: bigint; /** * The application index if the transaction was found and it created an application. */ - applicationIndex?: bigint; + appId?: bigint; /** * Rewards in microalgos applied to the close remainder to account. diff --git a/packages/typescript/algod_client/src/models/rawtransaction.ts b/packages/typescript/algod_client/src/models/raw-transaction.ts similarity index 100% rename from packages/typescript/algod_client/src/models/rawtransaction.ts rename to packages/typescript/algod_client/src/models/raw-transaction.ts diff --git a/packages/typescript/algod_client/src/models/scratchchange.ts b/packages/typescript/algod_client/src/models/scratch-change.ts similarity index 100% rename from packages/typescript/algod_client/src/models/scratchchange.ts rename to packages/typescript/algod_client/src/models/scratch-change.ts diff --git a/packages/typescript/algod_client/src/models/shutdownnode.ts b/packages/typescript/algod_client/src/models/shutdown-node.ts similarity index 100% rename from packages/typescript/algod_client/src/models/shutdownnode.ts rename to packages/typescript/algod_client/src/models/shutdown-node.ts diff --git a/packages/typescript/algod_client/src/models/simulateinitialstates.ts b/packages/typescript/algod_client/src/models/simulate-initial-states.ts similarity index 100% rename from packages/typescript/algod_client/src/models/simulateinitialstates.ts rename to packages/typescript/algod_client/src/models/simulate-initial-states.ts diff --git a/packages/typescript/algod_client/src/models/simulaterequesttransactiongroup.ts b/packages/typescript/algod_client/src/models/simulate-request-transaction-group.ts similarity index 100% rename from packages/typescript/algod_client/src/models/simulaterequesttransactiongroup.ts rename to packages/typescript/algod_client/src/models/simulate-request-transaction-group.ts diff --git a/packages/typescript/algod_client/src/models/simulaterequest.ts b/packages/typescript/algod_client/src/models/simulate-request.ts similarity index 100% rename from packages/typescript/algod_client/src/models/simulaterequest.ts rename to packages/typescript/algod_client/src/models/simulate-request.ts diff --git a/packages/typescript/algod_client/src/models/simulatetraceconfig.ts b/packages/typescript/algod_client/src/models/simulate-trace-config.ts similarity index 100% rename from packages/typescript/algod_client/src/models/simulatetraceconfig.ts rename to packages/typescript/algod_client/src/models/simulate-trace-config.ts diff --git a/packages/typescript/algod_client/src/models/simulatetransactiongroupresult.ts b/packages/typescript/algod_client/src/models/simulate-transaction-group-result.ts similarity index 100% rename from packages/typescript/algod_client/src/models/simulatetransactiongroupresult.ts rename to packages/typescript/algod_client/src/models/simulate-transaction-group-result.ts diff --git a/packages/typescript/algod_client/src/models/simulatetransactionresult.ts b/packages/typescript/algod_client/src/models/simulate-transaction-result.ts similarity index 100% rename from packages/typescript/algod_client/src/models/simulatetransactionresult.ts rename to packages/typescript/algod_client/src/models/simulate-transaction-result.ts diff --git a/packages/typescript/algod_client/src/models/simulatetransaction.ts b/packages/typescript/algod_client/src/models/simulate-transaction.ts similarity index 100% rename from packages/typescript/algod_client/src/models/simulatetransaction.ts rename to packages/typescript/algod_client/src/models/simulate-transaction.ts diff --git a/packages/typescript/algod_client/src/models/simulateunnamedresourcesaccessed.ts b/packages/typescript/algod_client/src/models/simulate-unnamed-resources-accessed.ts similarity index 100% rename from packages/typescript/algod_client/src/models/simulateunnamedresourcesaccessed.ts rename to packages/typescript/algod_client/src/models/simulate-unnamed-resources-accessed.ts diff --git a/packages/typescript/algod_client/src/models/simulationevaloverrides.ts b/packages/typescript/algod_client/src/models/simulation-eval-overrides.ts similarity index 100% rename from packages/typescript/algod_client/src/models/simulationevaloverrides.ts rename to packages/typescript/algod_client/src/models/simulation-eval-overrides.ts diff --git a/packages/typescript/algod_client/src/models/simulationopcodetraceunit.ts b/packages/typescript/algod_client/src/models/simulation-opcode-trace-unit.ts similarity index 100% rename from packages/typescript/algod_client/src/models/simulationopcodetraceunit.ts rename to packages/typescript/algod_client/src/models/simulation-opcode-trace-unit.ts diff --git a/packages/typescript/algod_client/src/models/simulationtransactionexectrace.ts b/packages/typescript/algod_client/src/models/simulation-transaction-exec-trace.ts similarity index 100% rename from packages/typescript/algod_client/src/models/simulationtransactionexectrace.ts rename to packages/typescript/algod_client/src/models/simulation-transaction-exec-trace.ts diff --git a/packages/typescript/algod_client/src/models/startcatchup.ts b/packages/typescript/algod_client/src/models/start-catchup.ts similarity index 100% rename from packages/typescript/algod_client/src/models/startcatchup.ts rename to packages/typescript/algod_client/src/models/start-catchup.ts diff --git a/packages/typescript/algod_client/src/models/statedelta.ts b/packages/typescript/algod_client/src/models/state-delta.ts similarity index 100% rename from packages/typescript/algod_client/src/models/statedelta.ts rename to packages/typescript/algod_client/src/models/state-delta.ts diff --git a/packages/typescript/algod_client/src/models/stateproofmessage.ts b/packages/typescript/algod_client/src/models/state-proof-message.ts similarity index 100% rename from packages/typescript/algod_client/src/models/stateproofmessage.ts rename to packages/typescript/algod_client/src/models/state-proof-message.ts diff --git a/packages/typescript/algod_client/src/models/stateproof.ts b/packages/typescript/algod_client/src/models/state-proof.ts similarity index 100% rename from packages/typescript/algod_client/src/models/stateproof.ts rename to packages/typescript/algod_client/src/models/state-proof.ts diff --git a/packages/typescript/algod_client/src/models/tealcompile.ts b/packages/typescript/algod_client/src/models/teal-compile.ts similarity index 100% rename from packages/typescript/algod_client/src/models/tealcompile.ts rename to packages/typescript/algod_client/src/models/teal-compile.ts diff --git a/packages/typescript/algod_client/src/models/tealdisassemble.ts b/packages/typescript/algod_client/src/models/teal-disassemble.ts similarity index 100% rename from packages/typescript/algod_client/src/models/tealdisassemble.ts rename to packages/typescript/algod_client/src/models/teal-disassemble.ts diff --git a/packages/typescript/algod_client/src/models/tealdryrun.ts b/packages/typescript/algod_client/src/models/teal-dryrun.ts similarity index 100% rename from packages/typescript/algod_client/src/models/tealdryrun.ts rename to packages/typescript/algod_client/src/models/teal-dryrun.ts diff --git a/packages/typescript/algod_client/src/models/tealkeyvaluestore.ts b/packages/typescript/algod_client/src/models/teal-key-value-store.ts similarity index 100% rename from packages/typescript/algod_client/src/models/tealkeyvaluestore.ts rename to packages/typescript/algod_client/src/models/teal-key-value-store.ts diff --git a/packages/typescript/algod_client/src/models/tealkeyvalue.ts b/packages/typescript/algod_client/src/models/teal-key-value.ts similarity index 100% rename from packages/typescript/algod_client/src/models/tealkeyvalue.ts rename to packages/typescript/algod_client/src/models/teal-key-value.ts diff --git a/packages/typescript/algod_client/src/models/tealvalue.ts b/packages/typescript/algod_client/src/models/teal-value.ts similarity index 100% rename from packages/typescript/algod_client/src/models/tealvalue.ts rename to packages/typescript/algod_client/src/models/teal-value.ts diff --git a/packages/typescript/algod_client/src/models/transactionparams.ts b/packages/typescript/algod_client/src/models/transaction-params.ts similarity index 100% rename from packages/typescript/algod_client/src/models/transactionparams.ts rename to packages/typescript/algod_client/src/models/transaction-params.ts diff --git a/packages/typescript/algod_client/src/models/transactionproof.ts b/packages/typescript/algod_client/src/models/transaction-proof.ts similarity index 100% rename from packages/typescript/algod_client/src/models/transactionproof.ts rename to packages/typescript/algod_client/src/models/transaction-proof.ts diff --git a/packages/typescript/algod_client/src/models/waitforblock.ts b/packages/typescript/algod_client/src/models/wait-for-block.ts similarity index 100% rename from packages/typescript/algod_client/src/models/waitforblock.ts rename to packages/typescript/algod_client/src/models/wait-for-block.ts diff --git a/packages/typescript/indexer_client/bun.lock b/packages/typescript/indexer_client/bun.lock index b0815b8bf..a0b6bff86 100644 --- a/packages/typescript/indexer_client/bun.lock +++ b/packages/typescript/indexer_client/bun.lock @@ -68,57 +68,59 @@ "@msgpack/msgpack": ["@msgpack/msgpack@3.1.2", "", {}, "sha512-JEW4DEtBzfe8HvUYecLU9e6+XJnKDlUAIve8FvPzF3Kzs6Xo/KuZkZJsDH0wJXl/qEZbeeE7edxDNY3kMs39hQ=="], - "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.50.1", "", { "os": "android", "cpu": "arm" }, "sha512-HJXwzoZN4eYTdD8bVV22DN8gsPCAj3V20NHKOs8ezfXanGpmVPR7kalUHd+Y31IJp9stdB87VKPFbsGY3H/2ag=="], + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.52.0", "", { "os": "android", "cpu": "arm" }, "sha512-VxDYCDqOaR7NXzAtvRx7G1u54d2kEHopb28YH/pKzY6y0qmogP3gG7CSiWsq9WvDFxOQMpNEyjVAHZFXfH3o/A=="], - "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.50.1", "", { "os": "android", "cpu": "arm64" }, "sha512-PZlsJVcjHfcH53mOImyt3bc97Ep3FJDXRpk9sMdGX0qgLmY0EIWxCag6EigerGhLVuL8lDVYNnSo8qnTElO4xw=="], + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.52.0", "", { "os": "android", "cpu": "arm64" }, "sha512-pqDirm8koABIKvzL59YI9W9DWbRlTX7RWhN+auR8HXJxo89m4mjqbah7nJZjeKNTNYopqL+yGg+0mhCpf3xZtQ=="], - "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.50.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-xc6i2AuWh++oGi4ylOFPmzJOEeAa2lJeGUGb4MudOtgfyyjr4UPNK+eEWTPLvmPJIY/pgw6ssFIox23SyrkkJw=="], + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.52.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-YCdWlY/8ltN6H78HnMsRHYlPiKvqKagBP1r+D7SSylxX+HnsgXGCmLiV3Y4nSyY9hW8qr8U9LDUx/Lo7M6MfmQ=="], - "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.50.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-2ofU89lEpDYhdLAbRdeyz/kX3Y2lpYc6ShRnDjY35bZhd2ipuDMDi6ZTQ9NIag94K28nFMofdnKeHR7BT0CATw=="], + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.52.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-z4nw6y1j+OOSGzuVbSWdIp1IUks9qNw4dc7z7lWuWDKojY38VMWBlEN7F9jk5UXOkUcp97vA1N213DF+Lz8BRg=="], - "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.50.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-wOsE6H2u6PxsHY/BeFHA4VGQN3KUJFZp7QJBmDYI983fgxq5Th8FDkVuERb2l9vDMs1D5XhOrhBrnqcEY6l8ZA=="], + "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.52.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-Q/dv9Yvyr5rKlK8WQJZVrp5g2SOYeZUs9u/t2f9cQ2E0gJjYB/BWoedXfUT0EcDJefi2zzVfhcOj8drWCzTviw=="], - "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.50.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-A/xeqaHTlKbQggxCqispFAcNjycpUEHP52mwMQZUNqDUJFFYtPHCXS1VAG29uMlDzIVr+i00tSFWFLivMcoIBQ=="], + "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.52.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-kdBsLs4Uile/fbjZVvCRcKB4q64R+1mUq0Yd7oU1CMm1Av336ajIFqNFovByipciuUQjBCPMxwJhCgfG2re3rg=="], - "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.50.1", "", { "os": "linux", "cpu": "arm" }, "sha512-54v4okehwl5TaSIkpp97rAHGp7t3ghinRd/vyC1iXqXMfjYUTm7TfYmCzXDoHUPTTf36L8pr0E7YsD3CfB3ZDg=="], + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.52.0", "", { "os": "linux", "cpu": "arm" }, "sha512-aL6hRwu0k7MTUESgkg7QHY6CoqPgr6gdQXRJI1/VbFlUMwsSzPGSR7sG5d+MCbYnJmJwThc2ol3nixj1fvI/zQ=="], - "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.50.1", "", { "os": "linux", "cpu": "arm" }, "sha512-p/LaFyajPN/0PUHjv8TNyxLiA7RwmDoVY3flXHPSzqrGcIp/c2FjwPPP5++u87DGHtw+5kSH5bCJz0mvXngYxw=="], + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.52.0", "", { "os": "linux", "cpu": "arm" }, "sha512-BTs0M5s1EJejgIBJhCeiFo7GZZ2IXWkFGcyZhxX4+8usnIo5Mti57108vjXFIQmmJaRyDwmV59Tw64Ap1dkwMw=="], - "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.50.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-2AbMhFFkTo6Ptna1zO7kAXXDLi7H9fGTbVaIq2AAYO7yzcAsuTNWPHhb2aTA6GPiP+JXh85Y8CiS54iZoj4opw=="], + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.52.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-uj672IVOU9m08DBGvoPKPi/J8jlVgjh12C9GmjjBxCTQc3XtVmRkRKyeHSmIKQpvJ7fIm1EJieBUcnGSzDVFyw=="], - "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.50.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-Cgef+5aZwuvesQNw9eX7g19FfKX5/pQRIyhoXLCiBOrWopjo7ycfB292TX9MDcDijiuIJlx1IzJz3IoCPfqs9w=="], + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.52.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-/+IVbeDMDCtB/HP/wiWsSzduD10SEGzIZX2945KSgZRNi4TSkjHqRJtNTVtVb8IRwhJ65ssI56krlLik+zFWkw=="], - "@rollup/rollup-linux-loongarch64-gnu": ["@rollup/rollup-linux-loongarch64-gnu@4.50.1", "", { "os": "linux", "cpu": "none" }, "sha512-RPhTwWMzpYYrHrJAS7CmpdtHNKtt2Ueo+BlLBjfZEhYBhK00OsEqM08/7f+eohiF6poe0YRDDd8nAvwtE/Y62Q=="], + "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.52.0", "", { "os": "linux", "cpu": "none" }, "sha512-U1vVzvSWtSMWKKrGoROPBXMh3Vwn93TA9V35PldokHGqiUbF6erSzox/5qrSMKp6SzakvyjcPiVF8yB1xKr9Pg=="], - "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.50.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-eSGMVQw9iekut62O7eBdbiccRguuDgiPMsw++BVUg+1K7WjZXHOg/YOT9SWMzPZA+w98G+Fa1VqJgHZOHHnY0Q=="], + "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.52.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-X/4WfuBAdQRH8cK3DYl8zC00XEE6aM472W+QCycpQJeLWVnHfkv7RyBFVaTqNUMsTgIX8ihMjCvFF9OUgeABzw=="], - "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.50.1", "", { "os": "linux", "cpu": "none" }, "sha512-S208ojx8a4ciIPrLgazF6AgdcNJzQE4+S9rsmOmDJkusvctii+ZvEuIC4v/xFqzbuP8yDjn73oBlNDgF6YGSXQ=="], + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.52.0", "", { "os": "linux", "cpu": "none" }, "sha512-xIRYc58HfWDBZoLmWfWXg2Sq8VCa2iJ32B7mqfWnkx5mekekl0tMe7FHpY8I72RXEcUkaWawRvl3qA55og+cwQ=="], - "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.50.1", "", { "os": "linux", "cpu": "none" }, "sha512-3Ag8Ls1ggqkGUvSZWYcdgFwriy2lWo+0QlYgEFra/5JGtAd6C5Hw59oojx1DeqcA2Wds2ayRgvJ4qxVTzCHgzg=="], + "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.52.0", "", { "os": "linux", "cpu": "none" }, "sha512-mbsoUey05WJIOz8U1WzNdf+6UMYGwE3fZZnQqsM22FZ3wh1N887HT6jAOjXs6CNEK3Ntu2OBsyQDXfIjouI4dw=="], - "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.50.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-t9YrKfaxCYe7l7ldFERE1BRg/4TATxIg+YieHQ966jwvo7ddHJxPj9cNFWLAzhkVsbBvNA4qTbPVNsZKBO4NSg=="], + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.52.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-qP6aP970bucEi5KKKR4AuPFd8aTx9EF6BvutvYxmZuWLJHmnq4LvBfp0U+yFDMGwJ+AIJEH5sIP+SNypauMWzg=="], - "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.50.1", "", { "os": "linux", "cpu": "x64" }, "sha512-MCgtFB2+SVNuQmmjHf+wfI4CMxy3Tk8XjA5Z//A0AKD7QXUYFMQcns91K6dEHBvZPCnhJSyDWLApk40Iq/H3tA=="], + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.52.0", "", { "os": "linux", "cpu": "x64" }, "sha512-nmSVN+F2i1yKZ7rJNKO3G7ZzmxJgoQBQZ/6c4MuS553Grmr7WqR7LLDcYG53Z2m9409z3JLt4sCOhLdbKQ3HmA=="], - "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.50.1", "", { "os": "linux", "cpu": "x64" }, "sha512-nEvqG+0jeRmqaUMuwzlfMKwcIVffy/9KGbAGyoa26iu6eSngAYQ512bMXuqqPrlTyfqdlB9FVINs93j534UJrg=="], + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.52.0", "", { "os": "linux", "cpu": "x64" }, "sha512-2d0qRo33G6TfQVjaMR71P+yJVGODrt5V6+T0BDYH4EMfGgdC/2HWDVjSSFw888GSzAZUwuska3+zxNUCDco6rQ=="], - "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.50.1", "", { "os": "none", "cpu": "arm64" }, "sha512-RDsLm+phmT3MJd9SNxA9MNuEAO/J2fhW8GXk62G/B4G7sLVumNFbRwDL6v5NrESb48k+QMqdGbHgEtfU0LCpbA=="], + "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.52.0", "", { "os": "none", "cpu": "arm64" }, "sha512-A1JalX4MOaFAAyGgpO7XP5khquv/7xKzLIyLmhNrbiCxWpMlnsTYr8dnsWM7sEeotNmxvSOEL7F65j0HXFcFsw=="], - "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.50.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-hpZB/TImk2FlAFAIsoElM3tLzq57uxnGYwplg6WDyAxbYczSi8O2eQ+H2Lx74504rwKtZ3N2g4bCUkiamzS6TQ=="], + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.52.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-YQugafP/rH0eOOHGjmNgDURrpYHrIX0yuojOI8bwCyXwxC9ZdTd3vYkmddPX0oHONLXu9Rb1dDmT0VNpjkzGGw=="], - "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.50.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-SXjv8JlbzKM0fTJidX4eVsH+Wmnp0/WcD8gJxIZyR6Gay5Qcsmdbi9zVtnbkGPG8v2vMR1AD06lGWy5FLMcG7A=="], + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.52.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-zYdUYhi3Qe2fndujBqL5FjAFzvNeLxtIqfzNEVKD1I7C37/chv1VxhscWSQHTNfjPCrBFQMnynwA3kpZpZ8w4A=="], - "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.50.1", "", { "os": "win32", "cpu": "x64" }, "sha512-StxAO/8ts62KZVRAm4JZYq9+NqNsV7RvimNK+YM7ry//zebEH6meuugqW/P5OFUCjyQgui+9fUxT6d5NShvMvA=="], + "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.52.0", "", { "os": "win32", "cpu": "x64" }, "sha512-fGk03kQylNaCOQ96HDMeT7E2n91EqvCDd3RwvT5k+xNdFCeMGnj5b5hEgTGrQuyidqSsD3zJDQ21QIaxXqTBJw=="], - "@types/bun": ["@types/bun@1.2.21", "", { "dependencies": { "bun-types": "1.2.21" } }, "sha512-NiDnvEqmbfQ6dmZ3EeUO577s4P5bf4HCTXtI6trMc6f6RzirY5IrF3aIookuSpyslFzrnvv2lmEWv5HyC1X79A=="], + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.52.0", "", { "os": "win32", "cpu": "x64" }, "sha512-6iKDCVSIUQ8jPMoIV0OytRKniaYyy5EbY/RRydmLW8ZR3cEBhxbWl5ro0rkUNe0ef6sScvhbY79HrjRm8i3vDQ=="], + + "@types/bun": ["@types/bun@1.2.22", "", { "dependencies": { "bun-types": "1.2.22" } }, "sha512-5A/KrKos2ZcN0c6ljRSOa1fYIyCKhZfIVYeuyb4snnvomnpFqC0tTsEkdqNxbAgExV384OETQ//WAjl3XbYqQA=="], "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], "@types/json-bigint": ["@types/json-bigint@1.0.4", "", {}, "sha512-ydHooXLbOmxBbubnA7Eh+RpBzuaIiQjh8WGJYQB50JFGFrdxW7JzVlyEV7fAXw0T2sqJ1ysTneJbiyNLqZRAag=="], - "@types/node": ["@types/node@20.19.13", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-yCAeZl7a0DxgNVteXFHt9+uyFbqXGy/ShC4BlcHkoE0AfGXYv/BUiplV72DjMYXHDBXFjhvr6DD1NiRVfB4j8g=="], + "@types/node": ["@types/node@20.19.17", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-gfehUI8N1z92kygssiuWvLiwcbOB3IRktR6hTDgJlXMYh5OvkPSRmgfoBUmfZt+vhwJtX7v1Yw4KvvAf7c5QKQ=="], - "@types/react": ["@types/react@19.1.12", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-cMoR+FoAf/Jyq6+Df2/Z41jISvGZZ2eTlnsaJRptmZ76Caldwy1odD4xTr/gNV9VLj0AWgg/nmkevIyUfIIq5w=="], + "@types/react": ["@types/react@19.1.13", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-hHkbU/eoO3EG5/MZkuFSKmYqPbSVk5byPFa3e7y/8TybHiLMACgI8seVYlicwk7H5K/rI2px9xrQp/C+AUDTiQ=="], "@vitest/expect": ["@vitest/expect@2.1.9", "", { "dependencies": { "@vitest/spy": "2.1.9", "@vitest/utils": "2.1.9", "chai": "^5.1.2", "tinyrainbow": "^1.2.0" } }, "sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw=="], @@ -136,13 +138,13 @@ "algorand-msgpack": ["algorand-msgpack@1.1.0", "", {}, "sha512-08k7pBQnkaUB5p+jL7f1TRaUIlTSDE0cesFu1mD7llLao+1cAhtvvZmGE3OnisTd0xOn118QMw74SRqddqaYvw=="], - "algosdk": ["algosdk@3.4.0", "", { "dependencies": { "algorand-msgpack": "^1.1.0", "hi-base32": "^0.5.1", "js-sha256": "^0.9.0", "js-sha3": "^0.8.0", "js-sha512": "^0.8.0", "json-bigint": "^1.0.0", "tweetnacl": "^1.0.3", "vlq": "^2.0.4" } }, "sha512-95NYlVxMsHKs9gV8/hUvNTRAqmRC55wtesGR53j37fjP/sHUWd1gxNGTNBy0d1+o4jDKxVaasVgUHh78IqgtCw=="], + "algosdk": ["algosdk@3.5.0", "", { "dependencies": { "algorand-msgpack": "^1.1.0", "hi-base32": "^0.5.1", "js-sha256": "^0.9.0", "js-sha3": "^0.8.0", "js-sha512": "^0.8.0", "json-bigint": "^1.0.0", "tweetnacl": "^1.0.3", "vlq": "^2.0.4" } }, "sha512-9Q6lKAbl5Zz0VKjAMC7OYpnpDqmK/qa5LOALKxcF/jBs5k309lMezFC3ka0dSXPq64IKsUzhShSdOZrwYfr7tA=="], "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="], "bignumber.js": ["bignumber.js@9.3.1", "", {}, "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ=="], - "bun-types": ["bun-types@1.2.21", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-sa2Tj77Ijc/NTLS0/Odjq/qngmEPZfbfnOERi0KRUYhT9R8M4VBioWVmMWE5GrYbKMc+5lVybXygLdibHaqVqw=="], + "bun-types": ["bun-types@1.2.22", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-hwaAu8tct/Zn6Zft4U9BsZcXkYomzpHJX28ofvx7k0Zz2HNz54n1n+tDgxoWFGB4PcFvJXJQloPhaV2eP3Q6EA=="], "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="], @@ -152,7 +154,7 @@ "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], - "debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], + "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], "deep-eql": ["deep-eql@5.0.2", "", {}, "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q=="], @@ -192,7 +194,7 @@ "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], - "rollup": ["rollup@4.50.1", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.50.1", "@rollup/rollup-android-arm64": "4.50.1", "@rollup/rollup-darwin-arm64": "4.50.1", "@rollup/rollup-darwin-x64": "4.50.1", "@rollup/rollup-freebsd-arm64": "4.50.1", "@rollup/rollup-freebsd-x64": "4.50.1", "@rollup/rollup-linux-arm-gnueabihf": "4.50.1", "@rollup/rollup-linux-arm-musleabihf": "4.50.1", "@rollup/rollup-linux-arm64-gnu": "4.50.1", "@rollup/rollup-linux-arm64-musl": "4.50.1", "@rollup/rollup-linux-loongarch64-gnu": "4.50.1", "@rollup/rollup-linux-ppc64-gnu": "4.50.1", "@rollup/rollup-linux-riscv64-gnu": "4.50.1", "@rollup/rollup-linux-riscv64-musl": "4.50.1", "@rollup/rollup-linux-s390x-gnu": "4.50.1", "@rollup/rollup-linux-x64-gnu": "4.50.1", "@rollup/rollup-linux-x64-musl": "4.50.1", "@rollup/rollup-openharmony-arm64": "4.50.1", "@rollup/rollup-win32-arm64-msvc": "4.50.1", "@rollup/rollup-win32-ia32-msvc": "4.50.1", "@rollup/rollup-win32-x64-msvc": "4.50.1", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-78E9voJHwnXQMiQdiqswVLZwJIzdBKJ1GdI5Zx6XwoFKUIk09/sSrr+05QFzvYb8q6Y9pPV45zzDuYa3907TZA=="], + "rollup": ["rollup@4.52.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.52.0", "@rollup/rollup-android-arm64": "4.52.0", "@rollup/rollup-darwin-arm64": "4.52.0", "@rollup/rollup-darwin-x64": "4.52.0", "@rollup/rollup-freebsd-arm64": "4.52.0", "@rollup/rollup-freebsd-x64": "4.52.0", "@rollup/rollup-linux-arm-gnueabihf": "4.52.0", "@rollup/rollup-linux-arm-musleabihf": "4.52.0", "@rollup/rollup-linux-arm64-gnu": "4.52.0", "@rollup/rollup-linux-arm64-musl": "4.52.0", "@rollup/rollup-linux-loong64-gnu": "4.52.0", "@rollup/rollup-linux-ppc64-gnu": "4.52.0", "@rollup/rollup-linux-riscv64-gnu": "4.52.0", "@rollup/rollup-linux-riscv64-musl": "4.52.0", "@rollup/rollup-linux-s390x-gnu": "4.52.0", "@rollup/rollup-linux-x64-gnu": "4.52.0", "@rollup/rollup-linux-x64-musl": "4.52.0", "@rollup/rollup-openharmony-arm64": "4.52.0", "@rollup/rollup-win32-arm64-msvc": "4.52.0", "@rollup/rollup-win32-ia32-msvc": "4.52.0", "@rollup/rollup-win32-x64-gnu": "4.52.0", "@rollup/rollup-win32-x64-msvc": "4.52.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-+IuescNkTJQgX7AkIDtITipZdIGcWF0pnVvZTWStiazUmcGA2ag8dfg0urest2XlXUi9kuhfQ+qmdc5Stc3z7g=="], "siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="], diff --git a/packages/typescript/indexer_client/src/core/casing.ts b/packages/typescript/indexer_client/src/core/casing.ts index 7ad409bd5..724bfac1f 100644 --- a/packages/typescript/indexer_client/src/core/casing.ts +++ b/packages/typescript/indexer_client/src/core/casing.ts @@ -1,4 +1,8 @@ +import { CANONICAL_CAMEL_TO_WIRE, WIRE_TO_CANONICAL } from "./rename-map"; + function toCamel(segmented: string): string { + const override = WIRE_TO_CANONICAL[segmented]; + if (override) segmented = override; if (!segmented) return segmented; // Fast path: if no hyphen, return as-is but ensure typical camel conversion for underscores if (!segmented.includes("-")) return segmented.replace(/_([a-z0-9])/g, (_, c) => c.toUpperCase()); @@ -9,6 +13,8 @@ function toCamel(segmented: string): string { } function toKebab(camel: string): string { + const override = CANONICAL_CAMEL_TO_WIRE[camel]; + if (override) return override; if (!camel) return camel; // Convert camelCase or mixedCase to kebab-case; leave existing hyphens and numbers intact return camel diff --git a/packages/typescript/indexer_client/src/core/codecs.ts b/packages/typescript/indexer_client/src/core/codecs.ts new file mode 100644 index 000000000..27ec22973 --- /dev/null +++ b/packages/typescript/indexer_client/src/core/codecs.ts @@ -0,0 +1,87 @@ +// Temporary copy of codec helpers from utils-ts until the shared core moves into the monorepo. +// These keep the generated clients self-contained and ready for future DTO <-> domain mappers. + +export abstract class Codec { + public abstract defaultValue(): TEncoded; + + protected toEncoded(value: T): TEncoded { + return value as unknown as TEncoded; + } + + protected fromEncoded(value: TEncoded): T { + return value as unknown as T; + } + + protected isDefaultValue(value: T): boolean { + return this.toEncoded(value) === this.defaultValue(); + } + + public encode(value?: T): TEncoded | undefined { + return value !== undefined && !this.isDefaultValue(value) ? this.toEncoded(value) : undefined; + } + + public decode(value: TEncoded | undefined): T { + return this.fromEncoded(value ?? this.defaultValue()); + } + + public decodeOptional(value: TEncoded | undefined): T | undefined { + if (value === undefined) { + return undefined; + } + return this.fromEncoded(value); + } +} + +export class NumberCodec extends Codec { + public defaultValue(): number { + return 0; + } +} + +export class BigIntCodec extends Codec { + public defaultValue(): bigint { + return 0n; + } + + protected fromEncoded(value: number | bigint): bigint { + return typeof value === "bigint" ? value : BigInt(value); + } +} + +export class StringCodec extends Codec { + public defaultValue(): string { + return ""; + } +} + +export class BytesCodec extends Codec { + public defaultValue(): Uint8Array { + return new Uint8Array(); + } + + protected isDefaultValue(value: Uint8Array): boolean { + return value.byteLength === 0; + } +} + +export class BooleanCodec extends Codec { + public defaultValue(): boolean { + return false; + } +} + +export class OmitEmptyObjectCodec extends Codec { + public defaultValue(): T | undefined { + return undefined; + } + + protected isDefaultValue(value: T): boolean { + return Object.values(value).filter((x) => x !== undefined).length === 0; + } +} + +export const numberCodec = new NumberCodec(); +export const bigIntCodec = new BigIntCodec(); +export const stringCodec = new StringCodec(); +export const bytesCodec = new BytesCodec(); +export const booleanCodec = new BooleanCodec(); diff --git a/packages/typescript/indexer_client/src/core/rename-map.ts b/packages/typescript/indexer_client/src/core/rename-map.ts new file mode 100644 index 000000000..a138a01c3 --- /dev/null +++ b/packages/typescript/indexer_client/src/core/rename-map.ts @@ -0,0 +1,7 @@ +/* Auto-generated rename hints derived from OpenAPI vendor extensions. */ + +export const WIRE_TO_CANONICAL: Record = {}; + +export const CANONICAL_CAMEL_TO_WIRE: Record = {}; + +export const HAS_RENAME_HINTS = Object.keys(WIRE_TO_CANONICAL).length > 0; diff --git a/packages/typescript/indexer_client/src/models/accountparticipation.ts b/packages/typescript/indexer_client/src/models/account-participation.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/accountparticipation.ts rename to packages/typescript/indexer_client/src/models/account-participation.ts diff --git a/packages/typescript/indexer_client/src/models/accountstatedelta.ts b/packages/typescript/indexer_client/src/models/account-state-delta.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/accountstatedelta.ts rename to packages/typescript/indexer_client/src/models/account-state-delta.ts diff --git a/packages/typescript/indexer_client/src/models/applicationlocalstate.ts b/packages/typescript/indexer_client/src/models/application-local-state.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/applicationlocalstate.ts rename to packages/typescript/indexer_client/src/models/application-local-state.ts diff --git a/packages/typescript/indexer_client/src/models/applicationlogdata.ts b/packages/typescript/indexer_client/src/models/application-log-data.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/applicationlogdata.ts rename to packages/typescript/indexer_client/src/models/application-log-data.ts diff --git a/packages/typescript/indexer_client/src/models/applicationparams.ts b/packages/typescript/indexer_client/src/models/application-params.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/applicationparams.ts rename to packages/typescript/indexer_client/src/models/application-params.ts diff --git a/packages/typescript/indexer_client/src/models/applicationstateschema.ts b/packages/typescript/indexer_client/src/models/application-state-schema.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/applicationstateschema.ts rename to packages/typescript/indexer_client/src/models/application-state-schema.ts diff --git a/packages/typescript/indexer_client/src/models/assetholding.ts b/packages/typescript/indexer_client/src/models/asset-holding.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/assetholding.ts rename to packages/typescript/indexer_client/src/models/asset-holding.ts diff --git a/packages/typescript/indexer_client/src/models/assetparams.ts b/packages/typescript/indexer_client/src/models/asset-params.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/assetparams.ts rename to packages/typescript/indexer_client/src/models/asset-params.ts diff --git a/packages/typescript/indexer_client/src/models/blockrewards.ts b/packages/typescript/indexer_client/src/models/block-rewards.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/blockrewards.ts rename to packages/typescript/indexer_client/src/models/block-rewards.ts diff --git a/packages/typescript/indexer_client/src/models/blockupgradestate.ts b/packages/typescript/indexer_client/src/models/block-upgrade-state.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/blockupgradestate.ts rename to packages/typescript/indexer_client/src/models/block-upgrade-state.ts diff --git a/packages/typescript/indexer_client/src/models/blockupgradevote.ts b/packages/typescript/indexer_client/src/models/block-upgrade-vote.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/blockupgradevote.ts rename to packages/typescript/indexer_client/src/models/block-upgrade-vote.ts diff --git a/packages/typescript/indexer_client/src/models/boxdescriptor.ts b/packages/typescript/indexer_client/src/models/box-descriptor.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/boxdescriptor.ts rename to packages/typescript/indexer_client/src/models/box-descriptor.ts diff --git a/packages/typescript/indexer_client/src/models/boxreference.ts b/packages/typescript/indexer_client/src/models/box-reference.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/boxreference.ts rename to packages/typescript/indexer_client/src/models/box-reference.ts diff --git a/packages/typescript/indexer_client/src/models/evaldeltakeyvalue.ts b/packages/typescript/indexer_client/src/models/eval-delta-key-value.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/evaldeltakeyvalue.ts rename to packages/typescript/indexer_client/src/models/eval-delta-key-value.ts diff --git a/packages/typescript/indexer_client/src/models/evaldelta.ts b/packages/typescript/indexer_client/src/models/eval-delta.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/evaldelta.ts rename to packages/typescript/indexer_client/src/models/eval-delta.ts diff --git a/packages/typescript/indexer_client/src/models/hashfactory.ts b/packages/typescript/indexer_client/src/models/hash-factory.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/hashfactory.ts rename to packages/typescript/indexer_client/src/models/hash-factory.ts diff --git a/packages/typescript/indexer_client/src/models/hbprooffields.ts b/packages/typescript/indexer_client/src/models/hb-proof-fields.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/hbprooffields.ts rename to packages/typescript/indexer_client/src/models/hb-proof-fields.ts diff --git a/packages/typescript/indexer_client/src/models/healthcheck.ts b/packages/typescript/indexer_client/src/models/health-check.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/healthcheck.ts rename to packages/typescript/indexer_client/src/models/health-check.ts diff --git a/packages/typescript/indexer_client/src/models/index.ts b/packages/typescript/indexer_client/src/models/index.ts index a9918c6f4..53ffc03b1 100644 --- a/packages/typescript/indexer_client/src/models/index.ts +++ b/packages/typescript/indexer_client/src/models/index.ts @@ -1,75 +1,75 @@ // Barrel file for models export type { Hashtype } from "./hashtype"; export type { Account } from "./account"; -export type { AccountParticipation } from "./accountparticipation"; -export type { ApplicationStateSchema } from "./applicationstateschema"; -export type { ApplicationLocalState } from "./applicationlocalstate"; -export type { TealKeyValueStore } from "./tealkeyvaluestore"; -export type { TealKeyValue } from "./tealkeyvalue"; -export type { TealValue } from "./tealvalue"; +export type { AccountParticipation } from "./account-participation"; +export type { ApplicationStateSchema } from "./application-state-schema"; +export type { ApplicationLocalState } from "./application-local-state"; +export type { TealKeyValueStore } from "./teal-key-value-store"; +export type { TealKeyValue } from "./teal-key-value"; +export type { TealValue } from "./teal-value"; export type { Application } from "./application"; -export type { ApplicationParams } from "./applicationparams"; -export type { ApplicationLogData } from "./applicationlogdata"; +export type { ApplicationParams } from "./application-params"; +export type { ApplicationLogData } from "./application-log-data"; export type { Asset } from "./asset"; -export type { AssetHolding } from "./assetholding"; -export type { AssetParams } from "./assetparams"; +export type { AssetHolding } from "./asset-holding"; +export type { AssetParams } from "./asset-params"; export type { Block } from "./block"; -export type { BlockRewards } from "./blockrewards"; -export type { BlockUpgradeState } from "./blockupgradestate"; -export type { BlockUpgradeVote } from "./blockupgradevote"; +export type { BlockRewards } from "./block-rewards"; +export type { BlockUpgradeState } from "./block-upgrade-state"; +export type { BlockUpgradeVote } from "./block-upgrade-vote"; export type { Box } from "./box"; -export type { BoxDescriptor } from "./boxdescriptor"; -export type { BoxReference } from "./boxreference"; -export type { HealthCheck } from "./healthcheck"; -export type { MiniAssetHolding } from "./miniassetholding"; -export type { OnCompletion } from "./oncompletion"; -export type { ParticipationUpdates } from "./participationupdates"; -export type { StateDelta } from "./statedelta"; -export type { AccountStateDelta } from "./accountstatedelta"; -export type { EvalDeltaKeyValue } from "./evaldeltakeyvalue"; -export type { EvalDelta } from "./evaldelta"; -export type { StateSchema } from "./stateschema"; +export type { BoxDescriptor } from "./box-descriptor"; +export type { BoxReference } from "./box-reference"; +export type { HealthCheck } from "./health-check"; +export type { MiniAssetHolding } from "./mini-asset-holding"; +export type { OnCompletion } from "./on-completion"; +export type { ParticipationUpdates } from "./participation-updates"; +export type { StateDelta } from "./state-delta"; +export type { AccountStateDelta } from "./account-state-delta"; +export type { EvalDeltaKeyValue } from "./eval-delta-key-value"; +export type { EvalDelta } from "./eval-delta"; +export type { StateSchema } from "./state-schema"; export type { Transaction } from "./transaction"; -export type { TransactionApplication } from "./transactionapplication"; -export type { TransactionAssetConfig } from "./transactionassetconfig"; -export type { TransactionAssetFreeze } from "./transactionassetfreeze"; -export type { TransactionStateProof } from "./transactionstateproof"; -export type { TransactionHeartbeat } from "./transactionheartbeat"; -export type { TransactionAssetTransfer } from "./transactionassettransfer"; -export type { TransactionKeyreg } from "./transactionkeyreg"; -export type { TransactionPayment } from "./transactionpayment"; -export type { TransactionSignature } from "./transactionsignature"; -export type { TransactionSignatureLogicsig } from "./transactionsignaturelogicsig"; -export type { TransactionSignatureMultisig } from "./transactionsignaturemultisig"; -export type { TransactionSignatureMultisigSubsignature } from "./transactionsignaturemultisigsubsignature"; -export type { StateProofFields } from "./stateprooffields"; -export type { HbProofFields } from "./hbprooffields"; -export type { IndexerStateProofMessage } from "./indexerstateproofmessage"; -export type { StateProofReveal } from "./stateproofreveal"; -export type { StateProofSigSlot } from "./stateproofsigslot"; -export type { StateProofSignature } from "./stateproofsignature"; -export type { StateProofParticipant } from "./stateproofparticipant"; -export type { StateProofVerifier } from "./stateproofverifier"; -export type { StateProofTracking } from "./stateprooftracking"; -export type { MerkleArrayProof } from "./merklearrayproof"; -export type { HashFactory } from "./hashfactory"; -export type { SearchForAccounts } from "./searchforaccounts"; -export type { LookupAccountById } from "./lookupaccountbyid"; -export type { LookupAccountAssets } from "./lookupaccountassets"; -export type { LookupAccountCreatedAssets } from "./lookupaccountcreatedassets"; -export type { LookupAccountAppLocalStates } from "./lookupaccountapplocalstates"; -export type { LookupAccountCreatedApplications } from "./lookupaccountcreatedapplications"; -export type { LookupAccountTransactions } from "./lookupaccounttransactions"; -export type { SearchForApplications } from "./searchforapplications"; -export type { LookupApplicationById } from "./lookupapplicationbyid"; -export type { SearchForApplicationBoxes } from "./searchforapplicationboxes"; -export type { LookupApplicationLogsById } from "./lookupapplicationlogsbyid"; -export type { SearchForAssets } from "./searchforassets"; -export type { LookupAssetById } from "./lookupassetbyid"; -export type { LookupAssetBalances } from "./lookupassetbalances"; -export type { LookupAssetTransactions } from "./lookupassettransactions"; -export type { SearchForBlockHeaders } from "./searchforblockheaders"; -export type { LookupTransaction } from "./lookuptransaction"; -export type { SearchForTransactions } from "./searchfortransactions"; +export type { TransactionApplication } from "./transaction-application"; +export type { TransactionAssetConfig } from "./transaction-asset-config"; +export type { TransactionAssetFreeze } from "./transaction-asset-freeze"; +export type { TransactionStateProof } from "./transaction-state-proof"; +export type { TransactionHeartbeat } from "./transaction-heartbeat"; +export type { TransactionAssetTransfer } from "./transaction-asset-transfer"; +export type { TransactionKeyreg } from "./transaction-keyreg"; +export type { TransactionPayment } from "./transaction-payment"; +export type { TransactionSignature } from "./transaction-signature"; +export type { TransactionSignatureLogicsig } from "./transaction-signature-logicsig"; +export type { TransactionSignatureMultisig } from "./transaction-signature-multisig"; +export type { TransactionSignatureMultisigSubsignature } from "./transaction-signature-multisig-subsignature"; +export type { StateProofFields } from "./state-proof-fields"; +export type { HbProofFields } from "./hb-proof-fields"; +export type { IndexerStateProofMessage } from "./indexer-state-proof-message"; +export type { StateProofReveal } from "./state-proof-reveal"; +export type { StateProofSigSlot } from "./state-proof-sig-slot"; +export type { StateProofSignature } from "./state-proof-signature"; +export type { StateProofParticipant } from "./state-proof-participant"; +export type { StateProofVerifier } from "./state-proof-verifier"; +export type { StateProofTracking } from "./state-proof-tracking"; +export type { MerkleArrayProof } from "./merkle-array-proof"; +export type { HashFactory } from "./hash-factory"; +export type { SearchForAccounts } from "./search-for-accounts"; +export type { LookupAccountById } from "./lookup-account-by-id"; +export type { LookupAccountAssets } from "./lookup-account-assets"; +export type { LookupAccountCreatedAssets } from "./lookup-account-created-assets"; +export type { LookupAccountAppLocalStates } from "./lookup-account-app-local-states"; +export type { LookupAccountCreatedApplications } from "./lookup-account-created-applications"; +export type { LookupAccountTransactions } from "./lookup-account-transactions"; +export type { SearchForApplications } from "./search-for-applications"; +export type { LookupApplicationById } from "./lookup-application-by-id"; +export type { SearchForApplicationBoxes } from "./search-for-application-boxes"; +export type { LookupApplicationLogsById } from "./lookup-application-logs-by-id"; +export type { SearchForAssets } from "./search-for-assets"; +export type { LookupAssetById } from "./lookup-asset-by-id"; +export type { LookupAssetBalances } from "./lookup-asset-balances"; +export type { LookupAssetTransactions } from "./lookup-asset-transactions"; +export type { SearchForBlockHeaders } from "./search-for-block-headers"; +export type { LookupTransaction } from "./lookup-transaction"; +export type { SearchForTransactions } from "./search-for-transactions"; // TODO(utils-ts): Remove this export when utils-ts provides SignedTransaction types export type { AlgokitSignedTransaction } from "./algokitsignedtransaction"; diff --git a/packages/typescript/indexer_client/src/models/indexerstateproofmessage.ts b/packages/typescript/indexer_client/src/models/indexer-state-proof-message.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/indexerstateproofmessage.ts rename to packages/typescript/indexer_client/src/models/indexer-state-proof-message.ts diff --git a/packages/typescript/indexer_client/src/models/lookupaccountapplocalstates.ts b/packages/typescript/indexer_client/src/models/lookup-account-app-local-states.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/lookupaccountapplocalstates.ts rename to packages/typescript/indexer_client/src/models/lookup-account-app-local-states.ts diff --git a/packages/typescript/indexer_client/src/models/lookupaccountassets.ts b/packages/typescript/indexer_client/src/models/lookup-account-assets.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/lookupaccountassets.ts rename to packages/typescript/indexer_client/src/models/lookup-account-assets.ts diff --git a/packages/typescript/indexer_client/src/models/lookupaccountbyid.ts b/packages/typescript/indexer_client/src/models/lookup-account-by-id.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/lookupaccountbyid.ts rename to packages/typescript/indexer_client/src/models/lookup-account-by-id.ts diff --git a/packages/typescript/indexer_client/src/models/lookupaccountcreatedapplications.ts b/packages/typescript/indexer_client/src/models/lookup-account-created-applications.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/lookupaccountcreatedapplications.ts rename to packages/typescript/indexer_client/src/models/lookup-account-created-applications.ts diff --git a/packages/typescript/indexer_client/src/models/lookupaccountcreatedassets.ts b/packages/typescript/indexer_client/src/models/lookup-account-created-assets.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/lookupaccountcreatedassets.ts rename to packages/typescript/indexer_client/src/models/lookup-account-created-assets.ts diff --git a/packages/typescript/indexer_client/src/models/lookupaccounttransactions.ts b/packages/typescript/indexer_client/src/models/lookup-account-transactions.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/lookupaccounttransactions.ts rename to packages/typescript/indexer_client/src/models/lookup-account-transactions.ts diff --git a/packages/typescript/indexer_client/src/models/lookupapplicationbyid.ts b/packages/typescript/indexer_client/src/models/lookup-application-by-id.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/lookupapplicationbyid.ts rename to packages/typescript/indexer_client/src/models/lookup-application-by-id.ts diff --git a/packages/typescript/indexer_client/src/models/lookupapplicationlogsbyid.ts b/packages/typescript/indexer_client/src/models/lookup-application-logs-by-id.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/lookupapplicationlogsbyid.ts rename to packages/typescript/indexer_client/src/models/lookup-application-logs-by-id.ts diff --git a/packages/typescript/indexer_client/src/models/lookupassetbalances.ts b/packages/typescript/indexer_client/src/models/lookup-asset-balances.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/lookupassetbalances.ts rename to packages/typescript/indexer_client/src/models/lookup-asset-balances.ts diff --git a/packages/typescript/indexer_client/src/models/lookupassetbyid.ts b/packages/typescript/indexer_client/src/models/lookup-asset-by-id.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/lookupassetbyid.ts rename to packages/typescript/indexer_client/src/models/lookup-asset-by-id.ts diff --git a/packages/typescript/indexer_client/src/models/lookupassettransactions.ts b/packages/typescript/indexer_client/src/models/lookup-asset-transactions.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/lookupassettransactions.ts rename to packages/typescript/indexer_client/src/models/lookup-asset-transactions.ts diff --git a/packages/typescript/indexer_client/src/models/lookuptransaction.ts b/packages/typescript/indexer_client/src/models/lookup-transaction.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/lookuptransaction.ts rename to packages/typescript/indexer_client/src/models/lookup-transaction.ts diff --git a/packages/typescript/indexer_client/src/models/merklearrayproof.ts b/packages/typescript/indexer_client/src/models/merkle-array-proof.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/merklearrayproof.ts rename to packages/typescript/indexer_client/src/models/merkle-array-proof.ts diff --git a/packages/typescript/indexer_client/src/models/miniassetholding.ts b/packages/typescript/indexer_client/src/models/mini-asset-holding.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/miniassetholding.ts rename to packages/typescript/indexer_client/src/models/mini-asset-holding.ts diff --git a/packages/typescript/indexer_client/src/models/oncompletion.ts b/packages/typescript/indexer_client/src/models/on-completion.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/oncompletion.ts rename to packages/typescript/indexer_client/src/models/on-completion.ts diff --git a/packages/typescript/indexer_client/src/models/participationupdates.ts b/packages/typescript/indexer_client/src/models/participation-updates.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/participationupdates.ts rename to packages/typescript/indexer_client/src/models/participation-updates.ts diff --git a/packages/typescript/indexer_client/src/models/searchforaccounts.ts b/packages/typescript/indexer_client/src/models/search-for-accounts.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/searchforaccounts.ts rename to packages/typescript/indexer_client/src/models/search-for-accounts.ts diff --git a/packages/typescript/indexer_client/src/models/searchforapplicationboxes.ts b/packages/typescript/indexer_client/src/models/search-for-application-boxes.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/searchforapplicationboxes.ts rename to packages/typescript/indexer_client/src/models/search-for-application-boxes.ts diff --git a/packages/typescript/indexer_client/src/models/searchforapplications.ts b/packages/typescript/indexer_client/src/models/search-for-applications.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/searchforapplications.ts rename to packages/typescript/indexer_client/src/models/search-for-applications.ts diff --git a/packages/typescript/indexer_client/src/models/searchforassets.ts b/packages/typescript/indexer_client/src/models/search-for-assets.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/searchforassets.ts rename to packages/typescript/indexer_client/src/models/search-for-assets.ts diff --git a/packages/typescript/indexer_client/src/models/searchforblockheaders.ts b/packages/typescript/indexer_client/src/models/search-for-block-headers.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/searchforblockheaders.ts rename to packages/typescript/indexer_client/src/models/search-for-block-headers.ts diff --git a/packages/typescript/indexer_client/src/models/searchfortransactions.ts b/packages/typescript/indexer_client/src/models/search-for-transactions.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/searchfortransactions.ts rename to packages/typescript/indexer_client/src/models/search-for-transactions.ts diff --git a/packages/typescript/indexer_client/src/models/statedelta.ts b/packages/typescript/indexer_client/src/models/state-delta.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/statedelta.ts rename to packages/typescript/indexer_client/src/models/state-delta.ts diff --git a/packages/typescript/indexer_client/src/models/stateprooffields.ts b/packages/typescript/indexer_client/src/models/state-proof-fields.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/stateprooffields.ts rename to packages/typescript/indexer_client/src/models/state-proof-fields.ts diff --git a/packages/typescript/indexer_client/src/models/stateproofparticipant.ts b/packages/typescript/indexer_client/src/models/state-proof-participant.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/stateproofparticipant.ts rename to packages/typescript/indexer_client/src/models/state-proof-participant.ts diff --git a/packages/typescript/indexer_client/src/models/stateproofreveal.ts b/packages/typescript/indexer_client/src/models/state-proof-reveal.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/stateproofreveal.ts rename to packages/typescript/indexer_client/src/models/state-proof-reveal.ts diff --git a/packages/typescript/indexer_client/src/models/stateproofsigslot.ts b/packages/typescript/indexer_client/src/models/state-proof-sig-slot.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/stateproofsigslot.ts rename to packages/typescript/indexer_client/src/models/state-proof-sig-slot.ts diff --git a/packages/typescript/indexer_client/src/models/stateproofsignature.ts b/packages/typescript/indexer_client/src/models/state-proof-signature.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/stateproofsignature.ts rename to packages/typescript/indexer_client/src/models/state-proof-signature.ts diff --git a/packages/typescript/indexer_client/src/models/stateprooftracking.ts b/packages/typescript/indexer_client/src/models/state-proof-tracking.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/stateprooftracking.ts rename to packages/typescript/indexer_client/src/models/state-proof-tracking.ts diff --git a/packages/typescript/indexer_client/src/models/stateproofverifier.ts b/packages/typescript/indexer_client/src/models/state-proof-verifier.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/stateproofverifier.ts rename to packages/typescript/indexer_client/src/models/state-proof-verifier.ts diff --git a/packages/typescript/indexer_client/src/models/stateschema.ts b/packages/typescript/indexer_client/src/models/state-schema.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/stateschema.ts rename to packages/typescript/indexer_client/src/models/state-schema.ts diff --git a/packages/typescript/indexer_client/src/models/tealkeyvaluestore.ts b/packages/typescript/indexer_client/src/models/teal-key-value-store.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/tealkeyvaluestore.ts rename to packages/typescript/indexer_client/src/models/teal-key-value-store.ts diff --git a/packages/typescript/indexer_client/src/models/tealkeyvalue.ts b/packages/typescript/indexer_client/src/models/teal-key-value.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/tealkeyvalue.ts rename to packages/typescript/indexer_client/src/models/teal-key-value.ts diff --git a/packages/typescript/indexer_client/src/models/tealvalue.ts b/packages/typescript/indexer_client/src/models/teal-value.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/tealvalue.ts rename to packages/typescript/indexer_client/src/models/teal-value.ts diff --git a/packages/typescript/indexer_client/src/models/transactionapplication.ts b/packages/typescript/indexer_client/src/models/transaction-application.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/transactionapplication.ts rename to packages/typescript/indexer_client/src/models/transaction-application.ts diff --git a/packages/typescript/indexer_client/src/models/transactionassetconfig.ts b/packages/typescript/indexer_client/src/models/transaction-asset-config.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/transactionassetconfig.ts rename to packages/typescript/indexer_client/src/models/transaction-asset-config.ts diff --git a/packages/typescript/indexer_client/src/models/transactionassetfreeze.ts b/packages/typescript/indexer_client/src/models/transaction-asset-freeze.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/transactionassetfreeze.ts rename to packages/typescript/indexer_client/src/models/transaction-asset-freeze.ts diff --git a/packages/typescript/indexer_client/src/models/transactionassettransfer.ts b/packages/typescript/indexer_client/src/models/transaction-asset-transfer.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/transactionassettransfer.ts rename to packages/typescript/indexer_client/src/models/transaction-asset-transfer.ts diff --git a/packages/typescript/indexer_client/src/models/transactionheartbeat.ts b/packages/typescript/indexer_client/src/models/transaction-heartbeat.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/transactionheartbeat.ts rename to packages/typescript/indexer_client/src/models/transaction-heartbeat.ts diff --git a/packages/typescript/indexer_client/src/models/transactionkeyreg.ts b/packages/typescript/indexer_client/src/models/transaction-keyreg.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/transactionkeyreg.ts rename to packages/typescript/indexer_client/src/models/transaction-keyreg.ts diff --git a/packages/typescript/indexer_client/src/models/transactionpayment.ts b/packages/typescript/indexer_client/src/models/transaction-payment.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/transactionpayment.ts rename to packages/typescript/indexer_client/src/models/transaction-payment.ts diff --git a/packages/typescript/indexer_client/src/models/transactionsignaturelogicsig.ts b/packages/typescript/indexer_client/src/models/transaction-signature-logicsig.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/transactionsignaturelogicsig.ts rename to packages/typescript/indexer_client/src/models/transaction-signature-logicsig.ts diff --git a/packages/typescript/indexer_client/src/models/transactionsignaturemultisigsubsignature.ts b/packages/typescript/indexer_client/src/models/transaction-signature-multisig-subsignature.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/transactionsignaturemultisigsubsignature.ts rename to packages/typescript/indexer_client/src/models/transaction-signature-multisig-subsignature.ts diff --git a/packages/typescript/indexer_client/src/models/transactionsignaturemultisig.ts b/packages/typescript/indexer_client/src/models/transaction-signature-multisig.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/transactionsignaturemultisig.ts rename to packages/typescript/indexer_client/src/models/transaction-signature-multisig.ts diff --git a/packages/typescript/indexer_client/src/models/transactionsignature.ts b/packages/typescript/indexer_client/src/models/transaction-signature.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/transactionsignature.ts rename to packages/typescript/indexer_client/src/models/transaction-signature.ts diff --git a/packages/typescript/indexer_client/src/models/transactionstateproof.ts b/packages/typescript/indexer_client/src/models/transaction-state-proof.ts similarity index 100% rename from packages/typescript/indexer_client/src/models/transactionstateproof.ts rename to packages/typescript/indexer_client/src/models/transaction-state-proof.ts