diff --git a/.changeset/cyan-wasps-flash.md b/.changeset/cyan-wasps-flash.md new file mode 100644 index 00000000..fe4510a4 --- /dev/null +++ b/.changeset/cyan-wasps-flash.md @@ -0,0 +1,5 @@ +--- +"@fleet-sdk/serializer": patch +--- + +Add `deserializeBox` function diff --git a/.changeset/eleven-horses-count.md b/.changeset/eleven-horses-count.md new file mode 100644 index 00000000..07e84cab --- /dev/null +++ b/.changeset/eleven-horses-count.md @@ -0,0 +1,5 @@ +--- +"@fleet-sdk/serializer": patch +--- + +Add `deserializeTransaction` function diff --git a/.changeset/floppy-wings-dress.md b/.changeset/floppy-wings-dress.md new file mode 100644 index 00000000..6fe5b2b3 --- /dev/null +++ b/.changeset/floppy-wings-dress.md @@ -0,0 +1,5 @@ +--- +"@fleet-sdk/common": patch +--- + +Add offset support to `startsWith` diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 218f3053..4167227b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,6 +16,8 @@ jobs: lint: name: Lint runs-on: ubuntu-latest + permissions: + contents: read steps: - uses: actions/checkout@v4 @@ -35,6 +37,9 @@ jobs: format: name: Format runs-on: ubuntu-latest + permissions: + contents: read + steps: - uses: actions/checkout@v4 @@ -53,6 +58,9 @@ jobs: build-and-test-node: name: "[node] build and test" runs-on: ubuntu-latest + permissions: + contents: read + timeout-minutes: 20 strategy: fail-fast: false @@ -78,6 +86,8 @@ jobs: build-and-test-bun: name: "[bun] build and test" runs-on: ubuntu-latest + permissions: + contents: read timeout-minutes: 20 strategy: fail-fast: false @@ -102,6 +112,8 @@ jobs: build-and-test-other-envs: name: "[happy-dom, edge-runtime] test" runs-on: ubuntu-latest + permissions: + contents: read timeout-minutes: 20 strategy: fail-fast: false @@ -130,6 +142,8 @@ jobs: publish-preview: name: "Publish preview" runs-on: ubuntu-latest + permissions: + pull-requests: write # to be able to comment on the pull requests needs: build-and-test-node if: success() timeout-minutes: 20 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 00000000..3420e7db --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,100 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL Advanced" + +on: + push: + branches: ["master"] + pull_request: + branches: ["master"] + schedule: + - cron: "27 9 * * 1" + +jobs: + analyze: + name: Analyze (${{ matrix.language }}) + # Runner size impacts CodeQL analysis time. To learn more, please see: + # - https://gh.io/recommended-hardware-resources-for-running-codeql + # - https://gh.io/supported-runners-and-hardware-resources + # - https://gh.io/using-larger-runners (GitHub.com only) + # Consider using larger runners or machines with greater resources for possible analysis time improvements. + runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} + permissions: + # required for all workflows + security-events: write + + # required to fetch internal or private CodeQL packs + packages: read + + # only required for workflows in private repositories + actions: read + contents: read + + strategy: + fail-fast: false + matrix: + include: + - language: actions + build-mode: none + - language: javascript-typescript + build-mode: none + # CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' + # Use `c-cpp` to analyze code written in C, C++ or both + # Use 'java-kotlin' to analyze code written in Java, Kotlin or both + # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both + # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, + # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. + # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how + # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Add any setup steps before running the `github/codeql-action/init` action. + # This includes steps like installing compilers or runtimes (`actions/setup-node` + # or others). This is typically only required for manual builds. + # - name: Setup runtime (example) + # uses: actions/setup-example@v1 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + # If the analyze step fails for one of the languages you are analyzing with + # "We were unable to automatically build your code", modify the matrix above + # to set the build mode to "manual" for that language. Then modify this step + # to build your code. + # â„šī¸ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + - if: matrix.build-mode == 'manual' + shell: bash + run: | + echo 'If you are using a "manual" build mode for one or more of the' \ + 'languages you are analyzing, replace this with the commands to build' \ + 'your code, for example:' + echo ' make bootstrap' + echo ' make release' + exit 1 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 82dcc9a9..03cb30b5 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -10,6 +10,8 @@ on: jobs: coverage: + permissions: + contents: read name: Check and submit runs-on: ubuntu-latest steps: diff --git a/package.json b/package.json index e081b502..657e03fd 100644 --- a/package.json +++ b/package.json @@ -25,23 +25,23 @@ }, "devDependencies": { "@biomejs/biome": "^1.9.4", - "@changesets/cli": "^2.29.2", + "@changesets/cli": "^2.29.3", "@edge-runtime/vm": "^5.0.0", "@fleet-sdk/common": "workspace:^", "@fleet-sdk/crypto": "workspace:^", "@types/diff": "^7.0.2", - "@vitest/coverage-v8": "^3.1.1", + "@vitest/coverage-v8": "^3.1.3", "ergo-lib-wasm-nodejs": "^0.28.0", "fast-check": "^4.1.1", - "happy-dom": "^17.4.4", + "happy-dom": "^17.4.6", "npm-run-all": "^4.1.5", "open-cli": "^8.0.0", "sigmastate-js": "0.4.6", "tsup": "^8.4.0", - "type-fest": "^4.40.0", + "type-fest": "^4.41.0", "typescript": "^5.8.3", "vite-tsconfig-paths": "^5.1.4", - "vitest": "^3.1.1" + "vitest": "^3.1.3" }, "engines": { "node": ">=18", @@ -50,6 +50,9 @@ "pnpm": { "requiredScripts": [ "build" + ], + "onlyBuiltDependencies": [ + "esbuild" ] } } diff --git a/packages/common/src/constants.ts b/packages/common/src/constants.ts new file mode 100644 index 00000000..665272df --- /dev/null +++ b/packages/common/src/constants.ts @@ -0,0 +1,3 @@ +export const FEE_CONTRACT = + "1005040004000e36100204a00b08cd0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ea02d192a39a8cc7a701730073011001020402d19683030193a38cc7b2a57300000193c2b2a57301007473027303830108cdeeac93b1a57304"; +export const RECOMMENDED_MIN_FEE_VALUE = BigInt(1100000); diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts index 698f8f29..e892e9fb 100644 --- a/packages/common/src/index.ts +++ b/packages/common/src/index.ts @@ -2,3 +2,4 @@ export * from "./utils"; export * from "./types"; export * from "./models/collection"; export * from "./error"; +export * from "./constants"; diff --git a/packages/common/src/utils/array.spec.ts b/packages/common/src/utils/array.spec.ts index 14248955..65c09dfe 100644 --- a/packages/common/src/utils/array.spec.ts +++ b/packages/common/src/utils/array.spec.ts @@ -297,6 +297,17 @@ describe("startsWith()", () => { expect(startsWith(array, array)).toBeTruthy(); }); + it("Should return true if starts with target with offset", () => { + // index: 0, 1, 2, 3, 4, 5, 6, 7 + const array = [1, 2, 4, 5, 6, 7, 8, 9]; + + expect(startsWith(array, [2, 4], 1)).toBeTruthy(); + expect(startsWith(array, [6, 7], 4)).toBeTruthy(); + expect(startsWith(array, [9, 10], 7)).toBeFalsy(); + expect(startsWith(array, [1], 0)).toBeTruthy(); + expect(startsWith(array, array)).toBeTruthy(); + }); + it("Should return false for not starts with target", () => { const array = [1, 2, 4, 5, 0]; diff --git a/packages/common/src/utils/array.ts b/packages/common/src/utils/array.ts index 2a6998a7..b0cd8feb 100644 --- a/packages/common/src/utils/array.ts +++ b/packages/common/src/utils/array.ts @@ -205,19 +205,16 @@ export function areEqualBy( * startsWith(array, target2); // false * ``` */ -export function startsWith(array: ArrayLike, target: ArrayLike): boolean { - if (array === target) { - return true; - } - - if (target.length > array.length) { - return false; - } +export function startsWith( + array: ArrayLike, + target: ArrayLike, + offset = 0 +): boolean { + if (array === target) return true; + if (target.length > array.length) return false; for (let i = 0; i < target.length; i++) { - if (target[i] !== array[i]) { - return false; - } + if (target[i] !== array[i + offset]) return false; } return true; @@ -239,16 +236,10 @@ export function startsWith(array: ArrayLike, target: ArrayLike): boolea * ``` */ export function endsWith(array: ArrayLike, target: ArrayLike): boolean { - if (array === target) { - return true; - } - - if (target.length > array.length) { - return false; - } + if (array === target) return true; + if (target.length > array.length) return false; const offset = array.length - target.length; - for (let i = target.length - 1; i >= 0; i--) { if (target[i] !== array[i + offset]) { return false; diff --git a/packages/core/src/builder/pluginContext.spec.ts b/packages/core/src/builder/pluginContext.spec.ts index c298a036..6ff5d110 100644 --- a/packages/core/src/builder/pluginContext.spec.ts +++ b/packages/core/src/builder/pluginContext.spec.ts @@ -3,7 +3,8 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; import { NotAllowedTokenBurning } from "../errors"; import { OutputBuilder } from "./outputBuilder"; import { createPluginContext, type FleetPluginContext } from "./pluginContext"; -import { RECOMMENDED_MIN_FEE_VALUE, TransactionBuilder } from "./transactionBuilder"; +import { TransactionBuilder } from "./transactionBuilder"; +import { RECOMMENDED_MIN_FEE_VALUE } from "@fleet-sdk/common"; describe("Plugin context", () => { const creationHeight = 894169; diff --git a/packages/core/src/builder/transactionBuilder.spec.ts b/packages/core/src/builder/transactionBuilder.spec.ts index e5cece35..744aa36f 100644 --- a/packages/core/src/builder/transactionBuilder.spec.ts +++ b/packages/core/src/builder/transactionBuilder.spec.ts @@ -20,12 +20,9 @@ import { OutputBuilder, SAFE_MIN_BOX_VALUE } from "./outputBuilder"; -import { - FEE_CONTRACT, - RECOMMENDED_MIN_FEE_VALUE, - TransactionBuilder -} from "./transactionBuilder"; +import { TransactionBuilder } from "./transactionBuilder"; import { mockUTxO } from "packages/mock-chain/src"; +import { FEE_CONTRACT, RECOMMENDED_MIN_FEE_VALUE } from "@fleet-sdk/common"; const height = 844540; const a1 = { diff --git a/packages/core/src/builder/transactionBuilder.ts b/packages/core/src/builder/transactionBuilder.ts index 87b5f4f7..00757efc 100644 --- a/packages/core/src/builder/transactionBuilder.ts +++ b/packages/core/src/builder/transactionBuilder.ts @@ -10,11 +10,13 @@ import { byteSizeOf, chunk, ensureBigInt, + FEE_CONTRACT, first, isDefined, isHex, isUndefined, Network, + RECOMMENDED_MIN_FEE_VALUE, some, utxoDiff, utxoSum @@ -46,10 +48,6 @@ export type SelectorCallback = (selector: SelectorSettings) => void; export type FleetPlugin = (context: FleetPluginContext) => void; export type CollectionLike = { toArray(): T[] }; -export const RECOMMENDED_MIN_FEE_VALUE = BigInt(1100000); -export const FEE_CONTRACT = - "1005040004000e36100204a00b08cd0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ea02d192a39a8cc7a701730073011001020402d19683030193a38cc7b2a57300000193c2b2a57301007473027303830108cdeeac93b1a57304"; - type EjectorContext = { inputs: InputsCollection; dataInputs: InputsCollection; diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index b109c2f4..aac6dc07 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -2,5 +2,10 @@ export * from "./builder"; export * from "./models"; export * from "./errors"; export * from "./constantSerializer"; -export { AddressType, Network } from "@fleet-sdk/common"; +export { + AddressType, + Network, + RECOMMENDED_MIN_FEE_VALUE, + FEE_CONTRACT +} from "@fleet-sdk/common"; export type { Box, Amount, TokenAmount } from "@fleet-sdk/common"; diff --git a/packages/core/src/models/collections/outputsCollection.spec.ts b/packages/core/src/models/collections/outputsCollection.spec.ts index e0c48b5f..bee5bd89 100644 --- a/packages/core/src/models/collections/outputsCollection.spec.ts +++ b/packages/core/src/models/collections/outputsCollection.spec.ts @@ -1,7 +1,6 @@ -import { first } from "@fleet-sdk/common"; +import { first, RECOMMENDED_MIN_FEE_VALUE } from "@fleet-sdk/common"; import { describe, expect, it } from "vitest"; import { OutputBuilder, SAFE_MIN_BOX_VALUE } from "../../builder/outputBuilder"; -import { RECOMMENDED_MIN_FEE_VALUE } from "../../builder/transactionBuilder"; import { NotFoundError } from "../../errors"; import { OutputsCollection } from "./outputsCollection"; diff --git a/packages/core/src/models/ergoAddress.spec.ts b/packages/core/src/models/ergoAddress.spec.ts index 13373475..6b89833b 100644 --- a/packages/core/src/models/ergoAddress.spec.ts +++ b/packages/core/src/models/ergoAddress.spec.ts @@ -1,7 +1,6 @@ -import { AddressType, Network } from "@fleet-sdk/common"; +import { AddressType, Network, FEE_CONTRACT } from "@fleet-sdk/common"; import { blake2b256, hex } from "@fleet-sdk/crypto"; import { describe, expect, it, test } from "vitest"; -import { FEE_CONTRACT } from "../builder"; import { ergoTsTestVectors, FEE_MAINNET_ADDRESS_TV, diff --git a/packages/core/src/models/ergoAddress.ts b/packages/core/src/models/ergoAddress.ts index 0e1a82f3..0e512d21 100644 --- a/packages/core/src/models/ergoAddress.ts +++ b/packages/core/src/models/ergoAddress.ts @@ -28,8 +28,8 @@ import { const P2PK_ERGOTREE_PREFIX = hex.decode("0008cd"); const P2PK_ERGOTREE_LENGTH = 36; -const P2SH_ERGOTREE_SUFFIX = hex.decode("d40801"); const P2SH_ERGOTREE_PREFIX = hex.decode("00ea02d193b4cbe4e3010e040004300e18"); +const P2SH_ERGOTREE_SUFFIX = hex.decode("d40801"); const P2SH_ERGOTREE_LENGTH = 44; const P2SH_HASH_LENGTH = 24; diff --git a/packages/core/src/models/ergoUnsignedTransaction.spec.ts b/packages/core/src/models/ergoUnsignedTransaction.spec.ts index 87497658..70cae100 100644 --- a/packages/core/src/models/ergoUnsignedTransaction.spec.ts +++ b/packages/core/src/models/ergoUnsignedTransaction.spec.ts @@ -1,26 +1,20 @@ import { serializeTransaction } from "@fleet-sdk/serializer"; import { regularBoxes, validBoxes, mockedUnsignedTransactions } from "_test-vectors"; import { describe, expect, it } from "vitest"; -import { - FEE_CONTRACT, - OutputBuilder, - RECOMMENDED_MIN_FEE_VALUE, - SAFE_MIN_BOX_VALUE, - TransactionBuilder -} from "../builder"; +import { OutputBuilder, SAFE_MIN_BOX_VALUE, TransactionBuilder } from "../builder"; import { ErgoUnsignedInput } from "./ergoUnsignedInput"; import { ErgoUnsignedTransaction } from "./ergoUnsignedTransaction"; import { ErgoBoxCandidate } from "./ergoBoxCandidate"; import { ErgoAddress } from "./ergoAddress"; import { blake2b256, hex } from "@fleet-sdk/crypto"; import type { - Box, DataInput, EIP12UnsignedDataInput, EIP12UnsignedInput, UnsignedInput, UnsignedTransaction } from "@fleet-sdk/common"; +import { FEE_CONTRACT, RECOMMENDED_MIN_FEE_VALUE } from "@fleet-sdk/common"; describe("Model", () => { it("Should generate the right transactionId and boxIds for outputs", () => { diff --git a/packages/crypto/package.json b/packages/crypto/package.json index 627d55b3..0b4781df 100644 --- a/packages/crypto/package.json +++ b/packages/crypto/package.json @@ -37,8 +37,8 @@ }, "dependencies": { "@fleet-sdk/common": "workspace:^", - "@noble/hashes": "^1.7.2", - "@scure/base": "^1.2.4" + "@noble/hashes": "^1.8.0", + "@scure/base": "^1.2.5" }, "files": [ "dist", diff --git a/packages/mock-chain/src/objectMocking.spec.ts b/packages/mock-chain/src/objectMocking.spec.ts index 23d78fd2..631aec79 100644 --- a/packages/mock-chain/src/objectMocking.spec.ts +++ b/packages/mock-chain/src/objectMocking.spec.ts @@ -15,7 +15,7 @@ describe("mockUTxO()", () => { expect(utxo.value).to.be.equal(SAFE_MIN_BOX_VALUE); expect(utxo.ergoTree).to.be.equal(ergoTree); expect(utxo.assets).to.be.empty; - expect(utxo.creationHeight).to.be.equal(0); + expect(utxo.creationHeight).to.be.equal(849741); expect(utxo.additionalRegisters).to.be.empty; expect(utxo.transactionId).to.have.length(64); diff --git a/packages/mock-chain/src/objectMocking.ts b/packages/mock-chain/src/objectMocking.ts index 95a3482d..d3d9c6e9 100644 --- a/packages/mock-chain/src/objectMocking.ts +++ b/packages/mock-chain/src/objectMocking.ts @@ -16,7 +16,7 @@ export function mockUTxO(mock: MockBoxOptions): Box { value: mock.value ?? SAFE_MIN_BOX_VALUE, ergoTree: mock.ergoTree, assets: mock.assets ?? [], - creationHeight: mock.creationHeight ?? 0, + creationHeight: mock.creationHeight ?? 849741, additionalRegisters: mock.additionalRegisters ?? {}, transactionId: mock.transactionId ?? getRandomId(), diff --git a/packages/serializer/src/_test-vectors/boxVectors.ts b/packages/serializer/src/_test-vectors/boxVectors.ts index cd28d7aa..bbd2916f 100644 --- a/packages/serializer/src/_test-vectors/boxVectors.ts +++ b/packages/serializer/src/_test-vectors/boxVectors.ts @@ -1,4 +1,5 @@ -import type { Amount, Box } from "@fleet-sdk/common"; +import { FEE_CONTRACT, type Amount, type Box } from "@fleet-sdk/common"; +import { mockUTxO } from "packages/mock-chain/src"; export const boxVectors: { hex: string; @@ -23,6 +24,25 @@ export const boxVectors: { }, hex: "c0843d0008cd038d39af8c37583609ff51c6a577efe60684119da2fbd0d75f9c72372886a58a63cdee330150fdc80e168c153e472bd7e3dd18a4a0b9e90c550206fdbdb789ee8afdd3b1a90100ae11d207f0989945f63909d2f703b2640acf4f654a8fdadd23570a640f9d12ee00" }, + { + json: { + boxId: "135baecae94f7ec20caf981800166d450bd1dde4b959e5fdd0e2751b679d94dd", + transactionId: "ae11d207f0989945f63909d2f703b2640acf4f654a8fdadd23570a640f9d12ee", + value: "1000000", + creationHeight: 849741, + index: 0, + ergoTree: + "0008cd038d39af8c37583609ff51c6a577efe60684119da2fbd0d75f9c72372886a58a63", + additionalRegisters: { R4: undefined }, + assets: [ + { + tokenId: "50fdc80e168c153e472bd7e3dd18a4a0b9e90c550206fdbdb789ee8afdd3b1a9", + amount: "1" + } + ] + }, + hex: "c0843d0008cd038d39af8c37583609ff51c6a577efe60684119da2fbd0d75f9c72372886a58a63cdee330150fdc80e168c153e472bd7e3dd18a4a0b9e90c550206fdbdb789ee8afdd3b1a90100ae11d207f0989945f63909d2f703b2640acf4f654a8fdadd23570a640f9d12ee00" + }, { json: { boxId: "6a83a25cc07a1bb7a0c763f94ede470010c8129ddfa248d8ce645ae5d7bb95d4", @@ -210,3 +230,72 @@ export const boxVectors: { hex: "90bbe2ee371014040004000e208c27dd9d8a35aac1e3167d58858c0a8b4059b277da790552e37eba22df9b903504000400040204020101040205a0c21e040204080500040c040204a0c21e0402050a05c8010402d806d601b2a5730000d602b5db6501fed9010263ed93e4c67202050ec5a7938cb2db63087202730100017302d603b17202d604e4c6b272027303000605d605d90105049590720573047204e4c6b272029972057305000605d606b07202860273067307d901063c400163d803d6088c720601d6098c720801d60a8c72060286029a72097308ededed8c72080293c2b2a5720900d0cde4c6720a040792c1b2a5720900730992da720501997209730ae4c6720a0605ea02d1ededededededed93cbc27201e4c6a7060e927203730b93db63087201db6308a793e4c6720104059db07202730cd9010741639a8c720701e4c68c72070206057e72030593e4c6720105049ae4c6a70504730d92c1720199c1a77e9c9a7203730e730f058c72060292da720501998c72060173109972049d9c720473117312b2ad7202d9010763cde4c672070407e4c6b2a5731300040400db843401011d3364de07e5a26f0c4eef0852cddb387039a921b7154ef3cab22c6eda887f010305cab4cd9a0304bc89680e20f7ef73c4a4ab91b84bb0a2905108d534114472ec057be3a57a9dfc9b1fbd85c1f1ab205c16865eeadb8eeade83d3de93fbb6cf203da15a8a485dc449c71b663a00" } ]; + +export const deserializationTestVectors = [ + { + name: "size flag, with tokens and additional registers", + box: mockUTxO({ + ergoTree: + "1999030f0400040204020404040405feffffffffffffffff0105feffffffffffffffff01050004d00f040004000406050005000580dac409d819d601b2a5730000d602e4c6a70404d603db63087201d604db6308a7d605b27203730100d606b27204730200d607b27203730300d608b27204730400d6099973058c720602d60a999973068c7205027209d60bc17201d60cc1a7d60d99720b720cd60e91720d7307d60f8c720802d6107e720f06d6117e720d06d612998c720702720fd6137e720c06d6147308d6157e721206d6167e720a06d6177e720906d6189c72117217d6199c72157217d1ededededededed93c27201c2a793e4c672010404720293b27203730900b27204730a00938c7205018c720601938c7207018c72080193b17203730b9593720a730c95720e929c9c721072117e7202069c7ef07212069a9c72137e7214067e9c720d7e72020506929c9c721372157e7202069c7ef0720d069a9c72107e7214067e9c72127e7202050695ed720e917212730d907216a19d721872139d72197210ed9272189c721672139272199c7216721091720b730e", + assets: [ + { + tokenId: "50fdc80e168c153e472bd7e3dd18a4a0b9e90c550206fdbdb789ee8afdd3b1a9", + amount: 1n + } + ], + additionalRegisters: { + R4: "05cab4cd9a03", + R5: "04bc8968", + R6: "0e20f7ef73c4a4ab91b84bb0a2905108d534114472ec057be3a57a9dfc9b1fbd85c1" + } + }) + }, + { + name: "size flag, ergotree v1, with additional registers but no tokens", + box: mockUTxO({ + ergoTree: "19090104c801d191a37300", + additionalRegisters: { R4: "05cab4cd9a03" } + }) + }, + { + name: "size flag, ergotree v0, with tokens but not additional registers", + box: mockUTxO({ + ergoTree: "0806d191a304c801", + assets: [ + { + tokenId: "50fdc80e168c153e472bd7e3dd18a4a0b9e90c550206fdbdb789ee8afdd3b1a9", + amount: 1298743323231n + } + ] + }) + }, + { + name: "fee contract, no tokens, no additional registers", + box: mockUTxO({ ergoTree: FEE_CONTRACT }) + }, + { + name: "p2pk contract, with multiple tokens, but no additional registers", + box: mockUTxO({ + ergoTree: + "0008cd038d39af8c37583609ff51c6a577efe60684119da2fbd0d75f9c72372886a58a63", + assets: [ + { + tokenId: "de5ee573c6a492c129d51119649bfeaedfc9afa6f54af576e62e1f7f3bbd4207", + amount: 1581138830n + }, + { + tokenId: "1fd6e032e8476c4aa54c18c1a308dce83940e8f4a28f576440513ed7326ad489", + amount: 1002634n + }, + { + tokenId: "03faf2cb329f2e90d6d23b58d91bbb6c046aa143261cc21f52fbe2824bfcbf04", + amount: 50n + }, + { + tokenId: "74251ce2cb4eb2024a1a155e19ad1d1f58ff8b9e6eb034a3bb1fd58802757d23", + amount: 200000000000n + } + ] + }) + } +]; diff --git a/packages/serializer/src/_test-vectors/transactionVectors.ts b/packages/serializer/src/_test-vectors/transactionVectors.ts index ff987a32..e325c87e 100644 --- a/packages/serializer/src/_test-vectors/transactionVectors.ts +++ b/packages/serializer/src/_test-vectors/transactionVectors.ts @@ -1,4 +1,4 @@ -import type { UnsignedTransaction } from "@fleet-sdk/common"; +import type { SignedTransaction, UnsignedTransaction } from "@fleet-sdk/common"; export const unsignedTransactionVectors: { name: string; @@ -597,3 +597,392 @@ export const unsignedTransactionVectors: { } } ]; + +export const raffleSignedTransaction = { + id: "569b9f36b41c0dc0a6c488eea12fe803b7a6bd97d2b92079d455f6d0dd9080a2", + inputs: [ + { + boxId: "6394efce52392141d67cdc70d9474ff85fea07df49530e85b9d26fbe43362bc4", + spendingProof: { + proofBytes: + "b8b2b17792bccd7fc27f6b53203524da6d3d3863c556ba0a530c25df1c1a49c41df8728fad61ba4f4fb6621fb602498dd830055da030d35a", + extension: { + "0": "1101d00f", + "1": "1a02240008cd03b8b4b552caf9dbd5173eb5b1e441dc8f47630abe01105009f2716fee8e834506240008cd023625de27837c0d91735145f7330fb1867cfe23b8e27b20e2a7d31bc825ef4f8e" + } + } + }, + { + boxId: "0d12f7a3872db6673765fb245035040c8b21cfe70ab73f49249d38c424bcd113", + spendingProof: { + proofBytes: + "ff8213f8c7c0451986e0404026fa8c0ead0f7192f1a6e3edb5ae413311db6e1f444c4e9606d5b3de288bcf4ac71a0f6f1062be7cef82c202", + extension: {} + } + } + ], + dataInputs: [], + outputs: [ + { + boxId: "bfef0e91e167b37a3fdbe1cf0c23d6856865e0803ac62a5a116038a022664dab", + value: 15000000n, + ergoTree: + "19b70632040004000e20af97b783aeb7276a072a894c089bfebdd6ac8ab50bd40edc523dce2ce42cd12401010402040204000502050204020406040404000400040204080e20a311ddfab7e82e39036b94dd52044ca044215d8b97f3d5f25d43a168d0182875040004020e208d2b06d64a3bbe6d5a72070499ae86f6e107b388dfb652ece1f2b270f31f2fa304000404040e05000402040405d00f04060500040c040604000402040004040402040404000402050a05100404050005d00f04040500050005d00f05000100d803d601b2a5730000d602db63087201d603b2720273010095938c7203017302d17303d809d604b27202730400d6058c720402d606db6308a7d607b27206730500d6088c720702d609e4c6a70411d60ae4c6a7050ed60b8c720701d60c9683070193e4c672010411720993e4c67201050e720a93c27201c2a7937203b27206730600938c720401720b92c17201c1a793b17202b17206959372059a72087307d1720c959372059972087308d812d60db2a5730900d60edb6308720dd60fc5a7d610b27209730a00d611b2a5730b00d612db63087211d613e4c672110411d614b27213730c00d615b27209730d00d616b27209730e00d6179a9a721472157216d618e4c67211051ad619e4e3011ad61ae4c67211071ad61be4e30011d61cb1721bd61dc17211d61eb27213730f00d196831e01720c93cbc2720d7310938cb2720e73110001720f93b1720e731293c1720d721093cbc272117313938cb2721273140001720b90b17212731593b172137316927214731793b27213731800721593b2721373190072168f7217731a91b27213731b00731c93b27213731d00721093b17218731e93b27218731f00720a93b27218732000cbb2721973210093b27218732200cbb2721973230092b1e4c67211061a732493b2721a732500720f93b2721a732600cbb0721b830002d9011f4d0eb38c721f017a8c721f0293e4c672110804721c92721d9a9c9c732772107e721c059c7328721092721db2720973290093b0721b732ad9011f599a8c721f018c721f02732befaeb4a5732cb1a5d9011f63aedb6308721fd901214d0e938c722101720f919c721e7215732d919c721e7216732e919c721e99732f72177330d17331", + assets: [ + { + tokenId: "74e4d58add8c75f6f60c04bc20f077270f3083b0fa0c199d8f2e356b5e10e9b1", + amount: 1n + }, + { + tokenId: "df4beade44143b716c32f1bb8d6238dd01600a18f8619a4bc3b7fb34cfa4753d", + amount: 999999998n + } + ], + creationHeight: 1695302, + additionalRegisters: { + R4: "1104c801c80180a8d6b9078087a70e", + R5: "0e20edb662d009b16812a2bd2ffd1b926b965d62040ade9241fdc4b88237a99dfebe" + }, + transactionId: "569b9f36b41c0dc0a6c488eea12fe803b7a6bd97d2b92079d455f6d0dd9080a2", + index: 0 + }, + { + boxId: "ee91f384e156b24373ea5b2406b463f205984df108dac58ca2d3566bc9740363", + value: 15000000n, + ergoTree: + "19950108040004020400040004000e20df4beade44143b716c32f1bb8d6238dd01600a18f8619a4bc3b7fb34cfa4753d05020400d805d601db6308b2a5730000d602b27201730100d603b2db6308a7730200d6048c720301d605b2a4730300d196830401938cb27201730400017305938c7202017204938c72020299998c7203027ee4c67205080405730693b2e4c67205071a7307007204", + assets: [ + { + tokenId: "6394efce52392141d67cdc70d9474ff85fea07df49530e85b9d26fbe43362bc4", + amount: 1000000000n + } + ], + creationHeight: 1695302, + additionalRegisters: { + R4: "0e0f5469636b65745265706f546f6b656e", + R5: "0e00", + R6: "0e0130" + }, + transactionId: "569b9f36b41c0dc0a6c488eea12fe803b7a6bd97d2b92079d455f6d0dd9080a2", + index: 1 + }, + { + boxId: "7284c29e7a9941a8eae29aee38622d802f19561bdf53337d087cd959e4bdf489", + value: 1195000000n, + ergoTree: + "19cf052404000400040c040204060406040404000e20f23fd8c734a5e217c7efe671190e1ab0be7f777ce3c6686d1c8feaee86fc262d0400040004020402050a050004020404040201010e2005c331a7c66ca70aedafa4ea4d65f65d711aef0821b51a6f02c07ad07a0c7f8304000e20c5c2936541aa8b3e9614ca2df228c080fae9a5c9b2f328bd2c4c4881f6e000060400040205080402040a040404020500040205a01f05a01f040204020400d810d601b2a5730000d602db63087201d603db6308a7d604e4c6a7071ad605b27204730100d606b17203d607e4c6a70411d608b27207730200d609e4c6a70804d60a7e720905d60bb2a5730300d60cb4a573049a72097305d60dc5a7d60eb2a5730600d60fdb6308720ed610b2720f730700d19683180193cbc272017308938cb27202730900018cb27203730a0001938cb27202730b0001720593b172029a7206730c93c172019999c1a79c9c730d7208720a720893e4c672010411720793e4c67201051ae4c6a7051a93e4c672010604720993e4c672010705730e95ef937206730f93b2db63087201731000b27203731100731293cbc2720b731393e4c6720b041ae4c6a7061a938cb2db6308720b73140001720593c1720b7208afdb0c0e720cd9011104d803d613b2720c721100d614db63087213d615e4c6721304119683090193cbc272137315938cb2721473160001720593b17214731793c172139c7318720893b27215731900b27207731a0093b27215731b00720893e4c6721305049a7211731c93e4c672130605731d93e4c67213070e720d93b1720f731e938c721001720d938c7210029c731f720a93e4c6720e07118302057320720893e4c6720e080e720593e4c6720e09108302047209732193c1720e9c7208720a93b27204732200cbb0720c830002d901113c0e63b38c7211017ab2e4c68c7211020411732300efaea5d9011163ed94c57211c5720eaedb63087211d901134d0e938c721301720d", + assets: [ + { + tokenId: "df4beade44143b716c32f1bb8d6238dd01600a18f8619a4bc3b7fb34cfa4753d", + amount: 1n + } + ], + creationHeight: 1695302, + additionalRegisters: { + R4: "11079003c801c80180dac409d00f96f9ce018087a70e", + R5: "1a0320edb662d009b16812a2bd2ffd1b926b965d62040ade9241fdc4b88237a99dfebe20b894faef6f944647dac930d195680808a3fd7c660308196f2a0f4e94dc8c0fa820d217c8109e3bb5535c96d04875649efdb07b211b59bd0d1c62681baa8b8e0f11", + R6: "1a02045465737414536f6d65206465736372697074696f6e732e2e2e", + R7: "1a02206394efce52392141d67cdc70d9474ff85fea07df49530e85b9d26fbe43362bc4203851ae49debc087ff742ec6b70d461d54997173be5d50ba4ee1cac0e260850ce", + R8: "0402" + }, + transactionId: "569b9f36b41c0dc0a6c488eea12fe803b7a6bd97d2b92079d455f6d0dd9080a2", + index: 2 + }, + { + boxId: "734fcae73d4a7729f8c14c0b39a060ca6f93ae933b07d176b56233a4f338c7f2", + value: 15000000n, + ergoTree: + "1005040004000e36100204a00b08cd0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ea02d192a39a8cc7a701730073011001020402d19683030193a38cc7b2a57300000193c2b2a57301007473027303830108cdeeac93b1a57304", + assets: [], + creationHeight: 1695302, + additionalRegisters: {}, + transactionId: "569b9f36b41c0dc0a6c488eea12fe803b7a6bd97d2b92079d455f6d0dd9080a2", + index: 3 + }, + { + boxId: "44e46ec02820d18985ad733e04f0ce1bff7ce0cbecf329a0f8b8f238969d3d2a", + value: 157516100000n, + ergoTree: + "0008cd023625de27837c0d91735145f7330fb1867cfe23b8e27b20e2a7d31bc825ef4f8e", + assets: [ + { + tokenId: "4cccf7e1072b31ffd46819b317ec22900125f5c284fe5f48a5ab765a0dc4646b", + amount: 1999n + }, + { + tokenId: "0808146416deee934d68c3c664e44e59dd28137f508ada35c5d7023e932f5bfb", + amount: 1999n + }, + { + tokenId: "4d43aac602925a7bebe8f0ca9b807de6d12b0d38fa431b441a0ddb9da18f14f0", + amount: 1999n + }, + { + tokenId: "47303b1562e0daa1bb5e60800bf94c1d00b5cbd9822597902cf8d0891163e303", + amount: 999n + }, + { + tokenId: "6bd0539b01fffb7089f62c8273c4ea011e5afbf56abd36bce3e06df76d23950e", + amount: 999n + }, + { + tokenId: "b6f370819d260ab71ea604003166b8f3f50b396547f1871caf3b792b82ed9c18", + amount: 999n + }, + { + tokenId: "d2979568702864ed64a66fd8e463a4deac40414789e043412c4a6acc36244f27", + amount: 999n + }, + { + tokenId: "ca6207d95a30008aced30383f7a4d7f480bec9b0c5f8837b53b10e7325a7a25c", + amount: 999n + }, + { + tokenId: "0efd122a1ee77629173d58172cdfb95291011a63639fd566c662dad2f6b9d717", + amount: 998n + }, + { + tokenId: "9bed938ef060681c491fb5a9449b2d016ae4d70027ed37b7ba8edb9024236fd4", + amount: 1n + }, + { + tokenId: "18c4789bf5be7ca1f8fa948d545410f48b00f26c306a8b07fc70510acc7f2955", + amount: 1n + }, + { + tokenId: "19b12e031b016194d9392abd206b05b720151405a6f63836e9af9b14e0c5e8b8", + amount: 1n + }, + { + tokenId: "cb846674811fce92dc27f0eb7c383d4c4eef6e6d822106314e6b73c0ec7d844f", + amount: 1n + }, + { + tokenId: "8ad7115184b29508615d7a43280287eacad8da4f3d71a2249f8cf076fb0ac325", + amount: 1n + }, + { + tokenId: "2b6ee7dbee4fb54bb2208ceb94fbfd6e7d6b6d34a3e81a1a051246045320a6b1", + amount: 1n + }, + { + tokenId: "983a0bbd7c7812c99cacc1deea91ad0a66d230d2e5e1a214e07ae5a8f19cd285", + amount: 1n + }, + { + tokenId: "1f99db8f22d5b8a893a15ca0f2d2c82f27af105a0df4c56cb0c1693682dd717b", + amount: 1n + }, + { + tokenId: "38b1726143ae6d0b994a847cb60753832a3cd11f1c85f964cda339a6ec18cb27", + amount: 1n + }, + { + tokenId: "062a8e4347075de1b941e1df33a289208603f53604a2412e2c6f1d46643fbb2a", + amount: 1n + }, + { + tokenId: "b315facd2e470447b2b71742a67d7f75bf5634f0fd892e8b705bbc415a24bffe", + amount: 1n + }, + { + tokenId: "fd527aec6d1002684d92d4b01edcdc41735d70fcf4f810eba97fc6af303afd71", + amount: 1n + }, + { + tokenId: "53d789de7b995f1c70d0f2a5bd21a0215bb98249583bc421ba8ac1ac5ee19b6b", + amount: 1n + }, + { + tokenId: "a401b300df54c68a92bf7a9378b88b5aafb31fdd4519d8b2fee90bcd8a1e50d4", + amount: 1n + }, + { + tokenId: "217e87287fd1789dbd35e125216ddd2d9008e54bd15a306f5243ca95cc769a9f", + amount: 1n + }, + { + tokenId: "0599a724747cff93e7ff4632de47a2066a04873266911d9ad37cc3c5e2db557d", + amount: 1n + }, + { + tokenId: "b07116c93d89375b413e8b999b4d516765a1cbf62c8ad371f58ea614d223c125", + amount: 1n + }, + { + tokenId: "f8c961dacc8205cb87cecb489425f29a4e025329e0768aea2bb0090200dc9e9c", + amount: 1n + }, + { + tokenId: "0ee65950a205f621ee1f2dca4f4486f3abe6a212b8af67e32fe25cb6ff11269b", + amount: 1n + }, + { + tokenId: "cff034f703d03360c8d0c0f7bce5b583c846cb25736bb39f170effe84ce5f606", + amount: 1n + }, + { + tokenId: "93c229fd5f3c5c86552f5fa2388f2b2d67277d6931346f556cbd8659f1e3d291", + amount: 1n + }, + { + tokenId: "1c8dd09bea3e543693d83f071383913636a946d5212433196169791d9be26926", + amount: 1n + }, + { + tokenId: "315f8b2f359b0a075e37956ddcb5a1b01c1e0f0bbd11ab6f29bb63bb3dac5dcc", + amount: 1n + }, + { + tokenId: "e4e827c2075562040dbed13d1f9df4aa7997deffee4d5f9b70fa143ddc21d318", + amount: 1n + }, + { + tokenId: "65f44be8b1d8170c19d8fb7e04dde54ed417dfad0a5dd75e484e703f932cd378", + amount: 1n + }, + { + tokenId: "3ef6a5d12e8805d5b230cd0449ea583a31af4f5b401c89d5cb6c64507155607b", + amount: 1n + }, + { + tokenId: "23a0a5e17283e365fba81e740009dc1a914094f659beb1d7dc0016660ddfe595", + amount: 1n + }, + { + tokenId: "c594fec99373a13ac3b427194c7e7a7ba655aef9ed67784933cbed96947b0be5", + amount: 1n + }, + { + tokenId: "05e94d88deae5a3a226ae6e6525c2c5a31336383bf5b25cbd8bc528dd28cd7e0", + amount: 1n + }, + { + tokenId: "9efbd10417d7257acf30fd2ce05d87a799e2f7eae381b4ae227d2134e4597430", + amount: 1n + }, + { + tokenId: "0a400456dbd989b6fe3fb0657bb1e0b549393ecf47f5d1a40153ea7459952e4d", + amount: 1n + }, + { + tokenId: "2f267741a770ce2298d2c9a32e2c7c6437ec08d3e47d17d3e39ad4ff477b4ca6", + amount: 1n + }, + { + tokenId: "daba905eec3a0820ca871b48dc262d07fe40fa575f607898f9bdff1e546a754b", + amount: 1n + }, + { + tokenId: "da039d2d79666f4f45638da400610d7895e1b9349ff77719be2b090269de502e", + amount: 1n + }, + { + tokenId: "b6039680491bfb9fe1ed0f9c4099c62e0935f3ec6fcd31475d5bda09150fd747", + amount: 1n + }, + { + tokenId: "e3100c00a3457968aa2bd2aee4e973fd57a5c61306340eaffcdfbe70c7ffee73", + amount: 1n + }, + { + tokenId: "b2dce8dd5ed8c94756620d71a756c7cc2243cc791c429662b143ff04070f8fb0", + amount: 1n + }, + { + tokenId: "02407e5bbd0944b63dd80c2198642b80a99a3351364b29576bffd34efb396a77", + amount: 1n + }, + { + tokenId: "5aded41671c6b7868c98232bb3a1da63a0274bf04bb50f2ceeaabcc38d3169d6", + amount: 1n + }, + { + tokenId: "c90fbf556e52d54802c4d17b725dd2496e143e7cfd7e641752f4ed75a685a924", + amount: 1n + }, + { + tokenId: "1e1fd8b00c0a103bfc703f44bd37495578ae01e2431440124bc2a90035428841", + amount: 1n + }, + { + tokenId: "b317b8fe54aed1857d71d8fd8c0c2097e2ca10495b29b9397099f7fe13ebafa7", + amount: 1n + }, + { + tokenId: "7d2ed04b780493550fc6250c56306be56b241d20876e455cb031e174696676fd", + amount: 1n + }, + { + tokenId: "ed086bebbf2adebb55233e5a80f104a168894b721fddb158b5a0a08686171c38", + amount: 1n + }, + { + tokenId: "fcc804cd8e92d9642eecff884154da954a49a1fbb85d20e6330dfd2a2fea23e3", + amount: 1n + }, + { + tokenId: "fc6be8ea6960a047118ad021388212ad228cb173eefa6010fc243d9b1d597bb3", + amount: 1n + }, + { + tokenId: "2bd3445e39f3f12d121580497c4ee777107a8d4bddc975478f3828025460b70e", + amount: 1n + }, + { + tokenId: "aeba6450faf1abb69a88cab56984cb53da5a0c93793974f7a4ab277092ad7a82", + amount: 1n + }, + { + tokenId: "45932b98740c0a074ec4826bf66029f03813961c292ba4185c57235fee49daac", + amount: 1n + }, + { + tokenId: "58a0b64268ab8e17f8b9fed9f5f970ef028ef84b8709509e8d7c9a926c6027f5", + amount: 1n + }, + { + tokenId: "b5d6af4afe83f167d7696def8a785bd55395dc81eca55ec1fa28c6aa53bbcfc9", + amount: 12000n + }, + { + tokenId: "362acadb91689c757f2b5e45a42bdada7a6da8fd1ac83bc876082c0221c442c1", + amount: 1n + }, + { + tokenId: "f319c3d558d12b78463f65d09f392005f9e0b5adbd2b3bef97a993fda24092a4", + amount: 1000000000n + } + ], + creationHeight: 1695302, + additionalRegisters: {}, + transactionId: "569b9f36b41c0dc0a6c488eea12fe803b7a6bd97d2b92079d455f6d0dd9080a2", + index: 4 + } + ] +}; + +export const deserializableTxVectors: { + name: string; + tx: SignedTransaction | UnsignedTransaction; +}[] = [ + { name: "Unsigned transaction without tokens", tx: unsignedTransactionVectors[2].json }, + { + name: "Unsigned transaction with many tokens", + tx: unsignedTransactionVectors[4].json + }, + { + name: "Unsinged transaction with data inputs", + tx: { + ...unsignedTransactionVectors[4].json, + dataInputs: [ + { boxId: "6394efce52392141d67cdc70d9474ff85fea07df49530e85b9d26fbe43362bc4" }, + { boxId: "0d12f7a3872db6673765fb245035040c8b21cfe70ab73f49249d38c424bcd113" } + ] + } + }, + { + name: "raffle signed transaction", + tx: raffleSignedTransaction + } +]; diff --git a/packages/serializer/src/coders/sigmaByteReader.spec.ts b/packages/serializer/src/coders/sigmaByteReader.spec.ts new file mode 100644 index 00000000..86d9bdd6 --- /dev/null +++ b/packages/serializer/src/coders/sigmaByteReader.spec.ts @@ -0,0 +1,64 @@ +import { describe, it, expect } from "vitest"; +import { SigmaByteReader } from "./sigmaByteReader"; + +const u8a = (bytes: number[]) => new Uint8Array(bytes); + +describe("Sigma byte reader", () => { + it("should read bytes and move the cursor", () => { + const bytes = u8a([0x01, 0x02, 0x03, 0x04]); + const reader = new SigmaByteReader(bytes); + + expect(reader.readByte()).toBe(0x01); + expect(reader.readBytes(2)).toEqual(u8a([0x02, 0x03])); + expect(reader.readByte()).toBe(0x04); + }); + + it("should peek bytes ahead but not move the cursor", () => { + const bytes = u8a([0x01, 0x02, 0x03, 0x04]); + const reader = new SigmaByteReader(bytes); + + expect(reader.peek(1)).toEqual(u8a([0x01])); + expect(reader.peek(2)).toEqual(u8a([0x01, 0x02])); + expect(reader.peek(10)).toEqual(u8a([0x01, 0x02, 0x03, 0x04])); // read all bytes if length is greater than available bytes + + expect(reader.readByte()).toBe(0x01); // move cursor + expect(reader.peek(1)).toEqual(u8a([0x02])); + }); + + it("should peek bytes ahead but not move the cursor with offset", () => { + const bytes = u8a([0x01, 0x02, 0x03, 0x04]); + const reader = new SigmaByteReader(bytes); + + expect(reader.peek(1, 1)).toEqual(u8a([0x02])); + expect(reader.peek(2, 2)).toEqual(u8a([0x03, 0x04])); + expect(reader.peek(10, 2)).toEqual(u8a([0x03, 0x04])); // read all bytes if length is greater than available bytes + + expect(reader.readByte()).toBe(0x01); // move cursor + expect(reader.peek(1, 2)).toEqual(u8a([0x04])); + }); + + it("should match bytes ahead", () => { + const bytes = u8a([0x01, 0x02, 0x03, 0x04]); + const reader = new SigmaByteReader(bytes); + + expect(reader.match(u8a([0x01, 0x02]))).toBe(true); + expect(reader.match(u8a([0x02, 0x03]))).toBe(false); + + expect(reader.match(u8a([0x01, 0x02, 0x03, 0x04]))).toBe(true); + expect(reader.match(u8a([0x01, 0x02, 0x03, 0x04, 0x05]))).toBe(false); + + expect(reader.readByte()).toBe(0x01); // move cursor + expect(reader.match(u8a([0x02, 0x03]))).toBe(true); + }); + + it("should match bytes ahead with offset", () => { + const bytes = u8a([0x01, 0x02, 0x03, 0x04, 0x05, 0x06]); + const reader = new SigmaByteReader(bytes); + + expect(reader.match(u8a([0x03, 0x04]), 2)).toBe(true); + expect(reader.match(u8a([0x01, 0x02]), 1)).toBe(false); + + expect(reader.match(u8a([0x04, 0x05, 0x06]), 3)).toBe(true); + expect(reader.match(u8a([0x04, 0x05, 0x06, 0x07]), 3)).toBe(false); + }); +}); diff --git a/packages/serializer/src/coders/sigmaByteReader.ts b/packages/serializer/src/coders/sigmaByteReader.ts index 9ff70d4f..afe2ac9c 100644 --- a/packages/serializer/src/coders/sigmaByteReader.ts +++ b/packages/serializer/src/coders/sigmaByteReader.ts @@ -1,4 +1,4 @@ -import { isEmpty } from "@fleet-sdk/common"; +import { isEmpty, startsWith } from "@fleet-sdk/common"; import { type ByteInput, ensureBytes, hex } from "@fleet-sdk/crypto"; import { hexToBigInt } from "./bigint"; import { readBigVLQ, readVLQ } from "./vlq"; @@ -9,8 +9,16 @@ export class SigmaByteReader { readonly #bytes: Uint8Array; #cursor: number; - public get isEmpty(): boolean { - return isEmpty(this.#bytes); + get isEmpty(): boolean { + return this.#bytes.length === this.#cursor; + } + + get bytes(): Uint8Array { + return this.#bytes; + } + + get cursor(): number { + return this.#cursor; } constructor(bytes: ByteInput) { @@ -18,11 +26,22 @@ export class SigmaByteReader { this.#cursor = 0; } - public readBool(): boolean { + readArray(readFn: (reader: SigmaByteReader, index: number) => T): Array { + const length = this.readUInt(); + const items = new Array(length); + + for (let i = 0; i < length; i++) { + items[i] = readFn(this, i); + } + + return items; + } + + readBool(): boolean { return this.readByte() === 0x01; } - public readBits(length: number): ArrayLike { + readBits(length: number): ArrayLike { const bits = new Array(length); let bitOffset = 0; @@ -41,37 +60,56 @@ export class SigmaByteReader { return bits; } - public readByte(): number { + readByte(): number { return this.#bytes[this.#cursor++]; } - public readBytes(length: number): Uint8Array { + readBytes(length: number): Uint8Array { return this.#bytes.subarray(this.#cursor, (this.#cursor += length)); } - public readVlq(): number { + readUInt(): number { return readVLQ(this); } - public readI8(): number { + readBigUInt(): bigint { + return readBigVLQ(this); + } + + readI8(): number { const byte = this.readByte(); return byte > MAX_I8 ? byte - (MAX_U8 + 1) : byte; } - public readI16(): number { + readI16(): number { return zigZag32.decode(readBigVLQ(this)); } - public readI32(): number { + readI32(): number { return zigZag32.decode(readBigVLQ(this)); } - public readI64(): bigint { + readI64(): bigint { return zigZag64.decode(readBigVLQ(this)); } - public readI256(): bigint { + readI256(): bigint { const len = readVLQ(this); return hexToBigInt(hex.encode(this.readBytes(len))); } + + /** + * Returns bytes without advancing the cursor. + */ + peek(count: number, offset = 0): Uint8Array { + const begin = this.#cursor + offset; + return this.#bytes.subarray(begin, begin + count); + } + + /** + * Checks if the current position in the byte array starts with the given bytes. + */ + match(bytes: Uint8Array, offset = 0): boolean { + return startsWith(this.#bytes, bytes, this.#cursor + offset); + } } diff --git a/packages/serializer/src/coders/sigmaByteWriter.ts b/packages/serializer/src/coders/sigmaByteWriter.ts index 695e0a62..07e45b59 100644 --- a/packages/serializer/src/coders/sigmaByteWriter.ts +++ b/packages/serializer/src/coders/sigmaByteWriter.ts @@ -17,7 +17,7 @@ export class SigmaByteWriter { readonly #bytes: Uint8Array; #cursor: number; - public get length() { + get length() { return this.#cursor; } @@ -26,70 +26,69 @@ export class SigmaByteWriter { this.#cursor = 0; } - public writeBool(value: boolean): SigmaByteWriter { + writeBool(value: boolean): SigmaByteWriter { this.write(value === true ? 0x01 : 0x00); - return this; } - public writeVLQ(value: number): SigmaByteWriter { + writeUInt(value: number): SigmaByteWriter { return writeVLQ(this, value); } - public writeBigVLQ(value: bigint): SigmaByteWriter { + writeBigUInt(value: bigint): SigmaByteWriter { return writeBigVLQ(this, value); } - public writeI16(value: number): SigmaByteWriter { + writeI16(value: number): SigmaByteWriter { if (value < MIN_I16 || value > MAX_I16) { throw new RangeError(`Value ${value} is out of range for a 16-bit integer`); } - this.writeBigVLQ(zigZag32.encode(value)); + this.writeBigUInt(zigZag32.encode(value)); return this; } - public writeI32(value: number): SigmaByteWriter { + writeI32(value: number): SigmaByteWriter { if (value < MIN_I32 || value > MAX_I32) { throw new RangeError(`Value ${value} is out of range for a 32-bit integer`); } - return this.writeBigVLQ(zigZag32.encode(value)); + return this.writeBigUInt(zigZag32.encode(value)); } - public writeI64(value: bigint): SigmaByteWriter { + writeI64(value: bigint): SigmaByteWriter { if (value < MIN_I64 || value > MAX_I64) { throw new RangeError(`Value ${value} is out of range for a 64-bit integer`); } - return this.writeBigVLQ(zigZag64.encode(value)); + return this.writeBigUInt(zigZag64.encode(value)); } - public writeI256(value: bigint): SigmaByteWriter { + writeI256(value: bigint): SigmaByteWriter { if (value < MIN_I256 || value > MAX_I256) { throw new RangeError(`Value ${value} is out of range for a 256-bit integer`); } const hex = bigIntToHex(value); - return this.writeVLQ(hex.length / 2).writeHex(hex); + return this.writeUInt(hex.length / 2).writeHex(hex); } - public write(byte: number): SigmaByteWriter { + write(byte: number): SigmaByteWriter { this.#bytes[this.#cursor++] = byte; return this; } - public writeBytes(bytes: ArrayLike): SigmaByteWriter { + writeBytes(bytes: ArrayLike): SigmaByteWriter { this.#bytes.set(bytes, this.#cursor); this.#cursor += bytes.length; return this; } - public writeHex(bytesHex: string): SigmaByteWriter { + writeHex(bytesHex: string): SigmaByteWriter { return this.writeBytes(hex.decode(bytesHex)); } - public writeBits(bits: ArrayLike): SigmaByteWriter { + writeBits(bits: ArrayLike): SigmaByteWriter { let bitOffset = 0; for (let i = 0; i < bits.length; i++) { @@ -110,16 +109,39 @@ export class SigmaByteWriter { return this; } - public writeChecksum(length = 4, hashFn = blake2b256): SigmaByteWriter { + writeChecksum(length = 4, hashFn = blake2b256): SigmaByteWriter { const hash = hashFn(this.toBytes()); return this.writeBytes(length ? hash.subarray(0, length) : hash); } - public encode(coder: Coder): T { + /** + * Writes a length-delimited array of items to the byte stream using a provided + * serializer function. + * + * @typeParam T - The type of items in the array. + * @param items - The array of items to serialize and write. + * @param serializer - A function that serializes each item and writes it using the provided SigmaByteWriter. + * @returns The current instance of SigmaByteWriter for method chaining. + */ + writeArray( + items: T[], + serializer: (item: T, writer: SigmaByteWriter) => void + ): SigmaByteWriter { + this.writeUInt(items.length); + if (items.length === 0) return this; + + for (const item of items) { + serializer(item, this); + } + + return this; + } + + encode(coder: Coder): T { return coder.encode(this.toBytes()); } - public toBytes(): Uint8Array { + toBytes(): Uint8Array { if (this.#cursor === this.#bytes.length) return this.#bytes; return this.#bytes.subarray(0, this.#cursor); } diff --git a/packages/serializer/src/serializers/boxSerializer.spec.ts b/packages/serializer/src/serializers/boxSerializer.spec.ts index 57671cf9..2353949d 100644 --- a/packages/serializer/src/serializers/boxSerializer.spec.ts +++ b/packages/serializer/src/serializers/boxSerializer.spec.ts @@ -1,11 +1,13 @@ import { type Box, byteSizeOf, ensureBigInt, first } from "@fleet-sdk/common"; -import { hex } from "@fleet-sdk/crypto"; +import { blake2b256, hex } from "@fleet-sdk/crypto"; import { manyTokensBoxes, regularBoxes, validBoxes } from "_test-vectors"; -import { describe, expect, it } from "vitest"; -import { boxVectors } from "../_test-vectors/boxVectors"; -import { estimateBoxSize, serializeBox } from "./boxSerializer"; +import { describe, expect, it, test } from "vitest"; +import { boxVectors, deserializationTestVectors } from "../_test-vectors/boxVectors"; +import { estimateBoxSize, deserializeBox, serializeBox } from "./boxSerializer"; +import { SigmaByteReader } from "../coders"; +import { mockUTxO } from "packages/mock-chain/src"; -describe("Serialize ErgoBox", () => { +describe("ErgoBox serialization", () => { it.each(boxVectors)("Should serialize [$json.boxId]", (tv) => { expect(serializeBox(tv.json).encode(hex)).toBe(tv.hex); }); @@ -79,4 +81,38 @@ describe("Serialize ErgoBox", () => { expect(() => estimateBoxSize(output)).toThrow(); }); + + test.each(deserializationTestVectors)( + "roundtrip box serialization, case: $name", + ({ name, box }) => { + const serialized = serializeBox(box).toBytes(); + const deserialized = deserializeBox(serialized); + expect(deserialized).toEqual(box); + + const boxId = hex.encode(blake2b256(serialized)); + expect(deserialized.boxId).toEqual(boxId); + } + ); + + it("Should deserialize from SigmaByteReader", () => { + const box = deserializationTestVectors[0].box; + + const serialized = serializeBox(box).toBytes(); + const deserialized = deserializeBox(new SigmaByteReader(serialized)); + expect(deserialized).toEqual(box); + + const boxId = hex.encode(blake2b256(serialized)); + expect(deserialized.boxId).toEqual(boxId); + }); + + it("Should fail to parse box without the size flag for a unknown contract", () => { + const box = mockUTxO({ + ergoTree: + "1014040004000e208c27dd9d8a35aac1e3167d58858c0a8b4059b277da790552e37eba22df9b903504000400040204020101040205a0c21e040204080500040c040204a0c21e0402050a05c8010402d806d601b2a5730000d602b5db6501fed9010263ed93e4c67202050ec5a7938cb2db63087202730100017302d603b17202d604e4c6b272027303000605d605d90105049590720573047204e4c6b272029972057305000605d606b07202860273067307d901063c400163d803d6088c720601d6098c720801d60a8c72060286029a72097308ededed8c72080293c2b2a5720900d0cde4c6720a040792c1b2a5720900730992da720501997209730ae4c6720a0605ea02d1ededededededed93cbc27201e4c6a7060e927203730b93db63087201db6308a793e4c6720104059db07202730cd9010741639a8c720701e4c68c72070206057e72030593e4c6720105049ae4c6a70504730d92c1720199c1a77e9c9a7203730e730f058c72060292da720501998c72060173109972049d9c720473117312b2ad7202d9010763cde4c672070407e4c6b2a5731300040400" + }); + + expect(() => deserializeBox(serializeBox(box).toBytes())).toThrow( + "ErgoTree parsing without the size flag is not supported." + ); + }); }); diff --git a/packages/serializer/src/serializers/boxSerializer.ts b/packages/serializer/src/serializers/boxSerializer.ts index 1827a36c..a01f42ce 100644 --- a/packages/serializer/src/serializers/boxSerializer.ts +++ b/packages/serializer/src/serializers/boxSerializer.ts @@ -1,41 +1,44 @@ import { - type Amount, - type Box, - type BoxCandidate, byteSizeOf, ensureBigInt, + ergoTreeHeaderFlags, + FEE_CONTRACT, isDefined, - isEmpty, - isUndefined, - type NonMandatoryRegisters, - some, - type TokenAmount + isUndefined } from "@fleet-sdk/common"; -import { estimateVLQSize, SigmaByteWriter } from "../coders"; +import type { + Amount, + Box, + BoxCandidate, + NonMandatoryRegisters, + TokenAmount +} from "@fleet-sdk/common"; +import { estimateVLQSize, SigmaByteReader, SigmaByteWriter } from "../coders"; +import { blake2b256, hex, validateEcPoint } from "@fleet-sdk/crypto"; +import type { ByteInput } from "../types/constructors"; +import { SConstant } from "../sigmaConstant"; const MAX_UINT16_VALUE = 65535; -export function serializeBox(box: Box): SigmaByteWriter; -export function serializeBox(box: Box, writer: SigmaByteWriter): SigmaByteWriter; -export function serializeBox( - box: BoxCandidate, - writer: SigmaByteWriter, - distinctTokenIds: string[] -): SigmaByteWriter; +const FEE_CONTRACT_BYTES = hex.decode(FEE_CONTRACT); +const P2PK_CONTRACT_PREFIX = hex.decode("0008cd"); +const COMPRESSED_PK_LENGTH = 33; +const P2PK_CONTRACT_LENGTH = P2PK_CONTRACT_PREFIX.length + COMPRESSED_PK_LENGTH; + export function serializeBox( box: Box | BoxCandidate, writer = new SigmaByteWriter(4_096), distinctTokenIds?: string[] ): SigmaByteWriter { - writer.writeBigVLQ(ensureBigInt(box.value)); + writer.writeBigUInt(ensureBigInt(box.value)); writer.writeHex(box.ergoTree); - writer.writeVLQ(box.creationHeight); + writer.writeUInt(box.creationHeight); writeTokens(writer, box.assets, distinctTokenIds); writeRegisters(writer, box.additionalRegisters); if (isDefined(distinctTokenIds)) return writer; if (!isBox(box)) throw new Error("Invalid box type."); - return writer.writeHex(box.transactionId).writeVLQ(box.index); + return writer.writeHex(box.transactionId).writeUInt(box.index); } function isBox(box: Box | BoxCandidate): box is Box { @@ -48,40 +51,31 @@ function writeTokens( tokens: TokenAmount[], tokenIds?: string[] ): void { - if (isEmpty(tokens)) { - writer.write(0); - return; - } - - writer.writeVLQ(tokens.length); - if (some(tokenIds)) { - tokens.map((token) => - writer - .writeVLQ(tokenIds.indexOf(token.tokenId)) - .writeBigVLQ(ensureBigInt(token.amount)) + if (tokenIds) { + writer.writeArray(tokens, (token, w) => + w + .writeUInt(tokenIds.indexOf(token.tokenId)) + .writeBigUInt(ensureBigInt(token.amount)) ); } else { - tokens.map((token) => - writer.writeHex(token.tokenId).writeBigVLQ(ensureBigInt(token.amount)) + writer.writeArray(tokens, (token, w) => + w.writeHex(token.tokenId).writeBigUInt(ensureBigInt(token.amount)) ); } } function writeRegisters(writer: SigmaByteWriter, registers: NonMandatoryRegisters): void { const keys = Object.keys(registers).sort(); - let length = 0; + const values: string[] = []; for (const key of keys) { - if (registers[key as keyof NonMandatoryRegisters]) length++; - } + const value = registers[key as keyof NonMandatoryRegisters]; + if (!value) continue; - writer.writeVLQ(length); - if (length === 0) return; - - for (const key of keys) { - const register = registers[key as keyof NonMandatoryRegisters]; - if (isDefined(register)) writer.writeHex(register); + values.push(value); } + + writer.writeArray(values, (value, w) => w.writeHex(value)); } /** @@ -122,3 +116,134 @@ export function estimateBoxSize( return size; } + +/** + * Deserializes a box embedded in a transaction. + * + * It efficiently calculates the box ID by accumulating the serialized data during + * deserialization and applying blake2b256 hashing, avoiding redundant serialization + * operations. + * + * @param reader - SigmaByteReader containing the serialized box data + * @param distinctTokenIds - Array of TokenIDs referenced in the parent transaction + * @param transactionId - ID of the transaction containing this box + * @param index - Index position of the box in the transaction outputs + * @returns A fully deserialized Box with all properties including boxId + */ +export function deserializeEmbeddedBox( + reader: SigmaByteReader, + distinctTokenIds: string[], + transactionId: string, + index: number +): Box { + // SigmaByteReader moves the cursor on read, so we need to save the current position to + // track read bytes. + let begin = reader.cursor; + + const value = reader.readBigUInt(); + const ergoTree = hex.encode(readErgoTree(reader)); + const creationHeight = reader.readUInt(); + + // Calculating the BoxID needs the full box data, so to avoid serialization road-trips, + // we will accumulate the the box data in a SigmaByteWriter and then calculate the hash + // from the its bytes. + const boxIdWriter = new SigmaByteWriter(4_096) // max size of a box + .writeBytes(reader.bytes.subarray(begin, reader.cursor)); // copy the bytes read so far + + const assets = readTokens(reader, distinctTokenIds); + + // TokenIDs need to be written in the full box writer + boxIdWriter.writeUInt(assets.length); + for (const asset of assets) { + boxIdWriter.writeHex(asset.tokenId).writeBigUInt(asset.amount); + } + + begin = reader.cursor; // save the current cursor position again to track the registers bytes + const additionalRegisters = readRegisters(reader); + + boxIdWriter + .writeBytes(reader.bytes.subarray(begin, reader.cursor)) // write the registers + .writeHex(transactionId) + .writeUInt(index); + + return { + boxId: hex.encode(blake2b256(boxIdWriter.toBytes())), + value, + ergoTree, + creationHeight, + assets, + additionalRegisters, + transactionId, + index + }; +} + +export function deserializeBox( + input: ByteInput | SigmaByteReader +): BoxCandidate | Box { + const reader = input instanceof SigmaByteReader ? input : new SigmaByteReader(input); + const begin = reader.cursor; // save the current cursor position to track the read bytes + + const box: Box = { + boxId: "", // placeholder, will be calculated later + value: reader.readBigUInt(), + ergoTree: hex.encode(readErgoTree(reader)), + creationHeight: reader.readUInt(), + assets: readTokens(reader), + additionalRegisters: readRegisters(reader), + transactionId: hex.encode(reader.readBytes(32)), + index: reader.readUInt() + }; + + box.boxId = hex.encode(blake2b256(reader.bytes.subarray(begin, reader.cursor))); + return box; +} + +function readErgoTree(reader: SigmaByteReader): Uint8Array { + // handles miner fee contract + if (reader.match(FEE_CONTRACT_BYTES)) { + return reader.readBytes(FEE_CONTRACT_BYTES.length); + } + + // handles P2PK contracts + if ( + reader.match(P2PK_CONTRACT_PREFIX) && + validateEcPoint(reader.peek(COMPRESSED_PK_LENGTH, P2PK_CONTRACT_PREFIX.length)) + ) { + return reader.readBytes(P2PK_CONTRACT_LENGTH); + } + + // handles contracts with the size flag enabled + const header = reader.readByte(); + const hasSize = (header & ergoTreeHeaderFlags.sizeInclusion) !== 0; + if (!hasSize) { + throw new Error("ErgoTree parsing without the size flag is not supported."); + } + + const size = reader.readUInt(); + return new SigmaByteWriter(1 + 4 + size) // header + vlq size + body + .write(header) + .writeUInt(size) + .writeBytes(reader.readBytes(size)) + .toBytes(); +} + +function readTokens(reader: SigmaByteReader, tokenIds?: string[]): TokenAmount[] { + return reader.readArray((r) => ({ + tokenId: tokenIds ? tokenIds[r.readUInt()] : hex.encode(r.readBytes(32)), + amount: r.readBigUInt() + })); +} + +function readRegisters(reader: SigmaByteReader): NonMandatoryRegisters { + const registers: NonMandatoryRegisters = {}; + const count = reader.readUInt(); + + for (let i = 0; i < count; i++) { + // const key = reader.readByte(); + const value = SConstant.from(reader).toHex(); + registers[`R${(i + 4).toString()}` as keyof NonMandatoryRegisters] = value; + } + + return registers; +} diff --git a/packages/serializer/src/serializers/dataSerializer.ts b/packages/serializer/src/serializers/dataSerializer.ts index 7f4e8464..5dc83d6b 100644 --- a/packages/serializer/src/serializers/dataSerializer.ts +++ b/packages/serializer/src/serializers/dataSerializer.ts @@ -47,7 +47,7 @@ export const dataSerializer = { assert(Array.isArray(data), `SColl expected an array, got ${typeof data}.`); } - writer.writeVLQ(data.length); + writer.writeUInt(data.length); switch (type.elementsType.code) { case descriptors.bool.code: { return writer.writeBits(data as boolean[]); @@ -114,7 +114,7 @@ export const dataSerializer = { } else { switch (type.code) { case descriptors.coll.code: { - const length = reader.readVlq(); + const length = reader.readUInt(); const embeddedType = (type as SCollType).elementsType; switch (embeddedType.code) { diff --git a/packages/serializer/src/serializers/transactionSerializer.spec.ts b/packages/serializer/src/serializers/transactionSerializer.spec.ts index dac06c73..4557dac4 100644 --- a/packages/serializer/src/serializers/transactionSerializer.spec.ts +++ b/packages/serializer/src/serializers/transactionSerializer.spec.ts @@ -1,7 +1,11 @@ import { blake2b256, hex } from "@fleet-sdk/crypto"; import { describe, expect, it, test } from "vitest"; -import { unsignedTransactionVectors } from "../_test-vectors/transactionVectors"; -import { serializeTransaction } from "./transactionSerializer"; +import { + deserializableTxVectors, + raffleSignedTransaction, + unsignedTransactionVectors +} from "../_test-vectors/transactionVectors"; +import { deserializeTransaction, serializeTransaction } from "./transactionSerializer"; import signedTransactionVectors from "../_test-vectors/signedTransactions.json"; import { isEmpty } from "@fleet-sdk/common"; @@ -17,7 +21,26 @@ describe("Transaction serializer", () => { ); test.each(signedTransactionVectors)("should serialize signed transaction", (tv) => { - expect(hex.encode(serializeTransaction(tv.json).toBytes())).toBe(tv.hex); + expect(serializeTransaction(tv.json).encode(hex)).toBe(tv.hex); + }); + + test.each(deserializableTxVectors)( + "should roundtrip transaction serialization, case: $name", + ({ name, tx }) => { + const serialized = serializeTransaction(tx).toBytes(); + const deserialized = deserializeTransaction(serialized); + + expect(deserialized).toMatchObject(tx); + } + ); + + it("should calculate the correct transaction id on deserialization", () => { + const tv = raffleSignedTransaction; // signed transaction + + const serialized = serializeTransaction(tv).encode(hex); + const deserialized = deserializeTransaction(serialized); + + expect(deserialized.id).toBe(tv.id); }); it("should serialize if input extension is undefined", () => { @@ -31,6 +54,6 @@ describe("Transaction serializer", () => { } } - expect(hex.encode(serializeTransaction(tx).toBytes())).toEqual(tv.hex); + expect(serializeTransaction(tx).encode(hex)).toEqual(tv.hex); }); }); diff --git a/packages/serializer/src/serializers/transactionSerializer.ts b/packages/serializer/src/serializers/transactionSerializer.ts index a95882ce..b613bf66 100644 --- a/packages/serializer/src/serializers/transactionSerializer.ts +++ b/packages/serializer/src/serializers/transactionSerializer.ts @@ -1,63 +1,56 @@ import type { Amount, BoxCandidate, - DataInput, SignedInput, SignedTransaction, - UnsignedInput + UnsignedInput, + UnsignedTransaction } from "@fleet-sdk/common"; -import { isDefined } from "@fleet-sdk/common"; -import { SigmaByteWriter } from "../coders"; -import { serializeBox } from "./boxSerializer"; -import { hex } from "@fleet-sdk/crypto"; - -export type MinimalUnsignedTransaction = { - inputs: UnsignedInput[]; - dataInputs: DataInput[]; - outputs: BoxCandidate[]; -}; +import { SigmaByteReader, SigmaByteWriter } from "../coders"; +import { deserializeEmbeddedBox, serializeBox } from "./boxSerializer"; +import { blake2b256, hex } from "@fleet-sdk/crypto"; +import type { ByteInput } from "../types/constructors"; +import { SConstant } from "../sigmaConstant"; type Nullish = T | null | undefined; +type Input = UnsignedInput | SignedInput; +type Transaction = UnsignedTransaction | SignedTransaction; -export function serializeTransaction( - transaction: MinimalUnsignedTransaction | SignedTransaction -): SigmaByteWriter { - const writer = new SigmaByteWriter(100_000); - - // write inputs - writer.writeVLQ(transaction.inputs.length); - transaction.inputs.map((input) => writeInput(writer, input)); - - // write data inputs - writer.writeVLQ(transaction.dataInputs.length); - transaction.dataInputs.map((dataInput) => writer.writeHex(dataInput.boxId)); - - // write distinct token IDs - const distinctTokenIds = getDistinctTokenIds(transaction.outputs); - writer.writeVLQ(distinctTokenIds.length); - distinctTokenIds.map((tokenId) => writer.writeHex(tokenId)); +export function serializeTransaction(transaction: Transaction): SigmaByteWriter { + const tokenIds = getDistinctTokenIds(transaction.outputs); - // write outputs - writer.writeVLQ(transaction.outputs.length); - transaction.outputs.map((output) => serializeBox(output, writer, distinctTokenIds)); - - return writer; + return new SigmaByteWriter(100_000) + .writeArray(transaction.inputs, (input, w) => writeInput(w, input)) + .writeArray(transaction.dataInputs, (dataInput, w) => w.writeHex(dataInput.boxId)) + .writeArray(tokenIds, (tokenId, w) => w.writeHex(tokenId)) + .writeArray(transaction.outputs, (output, w) => serializeBox(output, w, tokenIds)); } -function writeInput(writer: SigmaByteWriter, input: UnsignedInput | SignedInput): void { - writer.writeHex(input.boxId); - +function writeInput(writer: SigmaByteWriter, input: Input): void { if (isSignedInput(input)) { - writeProof(writer, input.spendingProof?.proofBytes); - writeExtension(writer, input.spendingProof?.extension); + writeSignedInput(writer, input); return; } + writeUnsignedInput(writer, input); +} + +function writeSignedInput(writer: SigmaByteWriter, input: SignedInput): void { + writer.writeHex(input.boxId); + writeProof(writer, input.spendingProof?.proofBytes); + writeExtension(writer, input.spendingProof?.extension); +} + +function writeUnsignedInput(writer: SigmaByteWriter, input: Input): void { + writer.writeHex(input.boxId); writeProof(writer, null); - writeExtension(writer, input.extension); + writeExtension( + writer, + isSignedInput(input) ? input.spendingProof?.extension : input.extension + ); } -function isSignedInput(input: UnsignedInput | SignedInput): input is SignedInput { +function isSignedInput(input: Input): input is SignedInput { return (input as SignedInput).spendingProof !== undefined; } @@ -68,8 +61,7 @@ function writeProof(writer: SigmaByteWriter, proof: Nullish): void { } const bytes = hex.decode(proof); - writer.writeVLQ(bytes.length); - writer.writeBytes(bytes); + writer.writeUInt(bytes.length).writeBytes(bytes); } function writeExtension( @@ -82,21 +74,18 @@ function writeExtension( } const keys = Object.keys(extension); - let length = 0; + const values: [string, string][] = []; for (const key of keys) { - if (isDefined(extension[key])) length++; - } + const value = extension[key]; + if (!value) continue; - writer.writeVLQ(length); - if (length === 0) return; - - for (const key of keys) { - const val = extension[key]; - if (isDefined(val)) { - writer.writeVLQ(Number(key)).writeHex(val); - } + values.push([key, value]); } + + writer.writeArray(values, ([key, value], w) => + w.writeUInt(Number(key)).writeHex(value) + ); } function getDistinctTokenIds(outputs: readonly BoxCandidate[]) { @@ -105,3 +94,50 @@ function getDistinctTokenIds(outputs: readonly BoxCandidate[]) { return Array.from(tokenIds); } + +export function deserializeTransaction(input: ByteInput): T { + const reader = new SigmaByteReader(input); + + const inputs = reader.readArray(readInput); + const id = computeId(reader, inputs); + const dataInputs = reader.readArray((r) => ({ boxId: hex.encode(r.readBytes(32)) })); + const tokenIds = reader.readArray((r) => hex.encode(r.readBytes(32))); + const outputs = reader.readArray((r, i) => deserializeEmbeddedBox(r, tokenIds, id, i)); + + return { + id, + inputs, + dataInputs, + outputs + } as T; +} + +function readInput(reader: SigmaByteReader): SignedInput | UnsignedInput { + const boxId = hex.encode(reader.readBytes(32)); + + const proofLength = reader.readUInt(); + const proofBytes = proofLength > 0 ? hex.encode(reader.readBytes(proofLength)) : null; + + const extensionLength = reader.readUInt(); + const extension: Record = {}; + for (let i = 0; i < extensionLength; i++) { + extension[reader.readUInt()] = SConstant.from(reader).toHex(); + } + + return proofBytes + ? { boxId, spendingProof: { proofBytes, extension } } + : { boxId, extension }; +} + +/** + * Computes the transaction ID by serializing inputs as unsigned (excluding proofs), + * even for signed transactions. + */ +function computeId(reader: SigmaByteReader, inputs: Input[]): string { + const bytes = new SigmaByteWriter(reader.bytes.length) + .writeArray(inputs, (input, writer) => writeUnsignedInput(writer, input)) // write inputs as unsigned + .writeBytes(reader.bytes.subarray(reader.cursor)) + .toBytes(); + + return hex.encode(blake2b256(bytes)); +} diff --git a/packages/serializer/src/serializers/typeSerializer.ts b/packages/serializer/src/serializers/typeSerializer.ts index 41e26389..8639a6b4 100644 --- a/packages/serializer/src/serializers/typeSerializer.ts +++ b/packages/serializer/src/serializers/typeSerializer.ts @@ -74,7 +74,7 @@ export const typeSerializer = { // Generic tuple writer.write(descriptors.tuple.genericTupleTypeCode); - writer.writeVLQ(len); + writer.writeUInt(len); } } @@ -141,7 +141,7 @@ export const typeSerializer = { switch (byte) { case descriptors.tuple.genericTupleTypeCode: { - const len = r.readVlq(); + const len = r.readUInt(); const wrapped = new Array(len); for (let i = 0; i < len; i++) { wrapped[i] = this.deserialize(r); diff --git a/packages/serializer/src/sigmaConstant.ts b/packages/serializer/src/sigmaConstant.ts index 0c0d3220..955c4ebe 100644 --- a/packages/serializer/src/sigmaConstant.ts +++ b/packages/serializer/src/sigmaConstant.ts @@ -16,10 +16,12 @@ export class SConstant { this.#data = type.coerce(data) as D; } - static from(bytes: ByteInput): SConstant { - assert(bytes.length > 0, "Empty constant bytes."); + static from( + bytes: ByteInput | SigmaByteReader + ): SConstant { + const reader = bytes instanceof SigmaByteReader ? bytes : new SigmaByteReader(bytes); + if (reader.isEmpty) throw new Error("Empty constant bytes."); - const reader = new SigmaByteReader(bytes); const type = typeSerializer.deserialize(reader); const data = dataSerializer.deserialize(type, reader); diff --git a/packages/wallet/package.json b/packages/wallet/package.json index 0efce3ab..ed44b098 100644 --- a/packages/wallet/package.json +++ b/packages/wallet/package.json @@ -43,9 +43,9 @@ "@fleet-sdk/core": "workspace:^", "@fleet-sdk/crypto": "workspace:^", "@fleet-sdk/serializer": "workspace:^", - "@noble/curves": "^1.8.2", - "@scure/bip32": "^1.6.2", - "@scure/bip39": "^1.5.4" + "@noble/curves": "^1.9.0", + "@scure/bip32": "^1.7.0", + "@scure/bip39": "^1.6.0" }, "engines": { "node": ">=18" diff --git a/packages/wallet/src/prover/prover.ts b/packages/wallet/src/prover/prover.ts index b7518b07..29dceca1 100644 --- a/packages/wallet/src/prover/prover.ts +++ b/packages/wallet/src/prover/prover.ts @@ -11,11 +11,7 @@ import { } from "@fleet-sdk/common"; import { ErgoMessage, ErgoUnsignedTransaction } from "@fleet-sdk/core"; import { blake2b256, type ByteInput, ensureBytes, hex } from "@fleet-sdk/crypto"; -import { - type MinimalUnsignedTransaction, - serializeBox, - serializeTransaction -} from "@fleet-sdk/serializer"; +import { serializeBox, serializeTransaction } from "@fleet-sdk/serializer"; import type { ErgoHDKey } from "../ergoHDKey"; import { sign, verify } from "./proveDLogProtocol"; @@ -26,7 +22,7 @@ export type KeyMap = Record & { _?: ErgoHDKey[] }; export type Message = | SignedTransaction | ErgoUnsignedTransaction - | MinimalUnsignedTransaction + | UnsignedTransaction | ErgoMessage | ByteInput | Base58String; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 81af243b..5e3c672f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,8 +12,8 @@ importers: specifier: ^1.9.4 version: 1.9.4 '@changesets/cli': - specifier: ^2.29.2 - version: 2.29.2 + specifier: ^2.29.3 + version: 2.29.3 '@edge-runtime/vm': specifier: ^5.0.0 version: 5.0.0 @@ -27,8 +27,8 @@ importers: specifier: ^7.0.2 version: 7.0.2 '@vitest/coverage-v8': - specifier: ^3.1.1 - version: 3.1.1(vitest@3.1.1(@edge-runtime/vm@5.0.0)(@types/node@20.9.0)(happy-dom@17.4.4)) + specifier: ^3.1.3 + version: 3.1.3(vitest@3.1.3(@edge-runtime/vm@5.0.0)(@types/node@20.9.0)(happy-dom@17.4.6)) ergo-lib-wasm-nodejs: specifier: ^0.28.0 version: 0.28.0 @@ -36,8 +36,8 @@ importers: specifier: ^4.1.1 version: 4.1.1 happy-dom: - specifier: ^17.4.4 - version: 17.4.4 + specifier: ^17.4.6 + version: 17.4.6 npm-run-all: specifier: ^4.1.5 version: 4.1.5 @@ -51,17 +51,17 @@ importers: specifier: ^8.4.0 version: 8.4.0(postcss@8.5.3)(typescript@5.8.3) type-fest: - specifier: ^4.40.0 - version: 4.40.0 + specifier: ^4.41.0 + version: 4.41.0 typescript: specifier: ^5.8.3 version: 5.8.3 vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.8.3)(vite@6.3.2(@types/node@20.9.0)) + version: 5.1.4(typescript@5.8.3)(vite@6.3.5(@types/node@20.9.0)) vitest: - specifier: ^3.1.1 - version: 3.1.1(@edge-runtime/vm@5.0.0)(@types/node@20.9.0)(happy-dom@17.4.4) + specifier: ^3.1.3 + version: 3.1.3(@edge-runtime/vm@5.0.0)(@types/node@20.9.0)(happy-dom@17.4.6) packages/blockchain-providers: dependencies: @@ -114,11 +114,11 @@ importers: specifier: workspace:^ version: link:../common '@noble/hashes': - specifier: ^1.7.2 - version: 1.7.2 + specifier: ^1.8.0 + version: 1.8.0 '@scure/base': - specifier: ^1.2.4 - version: 1.2.4 + specifier: ^1.2.5 + version: 1.2.5 packages/mock-chain: dependencies: @@ -171,14 +171,14 @@ importers: specifier: workspace:^ version: link:../serializer '@noble/curves': - specifier: ^1.8.2 - version: 1.8.2 + specifier: ^1.9.0 + version: 1.9.0 '@scure/bip32': - specifier: ^1.6.2 - version: 1.6.2 + specifier: ^1.7.0 + version: 1.7.0 '@scure/bip39': - specifier: ^1.5.4 - version: 1.5.4 + specifier: ^1.6.0 + version: 1.6.0 plugins/ageusd: dependencies: @@ -214,25 +214,25 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} - '@babel/helper-string-parser@7.25.9': - resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.25.9': - resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} + '@babel/helper-validator-identifier@7.27.1': + resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} engines: {node: '>=6.9.0'} - '@babel/parser@7.27.0': - resolution: {integrity: sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==} + '@babel/parser@7.27.2': + resolution: {integrity: sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==} engines: {node: '>=6.0.0'} hasBin: true - '@babel/runtime@7.27.0': - resolution: {integrity: sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==} + '@babel/runtime@7.27.1': + resolution: {integrity: sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==} engines: {node: '>=6.9.0'} - '@babel/types@7.27.0': - resolution: {integrity: sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==} + '@babel/types@7.27.1': + resolution: {integrity: sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==} engines: {node: '>=6.9.0'} '@bcoe/v8-coverage@1.0.2': @@ -295,14 +295,14 @@ packages: '@changesets/apply-release-plan@7.0.12': resolution: {integrity: sha512-EaET7As5CeuhTzvXTQCRZeBUcisoYPDDcXvgTE/2jmmypKp0RC7LxKj/yzqeh/1qFTZI7oDGFcL1PHRuQuketQ==} - '@changesets/assemble-release-plan@6.0.6': - resolution: {integrity: sha512-Frkj8hWJ1FRZiY3kzVCKzS0N5mMwWKwmv9vpam7vt8rZjLL1JMthdh6pSDVSPumHPshTTkKZ0VtNbE0cJHZZUg==} + '@changesets/assemble-release-plan@6.0.7': + resolution: {integrity: sha512-vS5J92Rm7ZUcrvtu6WvggGWIdohv8s1/3ypRYQX8FsPO+KPDx6JaNC3YwSfh2umY/faGGfNnq42A7PRT0aZPFw==} '@changesets/changelog-git@0.2.1': resolution: {integrity: sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q==} - '@changesets/cli@2.29.2': - resolution: {integrity: sha512-vwDemKjGYMOc0l6WUUTGqyAWH3AmueeyoJa1KmFRtCYiCoY5K3B68ErYpDB6H48T4lLI4czum4IEjh6ildxUeg==} + '@changesets/cli@2.29.3': + resolution: {integrity: sha512-TNhKr6Loc7I0CSD9LpAyVNSxWBHElXVmmvQYIZQvaMan5jddmL7geo3+08Wi7ImgHFVNB0Nhju/LzXqlrkoOxg==} hasBin: true '@changesets/config@3.1.1': @@ -314,8 +314,8 @@ packages: '@changesets/get-dependents-graph@2.1.3': resolution: {integrity: sha512-gphr+v0mv2I3Oxt19VdWRRUxq3sseyUpX9DaHpTUmLj92Y10AGy+XOtV+kbM6L/fDcpx7/ISDFK6T8A/P3lOdQ==} - '@changesets/get-release-plan@4.0.10': - resolution: {integrity: sha512-CCJ/f3edYaA3MqoEnWvGGuZm0uMEMzNJ97z9hdUR34AOvajSwySwsIzC/bBu3+kuGDsB+cny4FljG8UBWAa7jg==} + '@changesets/get-release-plan@4.0.11': + resolution: {integrity: sha512-4DZpsewsc/1m5TArVg5h1c0U94am+cJBnu3izAM3yYIZr8+zZwa3AXYdEyCNURzjx0wWr80u/TWoxshbwdZXOA==} '@changesets/get-version-range-type@0.4.0': resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==} @@ -358,152 +358,152 @@ packages: '@ergo-graphql/types@0.5.1': resolution: {integrity: sha512-VAGIBOSdK+uSn0mMWAWLF78hCLP8DzDh1hXEVLvUNkOBxg/L53SIUo9PJc9JgkhL6z09ArqdehrpAuwHJpHptg==} - '@esbuild/aix-ppc64@0.25.2': - resolution: {integrity: sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==} + '@esbuild/aix-ppc64@0.25.4': + resolution: {integrity: sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.25.2': - resolution: {integrity: sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==} + '@esbuild/android-arm64@0.25.4': + resolution: {integrity: sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.25.2': - resolution: {integrity: sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==} + '@esbuild/android-arm@0.25.4': + resolution: {integrity: sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.25.2': - resolution: {integrity: sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==} + '@esbuild/android-x64@0.25.4': + resolution: {integrity: sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.25.2': - resolution: {integrity: sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==} + '@esbuild/darwin-arm64@0.25.4': + resolution: {integrity: sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.25.2': - resolution: {integrity: sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==} + '@esbuild/darwin-x64@0.25.4': + resolution: {integrity: sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.25.2': - resolution: {integrity: sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==} + '@esbuild/freebsd-arm64@0.25.4': + resolution: {integrity: sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.25.2': - resolution: {integrity: sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==} + '@esbuild/freebsd-x64@0.25.4': + resolution: {integrity: sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.25.2': - resolution: {integrity: sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==} + '@esbuild/linux-arm64@0.25.4': + resolution: {integrity: sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.25.2': - resolution: {integrity: sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==} + '@esbuild/linux-arm@0.25.4': + resolution: {integrity: sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.25.2': - resolution: {integrity: sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==} + '@esbuild/linux-ia32@0.25.4': + resolution: {integrity: sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.25.2': - resolution: {integrity: sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==} + '@esbuild/linux-loong64@0.25.4': + resolution: {integrity: sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.25.2': - resolution: {integrity: sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==} + '@esbuild/linux-mips64el@0.25.4': + resolution: {integrity: sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.25.2': - resolution: {integrity: sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==} + '@esbuild/linux-ppc64@0.25.4': + resolution: {integrity: sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.25.2': - resolution: {integrity: sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==} + '@esbuild/linux-riscv64@0.25.4': + resolution: {integrity: sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.25.2': - resolution: {integrity: sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==} + '@esbuild/linux-s390x@0.25.4': + resolution: {integrity: sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.25.2': - resolution: {integrity: sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==} + '@esbuild/linux-x64@0.25.4': + resolution: {integrity: sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.25.2': - resolution: {integrity: sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==} + '@esbuild/netbsd-arm64@0.25.4': + resolution: {integrity: sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.25.2': - resolution: {integrity: sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==} + '@esbuild/netbsd-x64@0.25.4': + resolution: {integrity: sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.25.2': - resolution: {integrity: sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==} + '@esbuild/openbsd-arm64@0.25.4': + resolution: {integrity: sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.25.2': - resolution: {integrity: sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==} + '@esbuild/openbsd-x64@0.25.4': + resolution: {integrity: sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/sunos-x64@0.25.2': - resolution: {integrity: sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==} + '@esbuild/sunos-x64@0.25.4': + resolution: {integrity: sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.25.2': - resolution: {integrity: sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==} + '@esbuild/win32-arm64@0.25.4': + resolution: {integrity: sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.25.2': - resolution: {integrity: sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==} + '@esbuild/win32-ia32@0.25.4': + resolution: {integrity: sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.25.2': - resolution: {integrity: sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==} + '@esbuild/win32-x64@0.25.4': + resolution: {integrity: sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -544,15 +544,15 @@ packages: '@manypkg/get-packages@1.1.3': resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} - '@noble/curves@1.8.2': - resolution: {integrity: sha512-vnI7V6lFNe0tLAuJMu+2sX+FcL14TaCWy1qiczg1VwRmPrpQCdq5ESXQMqUc2tluRNf6irBXrWbl1mGN8uaU/g==} + '@noble/curves@1.9.0': + resolution: {integrity: sha512-7YDlXiNMdO1YZeH6t/kvopHHbIZzlxrCV9WLqCY6QhcXOoXiNCMDqJIglZ9Yjx5+w7Dz30TITFrlTjnRg7sKEg==} engines: {node: ^14.21.3 || >=16} '@noble/hashes@1.1.4': resolution: {integrity: sha512-+PYsVPrTSqtVjatKt2A/Proukn2Yrz61OBThOCKErc5w2/r1Fh37vbDv0Eah7pyNltrmacjwTvdw3JoR+WE4TA==} - '@noble/hashes@1.7.2': - resolution: {integrity: sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ==} + '@noble/hashes@1.8.0': + resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} engines: {node: ^14.21.3 || >=16} '@nodelib/fs.scandir@2.1.5': @@ -571,114 +571,114 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} - '@rollup/rollup-android-arm-eabi@4.40.0': - resolution: {integrity: sha512-+Fbls/diZ0RDerhE8kyC6hjADCXA1K4yVNlH0EYfd2XjyH0UGgzaQ8MlT0pCXAThfxv3QUAczHaL+qSv1E4/Cg==} + '@rollup/rollup-android-arm-eabi@4.40.2': + resolution: {integrity: sha512-JkdNEq+DFxZfUwxvB58tHMHBHVgX23ew41g1OQinthJ+ryhdRk67O31S7sYw8u2lTjHUPFxwar07BBt1KHp/hg==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.40.0': - resolution: {integrity: sha512-PPA6aEEsTPRz+/4xxAmaoWDqh67N7wFbgFUJGMnanCFs0TV99M0M8QhhaSCks+n6EbQoFvLQgYOGXxlMGQe/6w==} + '@rollup/rollup-android-arm64@4.40.2': + resolution: {integrity: sha512-13unNoZ8NzUmnndhPTkWPWbX3vtHodYmy+I9kuLxN+F+l+x3LdVF7UCu8TWVMt1POHLh6oDHhnOA04n8oJZhBw==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.40.0': - resolution: {integrity: sha512-GwYOcOakYHdfnjjKwqpTGgn5a6cUX7+Ra2HeNj/GdXvO2VJOOXCiYYlRFU4CubFM67EhbmzLOmACKEfvp3J1kQ==} + '@rollup/rollup-darwin-arm64@4.40.2': + resolution: {integrity: sha512-Gzf1Hn2Aoe8VZzevHostPX23U7N5+4D36WJNHK88NZHCJr7aVMG4fadqkIf72eqVPGjGc0HJHNuUaUcxiR+N/w==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.40.0': - resolution: {integrity: sha512-CoLEGJ+2eheqD9KBSxmma6ld01czS52Iw0e2qMZNpPDlf7Z9mj8xmMemxEucinev4LgHalDPczMyxzbq+Q+EtA==} + '@rollup/rollup-darwin-x64@4.40.2': + resolution: {integrity: sha512-47N4hxa01a4x6XnJoskMKTS8XZ0CZMd8YTbINbi+w03A2w4j1RTlnGHOz/P0+Bg1LaVL6ufZyNprSg+fW5nYQQ==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.40.0': - resolution: {integrity: sha512-r7yGiS4HN/kibvESzmrOB/PxKMhPTlz+FcGvoUIKYoTyGd5toHp48g1uZy1o1xQvybwwpqpe010JrcGG2s5nkg==} + '@rollup/rollup-freebsd-arm64@4.40.2': + resolution: {integrity: sha512-8t6aL4MD+rXSHHZUR1z19+9OFJ2rl1wGKvckN47XFRVO+QL/dUSpKA2SLRo4vMg7ELA8pzGpC+W9OEd1Z/ZqoQ==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.40.0': - resolution: {integrity: sha512-mVDxzlf0oLzV3oZOr0SMJ0lSDd3xC4CmnWJ8Val8isp9jRGl5Dq//LLDSPFrasS7pSm6m5xAcKaw3sHXhBjoRw==} + '@rollup/rollup-freebsd-x64@4.40.2': + resolution: {integrity: sha512-C+AyHBzfpsOEYRFjztcYUFsH4S7UsE9cDtHCtma5BK8+ydOZYgMmWg1d/4KBytQspJCld8ZIujFMAdKG1xyr4Q==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.40.0': - resolution: {integrity: sha512-y/qUMOpJxBMy8xCXD++jeu8t7kzjlOCkoxxajL58G62PJGBZVl/Gwpm7JK9+YvlB701rcQTzjUZ1JgUoPTnoQA==} + '@rollup/rollup-linux-arm-gnueabihf@4.40.2': + resolution: {integrity: sha512-de6TFZYIvJwRNjmW3+gaXiZ2DaWL5D5yGmSYzkdzjBDS3W+B9JQ48oZEsmMvemqjtAFzE16DIBLqd6IQQRuG9Q==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.40.0': - resolution: {integrity: sha512-GoCsPibtVdJFPv/BOIvBKO/XmwZLwaNWdyD8TKlXuqp0veo2sHE+A/vpMQ5iSArRUz/uaoj4h5S6Pn0+PdhRjg==} + '@rollup/rollup-linux-arm-musleabihf@4.40.2': + resolution: {integrity: sha512-urjaEZubdIkacKc930hUDOfQPysezKla/O9qV+O89enqsqUmQm8Xj8O/vh0gHg4LYfv7Y7UsE3QjzLQzDYN1qg==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.40.0': - resolution: {integrity: sha512-L5ZLphTjjAD9leJzSLI7rr8fNqJMlGDKlazW2tX4IUF9P7R5TMQPElpH82Q7eNIDQnQlAyiNVfRPfP2vM5Avvg==} + '@rollup/rollup-linux-arm64-gnu@4.40.2': + resolution: {integrity: sha512-KlE8IC0HFOC33taNt1zR8qNlBYHj31qGT1UqWqtvR/+NuCVhfufAq9fxO8BMFC22Wu0rxOwGVWxtCMvZVLmhQg==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.40.0': - resolution: {integrity: sha512-ATZvCRGCDtv1Y4gpDIXsS+wfFeFuLwVxyUBSLawjgXK2tRE6fnsQEkE4csQQYWlBlsFztRzCnBvWVfcae/1qxQ==} + '@rollup/rollup-linux-arm64-musl@4.40.2': + resolution: {integrity: sha512-j8CgxvfM0kbnhu4XgjnCWJQyyBOeBI1Zq91Z850aUddUmPeQvuAy6OiMdPS46gNFgy8gN1xkYyLgwLYZG3rBOg==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loongarch64-gnu@4.40.0': - resolution: {integrity: sha512-wG9e2XtIhd++QugU5MD9i7OnpaVb08ji3P1y/hNbxrQ3sYEelKJOq1UJ5dXczeo6Hj2rfDEL5GdtkMSVLa/AOg==} + '@rollup/rollup-linux-loongarch64-gnu@4.40.2': + resolution: {integrity: sha512-Ybc/1qUampKuRF4tQXc7G7QY9YRyeVSykfK36Y5Qc5dmrIxwFhrOzqaVTNoZygqZ1ZieSWTibfFhQ5qK8jpWxw==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.40.0': - resolution: {integrity: sha512-vgXfWmj0f3jAUvC7TZSU/m/cOE558ILWDzS7jBhiCAFpY2WEBn5jqgbqvmzlMjtp8KlLcBlXVD2mkTSEQE6Ixw==} + '@rollup/rollup-linux-powerpc64le-gnu@4.40.2': + resolution: {integrity: sha512-3FCIrnrt03CCsZqSYAOW/k9n625pjpuMzVfeI+ZBUSDT3MVIFDSPfSUgIl9FqUftxcUXInvFah79hE1c9abD+Q==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.40.0': - resolution: {integrity: sha512-uJkYTugqtPZBS3Z136arevt/FsKTF/J9dEMTX/cwR7lsAW4bShzI2R0pJVw+hcBTWF4dxVckYh72Hk3/hWNKvA==} + '@rollup/rollup-linux-riscv64-gnu@4.40.2': + resolution: {integrity: sha512-QNU7BFHEvHMp2ESSY3SozIkBPaPBDTsfVNGx3Xhv+TdvWXFGOSH2NJvhD1zKAT6AyuuErJgbdvaJhYVhVqrWTg==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-riscv64-musl@4.40.0': - resolution: {integrity: sha512-rKmSj6EXQRnhSkE22+WvrqOqRtk733x3p5sWpZilhmjnkHkpeCgWsFFo0dGnUGeA+OZjRl3+VYq+HyCOEuwcxQ==} + '@rollup/rollup-linux-riscv64-musl@4.40.2': + resolution: {integrity: sha512-5W6vNYkhgfh7URiXTO1E9a0cy4fSgfE4+Hl5agb/U1sa0kjOLMLC1wObxwKxecE17j0URxuTrYZZME4/VH57Hg==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.40.0': - resolution: {integrity: sha512-SpnYlAfKPOoVsQqmTFJ0usx0z84bzGOS9anAC0AZ3rdSo3snecihbhFTlJZ8XMwzqAcodjFU4+/SM311dqE5Sw==} + '@rollup/rollup-linux-s390x-gnu@4.40.2': + resolution: {integrity: sha512-B7LKIz+0+p348JoAL4X/YxGx9zOx3sR+o6Hj15Y3aaApNfAshK8+mWZEf759DXfRLeL2vg5LYJBB7DdcleYCoQ==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.40.0': - resolution: {integrity: sha512-RcDGMtqF9EFN8i2RYN2W+64CdHruJ5rPqrlYw+cgM3uOVPSsnAQps7cpjXe9be/yDp8UC7VLoCoKC8J3Kn2FkQ==} + '@rollup/rollup-linux-x64-gnu@4.40.2': + resolution: {integrity: sha512-lG7Xa+BmBNwpjmVUbmyKxdQJ3Q6whHjMjzQplOs5Z+Gj7mxPtWakGHqzMqNER68G67kmCX9qX57aRsW5V0VOng==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.40.0': - resolution: {integrity: sha512-HZvjpiUmSNx5zFgwtQAV1GaGazT2RWvqeDi0hV+AtC8unqqDSsaFjPxfsO6qPtKRRg25SisACWnJ37Yio8ttaw==} + '@rollup/rollup-linux-x64-musl@4.40.2': + resolution: {integrity: sha512-tD46wKHd+KJvsmije4bUskNuvWKFcTOIM9tZ/RrmIvcXnbi0YK/cKS9FzFtAm7Oxi2EhV5N2OpfFB348vSQRXA==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.40.0': - resolution: {integrity: sha512-UtZQQI5k/b8d7d3i9AZmA/t+Q4tk3hOC0tMOMSq2GlMYOfxbesxG4mJSeDp0EHs30N9bsfwUvs3zF4v/RzOeTQ==} + '@rollup/rollup-win32-arm64-msvc@4.40.2': + resolution: {integrity: sha512-Bjv/HG8RRWLNkXwQQemdsWw4Mg+IJ29LK+bJPW2SCzPKOUaMmPEppQlu/Fqk1d7+DX3V7JbFdbkh/NMmurT6Pg==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.40.0': - resolution: {integrity: sha512-+m03kvI2f5syIqHXCZLPVYplP8pQch9JHyXKZ3AGMKlg8dCyr2PKHjwRLiW53LTrN/Nc3EqHOKxUxzoSPdKddA==} + '@rollup/rollup-win32-ia32-msvc@4.40.2': + resolution: {integrity: sha512-dt1llVSGEsGKvzeIO76HToiYPNPYPkmjhMHhP00T9S4rDern8P2ZWvWAQUEJ+R1UdMWJ/42i/QqJ2WV765GZcA==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.40.0': - resolution: {integrity: sha512-lpPE1cLfP5oPzVjKMx10pgBmKELQnFJXHgvtHCtuJWOv8MxqdEIMNtgHgBFf7Ea2/7EuVwa9fodWUfXAlXZLZQ==} + '@rollup/rollup-win32-x64-msvc@4.40.2': + resolution: {integrity: sha512-bwspbWB04XJpeElvsp+DCylKfF4trJDa2Y9Go8O6A7YLX2LIKGcNK/CYImJN6ZP4DcuOHB4Utl3iCbnR62DudA==} cpu: [x64] os: [win32] - '@scure/base@1.2.4': - resolution: {integrity: sha512-5Yy9czTO47mqz+/J8GM6GIId4umdCk1wc1q8rKERQulIoc8VP9pzDcghv10Tl2E7R96ZUx/PhND3ESYUQX8NuQ==} + '@scure/base@1.2.5': + resolution: {integrity: sha512-9rE6EOVeIQzt5TSu4v+K523F8u6DhBsoZWPGKlnCshhlDhy0kJzUX4V+tr2dWmzF1GdekvThABoEQBGBQI7xZw==} - '@scure/bip32@1.6.2': - resolution: {integrity: sha512-t96EPDMbtGgtb7onKKqxRLfE5g05k7uHnHRM2xdE6BP/ZmxaLtPek4J4KfVn/90IQNrU1IOAqMgiDtUdtbe3nw==} + '@scure/bip32@1.7.0': + resolution: {integrity: sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw==} - '@scure/bip39@1.5.4': - resolution: {integrity: sha512-TFM4ni0vKvCfBpohoh+/lY05i9gRbSwXWngAsF4CABQxoaOHijxuaZ2R6cStDQ5CHtHO9aGJTr4ksVJASRRyMA==} + '@scure/bip39@1.6.0': + resolution: {integrity: sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==} '@tokenizer/token@0.3.0': resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} @@ -695,20 +695,20 @@ packages: '@types/node@20.9.0': resolution: {integrity: sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==} - '@vitest/coverage-v8@3.1.1': - resolution: {integrity: sha512-MgV6D2dhpD6Hp/uroUoAIvFqA8AuvXEFBC2eepG3WFc1pxTfdk1LEqqkWoWhjz+rytoqrnUUCdf6Lzco3iHkLQ==} + '@vitest/coverage-v8@3.1.3': + resolution: {integrity: sha512-cj76U5gXCl3g88KSnf80kof6+6w+K4BjOflCl7t6yRJPDuCrHtVu0SgNYOUARJOL5TI8RScDbm5x4s1/P9bvpw==} peerDependencies: - '@vitest/browser': 3.1.1 - vitest: 3.1.1 + '@vitest/browser': 3.1.3 + vitest: 3.1.3 peerDependenciesMeta: '@vitest/browser': optional: true - '@vitest/expect@3.1.1': - resolution: {integrity: sha512-q/zjrW9lgynctNbwvFtQkGK9+vvHA5UzVi2V8APrp1C6fG6/MuYYkmlx4FubuqLycCeSdHD5aadWfua/Vr0EUA==} + '@vitest/expect@3.1.3': + resolution: {integrity: sha512-7FTQQuuLKmN1Ig/h+h/GO+44Q1IlglPlR2es4ab7Yvfx+Uk5xsv+Ykk+MEt/M2Yn/xGmzaLKxGw2lgy2bwuYqg==} - '@vitest/mocker@3.1.1': - resolution: {integrity: sha512-bmpJJm7Y7i9BBELlLuuM1J1Q6EQ6K5Ye4wcyOpOMXMcePYKSIYlpcrCm4l/O6ja4VJA5G2aMJiuZkZdnxlC3SA==} + '@vitest/mocker@3.1.3': + resolution: {integrity: sha512-PJbLjonJK82uCWHjzgBJZuR7zmAOrSvKk1QBxrennDIgtH4uK0TB1PvYmc0XBCigxxtiAVPfWtAdy4lpz8SQGQ==} peerDependencies: msw: ^2.4.9 vite: ^5.0.0 || ^6.0.0 @@ -718,20 +718,20 @@ packages: vite: optional: true - '@vitest/pretty-format@3.1.1': - resolution: {integrity: sha512-dg0CIzNx+hMMYfNmSqJlLSXEmnNhMswcn3sXO7Tpldr0LiGmg3eXdLLhwkv2ZqgHb/d5xg5F7ezNFRA1fA13yA==} + '@vitest/pretty-format@3.1.3': + resolution: {integrity: sha512-i6FDiBeJUGLDKADw2Gb01UtUNb12yyXAqC/mmRWuYl+m/U9GS7s8us5ONmGkGpUUo7/iAYzI2ePVfOZTYvUifA==} - '@vitest/runner@3.1.1': - resolution: {integrity: sha512-X/d46qzJuEDO8ueyjtKfxffiXraPRfmYasoC4i5+mlLEJ10UvPb0XH5M9C3gWuxd7BAQhpK42cJgJtq53YnWVA==} + '@vitest/runner@3.1.3': + resolution: {integrity: sha512-Tae+ogtlNfFei5DggOsSUvkIaSuVywujMj6HzR97AHK6XK8i3BuVyIifWAm/sE3a15lF5RH9yQIrbXYuo0IFyA==} - '@vitest/snapshot@3.1.1': - resolution: {integrity: sha512-bByMwaVWe/+1WDf9exFxWWgAixelSdiwo2p33tpqIlM14vW7PRV5ppayVXtfycqze4Qhtwag5sVhX400MLBOOw==} + '@vitest/snapshot@3.1.3': + resolution: {integrity: sha512-XVa5OPNTYUsyqG9skuUkFzAeFnEzDp8hQu7kZ0N25B1+6KjGm4hWLtURyBbsIAOekfWQ7Wuz/N/XXzgYO3deWQ==} - '@vitest/spy@3.1.1': - resolution: {integrity: sha512-+EmrUOOXbKzLkTDwlsc/xrwOlPDXyVk3Z6P6K4oiCndxz7YLpp/0R0UsWVOKT0IXWjjBJuSMk6D27qipaupcvQ==} + '@vitest/spy@3.1.3': + resolution: {integrity: sha512-x6w+ctOEmEXdWaa6TO4ilb7l9DxPR5bwEb6hILKuxfU1NqWT2mpJD9NJN7t3OTfxmVlOMrvtoFJGdgyzZ605lQ==} - '@vitest/utils@3.1.1': - resolution: {integrity: sha512-1XIjflyaU2k3HMArJ50bwSh3wKWPD6Q47wz/NUSmRV0zNywPc4w79ARjg/i/aNINHwA+mIALhUVqD9/aUvZNgg==} + '@vitest/utils@3.1.3': + resolution: {integrity: sha512-2Ltrpht4OmHO9+c/nmHtF09HWiyWdworqnHIwjfvDyWjuwKbdkcS9AnhsDn+8E2RM4x++foD1/tNuLPVvWG1Rg==} abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} @@ -991,8 +991,8 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} - es-module-lexer@1.6.0: - resolution: {integrity: sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==} + es-module-lexer@1.7.0: + resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} es-object-atoms@1.1.1: resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} @@ -1006,8 +1006,8 @@ packages: resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} engines: {node: '>= 0.4'} - esbuild@0.25.2: - resolution: {integrity: sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==} + esbuild@0.25.4: + resolution: {integrity: sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==} engines: {node: '>=18'} hasBin: true @@ -1146,8 +1146,8 @@ packages: graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - happy-dom@17.4.4: - resolution: {integrity: sha512-/Pb0ctk3HTZ5xEL3BZ0hK1AqDSAUuRQitOmROPHhfUYEWpmTImwfD8vFDGADmMAX0JYgbcgxWoLFKtsWhcpuVA==} + happy-dom@17.4.6: + resolution: {integrity: sha512-OEV1hDe9i2rFr66+WZNiwy1S8rAJy6bRXmXql68YJDjdfHBRbN76om+qVh68vQACf6y5Bcr90e/oK53RQxsDdg==} engines: {node: '>=18.0.0'} has-bigints@1.1.0: @@ -1493,8 +1493,8 @@ packages: engines: {node: '>=18'} hasBin: true - open@10.1.1: - resolution: {integrity: sha512-zy1wx4+P3PfhXSEPJNtZmJXfhkkIaxU1VauWIrDZw1O7uJRDRJtKr9n3Ic4NgbA16KyOxOXO2ng9gYwCdXuSXA==} + open@10.1.2: + resolution: {integrity: sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw==} engines: {node: '>=18'} os-tmpdir@1.0.2: @@ -1676,9 +1676,6 @@ packages: resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} engines: {node: '>= 0.4'} - regenerator-runtime@0.14.1: - resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} - regexp.prototype.flags@1.5.4: resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} engines: {node: '>= 0.4'} @@ -1696,8 +1693,8 @@ packages: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rollup@4.40.0: - resolution: {integrity: sha512-Noe455xmA96nnqH5piFtLobsGbCij7Tu+tb3c1vYjNbTkfzGqXqQXG3wJaYXkRZuQ0vEYN4bhwg7QnIrqB5B+w==} + rollup@4.40.2: + resolution: {integrity: sha512-tfUOg6DTP4rhQ3VjOO6B4wyrJnGOX85requAXvqYTHsOgb2TFJdZ3aWpT8W2kPoypSGP7dZUyzxJ9ee4buM5Fg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -1997,8 +1994,8 @@ packages: resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} engines: {node: '>=12.20'} - type-fest@4.40.0: - resolution: {integrity: sha512-ABHZ2/tS2JkvH1PEjxFDTUWC8dB5OsIGZP4IFLhR293GqT5Y5qB1WwL2kMPYhQW9DVgVD8Hd7I8gjwPIf5GFkw==} + type-fest@4.41.0: + resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} engines: {node: '>=16'} typed-array-buffer@1.0.3: @@ -2040,8 +2037,8 @@ packages: validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - vite-node@3.1.1: - resolution: {integrity: sha512-V+IxPAE2FvXpTCHXyNem0M+gWm6J7eRyWPR6vYoG/Gl+IscNOjXzztUhimQgTxaAoUoj40Qqimaa0NLIOOAH4w==} + vite-node@3.1.3: + resolution: {integrity: sha512-uHV4plJ2IxCl4u1up1FQRrqclylKAogbtBfOTwcuJ28xFi+89PZ57BRh+naIRvH70HPwxy5QHYzg1OrEaC7AbA==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true @@ -2053,8 +2050,8 @@ packages: vite: optional: true - vite@6.3.2: - resolution: {integrity: sha512-ZSvGOXKGceizRQIZSz7TGJ0pS3QLlVY/9hwxVh17W3re67je1RKYzFHivZ/t0tubU78Vkyb9WnHPENSBCzbckg==} + vite@6.3.5: + resolution: {integrity: sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: @@ -2093,16 +2090,16 @@ packages: yaml: optional: true - vitest@3.1.1: - resolution: {integrity: sha512-kiZc/IYmKICeBAZr9DQ5rT7/6bD9G7uqQEki4fxazi1jdVl2mWGzedtBs5s6llz59yQhVb7FFY2MbHzHCnT79Q==} + vitest@3.1.3: + resolution: {integrity: sha512-188iM4hAHQ0km23TN/adso1q5hhwKqUpv+Sd6p5sOuh6FhQnRNW3IsiIpvxqahtBabsJ2SLZgmGSpcYK4wQYJw==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@types/debug': ^4.1.12 '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 - '@vitest/browser': 3.1.1 - '@vitest/ui': 3.1.1 + '@vitest/browser': 3.1.3 + '@vitest/ui': 3.1.3 happy-dom: '*' jsdom: '*' peerDependenciesMeta: @@ -2180,22 +2177,20 @@ snapshots: '@jridgewell/gen-mapping': 0.3.8 '@jridgewell/trace-mapping': 0.3.25 - '@babel/helper-string-parser@7.25.9': {} + '@babel/helper-string-parser@7.27.1': {} - '@babel/helper-validator-identifier@7.25.9': {} + '@babel/helper-validator-identifier@7.27.1': {} - '@babel/parser@7.27.0': + '@babel/parser@7.27.2': dependencies: - '@babel/types': 7.27.0 + '@babel/types': 7.27.1 - '@babel/runtime@7.27.0': - dependencies: - regenerator-runtime: 0.14.1 + '@babel/runtime@7.27.1': {} - '@babel/types@7.27.0': + '@babel/types@7.27.1': dependencies: - '@babel/helper-string-parser': 7.25.9 - '@babel/helper-validator-identifier': 7.25.9 + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 '@bcoe/v8-coverage@1.0.2': {} @@ -2250,7 +2245,7 @@ snapshots: resolve-from: 5.0.0 semver: 7.7.1 - '@changesets/assemble-release-plan@6.0.6': + '@changesets/assemble-release-plan@6.0.7': dependencies: '@changesets/errors': 0.2.0 '@changesets/get-dependents-graph': 2.1.3 @@ -2263,15 +2258,15 @@ snapshots: dependencies: '@changesets/types': 6.1.0 - '@changesets/cli@2.29.2': + '@changesets/cli@2.29.3': dependencies: '@changesets/apply-release-plan': 7.0.12 - '@changesets/assemble-release-plan': 6.0.6 + '@changesets/assemble-release-plan': 6.0.7 '@changesets/changelog-git': 0.2.1 '@changesets/config': 3.1.1 '@changesets/errors': 0.2.0 '@changesets/get-dependents-graph': 2.1.3 - '@changesets/get-release-plan': 4.0.10 + '@changesets/get-release-plan': 4.0.11 '@changesets/git': 3.0.4 '@changesets/logger': 0.1.1 '@changesets/pre': 2.0.2 @@ -2315,9 +2310,9 @@ snapshots: picocolors: 1.1.1 semver: 7.7.1 - '@changesets/get-release-plan@4.0.10': + '@changesets/get-release-plan@4.0.11': dependencies: - '@changesets/assemble-release-plan': 6.0.6 + '@changesets/assemble-release-plan': 6.0.7 '@changesets/config': 3.1.1 '@changesets/pre': 2.0.2 '@changesets/read': 0.6.5 @@ -2384,79 +2379,79 @@ snapshots: '@ergo-graphql/types@0.5.1': {} - '@esbuild/aix-ppc64@0.25.2': + '@esbuild/aix-ppc64@0.25.4': optional: true - '@esbuild/android-arm64@0.25.2': + '@esbuild/android-arm64@0.25.4': optional: true - '@esbuild/android-arm@0.25.2': + '@esbuild/android-arm@0.25.4': optional: true - '@esbuild/android-x64@0.25.2': + '@esbuild/android-x64@0.25.4': optional: true - '@esbuild/darwin-arm64@0.25.2': + '@esbuild/darwin-arm64@0.25.4': optional: true - '@esbuild/darwin-x64@0.25.2': + '@esbuild/darwin-x64@0.25.4': optional: true - '@esbuild/freebsd-arm64@0.25.2': + '@esbuild/freebsd-arm64@0.25.4': optional: true - '@esbuild/freebsd-x64@0.25.2': + '@esbuild/freebsd-x64@0.25.4': optional: true - '@esbuild/linux-arm64@0.25.2': + '@esbuild/linux-arm64@0.25.4': optional: true - '@esbuild/linux-arm@0.25.2': + '@esbuild/linux-arm@0.25.4': optional: true - '@esbuild/linux-ia32@0.25.2': + '@esbuild/linux-ia32@0.25.4': optional: true - '@esbuild/linux-loong64@0.25.2': + '@esbuild/linux-loong64@0.25.4': optional: true - '@esbuild/linux-mips64el@0.25.2': + '@esbuild/linux-mips64el@0.25.4': optional: true - '@esbuild/linux-ppc64@0.25.2': + '@esbuild/linux-ppc64@0.25.4': optional: true - '@esbuild/linux-riscv64@0.25.2': + '@esbuild/linux-riscv64@0.25.4': optional: true - '@esbuild/linux-s390x@0.25.2': + '@esbuild/linux-s390x@0.25.4': optional: true - '@esbuild/linux-x64@0.25.2': + '@esbuild/linux-x64@0.25.4': optional: true - '@esbuild/netbsd-arm64@0.25.2': + '@esbuild/netbsd-arm64@0.25.4': optional: true - '@esbuild/netbsd-x64@0.25.2': + '@esbuild/netbsd-x64@0.25.4': optional: true - '@esbuild/openbsd-arm64@0.25.2': + '@esbuild/openbsd-arm64@0.25.4': optional: true - '@esbuild/openbsd-x64@0.25.2': + '@esbuild/openbsd-x64@0.25.4': optional: true - '@esbuild/sunos-x64@0.25.2': + '@esbuild/sunos-x64@0.25.4': optional: true - '@esbuild/win32-arm64@0.25.2': + '@esbuild/win32-arm64@0.25.4': optional: true - '@esbuild/win32-ia32@0.25.2': + '@esbuild/win32-ia32@0.25.4': optional: true - '@esbuild/win32-x64@0.25.2': + '@esbuild/win32-x64@0.25.4': optional: true '@fleet-sdk/common@0.1.3': {} @@ -2491,27 +2486,27 @@ snapshots: '@manypkg/find-root@1.1.0': dependencies: - '@babel/runtime': 7.27.0 + '@babel/runtime': 7.27.1 '@types/node': 12.20.55 find-up: 4.1.0 fs-extra: 8.1.0 '@manypkg/get-packages@1.1.3': dependencies: - '@babel/runtime': 7.27.0 + '@babel/runtime': 7.27.1 '@changesets/types': 4.1.0 '@manypkg/find-root': 1.1.0 fs-extra: 8.1.0 globby: 11.1.0 read-yaml-file: 1.1.0 - '@noble/curves@1.8.2': + '@noble/curves@1.9.0': dependencies: - '@noble/hashes': 1.7.2 + '@noble/hashes': 1.8.0 '@noble/hashes@1.1.4': {} - '@noble/hashes@1.7.2': {} + '@noble/hashes@1.8.0': {} '@nodelib/fs.scandir@2.1.5': dependencies: @@ -2528,78 +2523,78 @@ snapshots: '@pkgjs/parseargs@0.11.0': optional: true - '@rollup/rollup-android-arm-eabi@4.40.0': + '@rollup/rollup-android-arm-eabi@4.40.2': optional: true - '@rollup/rollup-android-arm64@4.40.0': + '@rollup/rollup-android-arm64@4.40.2': optional: true - '@rollup/rollup-darwin-arm64@4.40.0': + '@rollup/rollup-darwin-arm64@4.40.2': optional: true - '@rollup/rollup-darwin-x64@4.40.0': + '@rollup/rollup-darwin-x64@4.40.2': optional: true - '@rollup/rollup-freebsd-arm64@4.40.0': + '@rollup/rollup-freebsd-arm64@4.40.2': optional: true - '@rollup/rollup-freebsd-x64@4.40.0': + '@rollup/rollup-freebsd-x64@4.40.2': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.40.0': + '@rollup/rollup-linux-arm-gnueabihf@4.40.2': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.40.0': + '@rollup/rollup-linux-arm-musleabihf@4.40.2': optional: true - '@rollup/rollup-linux-arm64-gnu@4.40.0': + '@rollup/rollup-linux-arm64-gnu@4.40.2': optional: true - '@rollup/rollup-linux-arm64-musl@4.40.0': + '@rollup/rollup-linux-arm64-musl@4.40.2': optional: true - '@rollup/rollup-linux-loongarch64-gnu@4.40.0': + '@rollup/rollup-linux-loongarch64-gnu@4.40.2': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.40.0': + '@rollup/rollup-linux-powerpc64le-gnu@4.40.2': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.40.0': + '@rollup/rollup-linux-riscv64-gnu@4.40.2': optional: true - '@rollup/rollup-linux-riscv64-musl@4.40.0': + '@rollup/rollup-linux-riscv64-musl@4.40.2': optional: true - '@rollup/rollup-linux-s390x-gnu@4.40.0': + '@rollup/rollup-linux-s390x-gnu@4.40.2': optional: true - '@rollup/rollup-linux-x64-gnu@4.40.0': + '@rollup/rollup-linux-x64-gnu@4.40.2': optional: true - '@rollup/rollup-linux-x64-musl@4.40.0': + '@rollup/rollup-linux-x64-musl@4.40.2': optional: true - '@rollup/rollup-win32-arm64-msvc@4.40.0': + '@rollup/rollup-win32-arm64-msvc@4.40.2': optional: true - '@rollup/rollup-win32-ia32-msvc@4.40.0': + '@rollup/rollup-win32-ia32-msvc@4.40.2': optional: true - '@rollup/rollup-win32-x64-msvc@4.40.0': + '@rollup/rollup-win32-x64-msvc@4.40.2': optional: true - '@scure/base@1.2.4': {} + '@scure/base@1.2.5': {} - '@scure/bip32@1.6.2': + '@scure/bip32@1.7.0': dependencies: - '@noble/curves': 1.8.2 - '@noble/hashes': 1.7.2 - '@scure/base': 1.2.4 + '@noble/curves': 1.9.0 + '@noble/hashes': 1.8.0 + '@scure/base': 1.2.5 - '@scure/bip39@1.5.4': + '@scure/bip39@1.6.0': dependencies: - '@noble/hashes': 1.7.2 - '@scure/base': 1.2.4 + '@noble/hashes': 1.8.0 + '@scure/base': 1.2.5 '@tokenizer/token@0.3.0': {} @@ -2614,7 +2609,7 @@ snapshots: undici-types: 5.26.5 optional: true - '@vitest/coverage-v8@3.1.1(vitest@3.1.1(@edge-runtime/vm@5.0.0)(@types/node@20.9.0)(happy-dom@17.4.4))': + '@vitest/coverage-v8@3.1.3(vitest@3.1.3(@edge-runtime/vm@5.0.0)(@types/node@20.9.0)(happy-dom@17.4.6))': dependencies: '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 1.0.2 @@ -2628,47 +2623,47 @@ snapshots: std-env: 3.9.0 test-exclude: 7.0.1 tinyrainbow: 2.0.0 - vitest: 3.1.1(@edge-runtime/vm@5.0.0)(@types/node@20.9.0)(happy-dom@17.4.4) + vitest: 3.1.3(@edge-runtime/vm@5.0.0)(@types/node@20.9.0)(happy-dom@17.4.6) transitivePeerDependencies: - supports-color - '@vitest/expect@3.1.1': + '@vitest/expect@3.1.3': dependencies: - '@vitest/spy': 3.1.1 - '@vitest/utils': 3.1.1 + '@vitest/spy': 3.1.3 + '@vitest/utils': 3.1.3 chai: 5.2.0 tinyrainbow: 2.0.0 - '@vitest/mocker@3.1.1(vite@6.3.2(@types/node@20.9.0))': + '@vitest/mocker@3.1.3(vite@6.3.5(@types/node@20.9.0))': dependencies: - '@vitest/spy': 3.1.1 + '@vitest/spy': 3.1.3 estree-walker: 3.0.3 magic-string: 0.30.17 optionalDependencies: - vite: 6.3.2(@types/node@20.9.0) + vite: 6.3.5(@types/node@20.9.0) - '@vitest/pretty-format@3.1.1': + '@vitest/pretty-format@3.1.3': dependencies: tinyrainbow: 2.0.0 - '@vitest/runner@3.1.1': + '@vitest/runner@3.1.3': dependencies: - '@vitest/utils': 3.1.1 + '@vitest/utils': 3.1.3 pathe: 2.0.3 - '@vitest/snapshot@3.1.1': + '@vitest/snapshot@3.1.3': dependencies: - '@vitest/pretty-format': 3.1.1 + '@vitest/pretty-format': 3.1.3 magic-string: 0.30.17 pathe: 2.0.3 - '@vitest/spy@3.1.1': + '@vitest/spy@3.1.3': dependencies: tinyspy: 3.0.2 - '@vitest/utils@3.1.1': + '@vitest/utils@3.1.3': dependencies: - '@vitest/pretty-format': 3.1.1 + '@vitest/pretty-format': 3.1.3 loupe: 3.1.3 tinyrainbow: 2.0.0 @@ -2753,9 +2748,9 @@ snapshots: dependencies: run-applescript: 7.0.0 - bundle-require@5.1.0(esbuild@0.25.2): + bundle-require@5.1.0(esbuild@0.25.4): dependencies: - esbuild: 0.25.2 + esbuild: 0.25.4 load-tsconfig: 0.2.5 cac@6.7.14: {} @@ -2971,7 +2966,7 @@ snapshots: es-errors@1.3.0: {} - es-module-lexer@1.6.0: {} + es-module-lexer@1.7.0: {} es-object-atoms@1.1.1: dependencies: @@ -2990,33 +2985,33 @@ snapshots: is-date-object: 1.1.0 is-symbol: 1.1.1 - esbuild@0.25.2: + esbuild@0.25.4: optionalDependencies: - '@esbuild/aix-ppc64': 0.25.2 - '@esbuild/android-arm': 0.25.2 - '@esbuild/android-arm64': 0.25.2 - '@esbuild/android-x64': 0.25.2 - '@esbuild/darwin-arm64': 0.25.2 - '@esbuild/darwin-x64': 0.25.2 - '@esbuild/freebsd-arm64': 0.25.2 - '@esbuild/freebsd-x64': 0.25.2 - '@esbuild/linux-arm': 0.25.2 - '@esbuild/linux-arm64': 0.25.2 - '@esbuild/linux-ia32': 0.25.2 - '@esbuild/linux-loong64': 0.25.2 - '@esbuild/linux-mips64el': 0.25.2 - '@esbuild/linux-ppc64': 0.25.2 - '@esbuild/linux-riscv64': 0.25.2 - '@esbuild/linux-s390x': 0.25.2 - '@esbuild/linux-x64': 0.25.2 - '@esbuild/netbsd-arm64': 0.25.2 - '@esbuild/netbsd-x64': 0.25.2 - '@esbuild/openbsd-arm64': 0.25.2 - '@esbuild/openbsd-x64': 0.25.2 - '@esbuild/sunos-x64': 0.25.2 - '@esbuild/win32-arm64': 0.25.2 - '@esbuild/win32-ia32': 0.25.2 - '@esbuild/win32-x64': 0.25.2 + '@esbuild/aix-ppc64': 0.25.4 + '@esbuild/android-arm': 0.25.4 + '@esbuild/android-arm64': 0.25.4 + '@esbuild/android-x64': 0.25.4 + '@esbuild/darwin-arm64': 0.25.4 + '@esbuild/darwin-x64': 0.25.4 + '@esbuild/freebsd-arm64': 0.25.4 + '@esbuild/freebsd-x64': 0.25.4 + '@esbuild/linux-arm': 0.25.4 + '@esbuild/linux-arm64': 0.25.4 + '@esbuild/linux-ia32': 0.25.4 + '@esbuild/linux-loong64': 0.25.4 + '@esbuild/linux-mips64el': 0.25.4 + '@esbuild/linux-ppc64': 0.25.4 + '@esbuild/linux-riscv64': 0.25.4 + '@esbuild/linux-s390x': 0.25.4 + '@esbuild/linux-x64': 0.25.4 + '@esbuild/netbsd-arm64': 0.25.4 + '@esbuild/netbsd-x64': 0.25.4 + '@esbuild/openbsd-arm64': 0.25.4 + '@esbuild/openbsd-x64': 0.25.4 + '@esbuild/sunos-x64': 0.25.4 + '@esbuild/win32-arm64': 0.25.4 + '@esbuild/win32-ia32': 0.25.4 + '@esbuild/win32-x64': 0.25.4 escape-string-regexp@1.0.5: {} @@ -3171,7 +3166,7 @@ snapshots: graceful-fs@4.2.11: {} - happy-dom@17.4.4: + happy-dom@17.4.6: dependencies: webidl-conversions: 7.0.0 whatwg-mimetype: 3.0.0 @@ -3422,8 +3417,8 @@ snapshots: magicast@0.3.5: dependencies: - '@babel/parser': 7.27.0 - '@babel/types': 7.27.0 + '@babel/parser': 7.27.2 + '@babel/types': 7.27.1 source-map-js: 1.2.1 make-dir@4.0.0: @@ -3506,10 +3501,10 @@ snapshots: file-type: 18.7.0 get-stdin: 9.0.0 meow: 12.1.1 - open: 10.1.1 + open: 10.1.2 tempy: 3.1.0 - open@10.1.1: + open@10.1.2: dependencies: default-browser: 5.2.1 define-lazy-prop: 3.0.0 @@ -3656,8 +3651,6 @@ snapshots: get-proto: 1.0.1 which-builtin-type: 1.2.1 - regenerator-runtime@0.14.1: {} - regexp.prototype.flags@1.5.4: dependencies: call-bind: 1.0.8 @@ -3677,30 +3670,30 @@ snapshots: reusify@1.1.0: {} - rollup@4.40.0: + rollup@4.40.2: dependencies: '@types/estree': 1.0.7 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.40.0 - '@rollup/rollup-android-arm64': 4.40.0 - '@rollup/rollup-darwin-arm64': 4.40.0 - '@rollup/rollup-darwin-x64': 4.40.0 - '@rollup/rollup-freebsd-arm64': 4.40.0 - '@rollup/rollup-freebsd-x64': 4.40.0 - '@rollup/rollup-linux-arm-gnueabihf': 4.40.0 - '@rollup/rollup-linux-arm-musleabihf': 4.40.0 - '@rollup/rollup-linux-arm64-gnu': 4.40.0 - '@rollup/rollup-linux-arm64-musl': 4.40.0 - '@rollup/rollup-linux-loongarch64-gnu': 4.40.0 - '@rollup/rollup-linux-powerpc64le-gnu': 4.40.0 - '@rollup/rollup-linux-riscv64-gnu': 4.40.0 - '@rollup/rollup-linux-riscv64-musl': 4.40.0 - '@rollup/rollup-linux-s390x-gnu': 4.40.0 - '@rollup/rollup-linux-x64-gnu': 4.40.0 - '@rollup/rollup-linux-x64-musl': 4.40.0 - '@rollup/rollup-win32-arm64-msvc': 4.40.0 - '@rollup/rollup-win32-ia32-msvc': 4.40.0 - '@rollup/rollup-win32-x64-msvc': 4.40.0 + '@rollup/rollup-android-arm-eabi': 4.40.2 + '@rollup/rollup-android-arm64': 4.40.2 + '@rollup/rollup-darwin-arm64': 4.40.2 + '@rollup/rollup-darwin-x64': 4.40.2 + '@rollup/rollup-freebsd-arm64': 4.40.2 + '@rollup/rollup-freebsd-x64': 4.40.2 + '@rollup/rollup-linux-arm-gnueabihf': 4.40.2 + '@rollup/rollup-linux-arm-musleabihf': 4.40.2 + '@rollup/rollup-linux-arm64-gnu': 4.40.2 + '@rollup/rollup-linux-arm64-musl': 4.40.2 + '@rollup/rollup-linux-loongarch64-gnu': 4.40.2 + '@rollup/rollup-linux-powerpc64le-gnu': 4.40.2 + '@rollup/rollup-linux-riscv64-gnu': 4.40.2 + '@rollup/rollup-linux-riscv64-musl': 4.40.2 + '@rollup/rollup-linux-s390x-gnu': 4.40.2 + '@rollup/rollup-linux-x64-gnu': 4.40.2 + '@rollup/rollup-linux-x64-musl': 4.40.2 + '@rollup/rollup-win32-arm64-msvc': 4.40.2 + '@rollup/rollup-win32-ia32-msvc': 4.40.2 + '@rollup/rollup-win32-x64-msvc': 4.40.2 fsevents: 2.3.3 run-applescript@7.0.0: {} @@ -3995,17 +3988,17 @@ snapshots: tsup@8.4.0(postcss@8.5.3)(typescript@5.8.3): dependencies: - bundle-require: 5.1.0(esbuild@0.25.2) + bundle-require: 5.1.0(esbuild@0.25.4) cac: 6.7.14 chokidar: 4.0.3 consola: 3.4.2 debug: 4.4.0 - esbuild: 0.25.2 + esbuild: 0.25.4 joycon: 3.1.1 picocolors: 1.1.1 postcss-load-config: 6.0.1(postcss@8.5.3) resolve-from: 5.0.0 - rollup: 4.40.0 + rollup: 4.40.2 source-map: 0.8.0-beta.0 sucrase: 3.35.0 tinyexec: 0.3.2 @@ -4024,7 +4017,7 @@ snapshots: type-fest@2.19.0: {} - type-fest@4.40.0: {} + type-fest@4.41.0: {} typed-array-buffer@1.0.3: dependencies: @@ -4082,13 +4075,13 @@ snapshots: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 - vite-node@3.1.1(@types/node@20.9.0): + vite-node@3.1.3(@types/node@20.9.0): dependencies: cac: 6.7.14 debug: 4.4.0 - es-module-lexer: 1.6.0 + es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 6.3.2(@types/node@20.9.0) + vite: 6.3.5(@types/node@20.9.0) transitivePeerDependencies: - '@types/node' - jiti @@ -4103,38 +4096,38 @@ snapshots: - tsx - yaml - vite-tsconfig-paths@5.1.4(typescript@5.8.3)(vite@6.3.2(@types/node@20.9.0)): + vite-tsconfig-paths@5.1.4(typescript@5.8.3)(vite@6.3.5(@types/node@20.9.0)): dependencies: debug: 4.4.0 globrex: 0.1.2 tsconfck: 3.1.5(typescript@5.8.3) optionalDependencies: - vite: 6.3.2(@types/node@20.9.0) + vite: 6.3.5(@types/node@20.9.0) transitivePeerDependencies: - supports-color - typescript - vite@6.3.2(@types/node@20.9.0): + vite@6.3.5(@types/node@20.9.0): dependencies: - esbuild: 0.25.2 + esbuild: 0.25.4 fdir: 6.4.4(picomatch@4.0.2) picomatch: 4.0.2 postcss: 8.5.3 - rollup: 4.40.0 + rollup: 4.40.2 tinyglobby: 0.2.13 optionalDependencies: '@types/node': 20.9.0 fsevents: 2.3.3 - vitest@3.1.1(@edge-runtime/vm@5.0.0)(@types/node@20.9.0)(happy-dom@17.4.4): + vitest@3.1.3(@edge-runtime/vm@5.0.0)(@types/node@20.9.0)(happy-dom@17.4.6): dependencies: - '@vitest/expect': 3.1.1 - '@vitest/mocker': 3.1.1(vite@6.3.2(@types/node@20.9.0)) - '@vitest/pretty-format': 3.1.1 - '@vitest/runner': 3.1.1 - '@vitest/snapshot': 3.1.1 - '@vitest/spy': 3.1.1 - '@vitest/utils': 3.1.1 + '@vitest/expect': 3.1.3 + '@vitest/mocker': 3.1.3(vite@6.3.5(@types/node@20.9.0)) + '@vitest/pretty-format': 3.1.3 + '@vitest/runner': 3.1.3 + '@vitest/snapshot': 3.1.3 + '@vitest/spy': 3.1.3 + '@vitest/utils': 3.1.3 chai: 5.2.0 debug: 4.4.0 expect-type: 1.2.1 @@ -4143,15 +4136,16 @@ snapshots: std-env: 3.9.0 tinybench: 2.9.0 tinyexec: 0.3.2 + tinyglobby: 0.2.13 tinypool: 1.0.2 tinyrainbow: 2.0.0 - vite: 6.3.2(@types/node@20.9.0) - vite-node: 3.1.1(@types/node@20.9.0) + vite: 6.3.5(@types/node@20.9.0) + vite-node: 3.1.3(@types/node@20.9.0) why-is-node-running: 2.3.0 optionalDependencies: '@edge-runtime/vm': 5.0.0 '@types/node': 20.9.0 - happy-dom: 17.4.4 + happy-dom: 17.4.6 transitivePeerDependencies: - jiti - less diff --git a/vitest.config.ts b/vitest.config.ts index 6ff4eedf..4bedc455 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -20,6 +20,7 @@ export default defineConfig({ "**/dist/**", "**/common/src/types/index.ts", // probably a vitest bug "**/common/src/types/enums.ts", // no need to test enums directly + "**/common/src/constants.ts", // no need to test constants directly "**/src/index.ts" ] }